VMMR0.cpp revision ea416cf4cff6b3415142253cbee1752b5c7947c7
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync * VMM - Host Context Ring 0.
1612ddf488e6d1a459dc02cd7078215985f87081vboxsync * Copyright (C) 2006 InnoTek Systemberatung GmbH
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync * available from http://www.virtualbox.org. This file is free software;
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync * you can redistribute it and/or modify it under the terms of the GNU
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync * General Public License as published by the Free Software Foundation,
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
78a072e1b56619e3230735ae073668311232ec94vboxsync * If you received this file as part of a commercial VirtualBox
78a072e1b56619e3230735ae073668311232ec94vboxsync * distribution, then only the terms of your commercial VirtualBox
78a072e1b56619e3230735ae073668311232ec94vboxsync * license agreement apply instead of the previous paragraph.
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync/*******************************************************************************
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync* Header Files *
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync*******************************************************************************/
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync#ifdef __AMD64__ /** @todo fix logging on __AMD64__ (swapgs) - this has been fixed now. please remove. */
d5d45608052fd506e4114bf112df6efae7fcd8a7vboxsync#if defined(_MSC_VER) && defined(__AMD64__) /** @todo check this with with VC7! */
78a072e1b56619e3230735ae073668311232ec94vboxsync/*******************************************************************************
cc260ed3418d1fd2771d0395f818f76808b60238vboxsync* Internal Functions *
cc260ed3418d1fd2771d0395f818f76808b60238vboxsync*******************************************************************************/
78a072e1b56619e3230735ae073668311232ec94vboxsync//#define DEBUG_NO_RING0_ASSERTIONS
cc260ed3418d1fd2771d0395f818f76808b60238vboxsync/*******************************************************************************
cc260ed3418d1fd2771d0395f818f76808b60238vboxsync* Global Variables *
cc260ed3418d1fd2771d0395f818f76808b60238vboxsync*******************************************************************************/
78a072e1b56619e3230735ae073668311232ec94vboxsync/** Pointer to the internal networking service instance. */
78a072e1b56619e3230735ae073668311232ec94vboxsync * Initialize the module.
78a072e1b56619e3230735ae073668311232ec94vboxsync * This is called when we're first loaded.
c7c6718a3ec95ca32bf4f2e5311b871e95c3b195vboxsync * @returns 0 on success.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @returns VBox status on failure.
78a072e1b56619e3230735ae073668311232ec94vboxsync LogFlow(("ModuleInit: g_pIntNet=%p\n", g_pIntNet));
78a072e1b56619e3230735ae073668311232ec94vboxsync LogFlow(("ModuleInit: g_pIntNet=%p should be NULL now...\n", g_pIntNet));
08c4185261c17943cff6cc94522579696eeeb478vboxsync LogFlow(("ModuleInit: returns success. g_pIntNet=%p\n", g_pIntNet));
08c4185261c17943cff6cc94522579696eeeb478vboxsync * Terminate the module.
08c4185261c17943cff6cc94522579696eeeb478vboxsync * This is called when we're finally unloaded.
08c4185261c17943cff6cc94522579696eeeb478vboxsync * Initaties the R0 driver for a particular VM instance.
08c4185261c17943cff6cc94522579696eeeb478vboxsync * @returns VBox status code.
08c4185261c17943cff6cc94522579696eeeb478vboxsync * @param pVM The VM instance in question.
08c4185261c17943cff6cc94522579696eeeb478vboxsync * @param uVersion The minimum module version required.
08c4185261c17943cff6cc94522579696eeeb478vboxsync * Check if compatible version.
08c4185261c17943cff6cc94522579696eeeb478vboxsync && ( VBOX_GET_VERSION_MAJOR(uVersion) != VBOX_VERSION_MAJOR
78a072e1b56619e3230735ae073668311232ec94vboxsync || VBOX_GET_VERSION_MINOR(uVersion) < VBOX_VERSION_MINOR))
a6ab77f04b22f0de7691f50dfdee8196024ce26dvboxsync * Register the EMT R0 logger instance.
78a072e1b56619e3230735ae073668311232ec94vboxsync#if 0 /* testing of the logger. */
9726c89eba6e777f3eb4d57f65ca6171a2241d29vboxsync LogCom(("VMMR0Init: before %p\n", RTLogDefaultInstance()));
08c4185261c17943cff6cc94522579696eeeb478vboxsync LogCom(("VMMR0Init: pfnFlush=%p actual=%p\n", pR0Logger->Logger.pfnFlush, vmmR0LoggerFlush));
08c4185261c17943cff6cc94522579696eeeb478vboxsync LogCom(("VMMR0Init: pfnLogger=%p actual=%p\n", pR0Logger->Logger.pfnLogger, vmmR0LoggerWrapper));
78a072e1b56619e3230735ae073668311232ec94vboxsync LogCom(("VMMR0Init: offScratch=%d fFlags=%#x fDestFlags=%#x\n", pR0Logger->Logger.offScratch, pR0Logger->Logger.fFlags, pR0Logger->Logger.fDestFlags));
08c4185261c17943cff6cc94522579696eeeb478vboxsync RTLogSetDefaultInstanceThread(&pR0Logger->Logger, (uintptr_t)pVM->pSession);
08c4185261c17943cff6cc94522579696eeeb478vboxsync LogCom(("VMMR0Init: after %p reg\n", RTLogDefaultInstance()));
08c4185261c17943cff6cc94522579696eeeb478vboxsync LogCom(("VMMR0Init: after %p dereg\n", RTLogDefaultInstance()));
08c4185261c17943cff6cc94522579696eeeb478vboxsync pR0Logger->Logger.pfnLogger("hello ring-0 logger\n");
08c4185261c17943cff6cc94522579696eeeb478vboxsync LogCom(("VMMR0Init: returned succesfully from direct logger call.\n"));
08c4185261c17943cff6cc94522579696eeeb478vboxsync LogCom(("VMMR0Init: returned succesfully from direct flush call.\n"));
da31d917654e0b617e7a9bf8b0cf786136edf8e8vboxsync RTLogSetDefaultInstanceThread(&pR0Logger->Logger, (uintptr_t)pVM->pSession);
78a072e1b56619e3230735ae073668311232ec94vboxsync LogCom(("VMMR0Init: after %p reg2\n", RTLogDefaultInstance()));
08c4185261c17943cff6cc94522579696eeeb478vboxsync pR0Logger->Logger.pfnLogger("hello ring-0 logger\n");
08c4185261c17943cff6cc94522579696eeeb478vboxsync LogCom(("VMMR0Init: returned succesfully from direct logger call (2). offScratch=%d\n", pR0Logger->Logger.offScratch));
9726c89eba6e777f3eb4d57f65ca6171a2241d29vboxsync LogCom(("VMMR0Init: after %p dereg2\n", RTLogDefaultInstance()));
da31d917654e0b617e7a9bf8b0cf786136edf8e8vboxsync RTLogLoggerEx(&pR0Logger->Logger, 0, ~0U, "hello ring-0 logger (RTLogLoggerEx)\n");
08c4185261c17943cff6cc94522579696eeeb478vboxsync LogCom(("VMMR0Init: RTLogLoggerEx returned fine offScratch=%d\n", pR0Logger->Logger.offScratch));
08c4185261c17943cff6cc94522579696eeeb478vboxsync RTLogSetDefaultInstanceThread(&pR0Logger->Logger, (uintptr_t)pVM->pSession);
78a072e1b56619e3230735ae073668311232ec94vboxsync * Init VMXM.
78a072e1b56619e3230735ae073668311232ec94vboxsync * Init CPUM.
78a072e1b56619e3230735ae073668311232ec94vboxsync * Terminates the R0 driver for a particular VM instance.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @returns VBox status code.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param pVM The VM instance in question.
cc260ed3418d1fd2771d0395f818f76808b60238vboxsync * Deregister the logger.
cc260ed3418d1fd2771d0395f818f76808b60238vboxsync * Calls the ring-3 host code.
58798710f0fd506acfbef1cece482642d0447550vboxsync * @returns VBox status code of the ring-3 call.
60a6d709c252770b3830c85deac9c493625e3f52vboxsync * @param pVM The VM handle.
cc260ed3418d1fd2771d0395f818f76808b60238vboxsync * @param enmOperation The operation.
cc260ed3418d1fd2771d0395f818f76808b60238vboxsync * @param uArg The argument to the operation.
cc260ed3418d1fd2771d0395f818f76808b60238vboxsyncVMMR0DECL(int) VMMR0CallHost(PVM pVM, VMMCALLHOST enmOperation, uint64_t uArg)
cc260ed3418d1fd2771d0395f818f76808b60238vboxsync/** @todo profile this! */
cc260ed3418d1fd2771d0395f818f76808b60238vboxsync int rc = vmmR0CallHostLongJmp(&pVM->vmm.s.CallHostR0JmpBuf, VINF_VMM_CALL_HOST);
cc260ed3418d1fd2771d0395f818f76808b60238vboxsync * Record return code statistics
2a7322928382e52db8e320d19df4f03dee16b3edvboxsync * @param pVM The VM handle.
cc260ed3418d1fd2771d0395f818f76808b60238vboxsync * @param rc The status code.
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync * Collect statistics.
78a072e1b56619e3230735ae073668311232ec94vboxsync STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetInterruptHyper);
78a072e1b56619e3230735ae073668311232ec94vboxsync STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetRingSwitchInt);
78a072e1b56619e3230735ae073668311232ec94vboxsync STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetExceptionPrivilege);
78a072e1b56619e3230735ae073668311232ec94vboxsync STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetStaleSelector);
78a072e1b56619e3230735ae073668311232ec94vboxsync STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetIOReadWrite);
78a072e1b56619e3230735ae073668311232ec94vboxsync STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetMMIOReadWrite);
78a072e1b56619e3230735ae073668311232ec94vboxsync STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetMMIOPatchRead);
78a072e1b56619e3230735ae073668311232ec94vboxsync STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetMMIOPatchWrite);
78a072e1b56619e3230735ae073668311232ec94vboxsync STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetPatchEmulate);
156101683587682f6d63b4af322f611d90b77fcevboxsync STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetPatchIretIRQ);
34aa2e97a2a6d7c3c0a5be5121edfd51a31281acvboxsync STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetPageOverflow);
78a072e1b56619e3230735ae073668311232ec94vboxsync STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetRescheduleREM);
78a072e1b56619e3230735ae073668311232ec94vboxsync STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetTimerPending);
cc260ed3418d1fd2771d0395f818f76808b60238vboxsync STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetInterruptPending);
78a072e1b56619e3230735ae073668311232ec94vboxsync STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetPDMQueueFlush);
78a072e1b56619e3230735ae073668311232ec94vboxsync STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetPGMPoolGrow);
78a072e1b56619e3230735ae073668311232ec94vboxsync STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetVMSetRuntimeError);
2a7322928382e52db8e320d19df4f03dee16b3edvboxsync STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetPATMDuplicateFn);
58798710f0fd506acfbef1cece482642d0447550vboxsync STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetPGMChangeMode);
58798710f0fd506acfbef1cece482642d0447550vboxsync STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetPendingRequest);
78a072e1b56619e3230735ae073668311232ec94vboxsync#endif /* VBOX_WITH_STATISTICS */
78a072e1b56619e3230735ae073668311232ec94vboxsync * The Ring 0 entry point, called by the support library (SUP).
78a072e1b56619e3230735ae073668311232ec94vboxsync * @returns VBox status code.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param pVM The VM to operate on.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param uOperation Which operation to execute. (VMMR0OPERATION)
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param pvArg Argument to the operation.
34aa2e97a2a6d7c3c0a5be5121edfd51a31281acvboxsyncVMMR0DECL(int) VMMR0Entry(PVM pVM, unsigned /* make me an enum */ uOperation, void *pvArg)
78a072e1b56619e3230735ae073668311232ec94vboxsync * Switch to GC.
78a072e1b56619e3230735ae073668311232ec94vboxsync * These calls return whatever the GC returns.
ae072e31d733f2a7c9cb1b2b4c4901b66197aadavboxsync /* Safety precaution as VMX disables the switcher. */
78a072e1b56619e3230735ae073668311232ec94vboxsync register int rc;
78a072e1b56619e3230735ae073668311232ec94vboxsync pVM->vmm.s.iLastGCRc = rc = pVM->vmm.s.pfnR0HostToGuest(pVM);
78a072e1b56619e3230735ae073668311232ec94vboxsync * Check if there is an exit R0 action associated with the return code.
78a072e1b56619e3230735ae073668311232ec94vboxsync * Default - no action, just return.
78a072e1b56619e3230735ae073668311232ec94vboxsync * We'll let TRPM change the stack frame so our return is different.
78a072e1b56619e3230735ae073668311232ec94vboxsync * Just keep in mind that after the call, things have changed!
78a072e1b56619e3230735ae073668311232ec94vboxsync#else /* !VBOX_WITHOUT_IDT_PATCHING */
78a072e1b56619e3230735ae073668311232ec94vboxsync * Don't trust the compiler to get this right.
78a072e1b56619e3230735ae073668311232ec94vboxsync * gcc -fomit-frame-pointer screws up big time here. This works fine in 64-bit
78a072e1b56619e3230735ae073668311232ec94vboxsync * mode too because we push the arguments on the stack in the IDT patch code.
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync# if defined(__GNUC__)
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync void *pvRet = (uint8_t *)__builtin_frame_address(0) + sizeof(void *);
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync# elif defined(_MSC_VER) && defined(__AMD64__) /** @todo check this with with VC7! */
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync void *pvRet = (uint8_t *)_AddressOfReturnAddress();
78a072e1b56619e3230735ae073668311232ec94vboxsync && ((uintptr_t *)pvRet)[2] == (uintptr_t)uOperation
78a072e1b56619e3230735ae073668311232ec94vboxsync static bool s_fHaveWarned = false;
78a072e1b56619e3230735ae073668311232ec94vboxsync //RTLogPrintf("VMMR0.r0: The compiler can't find the stack frame!\n"); -- @todo export me!
78a072e1b56619e3230735ae073668311232ec94vboxsync RTLogComPrintf("VMMR0.r0: The compiler can't find the stack frame!\n");
3af289fb9126c91f28ede0dcb3429da0de12b94evboxsync#endif /* !VBOX_WITHOUT_IDT_PATCHING */
78a072e1b56619e3230735ae073668311232ec94vboxsync /* Won't get here! */
78a072e1b56619e3230735ae073668311232ec94vboxsync * Run guest code using the available hardware acceleration technology.
78a072e1b56619e3230735ae073668311232ec94vboxsync rc = vmmR0CallHostSetJmp(&pVM->vmm.s.CallHostR0JmpBuf, HWACCMR0RunGuestCode, pVM); /* this may resume code. */
78a072e1b56619e3230735ae073668311232ec94vboxsync /* No special action required for external interrupts, just return. */
78a072e1b56619e3230735ae073668311232ec94vboxsync * Initialize the R0 part of a VM instance.
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync int rc = VMMR0Init(pVM, (unsigned)(uintptr_t)pvArg);
78a072e1b56619e3230735ae073668311232ec94vboxsync * Terminate the R0 part of a VM instance.
78a072e1b56619e3230735ae073668311232ec94vboxsync * Setup the hardware accelerated raw-mode session.
40fa6228bd9ab763bc67b51fe6290802e954eb8cvboxsync * Switch to GC to execute Hypervisor function.
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync /* Safety precaution as VMX disables the switcher. */
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync * Services.
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync * Validate arguments a bit first.
8c9f8fda080b7e99f35ef4d2ab8ec632ad2a4068vboxsync return VERR_FILE_NOT_FOUND; ///@todo fix this status code!
8c9f8fda080b7e99f35ef4d2ab8ec632ad2a4068vboxsync * Unpack the arguments and call the service.
78a072e1b56619e3230735ae073668311232ec94vboxsync return INTNETR0Open(g_pIntNet, pVM->pSession, &pArgs->szNetwork[0], pArgs->cbSend, pArgs->cbRecv, pArgs->fRestrictAccess, &pArgs->hIf);
78a072e1b56619e3230735ae073668311232ec94vboxsync PINTNETIFCLOSEARGS pArgs = (PINTNETIFCLOSEARGS)pvArg;
3af289fb9126c91f28ede0dcb3429da0de12b94evboxsync PINTNETIFGETRING3BUFFERARGS pArgs = (PINTNETIFGETRING3BUFFERARGS)pvArg;
3af289fb9126c91f28ede0dcb3429da0de12b94evboxsync return INTNETR0IfGetRing3Buffer(g_pIntNet, pArgs->hIf, &pArgs->pRing3Buf);
78a072e1b56619e3230735ae073668311232ec94vboxsync PINTNETIFSETPROMISCUOUSMODEARGS pArgs = (PINTNETIFSETPROMISCUOUSMODEARGS)pvArg;
78a072e1b56619e3230735ae073668311232ec94vboxsync return INTNETR0IfSetPromiscuousMode(g_pIntNet, pArgs->hIf, pArgs->fPromiscuous);
78a072e1b56619e3230735ae073668311232ec94vboxsync PINTNETIFSENDARGS pArgs = (PINTNETIFSENDARGS)pvArg;
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsync return INTNETR0IfSend(g_pIntNet, pArgs->hIf, pArgs->pvFrame, pArgs->cbFrame);
78a072e1b56619e3230735ae073668311232ec94vboxsync PINTNETIFWAITARGS pArgs = (PINTNETIFWAITARGS)pvArg;
eb563d667bee4ab4ac0ba8be38d68f911f1d53eavboxsync return INTNETR0IfWait(g_pIntNet, pArgs->hIf, pArgs->cMillies);
78a072e1b56619e3230735ae073668311232ec94vboxsync#endif /* VBOX_WITH_INTERNAL_NETWORKING */
78a072e1b56619e3230735ae073668311232ec94vboxsync * For profiling.
168f0d5dcd9366f5e1c22fcc49f8dc5a20d4686evboxsync * For testing Ring-0 APIs invoked in this environment.
78a072e1b56619e3230735ae073668311232ec94vboxsync /** @todo make new test */
36dd9dabf3f64468206cb74145b51245cf7fde54vboxsync * We're returning VERR_NOT_SUPPORT here so we've got something else
168f0d5dcd9366f5e1c22fcc49f8dc5a20d4686evboxsync * than -1 which the interrupt gate glue code might return.
f001a45ec92f71f1e4c1015485fc1ddf84e8059cvboxsync Log(("operation %#x is not supported\n", uOperation));
78a072e1b56619e3230735ae073668311232ec94vboxsync * Internal R0 logger worker: Flush logger.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param pLogger The logger instance to flush.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @remark This function must be exported!
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync * Convert the pLogger into a VM handle and 'call' back to Ring-3.
78a072e1b56619e3230735ae073668311232ec94vboxsync * (This is a bit paranoid code.)
f06e830c9fdbc3d9e89867d4429404c5446bc513vboxsync PVMMR0LOGGER pR0Logger = (PVMMR0LOGGER)((uintptr_t)pLogger - RT_OFFSETOF(VMMR0LOGGER, Logger));
78a072e1b56619e3230735ae073668311232ec94vboxsync LogCom(("vmmR0LoggerFlush: pLogger=%p!\n", pLogger));
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync LogCom(("vmmR0LoggerFlush: pVM=%p! pLogger=%p\n", pVM, pLogger));
5142b6456c5cec38e0ee291e235201d4ac73f10bvboxsync * Check that the jump buffer is armed.
78a072e1b56619e3230735ae073668311232ec94vboxsync LogCom(("vmmR0LoggerFlush: Jump buffer isn't armed!\n"));
78a072e1b56619e3230735ae073668311232ec94vboxsync VMMR0CallHost(pVM, VMMCALLHOST_VMM_LOGGER_FLUSH, 0);
034b3d77b1a08b77b1fa9bfd7489997421713f15vboxsync * Check if we really want to hit a breakpoint.
034b3d77b1a08b77b1fa9bfd7489997421713f15vboxsync * Can jump back to ring-3 when the longjmp is armed.
78a072e1b56619e3230735ae073668311232ec94vboxsync g_pVMAssert->vmm.s.enmCallHostOperation = VMMCALLHOST_VMM_LOGGER_FLUSH;
78a072e1b56619e3230735ae073668311232ec94vboxsync g_pVMAssert->vmm.s.rcCallHost = VERR_INTERNAL_ERROR;
78a072e1b56619e3230735ae073668311232ec94vboxsync int rc = vmmR0CallHostLongJmp(&g_pVMAssert->vmm.s.CallHostR0JmpBuf, VERR_INTERNAL_ERROR);
78a072e1b56619e3230735ae073668311232ec94vboxsync return true;
78a072e1b56619e3230735ae073668311232ec94vboxsync/** Runtime assert implementation for Native Win32 Ring-0. */
b0cec57d51e48736a3303366c728c3f025e8e81bvboxsyncDECLEXPORT(void) RTCALL AssertMsg1(const char *pszExpr, unsigned uLine, const char *pszFile, const char *pszFunction)
223d0cc6ed8bf5767cb97c734684460b8eae31a8vboxsync "Expression: %s\n"
78a072e1b56619e3230735ae073668311232ec94vboxsync "Location : %s(%d) %s\n",
78a072e1b56619e3230735ae073668311232ec94vboxsync * Callback for RTLogFormatV which writes to the com port.
37320c09d54b322461eb9833e3528aee029431e7vboxsync * See PFNLOGOUTPUT() for details.
37320c09d54b322461eb9833e3528aee029431e7vboxsyncstatic DECLCALLBACK(size_t) rtLogOutput(void *pv, const char *pachChars, size_t cbChars)
78a072e1b56619e3230735ae073668311232ec94vboxsyncDECLEXPORT(void) RTCALL AssertMsg2(const char *pszFormat, ...)