VirtualBox

Changeset 13698 in vbox


Ignore:
Timestamp:
Oct 30, 2008 10:54:28 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
38664
Message:

VMM: Fixed ring-0 access to the ring-3 mapping of the EMT stack. Moved the VMMR3FatalDump() code to a separate file.

Location:
trunk
Files:
9 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm.h

    r13697 r13698  
    110110} VMMCALLHOST;
    111111
    112 RTGCPTR             VMMGetStackGC(PVM pVM);
    113 RTHCPTR             VMMGetHCStack(PVM pVM);
     112RTRCPTR             VMMGetStackRC(PVM pVM);
    114113VMCPUID             VMMGetCpuId(PVM pVM);
    115114VMMDECL(uint32_t)   VMMGetSvnRev(void);
  • trunk/src/VBox/VMM/Makefile.kmk

    r13565 r13698  
    9292        VMReq.cpp \
    9393        VMM.cpp \
     94        VMMGuruMeditation.cpp \
    9495        VMMTests.cpp \
    9596        HWACCM.cpp \
  • trunk/src/VBox/VMM/SELM.cpp

    r13577 r13698  
    418418    pVM->selm.s.Tss.cr3     = PGMGetHyperCR3(pVM);
    419419    pVM->selm.s.Tss.ss0     = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS];
    420     pVM->selm.s.Tss.esp0    = VMMGetStackGC(pVM);
     420    pVM->selm.s.Tss.esp0    = VMMGetStackRC(pVM);
    421421    pVM->selm.s.Tss.cs      = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS];
    422422    pVM->selm.s.Tss.ds      = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS];
     
    428428    pVM->selm.s.TssTrap08.ss0    = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS];
    429429    pVM->selm.s.TssTrap08.ss     = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS];
    430     pVM->selm.s.TssTrap08.esp0   = VMMGetStackGC(pVM) - PAGE_SIZE / 2;  /* upper half can be analysed this way. */
     430    pVM->selm.s.TssTrap08.esp0   = VMMGetStackRC(pVM) - PAGE_SIZE / 2;  /* upper half can be analysed this way. */
    431431    pVM->selm.s.TssTrap08.esp    = pVM->selm.s.TssTrap08.esp0;
    432432    pVM->selm.s.TssTrap08.ebp    = pVM->selm.s.TssTrap08.esp0;
  • trunk/src/VBox/VMM/VMM.cpp

    r13697 r13698  
    214214    {
    215215        /*
    216          * Allocate & init VMM GC stack.
     216         * Allocate & init VMM RC stack.
    217217         * The stack pages are also used by the VMM R0 when VMMR0CallHost is invoked.
    218218         * (The page protection is modifed during R3 init completion.)
    219219         */
     220        /** @todo SMP: Per vCPU. */
    220221#ifdef VBOX_STRICT_VMM_STACK
    221222        rc = MMHyperAlloc(pVM, VMM_STACK_SIZE + PAGE_SIZE + PAGE_SIZE, PAGE_SIZE, MM_TAG_VMM, (void **)&pVM->vmm.s.pbHCStack);
    222223#else
    223         rc = MMHyperAlloc(pVM, VMM_STACK_SIZE, PAGE_SIZE, MM_TAG_VMM, (void **)&pVM->vmm.s.pbHCStack);
     224        rc = MMHyperAlloc(pVM, VMM_STACK_SIZE, PAGE_SIZE, MM_TAG_VMM, (void **)&pVM->vmm.s.pbEMTStackR3);
    224225#endif
    225226        if (VBOX_SUCCESS(rc))
    226227        {
    227228            /* Set HC and GC stack pointers to top of stack. */
    228             pVM->vmm.s.CallHostR0JmpBuf.pvSavedStack = (RTR0PTR)pVM->vmm.s.pbHCStack;
    229             pVM->vmm.s.pbGCStack = MMHyperHC2GC(pVM, pVM->vmm.s.pbHCStack);
    230             pVM->vmm.s.pbGCStackBottom = pVM->vmm.s.pbGCStack + VMM_STACK_SIZE;
    231             AssertRelease(pVM->vmm.s.pbGCStack);
    232 
    233             /* Set hypervisor eip. */
    234             CPUMSetHyperESP(pVM, pVM->vmm.s.pbGCStack);
     229            pVM->vmm.s.CallHostR0JmpBuf.pvSavedStack = MMHyperR3ToR0(pVM, pVM->vmm.s.pbEMTStackR3);
     230            pVM->vmm.s.pbEMTStackRC = MMHyperR3ToRC(pVM, pVM->vmm.s.pbEMTStackR3);
     231            pVM->vmm.s.pbEMTStackBottomRC = pVM->vmm.s.pbEMTStackRC + VMM_STACK_SIZE;
     232            AssertRelease(pVM->vmm.s.pbEMTStackRC);
     233
     234            /* Set hypervisor esp. */
     235            CPUMSetHyperESP(pVM, pVM->vmm.s.pbEMTStackBottomRC);
    235236
    236237            /*
     
    528529     * Set page attributes to r/w for stack pages.
    529530     */
    530     int rc = PGMMapSetPage(pVM, pVM->vmm.s.pbGCStack, VMM_STACK_SIZE, X86_PTE_P | X86_PTE_A | X86_PTE_D | X86_PTE_RW);
     531    int rc = PGMMapSetPage(pVM, pVM->vmm.s.pbEMTStackRC, VMM_STACK_SIZE, X86_PTE_P | X86_PTE_A | X86_PTE_D | X86_PTE_RW);
    531532    AssertRC(rc);
    532533    if (VBOX_SUCCESS(rc))
     
    628629    {
    629630        CPUMHyperSetCtxCore(pVM, NULL);
    630         CPUMSetHyperESP(pVM, pVM->vmm.s.pbGCStackBottom); /* Clear the stack. */
     631        CPUMSetHyperESP(pVM, pVM->vmm.s.pbEMTStackBottomRC); /* Clear the stack. */
    631632        uint64_t u64TS = RTTimeProgramStartNanoTS();
    632633        CPUMPushHyper(pVM, (uint32_t)(u64TS >> 32));    /* Param 3: The program startup TS - Hi. */
     
    748749     */
    749750    CPUMSetHyperESP(pVM, CPUMGetHyperESP(pVM) + offDelta);
    750     pVM->vmm.s.pbGCStack = MMHyperHC2GC(pVM, pVM->vmm.s.pbHCStack);
    751     pVM->vmm.s.pbGCStackBottom = pVM->vmm.s.pbGCStack + VMM_STACK_SIZE;
     751    pVM->vmm.s.pbEMTStackRC = MMHyperR3ToRC(pVM, pVM->vmm.s.pbEMTStackR3);
     752    pVM->vmm.s.pbEMTStackBottomRC = pVM->vmm.s.pbEMTStackRC + VMM_STACK_SIZE;
    752753
    753754    /*
     
    15461547    /*
    15471548     * The hypervisor stack.
    1548      */
    1549     SSMR3PutRCPtr(pSSM, pVM->vmm.s.pbGCStackBottom);
    1550     RTRCPTR GCPtrESP = CPUMGetHyperESP(pVM);
    1551     AssertMsg(pVM->vmm.s.pbGCStackBottom - GCPtrESP <= VMM_STACK_SIZE, ("Bottom %VGv ESP=%VGv\n", pVM->vmm.s.pbGCStackBottom, GCPtrESP));
    1552     SSMR3PutRCPtr(pSSM, GCPtrESP);
    1553     SSMR3PutMem(pSSM, pVM->vmm.s.pbHCStack, VMM_STACK_SIZE);
     1549     * Note! See not in vmmR3Load.
     1550     */
     1551    SSMR3PutRCPtr(pSSM, pVM->vmm.s.pbEMTStackBottomRC);
     1552    RTRCPTR RCPtrESP = CPUMGetHyperESP(pVM);
     1553    AssertMsg(pVM->vmm.s.pbEMTStackBottomRC - RCPtrESP <= VMM_STACK_SIZE, ("Bottom %RRv ESP=%RRv\n", pVM->vmm.s.pbEMTStackBottomRC, RCPtrESP));
     1554    SSMR3PutRCPtr(pSSM, RCPtrESP);
     1555    SSMR3PutMem(pSSM, pVM->vmm.s.pbEMTStackR3, VMM_STACK_SIZE);
    15541556    return SSMR3PutU32(pSSM, ~0); /* terminator */
    15551557}
     
    15791581    /*
    15801582     * Check that the stack is in the same place, or that it's fearly empty.
    1581      */
    1582     RTRCPTR GCPtrStackBottom;
    1583     SSMR3GetRCPtr(pSSM, &GCPtrStackBottom);
    1584     RTRCPTR GCPtrESP;
    1585     int rc = SSMR3GetRCPtr(pSSM, &GCPtrESP);
     1583     *
     1584     * Note! This can be skipped next time we update saved state as we will
     1585     *       never be in a R0/RC -> ring-3 call when saving the state. The
     1586     *       stack and the two associated pointers are not required.
     1587     */
     1588    RTRCPTR RCPtrStackBottom;
     1589    SSMR3GetRCPtr(pSSM, &RCPtrStackBottom);
     1590    RTRCPTR RCPtrESP;
     1591    int rc = SSMR3GetRCPtr(pSSM, &RCPtrESP);
    15861592    if (VBOX_FAILURE(rc))
    15871593        return rc;
    15881594
    1589     /* Previously we checked if the location of the stack was identical or that the stack was empty.
    1590      * This is not required as we can never initiate a save when GC context code performs a ring 3 call.
    1591      */
    1592     /* restore the stack. (not necessary; just consistency checking) */
    1593     SSMR3GetMem(pSSM, pVM->vmm.s.pbHCStack, VMM_STACK_SIZE);
     1595    /* restore the stack.  */
     1596    SSMR3GetMem(pSSM, pVM->vmm.s.pbEMTStackR3, VMM_STACK_SIZE);
    15941597
    15951598    /* terminator */
     
    18631866                    ? pVM->vmm.s.pfnCPUMGCResumeGuestV86
    18641867                    : pVM->vmm.s.pfnCPUMGCResumeGuest);
    1865     CPUMSetHyperESP(pVM, pVM->vmm.s.pbGCStackBottom);
     1868    CPUMSetHyperESP(pVM, pVM->vmm.s.pbEMTStackBottomRC);
    18661869
    18671870    /*
     
    19871990     */
    19881991    CPUMHyperSetCtxCore(pVM, NULL);
    1989     memset(pVM->vmm.s.pbHCStack, 0xaa, VMM_STACK_SIZE); /* Clear the stack. */
    1990     CPUMSetHyperESP(pVM, pVM->vmm.s.pbGCStackBottom - cArgs * sizeof(RTGCUINTPTR32));
    1991     PRTGCUINTPTR32 pFrame = (PRTGCUINTPTR32)(pVM->vmm.s.pbHCStack + VMM_STACK_SIZE) - cArgs;
     1992    memset(pVM->vmm.s.pbEMTStackR3, 0xaa, VMM_STACK_SIZE); /* Clear the stack. */
     1993    CPUMSetHyperESP(pVM, pVM->vmm.s.pbEMTStackBottomRC - cArgs * sizeof(RTGCUINTPTR32));
     1994    PRTGCUINTPTR32 pFrame = (PRTGCUINTPTR32)(pVM->vmm.s.pbEMTStackR3 + VMM_STACK_SIZE) - cArgs;
    19921995    int i = cArgs;
    19931996    while (i-- > 0)
     
    22282231    return VINF_SUCCESS;
    22292232}
    2230 
    2231 
    2232 
    2233 /**
    2234  * Structure to pass to DBGFR3Info() and for doing all other
    2235  * output during fatal dump.
    2236  */
    2237 typedef struct VMMR3FATALDUMPINFOHLP
    2238 {
    2239     /** The helper core. */
    2240     DBGFINFOHLP Core;
    2241     /** The release logger instance. */
    2242     PRTLOGGER   pRelLogger;
    2243     /** The saved release logger flags. */
    2244     RTUINT      fRelLoggerFlags;
    2245     /** The logger instance. */
    2246     PRTLOGGER   pLogger;
    2247     /** The saved logger flags. */
    2248     RTUINT      fLoggerFlags;
    2249     /** The saved logger destination flags. */
    2250     RTUINT      fLoggerDestFlags;
    2251     /** Whether to output to stderr or not. */
    2252     bool        fStdErr;
    2253 } VMMR3FATALDUMPINFOHLP, *PVMMR3FATALDUMPINFOHLP;
    2254 typedef const VMMR3FATALDUMPINFOHLP *PCVMMR3FATALDUMPINFOHLP;
    2255 
    2256 
    2257 /**
    2258  * Print formatted string.
    2259  *
    2260  * @param   pHlp        Pointer to this structure.
    2261  * @param   pszFormat   The format string.
    2262  * @param   ...         Arguments.
    2263  */
    2264 static DECLCALLBACK(void) vmmR3FatalDumpInfoHlp_pfnPrintf(PCDBGFINFOHLP pHlp, const char *pszFormat, ...)
    2265 {
    2266     va_list args;
    2267     va_start(args, pszFormat);
    2268     pHlp->pfnPrintfV(pHlp, pszFormat, args);
    2269     va_end(args);
    2270 }
    2271 
    2272 
    2273 /**
    2274  * Print formatted string.
    2275  *
    2276  * @param   pHlp        Pointer to this structure.
    2277  * @param   pszFormat   The format string.
    2278  * @param   args        Argument list.
    2279  */
    2280 static DECLCALLBACK(void) vmmR3FatalDumpInfoHlp_pfnPrintfV(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args)
    2281 {
    2282     PCVMMR3FATALDUMPINFOHLP pMyHlp = (PCVMMR3FATALDUMPINFOHLP)pHlp;
    2283 
    2284     if (pMyHlp->pRelLogger)
    2285     {
    2286         va_list args2;
    2287         va_copy(args2, args);
    2288         RTLogLoggerV(pMyHlp->pRelLogger, pszFormat, args2);
    2289         va_end(args2);
    2290     }
    2291     if (pMyHlp->pLogger)
    2292     {
    2293         va_list args2;
    2294         va_copy(args2, args);
    2295         RTLogLoggerV(pMyHlp->pLogger, pszFormat, args);
    2296         va_end(args2);
    2297     }
    2298     if (pMyHlp->fStdErr)
    2299     {
    2300         va_list args2;
    2301         va_copy(args2, args);
    2302         RTStrmPrintfV(g_pStdErr, pszFormat, args);
    2303         va_end(args2);
    2304     }
    2305 }
    2306 
    2307 
    2308 /**
    2309  * Initializes the fatal dump output helper.
    2310  *
    2311  * @param   pHlp        The structure to initialize.
    2312  */
    2313 static void vmmR3FatalDumpInfoHlpInit(PVMMR3FATALDUMPINFOHLP pHlp)
    2314 {
    2315     memset(pHlp, 0, sizeof(*pHlp));
    2316 
    2317     pHlp->Core.pfnPrintf = vmmR3FatalDumpInfoHlp_pfnPrintf;
    2318     pHlp->Core.pfnPrintfV = vmmR3FatalDumpInfoHlp_pfnPrintfV;
    2319 
    2320     /*
    2321      * The loggers.
    2322      */
    2323     pHlp->pRelLogger = RTLogRelDefaultInstance();
    2324 #ifndef LOG_ENABLED
    2325     if (!pHlp->pRelLogger)
    2326 #endif
    2327         pHlp->pLogger = RTLogDefaultInstance();
    2328 
    2329     if (pHlp->pRelLogger)
    2330     {
    2331         pHlp->fRelLoggerFlags = pHlp->pRelLogger->fFlags;
    2332         pHlp->pRelLogger->fFlags &= ~(RTLOGFLAGS_BUFFERED | RTLOGFLAGS_DISABLED);
    2333     }
    2334 
    2335     if (pHlp->pLogger)
    2336     {
    2337         pHlp->fLoggerFlags     = pHlp->pLogger->fFlags;
    2338         pHlp->fLoggerDestFlags = pHlp->pLogger->fDestFlags;
    2339         pHlp->pLogger->fFlags     &= ~(RTLOGFLAGS_BUFFERED | RTLOGFLAGS_DISABLED);
    2340 #ifndef DEBUG_sandervl
    2341         pHlp->pLogger->fDestFlags |= RTLOGDEST_DEBUGGER;
    2342 #endif
    2343     }
    2344 
    2345     /*
    2346      * Check if we need write to stderr.
    2347      */
    2348 #ifdef DEBUG_sandervl
    2349     pHlp->fStdErr = false; /* takes too long to display here */
    2350 #else
    2351     pHlp->fStdErr = (!pHlp->pRelLogger || !(pHlp->pRelLogger->fDestFlags & (RTLOGDEST_STDOUT | RTLOGDEST_STDERR)))
    2352                  && (!pHlp->pLogger || !(pHlp->pLogger->fDestFlags & (RTLOGDEST_STDOUT | RTLOGDEST_STDERR)));
    2353 #endif
    2354 }
    2355 
    2356 
    2357 /**
    2358  * Deletes the fatal dump output helper.
    2359  *
    2360  * @param   pHlp        The structure to delete.
    2361  */
    2362 static void vmmR3FatalDumpInfoHlpDelete(PVMMR3FATALDUMPINFOHLP pHlp)
    2363 {
    2364     if (pHlp->pRelLogger)
    2365     {
    2366         RTLogFlush(pHlp->pRelLogger);
    2367         pHlp->pRelLogger->fFlags = pHlp->fRelLoggerFlags;
    2368     }
    2369 
    2370     if (pHlp->pLogger)
    2371     {
    2372         RTLogFlush(pHlp->pLogger);
    2373         pHlp->pLogger->fFlags     = pHlp->fLoggerFlags;
    2374         pHlp->pLogger->fDestFlags = pHlp->fLoggerDestFlags;
    2375     }
    2376 }
    2377 
    2378 
    2379 /**
    2380  * Dumps the VM state on a fatal error.
    2381  *
    2382  * @param   pVM         VM Handle.
    2383  * @param   rcErr       VBox status code.
    2384  */
    2385 VMMR3DECL(void) VMMR3FatalDump(PVM pVM, int rcErr)
    2386 {
    2387     /*
    2388      * Create our output helper and sync it with the log settings.
    2389      * This helper will be used for all the output.
    2390      */
    2391     VMMR3FATALDUMPINFOHLP   Hlp;
    2392     PCDBGFINFOHLP           pHlp = &Hlp.Core;
    2393     vmmR3FatalDumpInfoHlpInit(&Hlp);
    2394 
    2395     /*
    2396      * Header.
    2397      */
    2398     pHlp->pfnPrintf(pHlp,
    2399                     "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
    2400                     "!!\n"
    2401                     "!!                 Guru Meditation %d (%Vrc)\n"
    2402                     "!!\n",
    2403                     rcErr, rcErr);
    2404 
    2405     /*
    2406      * Continue according to context.
    2407      */
    2408     bool fDoneHyper = false;
    2409     switch (rcErr)
    2410     {
    2411         /*
    2412          * Hypervisor errors.
    2413          */
    2414         case VINF_EM_DBG_HYPER_ASSERTION:
    2415         {
    2416             const char *pszMsg1 = HWACCMR3IsActive(pVM) ? pVM->vmm.s.szRing0AssertMsg1 : VMMR3GetGCAssertMsg1(pVM);
    2417             while (pszMsg1 && *pszMsg1 == '\n')
    2418                 pszMsg1++;
    2419             const char *pszMsg2 = HWACCMR3IsActive(pVM) ? pVM->vmm.s.szRing0AssertMsg2 : VMMR3GetGCAssertMsg2(pVM);
    2420             while (pszMsg2 && *pszMsg2 == '\n')
    2421                 pszMsg2++;
    2422             pHlp->pfnPrintf(pHlp,
    2423                             "%s"
    2424                             "%s",
    2425                             pszMsg1,
    2426                             pszMsg2);
    2427             if (    !pszMsg2
    2428                 ||  !*pszMsg2
    2429                 ||  strchr(pszMsg2, '\0')[-1] != '\n')
    2430                 pHlp->pfnPrintf(pHlp, "\n");
    2431             pHlp->pfnPrintf(pHlp, "!!\n");
    2432             /* fall thru */
    2433         }
    2434         case VERR_TRPM_DONT_PANIC:
    2435         case VERR_TRPM_PANIC:
    2436         case VINF_EM_RAW_STALE_SELECTOR:
    2437         case VINF_EM_RAW_IRET_TRAP:
    2438         case VINF_EM_DBG_HYPER_BREAKPOINT:
    2439         case VINF_EM_DBG_HYPER_STEPPED:
    2440         {
    2441             /*
    2442              * Active trap? This is only of partial interest when in hardware
    2443              * assisted virtualization mode, thus the different messages.
    2444              */
    2445             uint32_t        uEIP       = CPUMGetHyperEIP(pVM);
    2446             TRPMEVENT       enmType;
    2447             uint8_t         u8TrapNo   =       0xce;
    2448             RTGCUINT        uErrorCode = 0xdeadface;
    2449             RTGCUINTPTR     uCR2       = 0xdeadface;
    2450             int rc2 = TRPMQueryTrapAll(pVM, &u8TrapNo, &enmType, &uErrorCode, &uCR2);
    2451             if (!HWACCMR3IsActive(pVM))
    2452             {
    2453                 if (RT_SUCCESS(rc2))
    2454                     pHlp->pfnPrintf(pHlp,
    2455                                     "!! TRAP=%02x ERRCD=%RGv CR2=%RGv EIP=%RX32 Type=%d\n",
    2456                                     u8TrapNo, uErrorCode, uCR2, uEIP, enmType);
    2457                 else
    2458                     pHlp->pfnPrintf(pHlp,
    2459                                     "!! EIP=%RX32 NOTRAP\n",
    2460                                     uEIP);
    2461             }
    2462             else if (RT_SUCCESS(rc2))
    2463                 pHlp->pfnPrintf(pHlp,
    2464                                 "!! ACTIVE TRAP=%02x ERRCD=%RGv CR2=%RGv PC=%RGr Type=%d (Guest!)\n",
    2465                                 u8TrapNo, uErrorCode, uCR2, CPUMGetGuestRIP(pVM), enmType);
    2466 
    2467             /*
    2468              * The hypervisor dump is not relevant when we're in VT-x/AMD-V mode.
    2469              */
    2470             if (HWACCMR3IsActive(pVM))
    2471                 pHlp->pfnPrintf(pHlp, "\n");
    2472             else
    2473             {
    2474                 /*
    2475                  * Try figure out where eip is.
    2476                  */
    2477                 /* core code? */
    2478                 if (uEIP - (RTGCUINTPTR)pVM->vmm.s.pvGCCoreCode < pVM->vmm.s.cbCoreCode)
    2479                     pHlp->pfnPrintf(pHlp,
    2480                                 "!! EIP is in CoreCode, offset %#x\n",
    2481                                 uEIP - (RTGCUINTPTR)pVM->vmm.s.pvGCCoreCode);
    2482                 else
    2483                 {   /* ask PDM */  /** @todo ask DBGFR3Sym later? */
    2484                     char        szModName[64];
    2485                     RTRCPTR     RCPtrMod;
    2486                     char        szNearSym1[260];
    2487                     RTRCPTR     RCPtrNearSym1;
    2488                     char        szNearSym2[260];
    2489                     RTRCPTR     RCPtrNearSym2;
    2490                     int rc = PDMR3LdrQueryRCModFromPC(pVM, uEIP,
    2491                                                       &szModName[0],  sizeof(szModName),  &RCPtrMod,
    2492                                                       &szNearSym1[0], sizeof(szNearSym1), &RCPtrNearSym1,
    2493                                                       &szNearSym2[0], sizeof(szNearSym2), &RCPtrNearSym2);
    2494                     if (VBOX_SUCCESS(rc))
    2495                         pHlp->pfnPrintf(pHlp,
    2496                                         "!! EIP in %s (%RRv) at rva %x near symbols:\n"
    2497                                         "!!    %RRv rva %RRv off %08x  %s\n"
    2498                                         "!!    %RRv rva %RRv off -%08x %s\n",
    2499                                         szModName,  RCPtrMod, (unsigned)(uEIP - RCPtrMod),
    2500                                         RCPtrNearSym1, RCPtrNearSym1 - RCPtrMod, (unsigned)(uEIP - RCPtrNearSym1), szNearSym1,
    2501                                         RCPtrNearSym2, RCPtrNearSym2 - RCPtrMod, (unsigned)(RCPtrNearSym2 - uEIP), szNearSym2);
    2502                     else
    2503                         pHlp->pfnPrintf(pHlp,
    2504                                         "!! EIP is not in any code known to VMM!\n");
    2505                 }
    2506 
    2507                 /* Disassemble the instruction. */
    2508                 char szInstr[256];
    2509                 rc2 = DBGFR3DisasInstrEx(pVM, 0, 0, DBGF_DISAS_FLAGS_CURRENT_HYPER, &szInstr[0], sizeof(szInstr), NULL);
    2510                 if (VBOX_SUCCESS(rc2))
    2511                     pHlp->pfnPrintf(pHlp,
    2512                                     "!! %s\n", szInstr);
    2513 
    2514                 /* Dump the hypervisor cpu state. */
    2515                 pHlp->pfnPrintf(pHlp,
    2516                                 "!!\n"
    2517                                 "!!\n"
    2518                                 "!!\n");
    2519                 rc2 = DBGFR3Info(pVM, "cpumhyper", "verbose", pHlp);
    2520                 fDoneHyper = true;
    2521 
    2522                 /* Callstack. */
    2523                 DBGFSTACKFRAME Frame = {0};
    2524                 rc2 = DBGFR3StackWalkBeginHyper(pVM, &Frame);
    2525                 if (VBOX_SUCCESS(rc2))
    2526                 {
    2527                     pHlp->pfnPrintf(pHlp,
    2528                                     "!!\n"
    2529                                     "!! Call Stack:\n"
    2530                                     "!!\n"
    2531                                     "EBP      Ret EBP  Ret CS:EIP    Arg0     Arg1     Arg2     Arg3     CS:EIP        Symbol [line]\n");
    2532                     do
    2533                     {
    2534                         pHlp->pfnPrintf(pHlp,
    2535                                         "%08RX32 %08RX32 %04RX32:%08RX32 %08RX32 %08RX32 %08RX32 %08RX32",
    2536                                         (uint32_t)Frame.AddrFrame.off,
    2537                                         (uint32_t)Frame.AddrReturnFrame.off,
    2538                                         (uint32_t)Frame.AddrReturnPC.Sel,
    2539                                         (uint32_t)Frame.AddrReturnPC.off,
    2540                                         Frame.Args.au32[0],
    2541                                         Frame.Args.au32[1],
    2542                                         Frame.Args.au32[2],
    2543                                         Frame.Args.au32[3]);
    2544                         pHlp->pfnPrintf(pHlp, " %RTsel:%08RGv", Frame.AddrPC.Sel, Frame.AddrPC.off);
    2545                         if (Frame.pSymPC)
    2546                         {
    2547                             RTGCINTPTR offDisp = Frame.AddrPC.FlatPtr - Frame.pSymPC->Value;
    2548                             if (offDisp > 0)
    2549                                 pHlp->pfnPrintf(pHlp, " %s+%llx", Frame.pSymPC->szName, (int64_t)offDisp);
    2550                             else if (offDisp < 0)
    2551                                 pHlp->pfnPrintf(pHlp, " %s-%llx", Frame.pSymPC->szName, -(int64_t)offDisp);
    2552                             else
    2553                                 pHlp->pfnPrintf(pHlp, " %s", Frame.pSymPC->szName);
    2554                         }
    2555                         if (Frame.pLinePC)
    2556                             pHlp->pfnPrintf(pHlp, " [%s @ 0i%d]", Frame.pLinePC->szFilename, Frame.pLinePC->uLineNo);
    2557                         pHlp->pfnPrintf(pHlp, "\n");
    2558 
    2559                         /* next */
    2560                         rc2 = DBGFR3StackWalkNext(pVM, &Frame);
    2561                     } while (VBOX_SUCCESS(rc2));
    2562                     DBGFR3StackWalkEnd(pVM, &Frame);
    2563                 }
    2564 
    2565                 /* raw stack */
    2566                 pHlp->pfnPrintf(pHlp,
    2567                                 "!!\n"
    2568                                 "!! Raw stack (mind the direction).\n"
    2569                                 "!!\n"
    2570                                 "%.*Vhxd\n",
    2571                                 VMM_STACK_SIZE, (char *)pVM->vmm.s.pbHCStack);
    2572             } /* !HWACCMR3IsActive */
    2573             break;
    2574         }
    2575 
    2576         default:
    2577         {
    2578             break;
    2579         }
    2580 
    2581     } /* switch (rcErr) */
    2582 
    2583 
    2584     /*
    2585      * Generic info dumper loop.
    2586      */
    2587     static struct
    2588     {
    2589         const char *pszInfo;
    2590         const char *pszArgs;
    2591     } const     aInfo[] =
    2592     {
    2593         { "mappings",       NULL },
    2594         { "hma",            NULL },
    2595         { "cpumguest",      "verbose" },
    2596         { "cpumguestinstr", "verbose" },
    2597         { "cpumhyper",      "verbose" },
    2598         { "cpumhost",       "verbose" },
    2599         { "mode",           "all" },
    2600         { "cpuid",          "verbose" },
    2601         { "gdt",            NULL },
    2602         { "ldt",            NULL },
    2603         //{ "tss",            NULL },
    2604         { "ioport",         NULL },
    2605         { "mmio",           NULL },
    2606         { "phys",           NULL },
    2607         //{ "pgmpd",          NULL }, - doesn't always work at init time...
    2608         { "timers",         NULL },
    2609         { "activetimers",   NULL },
    2610         { "handlers",       "phys virt hyper stats" },
    2611         { "cfgm",           NULL },
    2612     };
    2613     for (unsigned i = 0; i < RT_ELEMENTS(aInfo); i++)
    2614     {
    2615         if (fDoneHyper && !strcmp(aInfo[i].pszInfo, "cpumhyper"))
    2616             continue;
    2617         pHlp->pfnPrintf(pHlp,
    2618                         "!!\n"
    2619                         "!! {%s, %s}\n"
    2620                         "!!\n",
    2621                         aInfo[i].pszInfo, aInfo[i].pszArgs);
    2622         DBGFR3Info(pVM, aInfo[i].pszInfo, aInfo[i].pszArgs, pHlp);
    2623     }
    2624 
    2625     /* done */
    2626     pHlp->pfnPrintf(pHlp,
    2627                     "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
    2628 
    2629 
    2630     /*
    2631      * Delete the output instance (flushing and restoring of flags).
    2632      */
    2633     vmmR3FatalDumpInfoHlpDelete(&Hlp);
    2634 }
    2635 
    26362233
    26372234
  • trunk/src/VBox/VMM/VMMAll/VMMAll.cpp

    r12667 r13698  
    3232
    3333#ifndef IN_RING0
    34 
    3534/**
    36  * Gets the bottom of the hypervisor stack - GC Ptr.
    37  * I.e. the returned address is not actually writable.
     35 * Gets the bottom of the hypervisor stack - RC Ptr.
     36 *
     37 * (The returned address is not actually writable, only after it's decremented
     38 * by a push/ret/whatever does it become writable.)
    3839 *
    3940 * @returns bottom of the stack.
    4041 * @param   pVM         The VM handle.
    4142 */
    42 RTGCPTR VMMGetStackGC(PVM pVM)
     43RTRCPTR VMMGetStackRC(PVM pVM)
    4344{
    44     return (RTGCPTR)pVM->vmm.s.pbGCStackBottom;
     45    return (RTRCPTR)pVM->vmm.s.pbEMTStackBottomRC;
    4546}
    46 
    47 
    48 /**
    49  * Gets the bottom of the hypervisor stack - HC Ptr.
    50  * I.e. the returned address is not actually writable.
    51  *
    52  * @returns bottom of the stack.
    53  * @param   pVM         The VM handle.
    54  */
    55 RTHCPTR VMMGetHCStack(PVM pVM)
    56 {
    57     return pVM->vmm.s.pbHCStack + VMM_STACK_SIZE;
    58 }
    59 
    6047#endif /* !IN_RING0 */
    6148
  • trunk/src/VBox/VMM/VMMGC/TRPMGCHandlers.cpp

    r13635 r13698  
    11021102         * a guru meditation (the alternative is a triple fault).
    11031103         */
    1104         RTGCUINTPTR cbStackUsed = (RTGCUINTPTR)VMMGetStackGC(pVM) - pRegFrame->esp;
     1104        RTRCUINTPTR cbStackUsed = (RTRCUINTPTR)VMMGetStackRC(pVM) - pRegFrame->esp;
    11051105        if (cbStackUsed > VMM_STACK_SIZE - _1K)
    11061106        {
  • trunk/src/VBox/VMM/VMMGuruMeditation.cpp

    r13697 r13698  
    11/* $Id$ */
    22/** @file
    3  * VMM - The Virtual Machine Monitor Core.
     3 * VMM - The Virtual Machine Monitor, Guru Meditation Code.
    44 */
    55
     
    2020 */
    2121
    22 //#define NO_SUPCALLR0VMM
    23 
    24 /** @page pg_vmm        VMM - The Virtual Machine Monitor
    25  *
    26  * The VMM component is two things at the moment, it's a component doing a few
    27  * management and routing tasks, and it's the whole virtual machine monitor
    28  * thing.  For hysterical reasons, it is not doing all the management that one
    29  * would expect, this is instead done by @ref pg_vm.  We'll address this
    30  * misdesign eventually.
    31  *
    32  * @see grp_vmm, grp_vm
    33  *
    34  *
    35  * @section sec_vmmstate        VMM State
    36  *
    37  * @image html VM_Statechart_Diagram.gif
    38  *
    39  * To be written.
    40  *
    41  *
    42  * @subsection  subsec_vmm_init     VMM Initialization
    43  *
    44  * To be written.
    45  *
    46  *
    47  * @subsection  subsec_vmm_term     VMM Termination
    48  *
    49  * To be written.
    50  *
    51  */
    52 
    5322/*******************************************************************************
    5423*   Header Files                                                               *
     
    5625#define LOG_GROUP LOG_GROUP_VMM
    5726#include <VBox/vmm.h>
    58 #include <VBox/vmapi.h>
    59 #include <VBox/pgm.h>
    60 #include <VBox/cfgm.h>
    61 #include <VBox/pdmqueue.h>
    6227#include <VBox/pdmapi.h>
    63 #include <VBox/cpum.h>
    64 #include <VBox/mm.h>
    65 #include <VBox/iom.h>
    6628#include <VBox/trpm.h>
    67 #include <VBox/selm.h>
    68 #include <VBox/em.h>
    69 #include <VBox/sup.h>
    7029#include <VBox/dbgf.h>
    71 #include <VBox/csam.h>
    72 #include <VBox/patm.h>
    73 #include <VBox/rem.h>
    74 #include <VBox/ssm.h>
    75 #include <VBox/tm.h>
    7630#include "VMMInternal.h"
    77 #include "VMMSwitcher/VMMSwitcher.h"
    7831#include <VBox/vm.h>
    7932
     
    8134#include <VBox/param.h>
    8235#include <VBox/version.h>
    83 #include <VBox/x86.h>
    8436#include <VBox/hwaccm.h>
    8537#include <iprt/assert.h>
    86 #include <iprt/alloc.h>
    87 #include <iprt/asm.h>
    8838#include <iprt/time.h>
    8939#include <iprt/stream.h>
    9040#include <iprt/string.h>
    9141#include <iprt/stdarg.h>
    92 #include <iprt/ctype.h>
    93 
    94 
    95 
    96 /** The saved state version. */
    97 #define VMM_SAVED_STATE_VERSION     3
    9842
    9943
    10044/*******************************************************************************
    101 *   Global Variables                                                           *
     45*   Structures and Typedefs                                                    *
    10246*******************************************************************************/
    103 /** Array of switcher defininitions.
    104  * The type and index shall match!
    105  */
    106 static PVMMSWITCHERDEF s_apSwitchers[VMMSWITCHER_MAX] =
    107 {
    108     NULL, /* invalid entry */
    109 #ifndef RT_ARCH_AMD64
    110     &vmmR3Switcher32BitTo32Bit_Def,
    111     &vmmR3Switcher32BitToPAE_Def,
    112     NULL,   //&vmmR3Switcher32BitToAMD64_Def,
    113     &vmmR3SwitcherPAETo32Bit_Def,
    114     &vmmR3SwitcherPAEToPAE_Def,
    115     NULL,   //&vmmR3SwitcherPAEToAMD64_Def,
    116 # ifdef VBOX_WITH_HYBIRD_32BIT_KERNEL
    117     &vmmR3SwitcherAMD64ToPAE_Def,
    118 # else
    119     NULL,   //&vmmR3SwitcherAMD64ToPAE_Def,
    120 # endif
    121     NULL    //&vmmR3SwitcherAMD64ToAMD64_Def,
    122 #else  /* RT_ARCH_AMD64 */
    123     NULL,   //&vmmR3Switcher32BitTo32Bit_Def,
    124     NULL,   //&vmmR3Switcher32BitToPAE_Def,
    125     NULL,   //&vmmR3Switcher32BitToAMD64_Def,
    126     NULL,   //&vmmR3SwitcherPAETo32Bit_Def,
    127     NULL,   //&vmmR3SwitcherPAEToPAE_Def,
    128     NULL,   //&vmmR3SwitcherPAEToAMD64_Def,
    129     &vmmR3SwitcherAMD64ToPAE_Def,
    130     NULL    //&vmmR3SwitcherAMD64ToAMD64_Def,
    131 #endif /* RT_ARCH_AMD64 */
    132 };
    133 
    134 
    135 /*******************************************************************************
    136 *   Internal Functions                                                         *
    137 *******************************************************************************/
    138 static int                  vmmR3InitCoreCode(PVM pVM);
    139 static DECLCALLBACK(int)    vmmR3Save(PVM pVM, PSSMHANDLE pSSM);
    140 static DECLCALLBACK(int)    vmmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version);
    141 static DECLCALLBACK(void)   vmmR3YieldEMT(PVM pVM, PTMTIMER pTimer, void *pvUser);
    142 static int                  vmmR3ServiceCallHostRequest(PVM pVM);
    143 static DECLCALLBACK(void)   vmmR3InfoFF(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
    144 
    145 
    146 /**
    147  * Initializes the VMM.
    148  *
    149  * @returns VBox status code.
    150  * @param   pVM         The VM to operate on.
    151  */
    152 VMMR3DECL(int) VMMR3Init(PVM pVM)
    153 {
    154     LogFlow(("VMMR3Init\n"));
    155 
    156     /*
    157      * Assert alignment, sizes and order.
    158      */
    159     AssertMsg(pVM->vmm.s.offVM == 0, ("Already initialized!\n"));
    160     AssertMsg(sizeof(pVM->vmm.padding) >= sizeof(pVM->vmm.s),
    161               ("pVM->vmm.padding is too small! vmm.padding %d while vmm.s is %d\n",
    162                sizeof(pVM->vmm.padding), sizeof(pVM->vmm.s)));
    163 
    164     /*
    165      * Init basic VM VMM members.
    166      */
    167     pVM->vmm.s.offVM = RT_OFFSETOF(VM, vmm);
    168     int rc = CFGMR3QueryU32(CFGMR3GetRoot(pVM), "YieldEMTInterval", &pVM->vmm.s.cYieldEveryMillies);
    169     if (rc == VERR_CFGM_VALUE_NOT_FOUND)
    170         pVM->vmm.s.cYieldEveryMillies = 23; /* Value arrived at after experimenting with the grub boot prompt. */
    171         //pVM->vmm.s.cYieldEveryMillies = 8; //debugging
    172     else
    173         AssertMsgRCReturn(rc, ("Configuration error. Failed to query \"YieldEMTInterval\", rc=%Vrc\n", rc), rc);
    174 
    175     /* GC switchers are enabled by default. Turned off by HWACCM. */
    176     pVM->vmm.s.fSwitcherDisabled = false;
    177 
    178     /* Get the CPU count.*/
    179     rc = CFGMR3QueryU32Def(CFGMR3GetRoot(pVM), "NumCPUs", &pVM->cCPUs, 1);
    180     AssertLogRelMsgRCReturn(rc, ("Configuration error: Querying \"NumCPUs\" as integer failed, rc=%Vrc\n", rc), rc);
    181 #ifdef VBOX_WITH_SMP_GUESTS
    182     AssertLogRelMsgReturn(pVM->cCPUs > 0 && pVM->cCPUs <= 256,
    183                           ("Configuration error: \"NumCPUs\"=%RU32 is out of range [1..256]\n", pVM->cCPUs), VERR_INVALID_PARAMETER);
    184 #else
    185     AssertLogRelMsgReturn(pVM->cCPUs != 0,
    186                           ("Configuration error: \"NumCPUs\"=%RU32, expected 1\n", pVM->cCPUs), VERR_INVALID_PARAMETER);
    187 #endif
    188 
    189 #ifdef VBOX_WITH_SMP_GUESTS
    190     LogRel(("[SMP] VMM with %RU32 CPUs\n", pVM->cCPUs));
    191 #endif
    192 
    193     /*
    194      * Register the saved state data unit.
    195      */
    196     rc = SSMR3RegisterInternal(pVM, "vmm", 1, VMM_SAVED_STATE_VERSION, VMM_STACK_SIZE + sizeof(RTGCPTR),
    197                                NULL, vmmR3Save, NULL,
    198                                NULL, vmmR3Load, NULL);
    199     if (VBOX_FAILURE(rc))
    200         return rc;
    201 
    202     /*
    203      * Register the Ring-0 VM handle with the session for fast ioctl calls.
    204      */
    205     rc = SUPSetVMForFastIOCtl(pVM->pVMR0);
    206     if (VBOX_FAILURE(rc))
    207         return rc;
    208 
    209     /*
    210      * Init core code.
    211      */
    212     rc = vmmR3InitCoreCode(pVM);
    213     if (VBOX_SUCCESS(rc))
    214     {
    215         /*
    216          * Allocate & init VMM GC stack.
    217          * The stack pages are also used by the VMM R0 when VMMR0CallHost is invoked.
    218          * (The page protection is modifed during R3 init completion.)
    219          */
    220 #ifdef VBOX_STRICT_VMM_STACK
    221         rc = MMHyperAlloc(pVM, VMM_STACK_SIZE + PAGE_SIZE + PAGE_SIZE, PAGE_SIZE, MM_TAG_VMM, (void **)&pVM->vmm.s.pbHCStack);
    222 #else
    223         rc = MMHyperAlloc(pVM, VMM_STACK_SIZE, PAGE_SIZE, MM_TAG_VMM, (void **)&pVM->vmm.s.pbHCStack);
    224 #endif
    225         if (VBOX_SUCCESS(rc))
    226         {
    227             /* Set HC and GC stack pointers to top of stack. */
    228             pVM->vmm.s.CallHostR0JmpBuf.pvSavedStack = (RTR0PTR)pVM->vmm.s.pbHCStack;
    229             pVM->vmm.s.pbGCStack = MMHyperHC2GC(pVM, pVM->vmm.s.pbHCStack);
    230             pVM->vmm.s.pbGCStackBottom = pVM->vmm.s.pbGCStack + VMM_STACK_SIZE;
    231             AssertRelease(pVM->vmm.s.pbGCStack);
    232 
    233             /* Set hypervisor eip. */
    234             CPUMSetHyperESP(pVM, pVM->vmm.s.pbGCStack);
    235 
    236             /*
    237              * Allocate GC & R0 Logger instances (they are finalized in the relocator).
    238              */
    239 #ifdef LOG_ENABLED
    240             PRTLOGGER pLogger = RTLogDefaultInstance();
    241             if (pLogger)
    242             {
    243                 pVM->vmm.s.cbLoggerGC = RT_OFFSETOF(RTLOGGERRC, afGroups[pLogger->cGroups]);
    244                 rc = MMHyperAlloc(pVM, pVM->vmm.s.cbLoggerGC, 0, MM_TAG_VMM, (void **)&pVM->vmm.s.pLoggerHC);
    245                 if (VBOX_SUCCESS(rc))
    246                 {
    247                     pVM->vmm.s.pLoggerGC = MMHyperHC2GC(pVM, pVM->vmm.s.pLoggerHC);
    248 
    249 # ifdef VBOX_WITH_R0_LOGGING
    250                     rc = MMHyperAlloc(pVM, RT_OFFSETOF(VMMR0LOGGER, Logger.afGroups[pLogger->cGroups]),
    251                                       0, MM_TAG_VMM, (void **)&pVM->vmm.s.pR0Logger);
    252                     if (VBOX_SUCCESS(rc))
    253                     {
    254                         pVM->vmm.s.pR0Logger->pVM = pVM->pVMR0;
    255                         //pVM->vmm.s.pR0Logger->fCreated = false;
    256                         pVM->vmm.s.pR0Logger->cbLogger = RT_OFFSETOF(RTLOGGER, afGroups[pLogger->cGroups]);
    257                     }
    258 # endif
    259                 }
    260             }
    261 #endif /* LOG_ENABLED */
    262 
    263 #ifdef VBOX_WITH_RC_RELEASE_LOGGING
    264             /*
    265              * Allocate RC release logger instances (finalized in the relocator).
    266              */
    267             if (VBOX_SUCCESS(rc))
    268             {
    269                 PRTLOGGER pRelLogger = RTLogRelDefaultInstance();
    270                 if (pRelLogger)
    271                 {
    272                     pVM->vmm.s.cbRelLoggerGC = RT_OFFSETOF(RTLOGGERRC, afGroups[pRelLogger->cGroups]);
    273                     rc = MMHyperAlloc(pVM, pVM->vmm.s.cbRelLoggerGC, 0, MM_TAG_VMM, (void **)&pVM->vmm.s.pRelLoggerHC);
    274                     if (VBOX_SUCCESS(rc))
    275                         pVM->vmm.s.pRelLoggerGC = MMHyperHC2GC(pVM, pVM->vmm.s.pRelLoggerHC);
    276                 }
    277             }
    278 #endif /* VBOX_WITH_RC_RELEASE_LOGGING */
    279 
    280 #ifdef VBOX_WITH_NMI
    281             /*
    282              * Allocate mapping for the host APIC.
    283              */
    284             if (VBOX_SUCCESS(rc))
    285             {
    286                 rc = MMR3HyperReserve(pVM, PAGE_SIZE, "Host APIC", &pVM->vmm.s.GCPtrApicBase);
    287                 AssertRC(rc);
    288             }
    289 #endif
    290             if (VBOX_SUCCESS(rc))
    291             {
    292                 rc = RTCritSectInit(&pVM->vmm.s.CritSectVMLock);
    293                 if (VBOX_SUCCESS(rc))
    294                 {
    295                     /*
    296                      * Debug info.
    297                      */
    298                     DBGFR3InfoRegisterInternal(pVM, "ff", "Displays the current Forced actions Flags.", vmmR3InfoFF);
    299 
    300                     /*
    301                      * Statistics.
    302                      */
    303                     STAM_REG(pVM, &pVM->vmm.s.StatRunGC,                    STAMTYPE_COUNTER, "/VMM/RunGC",                     STAMUNIT_OCCURENCES, "Number of context switches.");
    304                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetNormal,              STAMTYPE_COUNTER, "/VMM/GCRet/Normal",              STAMUNIT_OCCURENCES, "Number of VINF_SUCCESS returns.");
    305                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetInterrupt,           STAMTYPE_COUNTER, "/VMM/GCRet/Interrupt",           STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_INTERRUPT returns.");
    306                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetInterruptHyper,      STAMTYPE_COUNTER, "/VMM/GCRet/InterruptHyper",      STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_INTERRUPT_HYPER returns.");
    307                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetGuestTrap,           STAMTYPE_COUNTER, "/VMM/GCRet/GuestTrap",           STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_GUEST_TRAP returns.");
    308                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetRingSwitch,          STAMTYPE_COUNTER, "/VMM/GCRet/RingSwitch",          STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_RING_SWITCH returns.");
    309                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetRingSwitchInt,       STAMTYPE_COUNTER, "/VMM/GCRet/RingSwitchInt",       STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_RING_SWITCH_INT returns.");
    310                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetExceptionPrivilege,  STAMTYPE_COUNTER, "/VMM/GCRet/ExceptionPrivilege",  STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_EXCEPTION_PRIVILEGED returns.");
    311                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetStaleSelector,       STAMTYPE_COUNTER, "/VMM/GCRet/StaleSelector",       STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_STALE_SELECTOR returns.");
    312                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetIRETTrap,            STAMTYPE_COUNTER, "/VMM/GCRet/IRETTrap",            STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_IRET_TRAP returns.");
    313                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetEmulate,             STAMTYPE_COUNTER, "/VMM/GCRet/Emulate",             STAMUNIT_OCCURENCES, "Number of VINF_EM_EXECUTE_INSTRUCTION returns.");
    314                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetPatchEmulate,        STAMTYPE_COUNTER, "/VMM/GCRet/PatchEmulate",        STAMUNIT_OCCURENCES, "Number of VINF_PATCH_EMULATE_INSTR returns.");
    315                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetIORead,              STAMTYPE_COUNTER, "/VMM/GCRet/IORead",              STAMUNIT_OCCURENCES, "Number of VINF_IOM_HC_IOPORT_READ returns.");
    316                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetIOWrite,             STAMTYPE_COUNTER, "/VMM/GCRet/IOWrite",             STAMUNIT_OCCURENCES, "Number of VINF_IOM_HC_IOPORT_WRITE returns.");
    317                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetMMIORead,            STAMTYPE_COUNTER, "/VMM/GCRet/MMIORead",            STAMUNIT_OCCURENCES, "Number of VINF_IOM_HC_MMIO_READ returns.");
    318                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetMMIOWrite,           STAMTYPE_COUNTER, "/VMM/GCRet/MMIOWrite",           STAMUNIT_OCCURENCES, "Number of VINF_IOM_HC_MMIO_WRITE returns.");
    319                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetMMIOReadWrite,       STAMTYPE_COUNTER, "/VMM/GCRet/MMIOReadWrite",       STAMUNIT_OCCURENCES, "Number of VINF_IOM_HC_MMIO_READ_WRITE returns.");
    320                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetMMIOPatchRead,       STAMTYPE_COUNTER, "/VMM/GCRet/MMIOPatchRead",       STAMUNIT_OCCURENCES, "Number of VINF_IOM_HC_MMIO_PATCH_READ returns.");
    321                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetMMIOPatchWrite,      STAMTYPE_COUNTER, "/VMM/GCRet/MMIOPatchWrite",      STAMUNIT_OCCURENCES, "Number of VINF_IOM_HC_MMIO_PATCH_WRITE returns.");
    322                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetLDTFault,            STAMTYPE_COUNTER, "/VMM/GCRet/LDTFault",            STAMUNIT_OCCURENCES, "Number of VINF_EM_EXECUTE_INSTRUCTION_GDT_FAULT returns.");
    323                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetGDTFault,            STAMTYPE_COUNTER, "/VMM/GCRet/GDTFault",            STAMUNIT_OCCURENCES, "Number of VINF_EM_EXECUTE_INSTRUCTION_LDT_FAULT returns.");
    324                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetIDTFault,            STAMTYPE_COUNTER, "/VMM/GCRet/IDTFault",            STAMUNIT_OCCURENCES, "Number of VINF_EM_EXECUTE_INSTRUCTION_IDT_FAULT returns.");
    325                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetTSSFault,            STAMTYPE_COUNTER, "/VMM/GCRet/TSSFault",            STAMUNIT_OCCURENCES, "Number of VINF_EM_EXECUTE_INSTRUCTION_TSS_FAULT returns.");
    326                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetPDFault,             STAMTYPE_COUNTER, "/VMM/GCRet/PDFault",             STAMUNIT_OCCURENCES, "Number of VINF_EM_EXECUTE_INSTRUCTION_PD_FAULT returns.");
    327                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetCSAMTask,            STAMTYPE_COUNTER, "/VMM/GCRet/CSAMTask",            STAMUNIT_OCCURENCES, "Number of VINF_CSAM_PENDING_ACTION returns.");
    328                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetSyncCR3,             STAMTYPE_COUNTER, "/VMM/GCRet/SyncCR",              STAMUNIT_OCCURENCES, "Number of VINF_PGM_SYNC_CR3 returns.");
    329                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetMisc,                STAMTYPE_COUNTER, "/VMM/GCRet/Misc",                STAMUNIT_OCCURENCES, "Number of misc returns.");
    330                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetPatchInt3,           STAMTYPE_COUNTER, "/VMM/GCRet/PatchInt3",           STAMUNIT_OCCURENCES, "Number of VINF_PATM_PATCH_INT3 returns.");
    331                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetPatchPF,             STAMTYPE_COUNTER, "/VMM/GCRet/PatchPF",             STAMUNIT_OCCURENCES, "Number of VINF_PATM_PATCH_TRAP_PF returns.");
    332                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetPatchGP,             STAMTYPE_COUNTER, "/VMM/GCRet/PatchGP",             STAMUNIT_OCCURENCES, "Number of VINF_PATM_PATCH_TRAP_GP returns.");
    333                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetPatchIretIRQ,        STAMTYPE_COUNTER, "/VMM/GCRet/PatchIret",           STAMUNIT_OCCURENCES, "Number of VINF_PATM_PENDING_IRQ_AFTER_IRET returns.");
    334                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetPageOverflow,        STAMTYPE_COUNTER, "/VMM/GCRet/InvlpgOverflow",      STAMUNIT_OCCURENCES, "Number of VERR_REM_FLUSHED_PAGES_OVERFLOW returns.");
    335                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetRescheduleREM,       STAMTYPE_COUNTER, "/VMM/GCRet/ScheduleREM",         STAMUNIT_OCCURENCES, "Number of VINF_EM_RESCHEDULE_REM returns.");
    336                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetToR3,                STAMTYPE_COUNTER, "/VMM/GCRet/ToR3",                STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_TO_R3 returns.");
    337                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetTimerPending,        STAMTYPE_COUNTER, "/VMM/GCRet/TimerPending",        STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_TIMER_PENDING returns.");
    338                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetInterruptPending,    STAMTYPE_COUNTER, "/VMM/GCRet/InterruptPending",    STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_INTERRUPT_PENDING returns.");
    339                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetCallHost,            STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/Misc",       STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");
    340                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetPGMGrowRAM,          STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/GrowRAM",    STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");
    341                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetPDMLock,             STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/PDMLock",    STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");
    342                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetLogFlush,            STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/LogFlush",   STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");
    343                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetPDMQueueFlush,       STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/QueueFlush", STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");
    344                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetPGMPoolGrow,         STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/PGMPoolGrow",STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");
    345                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetRemReplay,           STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/REMReplay",  STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");
    346                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetVMSetError,          STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/VMSetError", STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");
    347                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetPGMLock,             STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/PGMLock",    STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");
    348                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetHyperAssertion,      STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/HyperAssert", STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");
    349                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetPATMDuplicateFn,     STAMTYPE_COUNTER, "/VMM/GCRet/PATMDuplicateFn",     STAMUNIT_OCCURENCES, "Number of VINF_PATM_DUPLICATE_FUNCTION returns.");
    350                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetPGMChangeMode,       STAMTYPE_COUNTER, "/VMM/GCRet/PGMChangeMode",       STAMUNIT_OCCURENCES, "Number of VINF_PGM_CHANGE_MODE returns.");
    351                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetEmulHlt,             STAMTYPE_COUNTER, "/VMM/GCRet/EmulHlt",             STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_EMULATE_INSTR_HLT returns.");
    352                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetPendingRequest,      STAMTYPE_COUNTER, "/VMM/GCRet/PendingRequest",      STAMUNIT_OCCURENCES, "Number of VINF_EM_PENDING_REQUEST returns.");
    353 
    354                     return VINF_SUCCESS;
    355                 }
    356                 AssertRC(rc);
    357             }
    358         }
    359         /** @todo: Need failure cleanup. */
    360 
    361         //more todo in here?
    362         //if (VBOX_SUCCESS(rc))
    363         //{
    364         //}
    365         //int rc2 = vmmR3TermCoreCode(pVM);
    366         //AssertRC(rc2));
    367     }
    368 
    369     return rc;
    370 }
    371 
    372 
    373 /**
    374  * VMMR3Init worker that initiates the core code.
    375  *
    376  * This is core per VM code which might need fixups and/or for ease of use are
    377  * put on linear contiguous backing.
    378  *
    379  * @returns VBox status code.
    380  * @param   pVM     Pointer to the shared VM structure.
    381  */
    382 static int vmmR3InitCoreCode(PVM pVM)
    383 {
    384     /*
    385      * Calc the size.
    386      */
    387     unsigned cbCoreCode = 0;
    388     for (unsigned iSwitcher = 0; iSwitcher < RT_ELEMENTS(s_apSwitchers); iSwitcher++)
    389     {
    390         pVM->vmm.s.aoffSwitchers[iSwitcher] = cbCoreCode;
    391         PVMMSWITCHERDEF pSwitcher = s_apSwitchers[iSwitcher];
    392         if (pSwitcher)
    393         {
    394             AssertRelease((unsigned)pSwitcher->enmType == iSwitcher);
    395             cbCoreCode += RT_ALIGN_32(pSwitcher->cbCode + 1, 32);
    396         }
    397     }
    398 
    399     /*
    400      * Allocate continguous pages for switchers and deal with
    401      * conflicts in the intermediate mapping of the code.
    402      */
    403     pVM->vmm.s.cbCoreCode = RT_ALIGN_32(cbCoreCode, PAGE_SIZE);
    404     pVM->vmm.s.pvHCCoreCodeR3 = SUPContAlloc2(pVM->vmm.s.cbCoreCode >> PAGE_SHIFT, &pVM->vmm.s.pvHCCoreCodeR0, &pVM->vmm.s.HCPhysCoreCode);
    405     int rc = VERR_NO_MEMORY;
    406     if (pVM->vmm.s.pvHCCoreCodeR3)
    407     {
    408         rc = PGMR3MapIntermediate(pVM, pVM->vmm.s.pvHCCoreCodeR0, pVM->vmm.s.HCPhysCoreCode, cbCoreCode);
    409         if (rc == VERR_PGM_INTERMEDIATE_PAGING_CONFLICT)
    410         {
    411             /* try more allocations - Solaris, Linux.  */
    412             const unsigned cTries = 8234;
    413             struct VMMInitBadTry
    414             {
    415                 RTR0PTR  pvR0;
    416                 void    *pvR3;
    417                 RTHCPHYS HCPhys;
    418                 RTUINT   cb;
    419             } *paBadTries = (struct VMMInitBadTry *)RTMemTmpAlloc(sizeof(*paBadTries) * cTries);
    420             AssertReturn(paBadTries, VERR_NO_TMP_MEMORY);
    421             unsigned i = 0;
    422             do
    423             {
    424                 paBadTries[i].pvR3 = pVM->vmm.s.pvHCCoreCodeR3;
    425                 paBadTries[i].pvR0 = pVM->vmm.s.pvHCCoreCodeR0;
    426                 paBadTries[i].HCPhys = pVM->vmm.s.HCPhysCoreCode;
    427                 i++;
    428                 pVM->vmm.s.pvHCCoreCodeR0 = NIL_RTR0PTR;
    429                 pVM->vmm.s.HCPhysCoreCode = NIL_RTHCPHYS;
    430                 pVM->vmm.s.pvHCCoreCodeR3 = SUPContAlloc2(pVM->vmm.s.cbCoreCode >> PAGE_SHIFT, &pVM->vmm.s.pvHCCoreCodeR0, &pVM->vmm.s.HCPhysCoreCode);
    431                 if (!pVM->vmm.s.pvHCCoreCodeR3)
    432                     break;
    433                 rc = PGMR3MapIntermediate(pVM, pVM->vmm.s.pvHCCoreCodeR0, pVM->vmm.s.HCPhysCoreCode, cbCoreCode);
    434             } while (   rc == VERR_PGM_INTERMEDIATE_PAGING_CONFLICT
    435                      && i < cTries - 1);
    436 
    437             /* cleanup */
    438             if (VBOX_FAILURE(rc))
    439             {
    440                 paBadTries[i].pvR3   = pVM->vmm.s.pvHCCoreCodeR3;
    441                 paBadTries[i].pvR0   = pVM->vmm.s.pvHCCoreCodeR0;
    442                 paBadTries[i].HCPhys = pVM->vmm.s.HCPhysCoreCode;
    443                 paBadTries[i].cb     = pVM->vmm.s.cbCoreCode;
    444                 i++;
    445                 LogRel(("Failed to allocated and map core code: rc=%Vrc\n", rc));
    446             }
    447             while (i-- > 0)
    448             {
    449                 LogRel(("Core code alloc attempt #%d: pvR3=%p pvR0=%p HCPhys=%VHp\n",
    450                         i, paBadTries[i].pvR3, paBadTries[i].pvR0, paBadTries[i].HCPhys));
    451                 SUPContFree(paBadTries[i].pvR3, paBadTries[i].cb >> PAGE_SHIFT);
    452             }
    453             RTMemTmpFree(paBadTries);
    454         }
    455     }
    456     if (VBOX_SUCCESS(rc))
    457     {
    458         /*
    459          * copy the code.
    460          */
    461         for (unsigned iSwitcher = 0; iSwitcher < RT_ELEMENTS(s_apSwitchers); iSwitcher++)
    462         {
    463             PVMMSWITCHERDEF pSwitcher = s_apSwitchers[iSwitcher];
    464             if (pSwitcher)
    465                 memcpy((uint8_t *)pVM->vmm.s.pvHCCoreCodeR3 + pVM->vmm.s.aoffSwitchers[iSwitcher],
    466                        pSwitcher->pvCode, pSwitcher->cbCode);
    467         }
    468 
    469         /*
    470          * Map the code into the GC address space.
    471          */
    472         RTGCPTR GCPtr;
    473         rc = MMR3HyperMapHCPhys(pVM, pVM->vmm.s.pvHCCoreCodeR3, pVM->vmm.s.HCPhysCoreCode, cbCoreCode, "Core Code", &GCPtr);
    474         if (VBOX_SUCCESS(rc))
    475         {
    476             pVM->vmm.s.pvGCCoreCode = GCPtr;
    477             MMR3HyperReserve(pVM, PAGE_SIZE, "fence", NULL);
    478             LogRel(("CoreCode: R3=%VHv R0=%VHv GC=%VRv Phys=%VHp cb=%#x\n",
    479                     pVM->vmm.s.pvHCCoreCodeR3, pVM->vmm.s.pvHCCoreCodeR0, pVM->vmm.s.pvGCCoreCode, pVM->vmm.s.HCPhysCoreCode, pVM->vmm.s.cbCoreCode));
    480 
    481             /*
    482              * Finally, PGM probably have selected a switcher already but we need
    483              * to get the routine addresses, so we'll reselect it.
    484              * This may legally fail so, we're ignoring the rc.
    485              */
    486             VMMR3SelectSwitcher(pVM, pVM->vmm.s.enmSwitcher);
    487             return rc;
    488         }
    489 
    490         /* shit */
    491         AssertMsgFailed(("PGMR3Map(,%VRv, %VGp, %#x, 0) failed with rc=%Vrc\n", pVM->vmm.s.pvGCCoreCode, pVM->vmm.s.HCPhysCoreCode, cbCoreCode, rc));
    492         SUPContFree(pVM->vmm.s.pvHCCoreCodeR3, pVM->vmm.s.cbCoreCode >> PAGE_SHIFT);
    493     }
    494     else
    495         VMSetError(pVM, rc, RT_SRC_POS,
    496                    N_("Failed to allocate %d bytes of contiguous memory for the world switcher code"),
    497                    cbCoreCode);
    498 
    499     pVM->vmm.s.pvHCCoreCodeR3 = NULL;
    500     pVM->vmm.s.pvHCCoreCodeR0 = NIL_RTR0PTR;
    501     pVM->vmm.s.pvGCCoreCode = 0;
    502     return rc;
    503 }
    504 
    505 
    506 /**
    507  * Ring-3 init finalizing.
    508  *
    509  * @returns VBox status code.
    510  * @param   pVM         The VM handle.
    511  */
    512 VMMR3DECL(int) VMMR3InitFinalize(PVM pVM)
    513 {
    514 #ifdef VBOX_STRICT_VMM_STACK
    515     /*
    516      * Two inaccessible pages at each sides of the stack to catch over/under-flows.
    517      */
    518     memset(pVM->vmm.s.pbHCStack - PAGE_SIZE, 0xcc, PAGE_SIZE);
    519     PGMMapSetPage(pVM, MMHyperHC2GC(pVM, pVM->vmm.s.pbHCStack - PAGE_SIZE), PAGE_SIZE, 0);
    520     RTMemProtect(pVM->vmm.s.pbHCStack - PAGE_SIZE, PAGE_SIZE, RTMEM_PROT_NONE);
    521 
    522     memset(pVM->vmm.s.pbHCStack + VMM_STACK_SIZE, 0xcc, PAGE_SIZE);
    523     PGMMapSetPage(pVM, MMHyperHC2GC(pVM, pVM->vmm.s.pbHCStack + VMM_STACK_SIZE), PAGE_SIZE, 0);
    524     RTMemProtect(pVM->vmm.s.pbHCStack + VMM_STACK_SIZE, PAGE_SIZE, RTMEM_PROT_NONE);
    525 #endif
    526 
    527     /*
    528      * Set page attributes to r/w for stack pages.
    529      */
    530     int rc = PGMMapSetPage(pVM, pVM->vmm.s.pbGCStack, VMM_STACK_SIZE, X86_PTE_P | X86_PTE_A | X86_PTE_D | X86_PTE_RW);
    531     AssertRC(rc);
    532     if (VBOX_SUCCESS(rc))
    533     {
    534         /*
    535          * Create the EMT yield timer.
    536          */
    537         rc = TMR3TimerCreateInternal(pVM, TMCLOCK_REAL, vmmR3YieldEMT, NULL, "EMT Yielder", &pVM->vmm.s.pYieldTimer);
    538         if (VBOX_SUCCESS(rc))
    539            rc = TMTimerSetMillies(pVM->vmm.s.pYieldTimer, pVM->vmm.s.cYieldEveryMillies);
    540     }
    541 
    542 #ifdef VBOX_WITH_NMI
    543     /*
    544      * Map the host APIC into GC - This may be host os specific!
    545      */
    546     if (VBOX_SUCCESS(rc))
    547         rc = PGMMap(pVM, pVM->vmm.s.GCPtrApicBase, 0xfee00000, PAGE_SIZE,
    548                     X86_PTE_P | X86_PTE_RW | X86_PTE_PWT | X86_PTE_PCD | X86_PTE_A | X86_PTE_D);
    549 #endif
    550     return rc;
    551 }
    552 
    553 
    554 /**
    555  * Initializes the R0 VMM.
    556  *
    557  * @returns VBox status code.
    558  * @param   pVM         The VM to operate on.
    559  */
    560 VMMR3DECL(int) VMMR3InitR0(PVM pVM)
    561 {
    562     int rc;
    563 
    564     /*
    565      * Initialize the ring-0 logger if we haven't done so yet.
    566      */
    567     if (    pVM->vmm.s.pR0Logger
    568         &&  !pVM->vmm.s.pR0Logger->fCreated)
    569     {
    570         rc = VMMR3UpdateLoggers(pVM);
    571         if (VBOX_FAILURE(rc))
    572             return rc;
    573     }
    574 
    575     /*
    576      * Call Ring-0 entry with init code.
    577      */
    578     for (;;)
    579     {
    580 #ifdef NO_SUPCALLR0VMM
    581         //rc = VERR_GENERAL_FAILURE;
    582         rc = VINF_SUCCESS;
    583 #else
    584         rc = SUPCallVMMR0Ex(pVM->pVMR0, VMMR0_DO_VMMR0_INIT, VMMGetSvnRev(), NULL);
    585 #endif
    586         if (    pVM->vmm.s.pR0Logger
    587             &&  pVM->vmm.s.pR0Logger->Logger.offScratch > 0)
    588             RTLogFlushToLogger(&pVM->vmm.s.pR0Logger->Logger, NULL);
    589         if (rc != VINF_VMM_CALL_HOST)
    590             break;
    591         rc = vmmR3ServiceCallHostRequest(pVM);
    592         if (VBOX_FAILURE(rc) || (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST))
    593             break;
    594         /* Resume R0 */
    595     }
    596 
    597     if (VBOX_FAILURE(rc) || (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST))
    598     {
    599         LogRel(("R0 init failed, rc=%Vra\n", rc));
    600         if (VBOX_SUCCESS(rc))
    601             rc = VERR_INTERNAL_ERROR;
    602     }
    603     return rc;
    604 }
    605 
    606 
    607 /**
    608  * Initializes the RC VMM.
    609  *
    610  * @returns VBox status code.
    611  * @param   pVM         The VM to operate on.
    612  */
    613 VMMR3DECL(int) VMMR3InitRC(PVM pVM)
    614 {
    615     /* In VMX mode, there's no need to init GC. */
    616     if (pVM->vmm.s.fSwitcherDisabled)
    617         return VINF_SUCCESS;
    618 
    619     /*
    620      * Call VMMGCInit():
    621      *      -# resolve the address.
    622      *      -# setup stackframe and EIP to use the trampoline.
    623      *      -# do a generic hypervisor call.
    624      */
    625     RTGCPTR32 GCPtrEP;
    626     int rc = PDMR3LdrGetSymbolRC(pVM, VMMGC_MAIN_MODULE_NAME, "VMMGCEntry", &GCPtrEP);
    627     if (VBOX_SUCCESS(rc))
    628     {
    629         CPUMHyperSetCtxCore(pVM, NULL);
    630         CPUMSetHyperESP(pVM, pVM->vmm.s.pbGCStackBottom); /* Clear the stack. */
    631         uint64_t u64TS = RTTimeProgramStartNanoTS();
    632         CPUMPushHyper(pVM, (uint32_t)(u64TS >> 32));    /* Param 3: The program startup TS - Hi. */
    633         CPUMPushHyper(pVM, (uint32_t)u64TS);            /* Param 3: The program startup TS - Lo. */
    634         CPUMPushHyper(pVM, VMMGetSvnRev());             /* Param 2: Version argument. */
    635         CPUMPushHyper(pVM, VMMGC_DO_VMMGC_INIT);        /* Param 1: Operation. */
    636         CPUMPushHyper(pVM, pVM->pVMGC);                 /* Param 0: pVM */
    637         CPUMPushHyper(pVM, 3 * sizeof(RTGCPTR32));      /* trampoline param: stacksize.  */
    638         CPUMPushHyper(pVM, GCPtrEP);                    /* Call EIP. */
    639         CPUMSetHyperEIP(pVM, pVM->vmm.s.pfnGCCallTrampoline);
    640 
    641         for (;;)
    642         {
    643 #ifdef NO_SUPCALLR0VMM
    644             //rc = VERR_GENERAL_FAILURE;
    645             rc = VINF_SUCCESS;
    646 #else
    647             rc = SUPCallVMMR0(pVM->pVMR0, VMMR0_DO_CALL_HYPERVISOR, NULL);
    648 #endif
    649 #ifdef LOG_ENABLED
    650             PRTLOGGERRC pLogger = pVM->vmm.s.pLoggerHC;
    651             if (    pLogger
    652                 &&  pLogger->offScratch > 0)
    653                 RTLogFlushGC(NULL, pLogger);
    654 #endif
    655 #ifdef VBOX_WITH_RC_RELEASE_LOGGING
    656             PRTLOGGERRC pRelLogger = pVM->vmm.s.pRelLoggerHC;
    657             if (RT_UNLIKELY(pRelLogger && pRelLogger->offScratch > 0))
    658                 RTLogFlushGC(RTLogRelDefaultInstance(), pRelLogger);
    659 #endif
    660             if (rc != VINF_VMM_CALL_HOST)
    661                 break;
    662             rc = vmmR3ServiceCallHostRequest(pVM);
    663             if (VBOX_FAILURE(rc) || (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST))
    664                 break;
    665         }
    666 
    667         if (VBOX_FAILURE(rc) || (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST))
    668         {
    669             VMMR3FatalDump(pVM, rc);
    670             if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
    671                 rc = VERR_INTERNAL_ERROR;
    672         }
    673         AssertRC(rc);
    674     }
    675     return rc;
    676 }
    677 
    678 
    679 /**
    680  * Terminate the VMM bits.
    681  *
    682  * @returns VINF_SUCCESS.
    683  * @param   pVM         The VM handle.
    684  */
    685 VMMR3DECL(int) VMMR3Term(PVM pVM)
    686 {
    687     /*
    688      * Call Ring-0 entry with termination code.
    689      */
    690     int rc;
    691     for (;;)
    692     {
    693 #ifdef NO_SUPCALLR0VMM
    694         //rc = VERR_GENERAL_FAILURE;
    695         rc = VINF_SUCCESS;
    696 #else
    697         rc = SUPCallVMMR0Ex(pVM->pVMR0, VMMR0_DO_VMMR0_TERM, 0, NULL);
    698 #endif
    699         if (    pVM->vmm.s.pR0Logger
    700             &&  pVM->vmm.s.pR0Logger->Logger.offScratch > 0)
    701             RTLogFlushToLogger(&pVM->vmm.s.pR0Logger->Logger, NULL);
    702         if (rc != VINF_VMM_CALL_HOST)
    703             break;
    704         rc = vmmR3ServiceCallHostRequest(pVM);
    705         if (VBOX_FAILURE(rc) || (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST))
    706             break;
    707         /* Resume R0 */
    708     }
    709     if (VBOX_FAILURE(rc) || (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST))
    710     {
    711         LogRel(("VMMR3Term: R0 term failed, rc=%Vra. (warning)\n", rc));
    712         if (VBOX_SUCCESS(rc))
    713             rc = VERR_INTERNAL_ERROR;
    714     }
    715 
    716 #ifdef VBOX_STRICT_VMM_STACK
    717     /*
    718      * Make the two stack guard pages present again.
    719      */
    720     RTMemProtect(pVM->vmm.s.pbHCStack - PAGE_SIZE,      PAGE_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
    721     RTMemProtect(pVM->vmm.s.pbHCStack + VMM_STACK_SIZE, PAGE_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
    722 #endif
    723     return rc;
    724 }
    725 
    726 
    727 /**
    728  * Applies relocations to data and code managed by this
    729  * component. This function will be called at init and
    730  * whenever the VMM need to relocate it self inside the GC.
    731  *
    732  * The VMM will need to apply relocations to the core code.
    733  *
    734  * @param   pVM         The VM handle.
    735  * @param   offDelta    The relocation delta.
    736  */
    737 VMMR3DECL(void) VMMR3Relocate(PVM pVM, RTGCINTPTR offDelta)
    738 {
    739     LogFlow(("VMMR3Relocate: offDelta=%VGv\n", offDelta));
    740 
    741     /*
    742      * Recalc the GC address.
    743      */
    744     pVM->vmm.s.pvGCCoreCode = MMHyperHC2GC(pVM, pVM->vmm.s.pvHCCoreCodeR3);
    745 
    746     /*
    747      * The stack.
    748      */
    749     CPUMSetHyperESP(pVM, CPUMGetHyperESP(pVM) + offDelta);
    750     pVM->vmm.s.pbGCStack = MMHyperHC2GC(pVM, pVM->vmm.s.pbHCStack);
    751     pVM->vmm.s.pbGCStackBottom = pVM->vmm.s.pbGCStack + VMM_STACK_SIZE;
    752 
    753     /*
    754      * All the switchers.
    755      */
    756     for (unsigned iSwitcher = 0; iSwitcher < RT_ELEMENTS(s_apSwitchers); iSwitcher++)
    757     {
    758         PVMMSWITCHERDEF pSwitcher = s_apSwitchers[iSwitcher];
    759         if (pSwitcher && pSwitcher->pfnRelocate)
    760         {
    761             unsigned off = pVM->vmm.s.aoffSwitchers[iSwitcher];
    762             pSwitcher->pfnRelocate(pVM,
    763                                    pSwitcher,
    764                                    (uint8_t *)pVM->vmm.s.pvHCCoreCodeR0 + off,
    765                                    (uint8_t *)pVM->vmm.s.pvHCCoreCodeR3 + off,
    766                                    pVM->vmm.s.pvGCCoreCode + off,
    767                                    pVM->vmm.s.HCPhysCoreCode + off);
    768         }
    769     }
    770 
    771     /*
    772      * Recalc the GC address for the current switcher.
    773      */
    774     PVMMSWITCHERDEF pSwitcher   = s_apSwitchers[pVM->vmm.s.enmSwitcher];
    775     RTGCPTR         GCPtr       = pVM->vmm.s.pvGCCoreCode + pVM->vmm.s.aoffSwitchers[pVM->vmm.s.enmSwitcher];
    776     pVM->vmm.s.pfnGCGuestToHost         = GCPtr + pSwitcher->offGCGuestToHost;
    777     pVM->vmm.s.pfnGCCallTrampoline      = GCPtr + pSwitcher->offGCCallTrampoline;
    778     pVM->pfnVMMGCGuestToHostAsm         = GCPtr + pSwitcher->offGCGuestToHostAsm;
    779     pVM->pfnVMMGCGuestToHostAsmHyperCtx = GCPtr + pSwitcher->offGCGuestToHostAsmHyperCtx;
    780     pVM->pfnVMMGCGuestToHostAsmGuestCtx = GCPtr + pSwitcher->offGCGuestToHostAsmGuestCtx;
    781 
    782     /*
    783      * Get other GC entry points.
    784      */
    785     int rc = PDMR3LdrGetSymbolRC(pVM, VMMGC_MAIN_MODULE_NAME, "CPUMGCResumeGuest", &pVM->vmm.s.pfnCPUMGCResumeGuest);
    786     AssertReleaseMsgRC(rc, ("CPUMGCResumeGuest not found! rc=%Vra\n", rc));
    787 
    788     rc = PDMR3LdrGetSymbolRC(pVM, VMMGC_MAIN_MODULE_NAME, "CPUMGCResumeGuestV86", &pVM->vmm.s.pfnCPUMGCResumeGuestV86);
    789     AssertReleaseMsgRC(rc, ("CPUMGCResumeGuestV86 not found! rc=%Vra\n", rc));
    790 
    791     /*
    792      * Update the logger.
    793      */
    794     VMMR3UpdateLoggers(pVM);
    795 }
    796 
    797 
    798 /**
    799  * Updates the settings for the GC and R0 loggers.
    800  *
    801  * @returns VBox status code.
    802  * @param   pVM     The VM handle.
    803  */
    804 VMMR3DECL(int)  VMMR3UpdateLoggers(PVM pVM)
    805 {
    806     /*
    807      * Simply clone the logger instance (for GC).
    808      */
    809     int rc = VINF_SUCCESS;
    810     RTGCPTR32 GCPtrLoggerFlush = 0;
    811 
    812     if (pVM->vmm.s.pLoggerHC
    813 #ifdef VBOX_WITH_RC_RELEASE_LOGGING
    814         || pVM->vmm.s.pRelLoggerHC
    815 #endif
    816        )
    817     {
    818         rc = PDMR3LdrGetSymbolRC(pVM, VMMGC_MAIN_MODULE_NAME, "vmmGCLoggerFlush", &GCPtrLoggerFlush);
    819         AssertReleaseMsgRC(rc, ("vmmGCLoggerFlush not found! rc=%Vra\n", rc));
    820     }
    821 
    822     if (pVM->vmm.s.pLoggerHC)
    823     {
    824         RTGCPTR32 GCPtrLoggerWrapper = 0;
    825         rc = PDMR3LdrGetSymbolRC(pVM, VMMGC_MAIN_MODULE_NAME, "vmmGCLoggerWrapper", &GCPtrLoggerWrapper);
    826         AssertReleaseMsgRC(rc, ("vmmGCLoggerWrapper not found! rc=%Vra\n", rc));
    827         pVM->vmm.s.pLoggerGC = MMHyperHC2GC(pVM, pVM->vmm.s.pLoggerHC);
    828         rc = RTLogCloneRC(NULL /* default */, pVM->vmm.s.pLoggerHC, pVM->vmm.s.cbLoggerGC,
    829                           GCPtrLoggerWrapper,  GCPtrLoggerFlush, RTLOGFLAGS_BUFFERED);
    830         AssertReleaseMsgRC(rc, ("RTLogCloneGC failed! rc=%Vra\n", rc));
    831     }
    832 
    833 #ifdef VBOX_WITH_RC_RELEASE_LOGGING
    834     if (pVM->vmm.s.pRelLoggerHC)
    835     {
    836         RTGCPTR32 GCPtrLoggerWrapper = 0;
    837         rc = PDMR3LdrGetSymbolRC(pVM, VMMGC_MAIN_MODULE_NAME, "vmmGCRelLoggerWrapper", &GCPtrLoggerWrapper);
    838         AssertReleaseMsgRC(rc, ("vmmGCRelLoggerWrapper not found! rc=%Vra\n", rc));
    839         pVM->vmm.s.pRelLoggerGC = MMHyperHC2GC(pVM, pVM->vmm.s.pRelLoggerHC);
    840         rc = RTLogCloneRC(RTLogRelDefaultInstance(), pVM->vmm.s.pRelLoggerHC, pVM->vmm.s.cbRelLoggerGC,
    841                           GCPtrLoggerWrapper,  GCPtrLoggerFlush, RTLOGFLAGS_BUFFERED);
    842         AssertReleaseMsgRC(rc, ("RTLogCloneGC failed! rc=%Vra\n", rc));
    843     }
    844 #endif /* VBOX_WITH_RC_RELEASE_LOGGING */
    845 
    846     /*
    847      * For the ring-0 EMT logger, we use a per-thread logger
    848      * instance in ring-0. Only initialize it once.
    849      */
    850     PVMMR0LOGGER pR0Logger = pVM->vmm.s.pR0Logger;
    851     if (pR0Logger)
    852     {
    853         if (!pR0Logger->fCreated)
    854         {
    855             RTR0PTR pfnLoggerWrapper = NIL_RTR0PTR;
    856             rc = PDMR3LdrGetSymbolR0(pVM, VMMR0_MAIN_MODULE_NAME, "vmmR0LoggerWrapper", &pfnLoggerWrapper);
    857             AssertReleaseMsgRCReturn(rc, ("VMMLoggerWrapper not found! rc=%Vra\n", rc), rc);
    858 
    859             RTR0PTR pfnLoggerFlush = NIL_RTR0PTR;
    860             rc = PDMR3LdrGetSymbolR0(pVM, VMMR0_MAIN_MODULE_NAME, "vmmR0LoggerFlush", &pfnLoggerFlush);
    861             AssertReleaseMsgRCReturn(rc, ("VMMLoggerFlush not found! rc=%Vra\n", rc), rc);
    862 
    863             rc = RTLogCreateForR0(&pR0Logger->Logger, pR0Logger->cbLogger,
    864                                   *(PFNRTLOGGER *)&pfnLoggerWrapper, *(PFNRTLOGFLUSH *)&pfnLoggerFlush,
    865                                   RTLOGFLAGS_BUFFERED, RTLOGDEST_DUMMY);
    866             AssertReleaseMsgRCReturn(rc, ("RTLogCloneGC failed! rc=%Vra\n", rc), rc);
    867             pR0Logger->fCreated = true;
    868         }
    869 
    870         rc = RTLogCopyGroupsAndFlags(&pR0Logger->Logger, NULL /* default */, pVM->vmm.s.pLoggerHC->fFlags, RTLOGFLAGS_BUFFERED);
    871         AssertRC(rc);
    872     }
    873 
    874     return rc;
    875 }
    876 
    877 
    878 /**
    879  * Generic switch code relocator.
    880  *
    881  * @param   pVM         The VM handle.
    882  * @param   pSwitcher   The switcher definition.
    883  * @param   pu8CodeR3   Pointer to the core code block for the switcher, ring-3 mapping.
    884  * @param   pu8CodeR0   Pointer to the core code block for the switcher, ring-0 mapping.
    885  * @param   GCPtrCode   The guest context address corresponding to pu8Code.
    886  * @param   u32IDCode   The identity mapped (ID) address corresponding to pu8Code.
    887  * @param   SelCS       The hypervisor CS selector.
    888  * @param   SelDS       The hypervisor DS selector.
    889  * @param   SelTSS      The hypervisor TSS selector.
    890  * @param   GCPtrGDT    The GC address of the hypervisor GDT.
    891  * @param   SelCS64     The 64-bit mode hypervisor CS selector.
    892  */
    893 static void vmmR3SwitcherGenericRelocate(PVM pVM, PVMMSWITCHERDEF pSwitcher, uint8_t *pu8CodeR0, uint8_t *pu8CodeR3, RTGCPTR GCPtrCode, uint32_t u32IDCode,
    894                                          RTSEL SelCS, RTSEL SelDS, RTSEL SelTSS, RTGCPTR GCPtrGDT, RTSEL SelCS64)
    895 {
    896     union
    897     {
    898         const uint8_t *pu8;
    899         const uint16_t *pu16;
    900         const uint32_t *pu32;
    901         const uint64_t *pu64;
    902         const void     *pv;
    903         uintptr_t       u;
    904     } u;
    905     u.pv = pSwitcher->pvFixups;
    906 
    907     /*
    908      * Process fixups.
    909      */
    910     uint8_t u8;
    911     while ((u8 = *u.pu8++) != FIX_THE_END)
    912     {
    913         /*
    914          * Get the source (where to write the fixup).
    915          */
    916         uint32_t offSrc = *u.pu32++;
    917         Assert(offSrc < pSwitcher->cbCode);
    918         union
    919         {
    920             uint8_t    *pu8;
    921             uint16_t   *pu16;
    922             uint32_t   *pu32;
    923             uint64_t   *pu64;
    924             uintptr_t   u;
    925         } uSrc;
    926         uSrc.pu8 = pu8CodeR3 + offSrc;
    927 
    928         /* The fixup target and method depends on the type. */
    929         switch (u8)
    930         {
    931             /*
    932              * 32-bit relative, source in HC and target in GC.
    933              */
    934             case FIX_HC_2_GC_NEAR_REL:
    935             {
    936                 Assert(offSrc - pSwitcher->offHCCode0 < pSwitcher->cbHCCode0 || offSrc - pSwitcher->offHCCode1 < pSwitcher->cbHCCode1);
    937                 uint32_t offTrg = *u.pu32++;
    938                 Assert(offTrg - pSwitcher->offGCCode < pSwitcher->cbGCCode);
    939                 *uSrc.pu32 = (uint32_t)((GCPtrCode + offTrg) - (uSrc.u + 4));
    940                 break;
    941             }
    942 
    943             /*
    944              * 32-bit relative, source in HC and target in ID.
    945              */
    946             case FIX_HC_2_ID_NEAR_REL:
    947             {
    948                 Assert(offSrc - pSwitcher->offHCCode0 < pSwitcher->cbHCCode0 || offSrc - pSwitcher->offHCCode1 < pSwitcher->cbHCCode1);
    949                 uint32_t offTrg = *u.pu32++;
    950                 Assert(offTrg - pSwitcher->offIDCode0 < pSwitcher->cbIDCode0 || offTrg - pSwitcher->offIDCode1 < pSwitcher->cbIDCode1);
    951                 *uSrc.pu32 = (uint32_t)((u32IDCode + offTrg) - ((uintptr_t)pu8CodeR0 + offSrc + 4));
    952                 break;
    953             }
    954 
    955             /*
    956              * 32-bit relative, source in GC and target in HC.
    957              */
    958             case FIX_GC_2_HC_NEAR_REL:
    959             {
    960                 Assert(offSrc - pSwitcher->offGCCode < pSwitcher->cbGCCode);
    961                 uint32_t offTrg = *u.pu32++;
    962                 Assert(offTrg - pSwitcher->offHCCode0 < pSwitcher->cbHCCode0 || offTrg - pSwitcher->offHCCode1 < pSwitcher->cbHCCode1);
    963                 *uSrc.pu32 = (uint32_t)(((uintptr_t)pu8CodeR0 + offTrg) - (GCPtrCode + offSrc + 4));
    964                 break;
    965             }
    966 
    967             /*
    968              * 32-bit relative, source in GC and target in ID.
    969              */
    970             case FIX_GC_2_ID_NEAR_REL:
    971             {
    972                 Assert(offSrc - pSwitcher->offGCCode < pSwitcher->cbGCCode);
    973                 uint32_t offTrg = *u.pu32++;
    974                 Assert(offTrg - pSwitcher->offIDCode0 < pSwitcher->cbIDCode0 || offTrg - pSwitcher->offIDCode1 < pSwitcher->cbIDCode1);
    975                 *uSrc.pu32 = (uint32_t)((u32IDCode + offTrg) - (GCPtrCode + offSrc + 4));
    976                 break;
    977             }
    978 
    979             /*
    980              * 32-bit relative, source in ID and target in HC.
    981              */
    982             case FIX_ID_2_HC_NEAR_REL:
    983             {
    984                 Assert(offSrc - pSwitcher->offIDCode0 < pSwitcher->cbIDCode0 || offSrc - pSwitcher->offIDCode1 < pSwitcher->cbIDCode1);
    985                 uint32_t offTrg = *u.pu32++;
    986                 Assert(offTrg - pSwitcher->offHCCode0 < pSwitcher->cbHCCode0 || offTrg - pSwitcher->offHCCode1 < pSwitcher->cbHCCode1);
    987                 *uSrc.pu32 = (uint32_t)(((uintptr_t)pu8CodeR0 + offTrg) - (u32IDCode + offSrc + 4));
    988                 break;
    989             }
    990 
    991             /*
    992              * 32-bit relative, source in ID and target in HC.
    993              */
    994             case FIX_ID_2_GC_NEAR_REL:
    995             {
    996                 Assert(offSrc - pSwitcher->offIDCode0 < pSwitcher->cbIDCode0 || offSrc - pSwitcher->offIDCode1 < pSwitcher->cbIDCode1);
    997                 uint32_t offTrg = *u.pu32++;
    998                 Assert(offTrg - pSwitcher->offGCCode < pSwitcher->cbGCCode);
    999                 *uSrc.pu32 = (uint32_t)((GCPtrCode + offTrg) - (u32IDCode + offSrc + 4));
    1000                 break;
    1001             }
    1002 
    1003             /*
    1004              * 16:32 far jump, target in GC.
    1005              */
    1006             case FIX_GC_FAR32:
    1007             {
    1008                 uint32_t offTrg = *u.pu32++;
    1009                 Assert(offTrg - pSwitcher->offGCCode < pSwitcher->cbGCCode);
    1010                 *uSrc.pu32++ = (uint32_t)(GCPtrCode + offTrg);
    1011                 *uSrc.pu16++ = SelCS;
    1012                 break;
    1013             }
    1014 
    1015             /*
    1016              * Make 32-bit GC pointer given CPUM offset.
    1017              */
    1018             case FIX_GC_CPUM_OFF:
    1019             {
    1020                 uint32_t offCPUM = *u.pu32++;
    1021                 Assert(offCPUM < sizeof(pVM->cpum));
    1022                 *uSrc.pu32 = (uint32_t)(VM_GUEST_ADDR(pVM, &pVM->cpum) + offCPUM);
    1023                 break;
    1024             }
    1025 
    1026             /*
    1027              * Make 32-bit GC pointer given VM offset.
    1028              */
    1029             case FIX_GC_VM_OFF:
    1030             {
    1031                 uint32_t offVM = *u.pu32++;
    1032                 Assert(offVM < sizeof(VM));
    1033                 *uSrc.pu32 = (uint32_t)(VM_GUEST_ADDR(pVM, pVM) + offVM);
    1034                 break;
    1035             }
    1036 
    1037             /*
    1038              * Make 32-bit HC pointer given CPUM offset.
    1039              */
    1040             case FIX_HC_CPUM_OFF:
    1041             {
    1042                 uint32_t offCPUM = *u.pu32++;
    1043                 Assert(offCPUM < sizeof(pVM->cpum));
    1044                 *uSrc.pu32 = (uint32_t)pVM->pVMR0 + RT_OFFSETOF(VM, cpum) + offCPUM;
    1045                 break;
    1046             }
    1047 
    1048             /*
    1049              * Make 32-bit R0 pointer given VM offset.
    1050              */
    1051             case FIX_HC_VM_OFF:
    1052             {
    1053                 uint32_t offVM = *u.pu32++;
    1054                 Assert(offVM < sizeof(VM));
    1055                 *uSrc.pu32 = (uint32_t)pVM->pVMR0 + offVM;
    1056                 break;
    1057             }
    1058 
    1059             /*
    1060              * Store the 32-Bit CR3 (32-bit) for the intermediate memory context.
    1061              */
    1062             case FIX_INTER_32BIT_CR3:
    1063             {
    1064 
    1065                 *uSrc.pu32 = PGMGetInter32BitCR3(pVM);
    1066                 break;
    1067             }
    1068 
    1069             /*
    1070              * Store the PAE CR3 (32-bit) for the intermediate memory context.
    1071              */
    1072             case FIX_INTER_PAE_CR3:
    1073             {
    1074 
    1075                 *uSrc.pu32 = PGMGetInterPaeCR3(pVM);
    1076                 break;
    1077             }
    1078 
    1079             /*
    1080              * Store the AMD64 CR3 (32-bit) for the intermediate memory context.
    1081              */
    1082             case FIX_INTER_AMD64_CR3:
    1083             {
    1084 
    1085                 *uSrc.pu32 = PGMGetInterAmd64CR3(pVM);
    1086                 break;
    1087             }
    1088 
    1089             /*
    1090              * Store the 32-Bit CR3 (32-bit) for the hypervisor (shadow) memory context.
    1091              */
    1092             case FIX_HYPER_32BIT_CR3:
    1093             {
    1094 
    1095                 *uSrc.pu32 = PGMGetHyper32BitCR3(pVM);
    1096                 break;
    1097             }
    1098 
    1099             /*
    1100              * Store the PAE CR3 (32-bit) for the hypervisor (shadow) memory context.
    1101              */
    1102             case FIX_HYPER_PAE_CR3:
    1103             {
    1104 
    1105                 *uSrc.pu32 = PGMGetHyperPaeCR3(pVM);
    1106                 break;
    1107             }
    1108 
    1109             /*
    1110              * Store the AMD64 CR3 (32-bit) for the hypervisor (shadow) memory context.
    1111              */
    1112             case FIX_HYPER_AMD64_CR3:
    1113             {
    1114 
    1115                 *uSrc.pu32 = PGMGetHyperAmd64CR3(pVM);
    1116                 break;
    1117             }
    1118 
    1119             /*
    1120              * Store Hypervisor CS (16-bit).
    1121              */
    1122             case FIX_HYPER_CS:
    1123             {
    1124                 *uSrc.pu16 = SelCS;
    1125                 break;
    1126             }
    1127 
    1128             /*
    1129              * Store Hypervisor DS (16-bit).
    1130              */
    1131             case FIX_HYPER_DS:
    1132             {
    1133                 *uSrc.pu16 = SelDS;
    1134                 break;
    1135             }
    1136 
    1137             /*
    1138              * Store Hypervisor TSS (16-bit).
    1139              */
    1140             case FIX_HYPER_TSS:
    1141             {
    1142                 *uSrc.pu16 = SelTSS;
    1143                 break;
    1144             }
    1145 
    1146             /*
    1147              * Store the 32-bit GC address of the 2nd dword of the TSS descriptor (in the GDT).
    1148              */
    1149             case FIX_GC_TSS_GDTE_DW2:
    1150             {
    1151                 RTGCPTR GCPtr = GCPtrGDT + (SelTSS & ~7) + 4;
    1152                 *uSrc.pu32 = (uint32_t)GCPtr;
    1153                 break;
    1154             }
    1155 
    1156 
    1157             ///@todo case FIX_CR4_MASK:
    1158             ///@todo case FIX_CR4_OSFSXR:
    1159 
    1160             /*
    1161              * Insert relative jump to specified target it FXSAVE/FXRSTOR isn't supported by the cpu.
    1162              */
    1163             case FIX_NO_FXSAVE_JMP:
    1164             {
    1165                 uint32_t offTrg = *u.pu32++;
    1166                 Assert(offTrg < pSwitcher->cbCode);
    1167                 if (!CPUMSupportsFXSR(pVM))
    1168                 {
    1169                     *uSrc.pu8++ = 0xe9; /* jmp rel32 */
    1170                     *uSrc.pu32++ = offTrg - (offSrc + 5);
    1171                 }
    1172                 else
    1173                 {
    1174                     *uSrc.pu8++ = *((uint8_t *)pSwitcher->pvCode + offSrc);
    1175                     *uSrc.pu32++ = *(uint32_t *)((uint8_t *)pSwitcher->pvCode + offSrc + 1);
    1176                 }
    1177                 break;
    1178             }
    1179 
    1180             /*
    1181              * Insert relative jump to specified target it SYSENTER isn't used by the host.
    1182              */
    1183             case FIX_NO_SYSENTER_JMP:
    1184             {
    1185                 uint32_t offTrg = *u.pu32++;
    1186                 Assert(offTrg < pSwitcher->cbCode);
    1187                 if (!CPUMIsHostUsingSysEnter(pVM))
    1188                 {
    1189                     *uSrc.pu8++ = 0xe9; /* jmp rel32 */
    1190                     *uSrc.pu32++ = offTrg - (offSrc + 5);
    1191                 }
    1192                 else
    1193                 {
    1194                     *uSrc.pu8++ = *((uint8_t *)pSwitcher->pvCode + offSrc);
    1195                     *uSrc.pu32++ = *(uint32_t *)((uint8_t *)pSwitcher->pvCode + offSrc + 1);
    1196                 }
    1197                 break;
    1198             }
    1199 
    1200             /*
    1201              * Insert relative jump to specified target it SYSENTER isn't used by the host.
    1202              */
    1203             case FIX_NO_SYSCALL_JMP:
    1204             {
    1205                 uint32_t offTrg = *u.pu32++;
    1206                 Assert(offTrg < pSwitcher->cbCode);
    1207                 if (!CPUMIsHostUsingSysEnter(pVM))
    1208                 {
    1209                     *uSrc.pu8++ = 0xe9; /* jmp rel32 */
    1210                     *uSrc.pu32++ = offTrg - (offSrc + 5);
    1211                 }
    1212                 else
    1213                 {
    1214                     *uSrc.pu8++ = *((uint8_t *)pSwitcher->pvCode + offSrc);
    1215                     *uSrc.pu32++ = *(uint32_t *)((uint8_t *)pSwitcher->pvCode + offSrc + 1);
    1216                 }
    1217                 break;
    1218             }
    1219 
    1220             /*
    1221              * 32-bit HC pointer fixup to (HC) target within the code (32-bit offset).
    1222              */
    1223             case FIX_HC_32BIT:
    1224             {
    1225                 uint32_t offTrg = *u.pu32++;
    1226                 Assert(offSrc < pSwitcher->cbCode);
    1227                 Assert(offTrg - pSwitcher->offHCCode0 < pSwitcher->cbHCCode0 || offTrg - pSwitcher->offHCCode1 < pSwitcher->cbHCCode1);
    1228                 *uSrc.pu32 = (uintptr_t)pu8CodeR0 + offTrg;
    1229                 break;
    1230             }
    1231 
    1232 #if defined(RT_ARCH_AMD64) || defined(VBOX_WITH_HYBIRD_32BIT_KERNEL)
    1233             /*
    1234              * 64-bit HC pointer fixup to (HC) target within the code (32-bit offset).
    1235              */
    1236             case FIX_HC_64BIT:
    1237             {
    1238                 uint32_t offTrg = *u.pu32++;
    1239                 Assert(offSrc < pSwitcher->cbCode);
    1240                 Assert(offTrg - pSwitcher->offHCCode0 < pSwitcher->cbHCCode0 || offTrg - pSwitcher->offHCCode1 < pSwitcher->cbHCCode1);
    1241                 *uSrc.pu64 = (uintptr_t)pu8CodeR0 + offTrg;
    1242                 break;
    1243             }
    1244 
    1245             /*
    1246              * 64-bit HC Code Selector (no argument).
    1247              */
    1248             case FIX_HC_64BIT_CS:
    1249             {
    1250                 Assert(offSrc < pSwitcher->cbCode);
    1251 #if defined(RT_OS_DARWIN) && defined(VBOX_WITH_HYBIRD_32BIT_KERNEL)
    1252                 *uSrc.pu16 = 0x80; /* KERNEL64_CS from i386/seg.h */
    1253 #else
    1254                 AssertFatalMsgFailed(("FIX_HC_64BIT_CS not implemented for this host\n"));
    1255 #endif
    1256                 break;
    1257             }
    1258 
    1259             /*
    1260              * 64-bit HC pointer to the CPUM instance data (no argument).
    1261              */
    1262             case FIX_HC_64BIT_CPUM:
    1263             {
    1264                 Assert(offSrc < pSwitcher->cbCode);
    1265                 *uSrc.pu64 = pVM->pVMR0 + RT_OFFSETOF(VM, cpum);
    1266                 break;
    1267             }
    1268 #endif
    1269 
    1270             /*
    1271              * 32-bit ID pointer to (ID) target within the code (32-bit offset).
    1272              */
    1273             case FIX_ID_32BIT:
    1274             {
    1275                 uint32_t offTrg = *u.pu32++;
    1276                 Assert(offSrc < pSwitcher->cbCode);
    1277                 Assert(offTrg - pSwitcher->offIDCode0 < pSwitcher->cbIDCode0 || offTrg - pSwitcher->offIDCode1 < pSwitcher->cbIDCode1);
    1278                 *uSrc.pu32 = u32IDCode + offTrg;
    1279                 break;
    1280             }
    1281 
    1282             /*
    1283              * 64-bit ID pointer to (ID) target within the code (32-bit offset).
    1284              */
    1285             case FIX_ID_64BIT:
    1286             {
    1287                 uint32_t offTrg = *u.pu32++;
    1288                 Assert(offSrc < pSwitcher->cbCode);
    1289                 Assert(offTrg - pSwitcher->offIDCode0 < pSwitcher->cbIDCode0 || offTrg - pSwitcher->offIDCode1 < pSwitcher->cbIDCode1);
    1290                 *uSrc.pu64 = u32IDCode + offTrg;
    1291                 break;
    1292             }
    1293 
    1294             /*
    1295              * Far 16:32 ID pointer to 64-bit mode (ID) target within the code (32-bit offset).
    1296              */
    1297             case FIX_ID_FAR32_TO_64BIT_MODE:
    1298             {
    1299                 uint32_t offTrg = *u.pu32++;
    1300                 Assert(offSrc < pSwitcher->cbCode);
    1301                 Assert(offTrg - pSwitcher->offIDCode0 < pSwitcher->cbIDCode0 || offTrg - pSwitcher->offIDCode1 < pSwitcher->cbIDCode1);
    1302                 *uSrc.pu32++ = u32IDCode + offTrg;
    1303                 *uSrc.pu16 = SelCS64;
    1304                 AssertRelease(SelCS64);
    1305                 break;
    1306             }
    1307 
    1308 #ifdef VBOX_WITH_NMI
    1309             /*
    1310              * 32-bit address to the APIC base.
    1311              */
    1312             case FIX_GC_APIC_BASE_32BIT:
    1313             {
    1314                 *uSrc.pu32 = pVM->vmm.s.GCPtrApicBase;
    1315                 break;
    1316             }
    1317 #endif
    1318 
    1319             default:
    1320                 AssertReleaseMsgFailed(("Unknown fixup %d in switcher %s\n", u8, pSwitcher->pszDesc));
    1321                 break;
    1322         }
    1323     }
    1324 
    1325 #ifdef LOG_ENABLED
    1326     /*
    1327      * If Log2 is enabled disassemble the switcher code.
    1328      *
    1329      * The switcher code have 1-2 HC parts, 1 GC part and 0-2 ID parts.
    1330      */
    1331     if (LogIs2Enabled())
    1332     {
    1333         RTLogPrintf("*** Disassembly of switcher %d '%s' %#x bytes ***\n"
    1334                     "   pu8CodeR0   = %p\n"
    1335                     "   pu8CodeR3   = %p\n"
    1336                     "   GCPtrCode   = %VGv\n"
    1337                     "   u32IDCode   = %08x\n"
    1338                     "   pVMGC       = %VGv\n"
    1339                     "   pCPUMGC     = %VGv\n"
    1340                     "   pVMHC       = %p\n"
    1341                     "   pCPUMHC     = %p\n"
    1342                     "   GCPtrGDT    = %VGv\n"
    1343                     "   InterCR3s   = %08x, %08x, %08x (32-Bit, PAE, AMD64)\n"
    1344                     "   HyperCR3s   = %08x, %08x, %08x (32-Bit, PAE, AMD64)\n"
    1345                     "   SelCS       = %04x\n"
    1346                     "   SelDS       = %04x\n"
    1347                     "   SelCS64     = %04x\n"
    1348                     "   SelTSS      = %04x\n",
    1349                     pSwitcher->enmType, pSwitcher->pszDesc, pSwitcher->cbCode,
    1350                     pu8CodeR0, pu8CodeR3, GCPtrCode, u32IDCode, VM_GUEST_ADDR(pVM, pVM),
    1351                     VM_GUEST_ADDR(pVM, &pVM->cpum), pVM, &pVM->cpum,
    1352                     GCPtrGDT,
    1353                     PGMGetHyper32BitCR3(pVM), PGMGetHyperPaeCR3(pVM), PGMGetHyperAmd64CR3(pVM),
    1354                     PGMGetInter32BitCR3(pVM), PGMGetInterPaeCR3(pVM), PGMGetInterAmd64CR3(pVM),
    1355                     SelCS, SelDS, SelCS64, SelTSS);
    1356 
    1357         uint32_t offCode = 0;
    1358         while (offCode < pSwitcher->cbCode)
    1359         {
    1360             /*
    1361              * Figure out where this is.
    1362              */
    1363             const char *pszDesc = NULL;
    1364             RTUINTPTR   uBase;
    1365             uint32_t    cbCode;
    1366             if (offCode - pSwitcher->offHCCode0 < pSwitcher->cbHCCode0)
    1367             {
    1368                 pszDesc = "HCCode0";
    1369                 uBase   = (RTUINTPTR)pu8CodeR0;
    1370                 offCode = pSwitcher->offHCCode0;
    1371                 cbCode  = pSwitcher->cbHCCode0;
    1372             }
    1373             else if (offCode - pSwitcher->offHCCode1 < pSwitcher->cbHCCode1)
    1374             {
    1375                 pszDesc = "HCCode1";
    1376                 uBase   = (RTUINTPTR)pu8CodeR0;
    1377                 offCode = pSwitcher->offHCCode1;
    1378                 cbCode  = pSwitcher->cbHCCode1;
    1379             }
    1380             else if (offCode - pSwitcher->offGCCode < pSwitcher->cbGCCode)
    1381             {
    1382                 pszDesc = "GCCode";
    1383                 uBase   = GCPtrCode;
    1384                 offCode = pSwitcher->offGCCode;
    1385                 cbCode  = pSwitcher->cbGCCode;
    1386             }
    1387             else if (offCode - pSwitcher->offIDCode0 < pSwitcher->cbIDCode0)
    1388             {
    1389                 pszDesc = "IDCode0";
    1390                 uBase   = u32IDCode;
    1391                 offCode = pSwitcher->offIDCode0;
    1392                 cbCode  = pSwitcher->cbIDCode0;
    1393             }
    1394             else if (offCode - pSwitcher->offIDCode1 < pSwitcher->cbIDCode1)
    1395             {
    1396                 pszDesc = "IDCode1";
    1397                 uBase   = u32IDCode;
    1398                 offCode = pSwitcher->offIDCode1;
    1399                 cbCode  = pSwitcher->cbIDCode1;
    1400             }
    1401             else
    1402             {
    1403                 RTLogPrintf("  %04x: %02x '%c' (nowhere)\n",
    1404                             offCode, pu8CodeR3[offCode], isprint(pu8CodeR3[offCode]) ? pu8CodeR3[offCode] : ' ');
    1405                 offCode++;
    1406                 continue;
    1407             }
    1408 
    1409             /*
    1410              * Disassemble it.
    1411              */
    1412             RTLogPrintf("  %s: offCode=%#x cbCode=%#x\n", pszDesc, offCode, cbCode);
    1413             DISCPUSTATE Cpu;
    1414 
    1415             memset(&Cpu, 0, sizeof(Cpu));
    1416             Cpu.mode = CPUMODE_32BIT;
    1417             while (cbCode > 0)
    1418             {
    1419                 /* try label it */
    1420                 if (pSwitcher->offR0HostToGuest == offCode)
    1421                     RTLogPrintf(" *R0HostToGuest:\n");
    1422                 if (pSwitcher->offGCGuestToHost == offCode)
    1423                     RTLogPrintf(" *GCGuestToHost:\n");
    1424                 if (pSwitcher->offGCCallTrampoline == offCode)
    1425                     RTLogPrintf(" *GCCallTrampoline:\n");
    1426                 if (pSwitcher->offGCGuestToHostAsm == offCode)
    1427                     RTLogPrintf(" *GCGuestToHostAsm:\n");
    1428                 if (pSwitcher->offGCGuestToHostAsmHyperCtx == offCode)
    1429                     RTLogPrintf(" *GCGuestToHostAsmHyperCtx:\n");
    1430                 if (pSwitcher->offGCGuestToHostAsmGuestCtx == offCode)
    1431                     RTLogPrintf(" *GCGuestToHostAsmGuestCtx:\n");
    1432 
    1433                 /* disas */
    1434                 uint32_t cbInstr = 0;
    1435                 char szDisas[256];
    1436                 if (RT_SUCCESS(DISInstr(&Cpu, (RTUINTPTR)pu8CodeR3 + offCode, uBase - (RTUINTPTR)pu8CodeR3, &cbInstr, szDisas)))
    1437                     RTLogPrintf("  %04x: %s", offCode, szDisas); //for whatever reason szDisas includes '\n'.
    1438                 else
    1439                 {
    1440                     RTLogPrintf("  %04x: %02x '%c'\n",
    1441                                 offCode, pu8CodeR3[offCode], isprint(pu8CodeR3[offCode]) ? pu8CodeR3[offCode] : ' ');
    1442                     cbInstr = 1;
    1443                 }
    1444                 offCode += cbInstr;
    1445                 cbCode -= RT_MIN(cbInstr, cbCode);
    1446             }
    1447         }
    1448     }
    1449 #endif
    1450 }
    1451 
    1452 
    1453 /**
    1454  * Relocator for the 32-Bit to 32-Bit world switcher.
    1455  */
    1456 DECLCALLBACK(void) vmmR3Switcher32BitTo32Bit_Relocate(PVM pVM, PVMMSWITCHERDEF pSwitcher, uint8_t *pu8CodeR0, uint8_t *pu8CodeR3, RTGCPTR GCPtrCode, uint32_t u32IDCode)
    1457 {
    1458     vmmR3SwitcherGenericRelocate(pVM, pSwitcher, pu8CodeR0, pu8CodeR3, GCPtrCode, u32IDCode,
    1459                                  SELMGetHyperCS(pVM), SELMGetHyperDS(pVM), SELMGetHyperTSS(pVM), SELMGetHyperGDT(pVM), 0);
    1460 }
    1461 
    1462 
    1463 /**
    1464  * Relocator for the 32-Bit to PAE world switcher.
    1465  */
    1466 DECLCALLBACK(void) vmmR3Switcher32BitToPAE_Relocate(PVM pVM, PVMMSWITCHERDEF pSwitcher, uint8_t *pu8CodeR0, uint8_t *pu8CodeR3, RTGCPTR GCPtrCode, uint32_t u32IDCode)
    1467 {
    1468     vmmR3SwitcherGenericRelocate(pVM, pSwitcher, pu8CodeR0, pu8CodeR3, GCPtrCode, u32IDCode,
    1469                                  SELMGetHyperCS(pVM), SELMGetHyperDS(pVM), SELMGetHyperTSS(pVM), SELMGetHyperGDT(pVM), 0);
    1470 }
    1471 
    1472 
    1473 /**
    1474  * Relocator for the PAE to 32-Bit world switcher.
    1475  */
    1476 DECLCALLBACK(void) vmmR3SwitcherPAETo32Bit_Relocate(PVM pVM, PVMMSWITCHERDEF pSwitcher, uint8_t *pu8CodeR0, uint8_t *pu8CodeR3, RTGCPTR GCPtrCode, uint32_t u32IDCode)
    1477 {
    1478     vmmR3SwitcherGenericRelocate(pVM, pSwitcher, pu8CodeR0, pu8CodeR3, GCPtrCode, u32IDCode,
    1479                                  SELMGetHyperCS(pVM), SELMGetHyperDS(pVM), SELMGetHyperTSS(pVM), SELMGetHyperGDT(pVM), 0);
    1480 }
    1481 
    1482 
    1483 /**
    1484  * Relocator for the PAE to PAE world switcher.
    1485  */
    1486 DECLCALLBACK(void) vmmR3SwitcherPAEToPAE_Relocate(PVM pVM, PVMMSWITCHERDEF pSwitcher, uint8_t *pu8CodeR0, uint8_t *pu8CodeR3, RTGCPTR GCPtrCode, uint32_t u32IDCode)
    1487 {
    1488     vmmR3SwitcherGenericRelocate(pVM, pSwitcher, pu8CodeR0, pu8CodeR3, GCPtrCode, u32IDCode,
    1489                                  SELMGetHyperCS(pVM), SELMGetHyperDS(pVM), SELMGetHyperTSS(pVM), SELMGetHyperGDT(pVM), 0);
    1490 }
    1491 
    1492 
    1493 /**
    1494  * Relocator for the AMD64 to PAE world switcher.
    1495  */
    1496 DECLCALLBACK(void) vmmR3SwitcherAMD64ToPAE_Relocate(PVM pVM, PVMMSWITCHERDEF pSwitcher, uint8_t *pu8CodeR0, uint8_t *pu8CodeR3, RTGCPTR GCPtrCode, uint32_t u32IDCode)
    1497 {
    1498     vmmR3SwitcherGenericRelocate(pVM, pSwitcher, pu8CodeR0, pu8CodeR3, GCPtrCode, u32IDCode,
    1499                                  SELMGetHyperCS(pVM), SELMGetHyperDS(pVM), SELMGetHyperTSS(pVM), SELMGetHyperGDT(pVM), SELMGetHyperCS64(pVM));
    1500 }
    1501 
    1502 
    1503 /**
    1504  * Gets the pointer to g_szRTAssertMsg1 in GC.
    1505  * @returns Pointer to VMMGC::g_szRTAssertMsg1.
    1506  *          Returns NULL if not present.
    1507  * @param   pVM         The VM handle.
    1508  */
    1509 VMMR3DECL(const char *) VMMR3GetGCAssertMsg1(PVM pVM)
    1510 {
    1511     RTGCPTR32 GCPtr;
    1512     int rc = PDMR3LdrGetSymbolRC(pVM, NULL, "g_szRTAssertMsg1", &GCPtr);
    1513     if (VBOX_SUCCESS(rc))
    1514         return (const char *)MMHyperGC2HC(pVM, GCPtr);
    1515     return NULL;
    1516 }
    1517 
    1518 
    1519 /**
    1520  * Gets the pointer to g_szRTAssertMsg2 in GC.
    1521  * @returns Pointer to VMMGC::g_szRTAssertMsg2.
    1522  *          Returns NULL if not present.
    1523  * @param   pVM         The VM handle.
    1524  */
    1525 VMMR3DECL(const char *) VMMR3GetGCAssertMsg2(PVM pVM)
    1526 {
    1527     RTGCPTR32 GCPtr;
    1528     int rc = PDMR3LdrGetSymbolRC(pVM, NULL, "g_szRTAssertMsg2", &GCPtr);
    1529     if (VBOX_SUCCESS(rc))
    1530         return (const char *)MMHyperGC2HC(pVM, GCPtr);
    1531     return NULL;
    1532 }
    1533 
    1534 
    1535 /**
    1536  * Execute state save operation.
    1537  *
    1538  * @returns VBox status code.
    1539  * @param   pVM             VM Handle.
    1540  * @param   pSSM            SSM operation handle.
    1541  */
    1542 static DECLCALLBACK(int) vmmR3Save(PVM pVM, PSSMHANDLE pSSM)
    1543 {
    1544     LogFlow(("vmmR3Save:\n"));
    1545 
    1546     /*
    1547      * The hypervisor stack.
    1548      */
    1549     SSMR3PutRCPtr(pSSM, pVM->vmm.s.pbGCStackBottom);
    1550     RTRCPTR GCPtrESP = CPUMGetHyperESP(pVM);
    1551     AssertMsg(pVM->vmm.s.pbGCStackBottom - GCPtrESP <= VMM_STACK_SIZE, ("Bottom %VGv ESP=%VGv\n", pVM->vmm.s.pbGCStackBottom, GCPtrESP));
    1552     SSMR3PutRCPtr(pSSM, GCPtrESP);
    1553     SSMR3PutMem(pSSM, pVM->vmm.s.pbHCStack, VMM_STACK_SIZE);
    1554     return SSMR3PutU32(pSSM, ~0); /* terminator */
    1555 }
    1556 
    1557 
    1558 /**
    1559  * Execute state load operation.
    1560  *
    1561  * @returns VBox status code.
    1562  * @param   pVM             VM Handle.
    1563  * @param   pSSM            SSM operation handle.
    1564  * @param   u32Version      Data layout version.
    1565  */
    1566 static DECLCALLBACK(int) vmmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version)
    1567 {
    1568     LogFlow(("vmmR3Load:\n"));
    1569 
    1570     /*
    1571      * Validate version.
    1572      */
    1573     if (u32Version != VMM_SAVED_STATE_VERSION)
    1574     {
    1575         AssertMsgFailed(("vmmR3Load: Invalid version u32Version=%d!\n", u32Version));
    1576         return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
    1577     }
    1578 
    1579     /*
    1580      * Check that the stack is in the same place, or that it's fearly empty.
    1581      */
    1582     RTRCPTR GCPtrStackBottom;
    1583     SSMR3GetRCPtr(pSSM, &GCPtrStackBottom);
    1584     RTRCPTR GCPtrESP;
    1585     int rc = SSMR3GetRCPtr(pSSM, &GCPtrESP);
    1586     if (VBOX_FAILURE(rc))
    1587         return rc;
    1588 
    1589     /* Previously we checked if the location of the stack was identical or that the stack was empty.
    1590      * This is not required as we can never initiate a save when GC context code performs a ring 3 call.
    1591      */
    1592     /* restore the stack. (not necessary; just consistency checking) */
    1593     SSMR3GetMem(pSSM, pVM->vmm.s.pbHCStack, VMM_STACK_SIZE);
    1594 
    1595     /* terminator */
    1596     uint32_t u32;
    1597     rc = SSMR3GetU32(pSSM, &u32);
    1598     if (VBOX_FAILURE(rc))
    1599         return rc;
    1600     if (u32 != ~0U)
    1601     {
    1602         AssertMsgFailed(("u32=%#x\n", u32));
    1603         return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
    1604     }
    1605     return VINF_SUCCESS;
    1606 }
    1607 
    1608 
    1609 /**
    1610  * Selects the switcher to be used for switching to GC.
    1611  *
    1612  * @returns VBox status code.
    1613  * @param   pVM             VM handle.
    1614  * @param   enmSwitcher     The new switcher.
    1615  * @remark  This function may be called before the VMM is initialized.
    1616  */
    1617 VMMR3DECL(int) VMMR3SelectSwitcher(PVM pVM, VMMSWITCHER enmSwitcher)
    1618 {
    1619     /*
    1620      * Validate input.
    1621      */
    1622     if (    enmSwitcher < VMMSWITCHER_INVALID
    1623         ||  enmSwitcher >= VMMSWITCHER_MAX)
    1624     {
    1625         AssertMsgFailed(("Invalid input enmSwitcher=%d\n", enmSwitcher));
    1626         return VERR_INVALID_PARAMETER;
    1627     }
    1628 
    1629     /* Do nothing if the switcher is disabled. */
    1630     if (pVM->vmm.s.fSwitcherDisabled)
    1631         return VINF_SUCCESS;
    1632 
    1633     /*
    1634      * Select the new switcher.
    1635      */
    1636     PVMMSWITCHERDEF pSwitcher = s_apSwitchers[enmSwitcher];
    1637     if (pSwitcher)
    1638     {
    1639         Log(("VMMR3SelectSwitcher: enmSwitcher %d -> %d %s\n", pVM->vmm.s.enmSwitcher, enmSwitcher, pSwitcher->pszDesc));
    1640         pVM->vmm.s.enmSwitcher = enmSwitcher;
    1641 
    1642         RTR0PTR     pbCodeR0 = (RTR0PTR)pVM->vmm.s.pvHCCoreCodeR0 + pVM->vmm.s.aoffSwitchers[enmSwitcher]; /** @todo fix the pvHCCoreCodeR0 type */
    1643         pVM->vmm.s.pfnR0HostToGuest = pbCodeR0 + pSwitcher->offR0HostToGuest;
    1644 
    1645         RTGCPTR     GCPtr = pVM->vmm.s.pvGCCoreCode + pVM->vmm.s.aoffSwitchers[enmSwitcher];
    1646         pVM->vmm.s.pfnGCGuestToHost         = GCPtr + pSwitcher->offGCGuestToHost;
    1647         pVM->vmm.s.pfnGCCallTrampoline      = GCPtr + pSwitcher->offGCCallTrampoline;
    1648         pVM->pfnVMMGCGuestToHostAsm         = GCPtr + pSwitcher->offGCGuestToHostAsm;
    1649         pVM->pfnVMMGCGuestToHostAsmHyperCtx = GCPtr + pSwitcher->offGCGuestToHostAsmHyperCtx;
    1650         pVM->pfnVMMGCGuestToHostAsmGuestCtx = GCPtr + pSwitcher->offGCGuestToHostAsmGuestCtx;
    1651         return VINF_SUCCESS;
    1652     }
    1653     return VERR_NOT_IMPLEMENTED;
    1654 }
    1655 
    1656 /**
    1657  * Disable the switcher logic permanently.
    1658  *
    1659  * @returns VBox status code.
    1660  * @param   pVM             VM handle.
    1661  */
    1662 VMMR3DECL(int) VMMR3DisableSwitcher(PVM pVM)
    1663 {
    1664 /** @todo r=bird: I would suggest that we create a dummy switcher which just does something like:
    1665  * @code
    1666  *       mov eax, VERR_INTERNAL_ERROR
    1667  *       ret
    1668  * @endcode
    1669  * And then check for fSwitcherDisabled in VMMR3SelectSwitcher() in order to prevent it from being removed.
    1670  */
    1671     pVM->vmm.s.fSwitcherDisabled = true;
    1672     return VINF_SUCCESS;
    1673 }
    1674 
    1675 
    1676 /**
    1677  * Resolve a builtin GC symbol.
    1678  * Called by PDM when loading or relocating GC modules.
    1679  *
    1680  * @returns VBox status
    1681  * @param   pVM         VM Handle.
    1682  * @param   pszSymbol   Symbol to resolv
    1683  * @param   pGCPtrValue Where to store the symbol value.
    1684  * @remark  This has to work before VMMR3Relocate() is called.
    1685  */
    1686 VMMR3DECL(int) VMMR3GetImportGC(PVM pVM, const char *pszSymbol, PRTGCPTR pGCPtrValue)
    1687 {
    1688     if (!strcmp(pszSymbol, "g_Logger"))
    1689     {
    1690         if (pVM->vmm.s.pLoggerHC)
    1691             pVM->vmm.s.pLoggerGC = MMHyperHC2GC(pVM, pVM->vmm.s.pLoggerHC);
    1692         *pGCPtrValue = pVM->vmm.s.pLoggerGC;
    1693     }
    1694     else if (!strcmp(pszSymbol, "g_RelLogger"))
    1695     {
    1696 #ifdef VBOX_WITH_RC_RELEASE_LOGGING
    1697         if (pVM->vmm.s.pRelLoggerHC)
    1698             pVM->vmm.s.pRelLoggerGC = MMHyperHC2GC(pVM, pVM->vmm.s.pRelLoggerHC);
    1699         *pGCPtrValue = pVM->vmm.s.pRelLoggerGC;
    1700 #else
    1701         *pGCPtrValue = NIL_RTGCPTR;
    1702 #endif
    1703     }
    1704     else
    1705         return VERR_SYMBOL_NOT_FOUND;
    1706     return VINF_SUCCESS;
    1707 }
    1708 
    1709 
    1710 /**
    1711  * Suspends the the CPU yielder.
    1712  *
    1713  * @param   pVM             The VM handle.
    1714  */
    1715 VMMR3DECL(void) VMMR3YieldSuspend(PVM pVM)
    1716 {
    1717     if (!pVM->vmm.s.cYieldResumeMillies)
    1718     {
    1719         uint64_t u64Now = TMTimerGet(pVM->vmm.s.pYieldTimer);
    1720         uint64_t u64Expire = TMTimerGetExpire(pVM->vmm.s.pYieldTimer);
    1721         if (u64Now >= u64Expire || u64Expire == ~(uint64_t)0)
    1722             pVM->vmm.s.cYieldResumeMillies = pVM->vmm.s.cYieldEveryMillies;
    1723         else
    1724             pVM->vmm.s.cYieldResumeMillies = TMTimerToMilli(pVM->vmm.s.pYieldTimer, u64Expire - u64Now);
    1725         TMTimerStop(pVM->vmm.s.pYieldTimer);
    1726     }
    1727     pVM->vmm.s.u64LastYield = RTTimeNanoTS();
    1728 }
    1729 
    1730 
    1731 /**
    1732  * Stops the the CPU yielder.
    1733  *
    1734  * @param   pVM             The VM handle.
    1735  */
    1736 VMMR3DECL(void) VMMR3YieldStop(PVM pVM)
    1737 {
    1738     if (!pVM->vmm.s.cYieldResumeMillies)
    1739         TMTimerStop(pVM->vmm.s.pYieldTimer);
    1740     pVM->vmm.s.cYieldResumeMillies = pVM->vmm.s.cYieldEveryMillies;
    1741     pVM->vmm.s.u64LastYield = RTTimeNanoTS();
    1742 }
    1743 
    1744 
    1745 /**
    1746  * Resumes the CPU yielder when it has been a suspended or stopped.
    1747  *
    1748  * @param   pVM             The VM handle.
    1749  */
    1750 VMMR3DECL(void) VMMR3YieldResume(PVM pVM)
    1751 {
    1752     if (pVM->vmm.s.cYieldResumeMillies)
    1753     {
    1754         TMTimerSetMillies(pVM->vmm.s.pYieldTimer, pVM->vmm.s.cYieldResumeMillies);
    1755         pVM->vmm.s.cYieldResumeMillies = 0;
    1756     }
    1757 }
    1758 
    1759 
    1760 /**
    1761  * Internal timer callback function.
    1762  *
    1763  * @param   pVM             The VM.
    1764  * @param   pTimer          The timer handle.
    1765  * @param   pvUser          User argument specified upon timer creation.
    1766  */
    1767 static DECLCALLBACK(void) vmmR3YieldEMT(PVM pVM, PTMTIMER pTimer, void *pvUser)
    1768 {
    1769     /*
    1770      * This really needs some careful tuning. While we shouldn't be too gready since
    1771      * that'll cause the rest of the system to stop up, we shouldn't be too nice either
    1772      * because that'll cause us to stop up.
    1773      *
    1774      * The current logic is to use the default interval when there is no lag worth
    1775      * mentioning, but when we start accumulating lag we don't bother yielding at all.
    1776      *
    1777      * (This depends on the TMCLOCK_VIRTUAL_SYNC to be scheduled before TMCLOCK_REAL
    1778      * so the lag is up to date.)
    1779      */
    1780     const uint64_t u64Lag = TMVirtualSyncGetLag(pVM);
    1781     if (    u64Lag     <   50000000 /* 50ms */
    1782         ||  (   u64Lag < 1000000000 /*  1s */
    1783              && RTTimeNanoTS() - pVM->vmm.s.u64LastYield < 500000000 /* 500 ms */)
    1784        )
    1785     {
    1786         uint64_t u64Elapsed = RTTimeNanoTS();
    1787         pVM->vmm.s.u64LastYield = u64Elapsed;
    1788 
    1789         RTThreadYield();
    1790 
    1791 #ifdef LOG_ENABLED
    1792         u64Elapsed = RTTimeNanoTS() - u64Elapsed;
    1793         Log(("vmmR3YieldEMT: %RI64 ns\n", u64Elapsed));
    1794 #endif
    1795     }
    1796     TMTimerSetMillies(pTimer, pVM->vmm.s.cYieldEveryMillies);
    1797 }
    1798 
    1799 
    1800 /**
    1801  * Acquire global VM lock.
    1802  *
    1803  * @returns VBox status code
    1804  * @param   pVM         The VM to operate on.
    1805  */
    1806 VMMR3DECL(int) VMMR3Lock(PVM pVM)
    1807 {
    1808     return RTCritSectEnter(&pVM->vmm.s.CritSectVMLock);
    1809 }
    1810 
    1811 
    1812 /**
    1813  * Release global VM lock.
    1814  *
    1815  * @returns VBox status code
    1816  * @param   pVM         The VM to operate on.
    1817  */
    1818 VMMR3DECL(int) VMMR3Unlock(PVM pVM)
    1819 {
    1820     return RTCritSectLeave(&pVM->vmm.s.CritSectVMLock);
    1821 }
    1822 
    1823 
    1824 /**
    1825  * Return global VM lock owner.
    1826  *
    1827  * @returns Thread id of owner.
    1828  * @returns NIL_RTTHREAD if no owner.
    1829  * @param   pVM         The VM to operate on.
    1830  */
    1831 VMMR3DECL(RTNATIVETHREAD) VMMR3LockGetOwner(PVM pVM)
    1832 {
    1833     return RTCritSectGetOwner(&pVM->vmm.s.CritSectVMLock);
    1834 }
    1835 
    1836 
    1837 /**
    1838  * Checks if the current thread is the owner of the global VM lock.
    1839  *
    1840  * @returns true if owner.
    1841  * @returns false if not owner.
    1842  * @param   pVM         The VM to operate on.
    1843  */
    1844 VMMR3DECL(bool) VMMR3LockIsOwner(PVM pVM)
    1845 {
    1846     return RTCritSectIsOwner(&pVM->vmm.s.CritSectVMLock);
    1847 }
    1848 
    1849 
    1850 /**
    1851  * Executes guest code.
    1852  *
    1853  * @param   pVM         VM handle.
    1854  */
    1855 VMMR3DECL(int) VMMR3RawRunGC(PVM pVM)
    1856 {
    1857     Log2(("VMMR3RawRunGC: (cs:eip=%04x:%08x)\n", CPUMGetGuestCS(pVM), CPUMGetGuestEIP(pVM)));
    1858 
    1859     /*
    1860      * Set the EIP and ESP.
    1861      */
    1862     CPUMSetHyperEIP(pVM, CPUMGetGuestEFlags(pVM) & X86_EFL_VM
    1863                     ? pVM->vmm.s.pfnCPUMGCResumeGuestV86
    1864                     : pVM->vmm.s.pfnCPUMGCResumeGuest);
    1865     CPUMSetHyperESP(pVM, pVM->vmm.s.pbGCStackBottom);
    1866 
    1867     /*
    1868      * We hide log flushes (outer) and hypervisor interrupts (inner).
    1869      */
    1870     for (;;)
    1871     {
    1872         int rc;
    1873         do
    1874         {
    1875 #ifdef NO_SUPCALLR0VMM
    1876             rc = VERR_GENERAL_FAILURE;
    1877 #else
    1878             rc = SUPCallVMMR0Fast(pVM->pVMR0, VMMR0_DO_RAW_RUN);
    1879             if (RT_LIKELY(rc == VINF_SUCCESS))
    1880                 rc = pVM->vmm.s.iLastGCRc;
    1881 #endif
    1882         } while (rc == VINF_EM_RAW_INTERRUPT_HYPER);
    1883 
    1884         /*
    1885          * Flush the logs.
    1886          */
    1887 #ifdef LOG_ENABLED
    1888         PRTLOGGERRC pLogger = pVM->vmm.s.pLoggerHC;
    1889         if (    pLogger
    1890             &&  pLogger->offScratch > 0)
    1891             RTLogFlushGC(NULL, pLogger);
    1892 #endif
    1893 #ifdef VBOX_WITH_RC_RELEASE_LOGGING
    1894         PRTLOGGERRC pRelLogger = pVM->vmm.s.pRelLoggerHC;
    1895         if (RT_UNLIKELY(pRelLogger && pRelLogger->offScratch > 0))
    1896             RTLogFlushGC(RTLogRelDefaultInstance(), pRelLogger);
    1897 #endif
    1898         if (rc != VINF_VMM_CALL_HOST)
    1899         {
    1900             Log2(("VMMR3RawRunGC: returns %Vrc (cs:eip=%04x:%08x)\n", rc, CPUMGetGuestCS(pVM), CPUMGetGuestEIP(pVM)));
    1901             return rc;
    1902         }
    1903         rc = vmmR3ServiceCallHostRequest(pVM);
    1904         if (VBOX_FAILURE(rc))
    1905             return rc;
    1906         /* Resume GC */
    1907     }
    1908 }
    1909 
    1910 
    1911 /**
    1912  * Executes guest code (Intel VT-x and AMD-V).
    1913  *
    1914  * @param   pVM         VM handle.
    1915  */
    1916 VMMR3DECL(int) VMMR3HwAccRunGC(PVM pVM)
    1917 {
    1918     Log2(("VMMR3HwAccRunGC: (cs:eip=%04x:%08x)\n", CPUMGetGuestCS(pVM), CPUMGetGuestEIP(pVM)));
    1919 
    1920     for (;;)
    1921     {
    1922         int rc;
    1923         do
    1924         {
    1925 #ifdef NO_SUPCALLR0VMM
    1926             rc = VERR_GENERAL_FAILURE;
    1927 #else
    1928             rc = SUPCallVMMR0Fast(pVM->pVMR0, VMMR0_DO_HWACC_RUN);
    1929             if (RT_LIKELY(rc == VINF_SUCCESS))
    1930                 rc = pVM->vmm.s.iLastGCRc;
    1931 #endif
    1932         } while (rc == VINF_EM_RAW_INTERRUPT_HYPER);
    1933 
    1934 #ifdef LOG_ENABLED
    1935         /*
    1936          * Flush the log
    1937          */
    1938         PVMMR0LOGGER pR0Logger = pVM->vmm.s.pR0Logger;
    1939         if (    pR0Logger
    1940             &&  pR0Logger->Logger.offScratch > 0)
    1941             RTLogFlushToLogger(&pR0Logger->Logger, NULL);
    1942 #endif /* !LOG_ENABLED */
    1943         if (rc != VINF_VMM_CALL_HOST)
    1944         {
    1945             Log2(("VMMR3HwAccRunGC: returns %Vrc (cs:eip=%04x:%08x)\n", rc, CPUMGetGuestCS(pVM), CPUMGetGuestEIP(pVM)));
    1946             return rc;
    1947         }
    1948         rc = vmmR3ServiceCallHostRequest(pVM);
    1949         if (VBOX_FAILURE(rc) || rc == VINF_EM_DBG_HYPER_ASSERTION)
    1950             return rc;
    1951         /* Resume R0 */
    1952     }
    1953 }
    1954 
    1955 /**
    1956  * Calls GC a function.
    1957  *
    1958  * @param   pVM         The VM handle.
    1959  * @param   GCPtrEntry  The GC function address.
    1960  * @param   cArgs       The number of arguments in the ....
    1961  * @param   ...         Arguments to the function.
    1962  */
    1963 VMMR3DECL(int) VMMR3CallGC(PVM pVM, RTRCPTR GCPtrEntry, unsigned cArgs, ...)
    1964 {
    1965     va_list args;
    1966     va_start(args, cArgs);
    1967     int rc = VMMR3CallGCV(pVM, GCPtrEntry, cArgs, args);
    1968     va_end(args);
    1969     return rc;
    1970 }
    1971 
    1972 
    1973 /**
    1974  * Calls GC a function.
    1975  *
    1976  * @param   pVM         The VM handle.
    1977  * @param   GCPtrEntry  The GC function address.
    1978  * @param   cArgs       The number of arguments in the ....
    1979  * @param   args        Arguments to the function.
    1980  */
    1981 VMMR3DECL(int) VMMR3CallGCV(PVM pVM, RTRCPTR GCPtrEntry, unsigned cArgs, va_list args)
    1982 {
    1983     Log2(("VMMR3CallGCV: GCPtrEntry=%VRv cArgs=%d\n", GCPtrEntry, cArgs));
    1984 
    1985     /*
    1986      * Setup the call frame using the trampoline.
    1987      */
    1988     CPUMHyperSetCtxCore(pVM, NULL);
    1989     memset(pVM->vmm.s.pbHCStack, 0xaa, VMM_STACK_SIZE); /* Clear the stack. */
    1990     CPUMSetHyperESP(pVM, pVM->vmm.s.pbGCStackBottom - cArgs * sizeof(RTGCUINTPTR32));
    1991     PRTGCUINTPTR32 pFrame = (PRTGCUINTPTR32)(pVM->vmm.s.pbHCStack + VMM_STACK_SIZE) - cArgs;
    1992     int i = cArgs;
    1993     while (i-- > 0)
    1994         *pFrame++ = va_arg(args, RTGCUINTPTR32);
    1995 
    1996     CPUMPushHyper(pVM, cArgs * sizeof(RTGCUINTPTR32));                          /* stack frame size */
    1997     CPUMPushHyper(pVM, GCPtrEntry);                                             /* what to call */
    1998     CPUMSetHyperEIP(pVM, pVM->vmm.s.pfnGCCallTrampoline);
    1999 
    2000     /*
    2001      * We hide log flushes (outer) and hypervisor interrupts (inner).
    2002      */
    2003     for (;;)
    2004     {
    2005         int rc;
    2006         do
    2007         {
    2008 #ifdef NO_SUPCALLR0VMM
    2009             rc = VERR_GENERAL_FAILURE;
    2010 #else
    2011             rc = SUPCallVMMR0Fast(pVM->pVMR0, VMMR0_DO_RAW_RUN);
    2012             if (RT_LIKELY(rc == VINF_SUCCESS))
    2013                 rc = pVM->vmm.s.iLastGCRc;
    2014 #endif
    2015         } while (rc == VINF_EM_RAW_INTERRUPT_HYPER);
    2016 
    2017         /*
    2018          * Flush the logs.
    2019          */
    2020 #ifdef LOG_ENABLED
    2021         PRTLOGGERRC pLogger = pVM->vmm.s.pLoggerHC;
    2022         if (    pLogger
    2023             &&  pLogger->offScratch > 0)
    2024             RTLogFlushGC(NULL, pLogger);
    2025 #endif
    2026 #ifdef VBOX_WITH_RC_RELEASE_LOGGING
    2027         PRTLOGGERRC pRelLogger = pVM->vmm.s.pRelLoggerHC;
    2028         if (RT_UNLIKELY(pRelLogger && pRelLogger->offScratch > 0))
    2029             RTLogFlushGC(RTLogRelDefaultInstance(), pRelLogger);
    2030 #endif
    2031         if (rc == VERR_TRPM_PANIC || rc == VERR_TRPM_DONT_PANIC)
    2032             VMMR3FatalDump(pVM, rc);
    2033         if (rc != VINF_VMM_CALL_HOST)
    2034         {
    2035             Log2(("VMMR3CallGCV: returns %Vrc (cs:eip=%04x:%08x)\n", rc, CPUMGetGuestCS(pVM), CPUMGetGuestEIP(pVM)));
    2036             return rc;
    2037         }
    2038         rc = vmmR3ServiceCallHostRequest(pVM);
    2039         if (VBOX_FAILURE(rc))
    2040             return rc;
    2041     }
    2042 }
    2043 
    2044 
    2045 /**
    2046  * Resumes executing hypervisor code when interrupted
    2047  * by a queue flush or a debug event.
    2048  *
    2049  * @returns VBox status code.
    2050  * @param   pVM         VM handle.
    2051  */
    2052 VMMR3DECL(int) VMMR3ResumeHyper(PVM pVM)
    2053 {
    2054     Log(("VMMR3ResumeHyper: eip=%VGv esp=%VGv\n", CPUMGetHyperEIP(pVM), CPUMGetHyperESP(pVM)));
    2055 
    2056     /*
    2057      * We hide log flushes (outer) and hypervisor interrupts (inner).
    2058      */
    2059     for (;;)
    2060     {
    2061         int rc;
    2062         do
    2063         {
    2064 #ifdef NO_SUPCALLR0VMM
    2065             rc = VERR_GENERAL_FAILURE;
    2066 #else
    2067             rc = SUPCallVMMR0Fast(pVM->pVMR0, VMMR0_DO_RAW_RUN);
    2068             if (RT_LIKELY(rc == VINF_SUCCESS))
    2069                 rc = pVM->vmm.s.iLastGCRc;
    2070 #endif
    2071         } while (rc == VINF_EM_RAW_INTERRUPT_HYPER);
    2072 
    2073         /*
    2074          * Flush the loggers,
    2075          */
    2076 #ifdef LOG_ENABLED
    2077         PRTLOGGERRC pLogger = pVM->vmm.s.pLoggerHC;
    2078         if (    pLogger
    2079             &&  pLogger->offScratch > 0)
    2080             RTLogFlushGC(NULL, pLogger);
    2081 #endif
    2082 #ifdef VBOX_WITH_RC_RELEASE_LOGGING
    2083         PRTLOGGERRC pRelLogger = pVM->vmm.s.pRelLoggerHC;
    2084         if (RT_UNLIKELY(pRelLogger && pRelLogger->offScratch > 0))
    2085             RTLogFlushGC(RTLogRelDefaultInstance(), pRelLogger);
    2086 #endif
    2087         if (rc == VERR_TRPM_PANIC || rc == VERR_TRPM_DONT_PANIC)
    2088             VMMR3FatalDump(pVM, rc);
    2089         if (rc != VINF_VMM_CALL_HOST)
    2090         {
    2091             Log(("VMMR3ResumeHyper: returns %Vrc\n", rc));
    2092             return rc;
    2093         }
    2094         rc = vmmR3ServiceCallHostRequest(pVM);
    2095         if (VBOX_FAILURE(rc))
    2096             return rc;
    2097     }
    2098 }
    2099 
    2100 
    2101 /**
    2102  * Service a call to the ring-3 host code.
    2103  *
    2104  * @returns VBox status code.
    2105  * @param   pVM     VM handle.
    2106  * @remark  Careful with critsects.
    2107  */
    2108 static int vmmR3ServiceCallHostRequest(PVM pVM)
    2109 {
    2110     switch (pVM->vmm.s.enmCallHostOperation)
    2111     {
    2112         /*
    2113          * Acquire the PDM lock.
    2114          */
    2115         case VMMCALLHOST_PDM_LOCK:
    2116         {
    2117             pVM->vmm.s.rcCallHost = PDMR3LockCall(pVM);
    2118             break;
    2119         }
    2120 
    2121         /*
    2122          * Flush a PDM queue.
    2123          */
    2124         case VMMCALLHOST_PDM_QUEUE_FLUSH:
    2125         {
    2126             PDMR3QueueFlushWorker(pVM, NULL);
    2127             pVM->vmm.s.rcCallHost = VINF_SUCCESS;
    2128             break;
    2129         }
    2130 
    2131         /*
    2132          * Grow the PGM pool.
    2133          */
    2134         case VMMCALLHOST_PGM_POOL_GROW:
    2135         {
    2136             pVM->vmm.s.rcCallHost = PGMR3PoolGrow(pVM);
    2137             break;
    2138         }
    2139 
    2140         /*
    2141          * Maps an page allocation chunk into ring-3 so ring-0 can use it.
    2142          */
    2143         case VMMCALLHOST_PGM_MAP_CHUNK:
    2144         {
    2145             pVM->vmm.s.rcCallHost = PGMR3PhysChunkMap(pVM, pVM->vmm.s.u64CallHostArg);
    2146             break;
    2147         }
    2148 
    2149         /*
    2150          * Allocates more handy pages.
    2151          */
    2152         case VMMCALLHOST_PGM_ALLOCATE_HANDY_PAGES:
    2153         {
    2154             pVM->vmm.s.rcCallHost = PGMR3PhysAllocateHandyPages(pVM);
    2155             break;
    2156         }
    2157 #ifndef VBOX_WITH_NEW_PHYS_CODE
    2158 
    2159         case VMMCALLHOST_PGM_RAM_GROW_RANGE:
    2160         {
    2161             const RTGCPHYS GCPhys = pVM->vmm.s.u64CallHostArg;
    2162             pVM->vmm.s.rcCallHost = PGM3PhysGrowRange(pVM, &GCPhys);
    2163             break;
    2164         }
    2165 #endif
    2166 
    2167         /*
    2168          * Acquire the PGM lock.
    2169          */
    2170         case VMMCALLHOST_PGM_LOCK:
    2171         {
    2172             pVM->vmm.s.rcCallHost = PGMR3LockCall(pVM);
    2173             break;
    2174         }
    2175 
    2176         /*
    2177          * Flush REM handler notifications.
    2178          */
    2179         case VMMCALLHOST_REM_REPLAY_HANDLER_NOTIFICATIONS:
    2180         {
    2181             REMR3ReplayHandlerNotifications(pVM);
    2182             break;
    2183         }
    2184 
    2185         /*
    2186          * This is a noop. We just take this route to avoid unnecessary
    2187          * tests in the loops.
    2188          */
    2189         case VMMCALLHOST_VMM_LOGGER_FLUSH:
    2190             break;
    2191 
    2192         /*
    2193          * Set the VM error message.
    2194          */
    2195         case VMMCALLHOST_VM_SET_ERROR:
    2196             VMR3SetErrorWorker(pVM);
    2197             break;
    2198 
    2199         /*
    2200          * Set the VM runtime error message.
    2201          */
    2202         case VMMCALLHOST_VM_SET_RUNTIME_ERROR:
    2203             VMR3SetRuntimeErrorWorker(pVM);
    2204             break;
    2205 
    2206         /*
    2207          * Signal a ring 0 hypervisor assertion.
    2208          * Cancel the longjmp operation that's in progress.
    2209          */
    2210         case VMMCALLHOST_VM_R0_HYPER_ASSERTION:
    2211             pVM->vmm.s.enmCallHostOperation = VMMCALLHOST_INVALID;
    2212             pVM->vmm.s.CallHostR0JmpBuf.fInRing3Call = false;
    2213 #ifdef RT_ARCH_X86
    2214             pVM->vmm.s.CallHostR0JmpBuf.eip = 0;
    2215 #else
    2216             pVM->vmm.s.CallHostR0JmpBuf.rip = 0;
    2217 #endif
    2218             LogRel((pVM->vmm.s.szRing0AssertMsg1));
    2219             LogRel((pVM->vmm.s.szRing0AssertMsg2));
    2220             return VINF_EM_DBG_HYPER_ASSERTION;
    2221 
    2222         default:
    2223             AssertMsgFailed(("enmCallHostOperation=%d\n", pVM->vmm.s.enmCallHostOperation));
    2224             return VERR_INTERNAL_ERROR;
    2225     }
    2226 
    2227     pVM->vmm.s.enmCallHostOperation = VMMCALLHOST_INVALID;
    2228     return VINF_SUCCESS;
    2229 }
    2230 
    2231 
    2232 
    223347/**
    223448 * Structure to pass to DBGFR3Info() and for doing all other
     
    225266    bool        fStdErr;
    225367} VMMR3FATALDUMPINFOHLP, *PVMMR3FATALDUMPINFOHLP;
     68/** Pointer to a VMMR3FATALDUMPINFOHLP structure. */
    225469typedef const VMMR3FATALDUMPINFOHLP *PCVMMR3FATALDUMPINFOHLP;
    225570
     
    2569384                                "!!\n"
    2570385                                "%.*Vhxd\n",
    2571                                 VMM_STACK_SIZE, (char *)pVM->vmm.s.pbHCStack);
     386                                VMM_STACK_SIZE, pVM->vmm.s.pbEMTStackR3);
    2572387            } /* !HWACCMR3IsActive */
    2573388            break;
     
    2634449}
    2635450
    2636 
    2637 
    2638 /**
    2639  * Displays the Force action Flags.
    2640  *
    2641  * @param   pVM         The VM handle.
    2642  * @param   pHlp        The output helpers.
    2643  * @param   pszArgs     The additional arguments (ignored).
    2644  */
    2645 static DECLCALLBACK(void) vmmR3InfoFF(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
    2646 {
    2647     const uint32_t fForcedActions = pVM->fForcedActions;
    2648 
    2649     pHlp->pfnPrintf(pHlp, "Forced action Flags: %#RX32", fForcedActions);
    2650 
    2651     /* show the flag mnemonics  */
    2652     int c = 0;
    2653     uint32_t f = fForcedActions;
    2654 #define PRINT_FLAG(flag) do { \
    2655         if (f & (flag)) \
    2656         { \
    2657             static const char *s_psz = #flag; \
    2658             if (!(c % 6)) \
    2659                 pHlp->pfnPrintf(pHlp, "%s\n    %s", c ? "," : "", s_psz + 6); \
    2660             else \
    2661                 pHlp->pfnPrintf(pHlp, ", %s", s_psz + 6); \
    2662             c++; \
    2663             f &= ~(flag); \
    2664         } \
    2665     } while (0)
    2666     PRINT_FLAG(VM_FF_INTERRUPT_APIC);
    2667     PRINT_FLAG(VM_FF_INTERRUPT_PIC);
    2668     PRINT_FLAG(VM_FF_TIMER);
    2669     PRINT_FLAG(VM_FF_PDM_QUEUES);
    2670     PRINT_FLAG(VM_FF_PDM_DMA);
    2671     PRINT_FLAG(VM_FF_PDM_CRITSECT);
    2672     PRINT_FLAG(VM_FF_DBGF);
    2673     PRINT_FLAG(VM_FF_REQUEST);
    2674     PRINT_FLAG(VM_FF_TERMINATE);
    2675     PRINT_FLAG(VM_FF_RESET);
    2676     PRINT_FLAG(VM_FF_PGM_SYNC_CR3);
    2677     PRINT_FLAG(VM_FF_PGM_SYNC_CR3_NON_GLOBAL);
    2678     PRINT_FLAG(VM_FF_TRPM_SYNC_IDT);
    2679     PRINT_FLAG(VM_FF_SELM_SYNC_TSS);
    2680     PRINT_FLAG(VM_FF_SELM_SYNC_GDT);
    2681     PRINT_FLAG(VM_FF_SELM_SYNC_LDT);
    2682     PRINT_FLAG(VM_FF_INHIBIT_INTERRUPTS);
    2683     PRINT_FLAG(VM_FF_CSAM_SCAN_PAGE);
    2684     PRINT_FLAG(VM_FF_CSAM_PENDING_ACTION);
    2685     PRINT_FLAG(VM_FF_TO_R3);
    2686     PRINT_FLAG(VM_FF_DEBUG_SUSPEND);
    2687     if (f)
    2688         pHlp->pfnPrintf(pHlp, "%s\n    Unknown bits: %#RX32\n", c ? "," : "", f);
    2689     else
    2690         pHlp->pfnPrintf(pHlp, "\n");
    2691 #undef PRINT_FLAG
    2692 
    2693     /* the groups */
    2694     c = 0;
    2695 #define PRINT_GROUP(grp) do { \
    2696         if (fForcedActions & (grp)) \
    2697         { \
    2698             static const char *s_psz = #grp; \
    2699             if (!(c % 5)) \
    2700                 pHlp->pfnPrintf(pHlp, "%s    %s", c ? ",\n" : "Groups:\n", s_psz + 6); \
    2701             else \
    2702                 pHlp->pfnPrintf(pHlp, ", %s", s_psz + 6); \
    2703             c++; \
    2704         } \
    2705     } while (0)
    2706     PRINT_GROUP(VM_FF_EXTERNAL_SUSPENDED_MASK);
    2707     PRINT_GROUP(VM_FF_EXTERNAL_HALTED_MASK);
    2708     PRINT_GROUP(VM_FF_HIGH_PRIORITY_PRE_MASK);
    2709     PRINT_GROUP(VM_FF_HIGH_PRIORITY_PRE_RAW_MASK);
    2710     PRINT_GROUP(VM_FF_HIGH_PRIORITY_POST_MASK);
    2711     PRINT_GROUP(VM_FF_NORMAL_PRIORITY_POST_MASK);
    2712     PRINT_GROUP(VM_FF_NORMAL_PRIORITY_MASK);
    2713     PRINT_GROUP(VM_FF_RESUME_GUEST_MASK);
    2714     PRINT_GROUP(VM_FF_ALL_BUT_RAW_MASK);
    2715     if (c)
    2716         pHlp->pfnPrintf(pHlp, "\n");
    2717 #undef PRINT_GROUP
    2718 }
    2719 
  • trunk/src/VBox/VMM/VMMInternal.h

    r13697 r13698  
    206206#endif
    207207
    208     /** VMM stack, pointer to the top of the stack in HC.
     208    /** VMM stack, pointer to the top of the stack in R3.
    209209     * Stack is allocated from the hypervisor heap and is page aligned
    210      * and always writable in GC. */
    211     R3PTRTYPE(uint8_t *)        pbHCStack;
     210     * and always writable in RC. */
     211    R3PTRTYPE(uint8_t *)        pbEMTStackR3;
    212212    /** Pointer to the bottom of the stack - needed for doing relocations. */
    213     RCPTRTYPE(uint8_t *)        pbGCStack;
     213    RCPTRTYPE(uint8_t *)        pbEMTStackRC;
    214214    /** Pointer to the bottom of the stack - needed for doing relocations. */
    215     RCPTRTYPE(uint8_t *)        pbGCStackBottom;
     215    RCPTRTYPE(uint8_t *)        pbEMTStackBottomRC;
    216216
    217217    /** Pointer to the GC logger instance - GC Ptr.
  • trunk/src/VBox/VMM/VMMTests.cpp

    r13532 r13698  
    6262
    6363    CPUMHyperSetCtxCore(pVM, NULL);
    64     memset(pVM->vmm.s.pbHCStack, 0xaa, VMM_STACK_SIZE);
    65     CPUMSetHyperESP(pVM, pVM->vmm.s.pbGCStackBottom); /* Clear the stack. */
     64    memset(pVM->vmm.s.pbEMTStackR3, 0xaa, VMM_STACK_SIZE);
     65    CPUMSetHyperESP(pVM, pVM->vmm.s.pbEMTStackBottomRC); /* Clear the stack. */
    6666    CPUMPushHyper(pVM, uVariation);
    6767    CPUMPushHyper(pVM, enmTestcase);
     
    9999
    100100    CPUMHyperSetCtxCore(pVM, NULL);
    101     memset(pVM->vmm.s.pbHCStack, 0xaa, VMM_STACK_SIZE);
    102     CPUMSetHyperESP(pVM, pVM->vmm.s.pbGCStackBottom); /* Clear the stack. */
     101    memset(pVM->vmm.s.pbEMTStackR3, 0xaa, VMM_STACK_SIZE);
     102    CPUMSetHyperESP(pVM, pVM->vmm.s.pbEMTStackBottomRC); /* Clear the stack. */
    103103    CPUMPushHyper(pVM, uVariation);
    104104    CPUMPushHyper(pVM, u8Trap + VMMGC_DO_TESTCASE_TRAP_FIRST);
     
    334334         */
    335335        CPUMHyperSetCtxCore(pVM, NULL);
    336         CPUMSetHyperESP(pVM, pVM->vmm.s.pbGCStackBottom); /* Clear the stack. */
     336        CPUMSetHyperESP(pVM, pVM->vmm.s.pbEMTStackBottomRC); /* Clear the stack. */
    337337        CPUMPushHyper(pVM, 0);
    338338        CPUMPushHyper(pVM, VMMGC_DO_TESTCASE_HYPER_INTERRUPT);
     
    396396        {
    397397            CPUMHyperSetCtxCore(pVM, NULL);
    398             CPUMSetHyperESP(pVM, pVM->vmm.s.pbGCStackBottom); /* Clear the stack. */
     398            CPUMSetHyperESP(pVM, pVM->vmm.s.pbEMTStackBottomRC); /* Clear the stack. */
    399399            CPUMPushHyper(pVM, 0);
    400400            CPUMPushHyper(pVM, VMMGC_DO_TESTCASE_NOP);
     
    523523            CPUMHyperSetCtxCore(pVM, NULL);
    524524
    525             CPUMSetHyperESP(pVM, pVM->vmm.s.pbGCStackBottom); /* Clear the stack. */
     525            CPUMSetHyperESP(pVM, pVM->vmm.s.pbEMTStackBottomRC); /* Clear the stack. */
    526526            CPUMPushHyper(pVM, 0);
    527527            CPUMPushHyper(pVM, VMMGC_DO_TESTCASE_HWACCM_NOP);
  • trunk/src/VBox/VMM/testcase/tstVMStructGC.cpp

    r13633 r13698  
    838838    GEN_CHECK_OFF(VMM, pfnCPUMGCResumeGuestV86);
    839839    GEN_CHECK_OFF(VMM, iLastGCRc);
    840     GEN_CHECK_OFF(VMM, pbHCStack);
    841     GEN_CHECK_OFF(VMM, pbGCStack);
    842     GEN_CHECK_OFF(VMM, pbGCStackBottom);
     840    GEN_CHECK_OFF(VMM, pbEMTStackR3);
     841    GEN_CHECK_OFF(VMM, pbEMTStackRC);
     842    GEN_CHECK_OFF(VMM, pbEMTStackBottomRC);
    843843    GEN_CHECK_OFF(VMM, pLoggerGC);
    844844    GEN_CHECK_OFF(VMM, pLoggerHC);
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette