VirtualBox

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

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

Proper interrupt redirection bitmap sync

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