VirtualBox

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

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

AMD64 debugging: Added checks for NMIs and that IF is cleared when doing the context switching.

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