VirtualBox

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

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

Temporarily disabled ring 0 to vbox log hack on Vista 64.

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