VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR0/VMMR0.cpp@ 1995

Last change on this file since 1995 was 1793, checked in by vboxsync, 18 years ago

backed out 19970

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 25.5 KB
Line 
1/* $Id: VMMR0.cpp 1793 2007-03-29 11:50:26Z vboxsync $ */
2/** @file
3 * VMM - Host Context Ring 0.
4 */
5
6/*
7 * Copyright (C) 2006 InnoTek Systemberatung GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#define LOG_GROUP LOG_GROUP_VMM
27#ifdef __AMD64__ /** @todo fix logging on __AMD64__ (swapgs) - this has been fixed now. please remove. */
28# define LOG_DISABLED
29#endif
30#include <VBox/vmm.h>
31#include <VBox/sup.h>
32#include <VBox/trpm.h>
33#include <VBox/cpum.h>
34#include <VBox/stam.h>
35#include <VBox/tm.h>
36#include "VMMInternal.h"
37#include <VBox/vm.h>
38#include <VBox/intnet.h>
39#include <VBox/hwaccm.h>
40
41#include <VBox/err.h>
42#include <VBox/version.h>
43#include <VBox/log.h>
44#include <iprt/assert.h>
45#include <iprt/stdarg.h>
46
47#if defined(_MSC_VER) && defined(__AMD64__) /** @todo check this with with VC7! */
48# pragma intrinsic(_AddressOfReturnAddress)
49#endif
50
51
52/*******************************************************************************
53* Internal Functions *
54*******************************************************************************/
55static int VMMR0Init(PVM pVM, unsigned uVersion);
56static int VMMR0Term(PVM pVM);
57__BEGIN_DECLS
58VMMR0DECL(int) ModuleInit(void);
59VMMR0DECL(void) ModuleTerm(void);
60__END_DECLS
61
62
63//#define DEBUG_NO_RING0_ASSERTIONS
64#ifdef DEBUG_NO_RING0_ASSERTIONS
65static PVM g_pVMAssert = 0;
66#endif
67
68/*******************************************************************************
69* Global Variables *
70*******************************************************************************/
71#ifdef VBOX_WITH_INTERNAL_NETWORKING
72/** Pointer to the internal networking service instance. */
73PINTNET g_pIntNet = 0;
74#endif
75
76
77/**
78 * Initialize the module.
79 * This is called when we're first loaded.
80 *
81 * @returns 0 on success.
82 * @returns VBox status on failure.
83 */
84VMMR0DECL(int) ModuleInit(void)
85{
86#ifdef VBOX_WITH_INTERNAL_NETWORKING
87 LogFlow(("ModuleInit: g_pIntNet=%p\n", g_pIntNet));
88 g_pIntNet = NULL;
89 LogFlow(("ModuleInit: g_pIntNet=%p should be NULL now...\n", g_pIntNet));
90 int rc = INTNETR0Create(&g_pIntNet);
91 if (VBOX_SUCCESS(rc))
92 {
93 LogFlow(("ModuleInit: returns success. g_pIntNet=%p\n", g_pIntNet));
94 return 0;
95 }
96 g_pIntNet = NULL;
97 LogFlow(("ModuleTerm: returns %Vrc\n", rc));
98 return rc;
99#else
100 return 0;
101#endif
102}
103
104
105/**
106 * Terminate the module.
107 * This is called when we're finally unloaded.
108 */
109VMMR0DECL(void) ModuleTerm(void)
110{
111#ifdef VBOX_WITH_INTERNAL_NETWORKING
112 LogFlow(("ModuleTerm:\n"));
113 if (g_pIntNet)
114 {
115 INTNETR0Destroy(g_pIntNet);
116 g_pIntNet = NULL;
117 }
118 LogFlow(("ModuleTerm: returns\n"));
119#endif
120}
121
122
123/**
124 * Initaties the R0 driver for a particular VM instance.
125 *
126 * @returns VBox status code.
127 *
128 * @param pVM The VM instance in question.
129 * @param uVersion The minimum module version required.
130 */
131static int VMMR0Init(PVM pVM, unsigned uVersion)
132{
133 /*
134 * Check if compatible version.
135 */
136 if ( uVersion != VBOX_VERSION
137 && ( VBOX_GET_VERSION_MAJOR(uVersion) != VBOX_VERSION_MAJOR
138 || VBOX_GET_VERSION_MINOR(uVersion) < VBOX_VERSION_MINOR))
139 return VERR_VERSION_MISMATCH;
140 if ( !VALID_PTR(pVM)
141 || pVM->pVMR0 != pVM)
142 return VERR_INVALID_PARAMETER;
143
144 /*
145 * Register the EMT R0 logger instance.
146 */
147 PVMMR0LOGGER pR0Logger = pVM->vmm.s.pR0Logger;
148 if (pR0Logger)
149 {
150#if 0 /* testing of the logger. */
151 LogCom(("VMMR0Init: before %p\n", RTLogDefaultInstance()));
152 LogCom(("VMMR0Init: pfnFlush=%p actual=%p\n", pR0Logger->Logger.pfnFlush, vmmR0LoggerFlush));
153 LogCom(("VMMR0Init: pfnLogger=%p actual=%p\n", pR0Logger->Logger.pfnLogger, vmmR0LoggerWrapper));
154 LogCom(("VMMR0Init: offScratch=%d fFlags=%#x fDestFlags=%#x\n", pR0Logger->Logger.offScratch, pR0Logger->Logger.fFlags, pR0Logger->Logger.fDestFlags));
155
156 RTLogSetDefaultInstanceThread(&pR0Logger->Logger, (uintptr_t)pVM->pSession);
157 LogCom(("VMMR0Init: after %p reg\n", RTLogDefaultInstance()));
158 RTLogSetDefaultInstanceThread(NULL, 0);
159 LogCom(("VMMR0Init: after %p dereg\n", RTLogDefaultInstance()));
160
161 pR0Logger->Logger.pfnLogger("hello ring-0 logger\n");
162 LogCom(("VMMR0Init: returned succesfully from direct logger call.\n"));
163 pR0Logger->Logger.pfnFlush(&pR0Logger->Logger);
164 LogCom(("VMMR0Init: returned succesfully from direct flush call.\n"));
165
166 RTLogSetDefaultInstanceThread(&pR0Logger->Logger, (uintptr_t)pVM->pSession);
167 LogCom(("VMMR0Init: after %p reg2\n", RTLogDefaultInstance()));
168 pR0Logger->Logger.pfnLogger("hello ring-0 logger\n");
169 LogCom(("VMMR0Init: returned succesfully from direct logger call (2). offScratch=%d\n", pR0Logger->Logger.offScratch));
170 RTLogSetDefaultInstanceThread(NULL, 0);
171 LogCom(("VMMR0Init: after %p dereg2\n", RTLogDefaultInstance()));
172
173 RTLogLoggerEx(&pR0Logger->Logger, 0, ~0U, "hello ring-0 logger (RTLogLoggerEx)\n");
174 LogCom(("VMMR0Init: RTLogLoggerEx returned fine offScratch=%d\n", pR0Logger->Logger.offScratch));
175#endif
176 RTLogSetDefaultInstanceThread(&pR0Logger->Logger, (uintptr_t)pVM->pSession);
177 }
178
179
180 /*
181 * Init VMXM.
182 */
183 HWACCMR0Init(pVM);
184
185 /*
186 * Init CPUM.
187 */
188 int rc = CPUMR0Init(pVM);
189
190 if (RT_FAILURE(rc))
191 RTLogSetDefaultInstanceThread(NULL, 0);
192 return rc;
193}
194
195
196/**
197 * Terminates the R0 driver for a particular VM instance.
198 *
199 * @returns VBox status code.
200 *
201 * @param pVM The VM instance in question.
202 */
203static int VMMR0Term(PVM pVM)
204{
205 /*
206 * Deregister the logger.
207 */
208 RTLogSetDefaultInstanceThread(NULL, 0);
209 return VINF_SUCCESS;
210}
211
212
213/**
214 * Calls the ring-3 host code.
215 *
216 * @returns VBox status code of the ring-3 call.
217 * @param pVM The VM handle.
218 * @param enmOperation The operation.
219 * @param uArg The argument to the operation.
220 */
221VMMR0DECL(int) VMMR0CallHost(PVM pVM, VMMCALLHOST enmOperation, uint64_t uArg)
222{
223/** @todo profile this! */
224 pVM->vmm.s.enmCallHostOperation = enmOperation;
225 pVM->vmm.s.u64CallHostArg = uArg;
226 pVM->vmm.s.rcCallHost = VERR_INTERNAL_ERROR;
227 int rc = vmmR0CallHostLongJmp(&pVM->vmm.s.CallHostR0JmpBuf, VINF_VMM_CALL_HOST);
228 if (rc == VINF_SUCCESS)
229 rc = pVM->vmm.s.rcCallHost;
230 return rc;
231}
232
233
234#ifdef VBOX_WITH_STATISTICS
235/**
236 * Record return code statistics
237 * @param pVM The VM handle.
238 * @param rc The status code.
239 */
240static void vmmR0RecordRC(PVM pVM, int rc)
241{
242 /*
243 * Collect statistics.
244 */
245 switch (rc)
246 {
247 case VINF_SUCCESS:
248 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetNormal);
249 break;
250 case VINF_EM_RAW_INTERRUPT:
251 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetInterrupt);
252 break;
253 case VINF_EM_RAW_INTERRUPT_HYPER:
254 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetInterruptHyper);
255 break;
256 case VINF_EM_RAW_GUEST_TRAP:
257 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetGuestTrap);
258 break;
259 case VINF_EM_RAW_RING_SWITCH:
260 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetRingSwitch);
261 break;
262 case VINF_EM_RAW_RING_SWITCH_INT:
263 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetRingSwitchInt);
264 break;
265 case VINF_EM_RAW_EXCEPTION_PRIVILEGED:
266 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetExceptionPrivilege);
267 break;
268 case VINF_EM_RAW_STALE_SELECTOR:
269 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetStaleSelector);
270 break;
271 case VINF_EM_RAW_IRET_TRAP:
272 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetIRETTrap);
273 break;
274 case VINF_IOM_HC_IOPORT_READ:
275 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetIORead);
276 break;
277 case VINF_IOM_HC_IOPORT_WRITE:
278 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetIOWrite);
279 break;
280 case VINF_IOM_HC_IOPORT_READWRITE:
281 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetIOReadWrite);
282 break;
283 case VINF_IOM_HC_MMIO_READ:
284 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetMMIORead);
285 break;
286 case VINF_IOM_HC_MMIO_WRITE:
287 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetMMIOWrite);
288 break;
289 case VINF_IOM_HC_MMIO_READ_WRITE:
290 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetMMIOReadWrite);
291 break;
292 case VINF_PATM_HC_MMIO_PATCH_READ:
293 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetMMIOPatchRead);
294 break;
295 case VINF_PATM_HC_MMIO_PATCH_WRITE:
296 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetMMIOPatchWrite);
297 break;
298 case VINF_EM_RAW_EMULATE_INSTR:
299 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetEmulate);
300 break;
301 case VINF_PATCH_EMULATE_INSTR:
302 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetPatchEmulate);
303 break;
304 case VINF_EM_RAW_EMULATE_INSTR_LDT_FAULT:
305 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetLDTFault);
306 break;
307 case VINF_EM_RAW_EMULATE_INSTR_GDT_FAULT:
308 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetGDTFault);
309 break;
310 case VINF_EM_RAW_EMULATE_INSTR_IDT_FAULT:
311 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetIDTFault);
312 break;
313 case VINF_EM_RAW_EMULATE_INSTR_TSS_FAULT:
314 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetTSSFault);
315 break;
316 case VINF_EM_RAW_EMULATE_INSTR_PD_FAULT:
317 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetPDFault);
318 break;
319 case VINF_CSAM_PENDING_ACTION:
320 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetCSAMTask);
321 break;
322 case VINF_PGM_SYNC_CR3:
323 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetSyncCR3);
324 break;
325 case VINF_PATM_PATCH_INT3:
326 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetPatchInt3);
327 break;
328 case VINF_PATM_PATCH_TRAP_PF:
329 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetPatchPF);
330 break;
331 case VINF_PATM_PATCH_TRAP_GP:
332 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetPatchGP);
333 break;
334 case VINF_PATM_PENDING_IRQ_AFTER_IRET:
335 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetPatchIretIRQ);
336 break;
337 case VERR_REM_FLUSHED_PAGES_OVERFLOW:
338 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetPageOverflow);
339 break;
340 case VINF_EM_RESCHEDULE_REM:
341 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetRescheduleREM);
342 break;
343 case VINF_EM_RAW_TO_R3:
344 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetToR3);
345 break;
346 case VINF_EM_RAW_TIMER_PENDING:
347 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetTimerPending);
348 break;
349 case VINF_EM_RAW_INTERRUPT_PENDING:
350 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetInterruptPending);
351 break;
352 case VINF_VMM_CALL_HOST:
353 switch (pVM->vmm.s.enmCallHostOperation)
354 {
355 case VMMCALLHOST_PDM_LOCK:
356 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetPDMLock);
357 break;
358 case VMMCALLHOST_PDM_QUEUE_FLUSH:
359 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetPDMQueueFlush);
360 break;
361 case VMMCALLHOST_PGM_POOL_GROW:
362 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetPGMPoolGrow);
363 break;
364 case VMMCALLHOST_PGM_LOCK:
365 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetPGMLock);
366 break;
367 case VMMCALLHOST_REM_REPLAY_HANDLER_NOTIFICATIONS:
368 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetRemReplay);
369 break;
370 case VMMCALLHOST_PGM_RAM_GROW_RANGE:
371 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetPGMGrowRAM);
372 break;
373 case VMMCALLHOST_VMM_LOGGER_FLUSH:
374 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetLogFlush);
375 break;
376 case VMMCALLHOST_VM_SET_ERROR:
377 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetVMSetError);
378 break;
379 case VMMCALLHOST_VM_SET_RUNTIME_ERROR:
380 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetVMSetRuntimeError);
381 break;
382 default:
383 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetCallHost);
384 break;
385 }
386 break;
387 case VINF_PATM_DUPLICATE_FUNCTION:
388 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetPATMDuplicateFn);
389 break;
390 case VINF_PGM_CHANGE_MODE:
391 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetPGMChangeMode);
392 break;
393 case VINF_EM_RAW_EMULATE_INSTR_HLT:
394 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetEmulHlt);
395 break;
396 case VINF_EM_PENDING_REQUEST:
397 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetPendingRequest);
398 break;
399 default:
400 STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetMisc);
401 break;
402 }
403}
404#endif /* VBOX_WITH_STATISTICS */
405
406
407/**
408 * The Ring 0 entry point, called by the support library (SUP).
409 *
410 * @returns VBox status code.
411 * @param pVM The VM to operate on.
412 * @param uOperation Which operation to execute. (VMMR0OPERATION)
413 * @param pvArg Argument to the operation.
414 */
415VMMR0DECL(int) VMMR0Entry(PVM pVM, unsigned /* make me an enum */ uOperation, void *pvArg)
416{
417 switch (uOperation)
418 {
419 /*
420 * Switch to GC.
421 * These calls return whatever the GC returns.
422 */
423 case VMMR0_DO_RAW_RUN:
424 {
425 /* Safety precaution as VMX disables the switcher. */
426 Assert(!pVM->vmm.s.fSwitcherDisabled);
427 if (pVM->vmm.s.fSwitcherDisabled)
428 return VERR_NOT_SUPPORTED;
429
430 STAM_COUNTER_INC(&pVM->vmm.s.StatRunGC);
431 register int rc;
432 pVM->vmm.s.iLastGCRc = rc = pVM->vmm.s.pfnR0HostToGuest(pVM);
433
434#ifdef VBOX_WITH_STATISTICS
435 vmmR0RecordRC(pVM, rc);
436#endif
437
438 /*
439 * Check if there is an exit R0 action associated with the return code.
440 */
441 switch (rc)
442 {
443 /*
444 * Default - no action, just return.
445 */
446 default:
447 return rc;
448
449 /*
450 * We'll let TRPM change the stack frame so our return is different.
451 * Just keep in mind that after the call, things have changed!
452 */
453 case VINF_EM_RAW_INTERRUPT:
454 case VINF_EM_RAW_INTERRUPT_HYPER:
455 {
456#ifdef VBOX_WITHOUT_IDT_PATCHING
457 TRPMR0DispatchHostInterrupt(pVM);
458#else /* !VBOX_WITHOUT_IDT_PATCHING */
459 /*
460 * Don't trust the compiler to get this right.
461 * gcc -fomit-frame-pointer screws up big time here. This works fine in 64-bit
462 * mode too because we push the arguments on the stack in the IDT patch code.
463 */
464# if defined(__GNUC__)
465 void *pvRet = (uint8_t *)__builtin_frame_address(0) + sizeof(void *);
466# elif defined(_MSC_VER) && defined(__AMD64__) /** @todo check this with with VC7! */
467 void *pvRet = (uint8_t *)_AddressOfReturnAddress();
468# elif defined(__X86__)
469 void *pvRet = (uint8_t *)&pVM - sizeof(pVM);
470# else
471# error "huh?"
472# endif
473 if ( ((uintptr_t *)pvRet)[1] == (uintptr_t)pVM
474 && ((uintptr_t *)pvRet)[2] == (uintptr_t)uOperation
475 && ((uintptr_t *)pvRet)[3] == (uintptr_t)pvArg)
476 TRPMR0SetupInterruptDispatcherFrame(pVM, pvRet);
477 else
478 {
479# if defined(DEBUG) || defined(LOG_ENABLED)
480 static bool s_fHaveWarned = false;
481 if (!s_fHaveWarned)
482 {
483 s_fHaveWarned = true;
484 //RTLogPrintf("VMMR0.r0: The compiler can't find the stack frame!\n"); -- @todo export me!
485 RTLogComPrintf("VMMR0.r0: The compiler can't find the stack frame!\n");
486 }
487# endif
488 TRPMR0DispatchHostInterrupt(pVM);
489 }
490#endif /* !VBOX_WITHOUT_IDT_PATCHING */
491 return rc;
492 }
493 }
494 /* Won't get here! */
495 break;
496 }
497
498 /*
499 * Run guest code using the available hardware acceleration technology.
500 */
501 case VMMR0_DO_HWACC_RUN:
502 {
503 int rc;
504
505 STAM_COUNTER_INC(&pVM->vmm.s.StatRunGC);
506 rc = HWACCMR0Enable(pVM);
507 if (VBOX_SUCCESS(rc))
508 {
509#ifdef DEBUG_NO_RING0_ASSERTIONS
510 g_pVMAssert = pVM;
511#endif
512 rc = vmmR0CallHostSetJmp(&pVM->vmm.s.CallHostR0JmpBuf, HWACCMR0RunGuestCode, pVM); /* this may resume code. */
513#ifdef DEBUG_NO_RING0_ASSERTIONS
514 g_pVMAssert = 0;
515#endif
516 int rc2 = HWACCMR0Disable(pVM);
517 AssertRC(rc2);
518 }
519 pVM->vmm.s.iLastGCRc = rc;
520
521#ifdef VBOX_WITH_STATISTICS
522 vmmR0RecordRC(pVM, rc);
523#endif
524 /* No special action required for external interrupts, just return. */
525 return rc;
526 }
527
528 /*
529 * Initialize the R0 part of a VM instance.
530 */
531 case VMMR0_DO_VMMR0_INIT:
532 {
533 RTCCUINTREG fFlags = ASMIntDisableFlags();
534 int rc = VMMR0Init(pVM, (unsigned)(uintptr_t)pvArg);
535 ASMSetFlags(fFlags);
536 return rc;
537 }
538
539 /*
540 * Terminate the R0 part of a VM instance.
541 */
542 case VMMR0_DO_VMMR0_TERM:
543 {
544 RTCCUINTREG fFlags = ASMIntDisableFlags();
545 int rc = VMMR0Term(pVM);
546 ASMSetFlags(fFlags);
547 return rc;
548 }
549
550 /*
551 * Setup the hardware accelerated raw-mode session.
552 */
553 case VMMR0_DO_HWACC_SETUP_VM:
554 {
555 RTCCUINTREG fFlags = ASMIntDisableFlags();
556 int rc = HWACCMR0SetupVMX(pVM);
557 ASMSetFlags(fFlags);
558 return rc;
559 }
560
561 /*
562 * Switch to GC to execute Hypervisor function.
563 */
564 case VMMR0_DO_CALL_HYPERVISOR:
565 {
566 /* Safety precaution as VMX disables the switcher. */
567 Assert(!pVM->vmm.s.fSwitcherDisabled);
568 if (pVM->vmm.s.fSwitcherDisabled)
569 return VERR_NOT_SUPPORTED;
570
571 RTCCUINTREG fFlags = ASMIntDisableFlags();
572 int rc = pVM->vmm.s.pfnR0HostToGuest(pVM);
573 ASMSetFlags(fFlags);
574 return rc;
575 }
576
577#ifdef VBOX_WITH_INTERNAL_NETWORKING
578 /*
579 * Services.
580 */
581 case VMMR0_DO_INTNET_OPEN:
582 case VMMR0_DO_INTNET_IF_CLOSE:
583 case VMMR0_DO_INTNET_IF_GET_RING3_BUFFER:
584 case VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE:
585 case VMMR0_DO_INTNET_IF_SEND:
586 case VMMR0_DO_INTNET_IF_WAIT:
587 {
588 /*
589 * Validate arguments a bit first.
590 */
591 if (!VALID_PTR(pvArg))
592 return VERR_INVALID_POINTER;
593 if (!VALID_PTR(pVM))
594 return VERR_INVALID_POINTER;
595 if (pVM->pVMR0 != pVM)
596 return VERR_INVALID_POINTER;
597 if (!VALID_PTR(pVM->pSession))
598 return VERR_INVALID_POINTER;
599 if (!g_pIntNet)
600 return VERR_FILE_NOT_FOUND; ///@todo fix this status code!
601
602 /*
603 * Unpack the arguments and call the service.
604 */
605 switch (uOperation)
606 {
607 case VMMR0_DO_INTNET_OPEN:
608 {
609 PINTNETOPENARGS pArgs = (PINTNETOPENARGS)pvArg;
610 return INTNETR0Open(g_pIntNet, pVM->pSession, &pArgs->szNetwork[0], pArgs->cbSend, pArgs->cbRecv, pArgs->fRestrictAccess, &pArgs->hIf);
611 }
612
613 case VMMR0_DO_INTNET_IF_CLOSE:
614 {
615 PINTNETIFCLOSEARGS pArgs = (PINTNETIFCLOSEARGS)pvArg;
616 return INTNETR0IfClose(g_pIntNet, pArgs->hIf);
617 }
618
619 case VMMR0_DO_INTNET_IF_GET_RING3_BUFFER:
620 {
621 PINTNETIFGETRING3BUFFERARGS pArgs = (PINTNETIFGETRING3BUFFERARGS)pvArg;
622 return INTNETR0IfGetRing3Buffer(g_pIntNet, pArgs->hIf, &pArgs->pRing3Buf);
623 }
624
625 case VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE:
626 {
627 PINTNETIFSETPROMISCUOUSMODEARGS pArgs = (PINTNETIFSETPROMISCUOUSMODEARGS)pvArg;
628 return INTNETR0IfSetPromiscuousMode(g_pIntNet, pArgs->hIf, pArgs->fPromiscuous);
629 }
630
631 case VMMR0_DO_INTNET_IF_SEND:
632 {
633 PINTNETIFSENDARGS pArgs = (PINTNETIFSENDARGS)pvArg;
634 return INTNETR0IfSend(g_pIntNet, pArgs->hIf, pArgs->pvFrame, pArgs->cbFrame);
635 }
636
637 case VMMR0_DO_INTNET_IF_WAIT:
638 {
639 PINTNETIFWAITARGS pArgs = (PINTNETIFWAITARGS)pvArg;
640 return INTNETR0IfWait(g_pIntNet, pArgs->hIf, pArgs->cMillies);
641 }
642
643 default:
644 return VERR_NOT_SUPPORTED;
645 }
646 }
647#endif /* VBOX_WITH_INTERNAL_NETWORKING */
648
649 /*
650 * For profiling.
651 */
652 case VMMR0_DO_NOP:
653 return VINF_SUCCESS;
654
655 /*
656 * For testing Ring-0 APIs invoked in this environment.
657 */
658 case VMMR0_DO_TESTS:
659 /** @todo make new test */
660 return VINF_SUCCESS;
661
662
663 default:
664 /*
665 * We're returning VERR_NOT_SUPPORT here so we've got something else
666 * than -1 which the interrupt gate glue code might return.
667 */
668 Log(("operation %#x is not supported\n", uOperation));
669 return VERR_NOT_SUPPORTED;
670 }
671}
672
673
674/**
675 * Internal R0 logger worker: Flush logger.
676 *
677 * @param pLogger The logger instance to flush.
678 * @remark This function must be exported!
679 */
680VMMR0DECL(void) vmmR0LoggerFlush(PRTLOGGER pLogger)
681{
682 /*
683 * Convert the pLogger into a VM handle and 'call' back to Ring-3.
684 * (This is a bit paranoid code.)
685 */
686 PVMMR0LOGGER pR0Logger = (PVMMR0LOGGER)((uintptr_t)pLogger - RT_OFFSETOF(VMMR0LOGGER, Logger));
687 if ( !VALID_PTR(pR0Logger)
688 || !VALID_PTR(pR0Logger + 1)
689 || !VALID_PTR(pLogger)
690 || pLogger->u32Magic != RTLOGGER_MAGIC)
691 {
692 LogCom(("vmmR0LoggerFlush: pLogger=%p!\n", pLogger));
693 return;
694 }
695
696 PVM pVM = pR0Logger->pVM;
697 if ( !VALID_PTR(pVM)
698 || pVM->pVMHC != pVM)
699 {
700 LogCom(("vmmR0LoggerFlush: pVM=%p! pLogger=%p\n", pVM, pLogger));
701 return;
702 }
703
704 /*
705 * Check that the jump buffer is armed.
706 */
707#ifdef __X86__
708 if (!pVM->vmm.s.CallHostR0JmpBuf.eip)
709#else
710 if (!pVM->vmm.s.CallHostR0JmpBuf.rip)
711#endif
712 {
713 LogCom(("vmmR0LoggerFlush: Jump buffer isn't armed!\n"));
714 pLogger->offScratch = 0;
715 return;
716 }
717
718 VMMR0CallHost(pVM, VMMCALLHOST_VMM_LOGGER_FLUSH, 0);
719}
720
721void R0LogFlush()
722{
723 vmmR0LoggerFlush(RTLogDefaultInstance());
724}
725
726#ifdef DEBUG_NO_RING0_ASSERTIONS
727/**
728 * Check if we really want to hit a breakpoint.
729 * Can jump back to ring-3 when the longjmp is armed.
730 */
731DECLEXPORT(bool) RTCALL RTAssertDoBreakpoint()
732{
733 if (g_pVMAssert)
734 {
735 g_pVMAssert->vmm.s.enmCallHostOperation = VMMCALLHOST_VMM_LOGGER_FLUSH;
736 g_pVMAssert->vmm.s.u64CallHostArg = 0;
737 g_pVMAssert->vmm.s.rcCallHost = VERR_INTERNAL_ERROR;
738 int rc = vmmR0CallHostLongJmp(&g_pVMAssert->vmm.s.CallHostR0JmpBuf, VERR_INTERNAL_ERROR);
739 if (rc == VINF_SUCCESS)
740 rc = g_pVMAssert->vmm.s.rcCallHost;
741 }
742
743 return true;
744}
745
746
747#undef LOG_GROUP
748#define LOG_GROUP LOG_GROUP_EM
749
750/** Runtime assert implementation for Native Win32 Ring-0. */
751DECLEXPORT(void) RTCALL AssertMsg1(const char *pszExpr, unsigned uLine, const char *pszFile, const char *pszFunction)
752{
753 Log(("\n!!R0-Assertion Failed!!\n"
754 "Expression: %s\n"
755 "Location : %s(%d) %s\n",
756 pszExpr, pszFile, uLine, pszFunction));
757}
758
759/**
760 * Callback for RTLogFormatV which writes to the com port.
761 * See PFNLOGOUTPUT() for details.
762 */
763static DECLCALLBACK(size_t) rtLogOutput(void *pv, const char *pachChars, size_t cbChars)
764{
765 for (size_t i=0;i<cbChars;i++)
766 Log(("%c", pachChars[i]));
767
768 return cbChars;
769}
770
771DECLEXPORT(void) RTCALL AssertMsg2(const char *pszFormat, ...)
772{
773 PRTLOGGER pLog = RTLogDefaultInstance();
774 if (pLog)
775 {
776 va_list args;
777
778 va_start(args, pszFormat);
779 RTLogFormatV(rtLogOutput, pLog, pszFormat, args);
780 va_end(args);
781 R0LogFlush();
782 }
783}
784
785#endif
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette