VirtualBox

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

Last change on this file since 3840 was 3696, checked in by vboxsync, 17 years ago

double underscore cleanup.

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