VirtualBox

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

Last change on this file since 1349 was 1348, checked in by vboxsync, 18 years ago

Some old amd64 hacks -> VBOX_WITH_INTERNAL_NETWORKING

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 25.7 KB
Line 
1/* $Id: VMMR0.cpp 1348 2007-03-08 21:37:48Z 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#if HC_ARCH_BITS == 64 /* AMD64 debugging - to be removed */
448 if ((unsigned)rc - 0xc0caff00U > 0xff)
449 return rc;
450 /* fall thru */
451#else
452 return rc;
453#endif
454
455 /*
456 * We'll let TRPM change the stack frame so our return is different.
457 * Just keep in mind that after the call, things have changed!
458 */
459 case VINF_EM_RAW_INTERRUPT:
460 case VINF_EM_RAW_INTERRUPT_HYPER:
461 {
462#ifdef VBOX_WITHOUT_IDT_PATCHING
463 TRPMR0DispatchHostInterrupt(pVM);
464#else /* !VBOX_WITHOUT_IDT_PATCHING */
465 /*
466 * Don't trust the compiler to get this right.
467 * gcc -fomit-frame-pointer screws up big time here. This works fine in 64-bit
468 * mode too because we push the arguments on the stack in the IDT patch code.
469 */
470# if defined(__GNUC__)
471 void *pvRet = (uint8_t *)__builtin_frame_address(0) + sizeof(void *);
472# elif defined(_MSC_VER) && defined(__AMD64__) /** @todo check this with with VC7! */
473 void *pvRet = (uint8_t *)_AddressOfReturnAddress();
474# elif defined(__X86__)
475 void *pvRet = (uint8_t *)&pVM - sizeof(pVM);
476# else
477# error "huh?"
478# endif
479 if ( ((uintptr_t *)pvRet)[1] == (uintptr_t)pVM
480 && ((uintptr_t *)pvRet)[2] == (uintptr_t)uOperation
481 && ((uintptr_t *)pvRet)[3] == (uintptr_t)pvArg)
482 TRPMR0SetupInterruptDispatcherFrame(pVM, pvRet);
483 else
484 {
485# if defined(DEBUG) || defined(LOG_ENABLED)
486 static bool s_fHaveWarned = false;
487 if (!s_fHaveWarned)
488 {
489 s_fHaveWarned = true;
490 //RTLogPrintf("VMMR0.r0: The compiler can't find the stack frame!\n"); -- @todo export me!
491 RTLogComPrintf("VMMR0.r0: The compiler can't find the stack frame!\n");
492 }
493# endif
494 TRPMR0DispatchHostInterrupt(pVM);
495 }
496#endif /* !VBOX_WITHOUT_IDT_PATCHING */
497 return rc;
498 }
499 }
500 /* Won't get here! */
501 break;
502 }
503
504 /*
505 * Run guest code using the available hardware acceleration technology.
506 */
507 case VMMR0_DO_HWACC_RUN:
508 {
509 int rc;
510
511 STAM_COUNTER_INC(&pVM->vmm.s.StatRunGC);
512 rc = HWACCMR0Enable(pVM);
513 if (VBOX_SUCCESS(rc))
514 {
515#ifdef DEBUG_NO_RING0_ASSERTIONS
516 g_pVMAssert = pVM;
517#endif
518 rc = vmmR0CallHostSetJmp(&pVM->vmm.s.CallHostR0JmpBuf, HWACCMR0RunGuestCode, pVM); /* this may resume code. */
519#ifdef DEBUG_NO_RING0_ASSERTIONS
520 g_pVMAssert = 0;
521#endif
522 int rc2 = HWACCMR0Disable(pVM);
523 AssertRC(rc2);
524 }
525 pVM->vmm.s.iLastGCRc = rc;
526
527#ifdef VBOX_WITH_STATISTICS
528 vmmR0RecordRC(pVM, rc);
529#endif
530 /* No special action required for external interrupts, just return. */
531 return rc;
532 }
533
534 /*
535 * Initialize the R0 part of a VM instance.
536 */
537 case VMMR0_DO_VMMR0_INIT:
538 {
539 RTCCUINTREG fFlags = ASMIntDisableFlags();
540 int rc = VMMR0Init(pVM, (unsigned)(uintptr_t)pvArg);
541 ASMSetFlags(fFlags);
542 return rc;
543 }
544
545 /*
546 * Terminate the R0 part of a VM instance.
547 */
548 case VMMR0_DO_VMMR0_TERM:
549 {
550 RTCCUINTREG fFlags = ASMIntDisableFlags();
551 int rc = VMMR0Term(pVM);
552 ASMSetFlags(fFlags);
553 return rc;
554 }
555
556 /*
557 * Setup the hardware accelerated raw-mode session.
558 */
559 case VMMR0_DO_HWACC_SETUP_VM:
560 {
561 RTCCUINTREG fFlags = ASMIntDisableFlags();
562 int rc = HWACCMR0SetupVMX(pVM);
563 ASMSetFlags(fFlags);
564 return rc;
565 }
566
567 /*
568 * Switch to GC to execute Hypervisor function.
569 */
570 case VMMR0_DO_CALL_HYPERVISOR:
571 {
572 /* Safety precaution as VMX disables the switcher. */
573 Assert(!pVM->vmm.s.fSwitcherDisabled);
574 if (pVM->vmm.s.fSwitcherDisabled)
575 return VERR_NOT_SUPPORTED;
576
577 RTCCUINTREG fFlags = ASMIntDisableFlags();
578 int rc = pVM->vmm.s.pfnR0HostToGuest(pVM);
579 ASMSetFlags(fFlags);
580 return rc;
581 }
582
583#ifdef VBOX_WITH_INTERNAL_NETWORKING
584 /*
585 * Services.
586 */
587 case VMMR0_DO_INTNET_OPEN:
588 case VMMR0_DO_INTNET_IF_CLOSE:
589 case VMMR0_DO_INTNET_IF_GET_RING3_BUFFER:
590 case VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE:
591 case VMMR0_DO_INTNET_IF_SEND:
592 case VMMR0_DO_INTNET_IF_WAIT:
593 {
594 /*
595 * Validate arguments a bit first.
596 */
597 if (!VALID_PTR(pvArg))
598 return VERR_INVALID_POINTER;
599 if (!VALID_PTR(pVM))
600 return VERR_INVALID_POINTER;
601 if (pVM->pVMR0 != pVM)
602 return VERR_INVALID_POINTER;
603 if (!VALID_PTR(pVM->pSession))
604 return VERR_INVALID_POINTER;
605 if (!g_pIntNet)
606 return VERR_FILE_NOT_FOUND; ///@todo fix this status code!
607
608 /*
609 * Unpack the arguments and call the service.
610 */
611 switch (uOperation)
612 {
613 case VMMR0_DO_INTNET_OPEN:
614 {
615 PINTNETOPENARGS pArgs = (PINTNETOPENARGS)pvArg;
616 return INTNETR0Open(g_pIntNet, pVM->pSession, &pArgs->szNetwork[0], pArgs->cbSend, pArgs->cbRecv, &pArgs->hIf);
617 }
618
619 case VMMR0_DO_INTNET_IF_CLOSE:
620 {
621 PINTNETIFCLOSEARGS pArgs = (PINTNETIFCLOSEARGS)pvArg;
622 return INTNETR0IfClose(g_pIntNet, pArgs->hIf);
623 }
624
625 case VMMR0_DO_INTNET_IF_GET_RING3_BUFFER:
626 {
627 PINTNETIFGETRING3BUFFERARGS pArgs = (PINTNETIFGETRING3BUFFERARGS)pvArg;
628 return INTNETR0IfGetRing3Buffer(g_pIntNet, pArgs->hIf, &pArgs->pRing3Buf);
629 }
630
631 case VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE:
632 {
633 PINTNETIFSETPROMISCUOUSMODEARGS pArgs = (PINTNETIFSETPROMISCUOUSMODEARGS)pvArg;
634 return INTNETR0IfSetPromiscuousMode(g_pIntNet, pArgs->hIf, pArgs->fPromiscuous);
635 }
636
637 case VMMR0_DO_INTNET_IF_SEND:
638 {
639 PINTNETIFSENDARGS pArgs = (PINTNETIFSENDARGS)pvArg;
640 return INTNETR0IfSend(g_pIntNet, pArgs->hIf, pArgs->pvFrame, pArgs->cbFrame);
641 }
642
643 case VMMR0_DO_INTNET_IF_WAIT:
644 {
645 PINTNETIFWAITARGS pArgs = (PINTNETIFWAITARGS)pvArg;
646 return INTNETR0IfWait(g_pIntNet, pArgs->hIf, pArgs->cMillies);
647 }
648
649 default:
650 return VERR_NOT_SUPPORTED;
651 }
652 }
653#endif /* VBOX_WITH_INTERNAL_NETWORKING */
654
655 /*
656 * For profiling.
657 */
658 case VMMR0_DO_NOP:
659 return VINF_SUCCESS;
660
661 /*
662 * For testing Ring-0 APIs invoked in this environment.
663 */
664 case VMMR0_DO_TESTS:
665 /** @todo make new test */
666 return VINF_SUCCESS;
667
668
669 default:
670 /*
671 * We're returning VERR_NOT_SUPPORT here so we've got something else
672 * than -1 which the interrupt gate glue code might return.
673 */
674 Log(("operation %#x is not supported\n", uOperation));
675 return VERR_NOT_SUPPORTED;
676 }
677}
678
679
680/**
681 * Internal R0 logger worker: Flush logger.
682 *
683 * @param pLogger The logger instance to flush.
684 * @remark This function must be exported!
685 */
686VMMR0DECL(void) vmmR0LoggerFlush(PRTLOGGER pLogger)
687{
688 /*
689 * Convert the pLogger into a VM handle and 'call' back to Ring-3.
690 * (This is a bit paranoid code.)
691 */
692 PVMMR0LOGGER pR0Logger = (PVMMR0LOGGER)((uintptr_t)pLogger - RT_OFFSETOF(VMMR0LOGGER, Logger));
693 if ( !VALID_PTR(pR0Logger)
694 || !VALID_PTR(pR0Logger + 1)
695 || !VALID_PTR(pLogger)
696 || pLogger->u32Magic != RTLOGGER_MAGIC)
697 {
698 LogCom(("vmmR0LoggerFlush: pLogger=%p!\n", pLogger));
699 return;
700 }
701
702 PVM pVM = pR0Logger->pVM;
703 if ( !VALID_PTR(pVM)
704 || pVM->pVMHC != pVM)
705 {
706 LogCom(("vmmR0LoggerFlush: pVM=%p! pLogger=%p\n", pVM, pLogger));
707 return;
708 }
709
710 /*
711 * Check that the jump buffer is armed.
712 */
713#ifdef __X86__
714 if (!pVM->vmm.s.CallHostR0JmpBuf.eip)
715#else
716 if (!pVM->vmm.s.CallHostR0JmpBuf.rip)
717#endif
718 {
719 LogCom(("vmmR0LoggerFlush: Jump buffer isn't armed!\n"));
720 pLogger->offScratch = 0;
721 return;
722 }
723
724 VMMR0CallHost(pVM, VMMCALLHOST_VMM_LOGGER_FLUSH, 0);
725}
726
727void R0LogFlush()
728{
729 vmmR0LoggerFlush(RTLogDefaultInstance());
730}
731
732#ifdef DEBUG_NO_RING0_ASSERTIONS
733/**
734 * Check if we really want to hit a breakpoint.
735 * Can jump back to ring-3 when the longjmp is armed.
736 */
737DECLEXPORT(bool) RTCALL RTAssertDoBreakpoint()
738{
739 if (g_pVMAssert)
740 {
741 g_pVMAssert->vmm.s.enmCallHostOperation = VMMCALLHOST_VMM_LOGGER_FLUSH;
742 g_pVMAssert->vmm.s.u64CallHostArg = 0;
743 g_pVMAssert->vmm.s.rcCallHost = VERR_INTERNAL_ERROR;
744 int rc = vmmR0CallHostLongJmp(&g_pVMAssert->vmm.s.CallHostR0JmpBuf, VERR_INTERNAL_ERROR);
745 if (rc == VINF_SUCCESS)
746 rc = g_pVMAssert->vmm.s.rcCallHost;
747 }
748
749 return true;
750}
751
752
753#undef LOG_GROUP
754#define LOG_GROUP LOG_GROUP_EM
755
756/** Runtime assert implementation for Native Win32 Ring-0. */
757DECLEXPORT(void) RTCALL AssertMsg1(const char *pszExpr, unsigned uLine, const char *pszFile, const char *pszFunction)
758{
759 Log(("\n!!R0-Assertion Failed!!\n"
760 "Expression: %s\n"
761 "Location : %s(%d) %s\n",
762 pszExpr, pszFile, uLine, pszFunction));
763}
764
765/**
766 * Callback for RTLogFormatV which writes to the com port.
767 * See PFNLOGOUTPUT() for details.
768 */
769static DECLCALLBACK(size_t) rtLogOutput(void *pv, const char *pachChars, size_t cbChars)
770{
771 for (size_t i=0;i<cbChars;i++)
772 Log(("%c", pachChars[i]));
773
774 return cbChars;
775}
776
777DECLEXPORT(void) RTCALL AssertMsg2(const char *pszFormat, ...)
778{
779 PRTLOGGER pLog = RTLogDefaultInstance();
780 if (pLog)
781 {
782 va_list args;
783
784 va_start(args, pszFormat);
785 RTLogFormatV(rtLogOutput, pLog, pszFormat, args);
786 va_end(args);
787 R0LogFlush();
788 }
789}
790
791#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