VirtualBox

Changeset 29737 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
May 21, 2010 2:07:52 PM (15 years ago)
Author:
vboxsync
Message:

Fixed dropping back to the recompiler too often when running unrestricted guest code that switches mode very often.

Location:
trunk/src/VBox/VMM
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/HWACCM.cpp

    r29250 r29737  
    21922192
    21932193    /* Note! The context supplied by REM is partial. If we add more checks here, be sure to verify that REM provides this info! */
    2194 #ifdef HWACCM_VMX_EMULATE_REALMODE
    2195     bool fVMMDeviceHeapEnabled = PDMVMMDevHeapIsEnabled(pVM);
    2196 
    21972194    Assert((pVM->hwaccm.s.vmx.fUnrestrictedGuest && !pVM->hwaccm.s.vmx.pRealModeTSS) || (!pVM->hwaccm.s.vmx.fUnrestrictedGuest && pVM->hwaccm.s.vmx.pRealModeTSS));
    21982195
    2199     /** The VMM device heap is a requirement for emulating real mode or protected mode without paging when the unrestricted guest execution feature is missing. */
    2200     if (fVMMDeviceHeapEnabled)
    2201     {
    2202         if (CPUMIsGuestInRealModeEx(pCtx))
     2196    bool fSupportsRealMode = pVM->hwaccm.s.vmx.fUnrestrictedGuest || PDMVMMDevHeapIsEnabled(pVM);
     2197    if (!pVM->hwaccm.s.vmx.fUnrestrictedGuest)
     2198    {
     2199        /** The VMM device heap is a requirement for emulating real mode or protected mode without paging when the unrestricted guest execution feature is missing. */
     2200        if (fSupportsRealMode)
    22032201        {
    2204             /* VT-x will not allow high selector bases in v86 mode; fall back to the recompiler in that case.
    2205              * The base must also be equal to (sel << 4).
    2206              */
    2207             if (   (   pCtx->cs != (pCtx->csHid.u64Base >> 4)
    2208                     && pCtx->csHid.u64Base != 0xffff0000 /* we can deal with the BIOS code as it's also mapped into the lower region. */)
    2209                 || pCtx->ds != (pCtx->dsHid.u64Base >> 4)
    2210                 || pCtx->es != (pCtx->esHid.u64Base >> 4)
    2211                 || pCtx->fs != (pCtx->fsHid.u64Base >> 4)
    2212                 || pCtx->gs != (pCtx->gsHid.u64Base >> 4)
    2213                 || pCtx->ss != (pCtx->ssHid.u64Base >> 4))
     2202            if (CPUMIsGuestInRealModeEx(pCtx))
    22142203            {
    2215                 return false;
     2204                /* VT-x will not allow high selector bases in v86 mode; fall back to the recompiler in that case.
     2205                 * The base must also be equal to (sel << 4).
     2206                 */
     2207                if (   (   pCtx->cs != (pCtx->csHid.u64Base >> 4)
     2208                        && pCtx->csHid.u64Base != 0xffff0000 /* we can deal with the BIOS code as it's also mapped into the lower region. */)
     2209                    || pCtx->ds != (pCtx->dsHid.u64Base >> 4)
     2210                    || pCtx->es != (pCtx->esHid.u64Base >> 4)
     2211                    || pCtx->fs != (pCtx->fsHid.u64Base >> 4)
     2212                    || pCtx->gs != (pCtx->gsHid.u64Base >> 4)
     2213                    || pCtx->ss != (pCtx->ssHid.u64Base >> 4))
     2214                {
     2215                    return false;
     2216                }
     2217            }
     2218            else
     2219            {
     2220                PGMMODE enmGuestMode = PGMGetGuestMode(pVCpu);
     2221                /* Verify the requirements for executing code in protected mode. VT-x can't handle the CPU state right after a switch
     2222                 * from real to protected mode. (all sorts of RPL & DPL assumptions)
     2223                 */
     2224                if (    pVCpu->hwaccm.s.vmx.enmLastSeenGuestMode == PGMMODE_REAL
     2225                    &&  enmGuestMode >= PGMMODE_PROTECTED)
     2226                {
     2227                    if (   (pCtx->cs & X86_SEL_RPL)
     2228                        || (pCtx->ds & X86_SEL_RPL)
     2229                        || (pCtx->es & X86_SEL_RPL)
     2230                        || (pCtx->fs & X86_SEL_RPL)
     2231                        || (pCtx->gs & X86_SEL_RPL)
     2232                        || (pCtx->ss & X86_SEL_RPL))
     2233                    {
     2234                        return false;
     2235                    }
     2236                }
    22162237            }
    22172238        }
    22182239        else
    22192240        {
    2220             PGMMODE enmGuestMode = PGMGetGuestMode(pVCpu);
    2221             /* Verify the requirements for executing code in protected mode. VT-x can't handle the CPU state right after a switch
    2222              * from real to protected mode. (all sorts of RPL & DPL assumptions)
    2223              */
    2224             if (    pVCpu->hwaccm.s.vmx.enmLastSeenGuestMode == PGMMODE_REAL
    2225                 &&  enmGuestMode >= PGMMODE_PROTECTED)
     2241            if (    !CPUMIsGuestInLongModeEx(pCtx)
     2242                &&  !pVM->hwaccm.s.vmx.fUnrestrictedGuest)
    22262243            {
    2227                 if (   (pCtx->cs & X86_SEL_RPL)
    2228                     || (pCtx->ds & X86_SEL_RPL)
    2229                     || (pCtx->es & X86_SEL_RPL)
    2230                     || (pCtx->fs & X86_SEL_RPL)
    2231                     || (pCtx->gs & X86_SEL_RPL)
    2232                     || (pCtx->ss & X86_SEL_RPL))
    2233                 {
     2244                /** @todo   This should (probably) be set on every excursion to the REM,
     2245                 *          however it's too risky right now. So, only apply it when we go
     2246                 *          back to REM for real mode execution. (The XP hack below doesn't
     2247                 *          work reliably without this.)
     2248                 *  Update: Implemented in EM.cpp, see #ifdef EM_NOTIFY_HWACCM.  */
     2249                pVM->aCpus[0].hwaccm.s.fContextUseFlags |= HWACCM_CHANGED_ALL_GUEST;
     2250
     2251                if (    !pVM->hwaccm.s.fNestedPaging        /* requires a fake PD for real *and* protected mode without paging - stored in the VMM device heap*/
     2252                    ||  CPUMIsGuestInRealModeEx(pCtx))      /* requires a fake TSS for real mode - stored in the VMM device heap */
    22342253                    return false;
    2235                 }
     2254
     2255                /* Too early for VT-x; Solaris guests will fail with a guru meditation otherwise; same for XP. */
     2256                if (pCtx->idtr.pIdt == 0 || pCtx->idtr.cbIdt == 0 || pCtx->tr == 0)
     2257                    return false;
     2258
     2259                /* The guest is about to complete the switch to protected mode. Wait a bit longer. */
     2260                /* Windows XP; switch to protected mode; all selectors are marked not present in the
     2261                 * hidden registers (possible recompiler bug; see load_seg_vm) */
     2262                if (pCtx->csHid.Attr.n.u1Present == 0)
     2263                    return false;
     2264                if (pCtx->ssHid.Attr.n.u1Present == 0)
     2265                    return false;
     2266
     2267                /* Windows XP: possible same as above, but new recompiler requires new heuristics?
     2268                   VT-x doesn't seem to like something about the guest state and this stuff avoids it. */
     2269                /** @todo This check is actually wrong, it doesn't take the direction of the
     2270                 *        stack segment into account. But, it does the job for now. */
     2271                if (pCtx->rsp >= pCtx->ssHid.u32Limit)
     2272                    return false;
     2273    #if 0
     2274                if (    pCtx->cs >= pCtx->gdtr.cbGdt
     2275                    ||  pCtx->ss >= pCtx->gdtr.cbGdt
     2276                    ||  pCtx->ds >= pCtx->gdtr.cbGdt
     2277                    ||  pCtx->es >= pCtx->gdtr.cbGdt
     2278                    ||  pCtx->fs >= pCtx->gdtr.cbGdt
     2279                    ||  pCtx->gs >= pCtx->gdtr.cbGdt)
     2280                    return false;
     2281    #endif
    22362282            }
    22372283        }
    22382284    }
    2239     else
    2240 #endif /* HWACCM_VMX_EMULATE_REALMODE */
    2241     {
    2242         if (    !CPUMIsGuestInLongModeEx(pCtx)
    2243             &&  !pVM->hwaccm.s.vmx.fUnrestrictedGuest)
     2285
     2286    if (pVM->hwaccm.s.vmx.fEnabled)
     2287    {
     2288        uint32_t mask;
     2289
     2290        /* if bit N is set in cr0_fixed0, then it must be set in the guest's cr0. */
     2291        mask = (uint32_t)pVM->hwaccm.s.vmx.msr.vmx_cr0_fixed0;
     2292        /* Note: We ignore the NE bit here on purpose; see vmmr0\hwaccmr0.cpp for details. */
     2293        mask &= ~X86_CR0_NE;
     2294
     2295        if (fSupportsRealMode)
    22442296        {
    2245             /** @todo   This should (probably) be set on every excursion to the REM,
    2246              *          however it's too risky right now. So, only apply it when we go
    2247              *          back to REM for real mode execution. (The XP hack below doesn't
    2248              *          work reliably without this.)
    2249              *  Update: Implemented in EM.cpp, see #ifdef EM_NOTIFY_HWACCM.  */
    2250             pVM->aCpus[0].hwaccm.s.fContextUseFlags |= HWACCM_CHANGED_ALL_GUEST;
    2251 
    2252             if (    !pVM->hwaccm.s.fNestedPaging        /* requires a fake PD for real *and* protected mode without paging - stored in the VMM device heap*/
    2253                 ||  CPUMIsGuestInRealModeEx(pCtx))      /* requires a fake TSS for real mode - stored in the VMM device heap */
    2254                 return false;
    2255 
    2256             /* Too early for VT-x; Solaris guests will fail with a guru meditation otherwise; same for XP. */
    2257             if (pCtx->idtr.pIdt == 0 || pCtx->idtr.cbIdt == 0 || pCtx->tr == 0)
    2258                 return false;
    2259 
    2260             /* The guest is about to complete the switch to protected mode. Wait a bit longer. */
    2261             /* Windows XP; switch to protected mode; all selectors are marked not present in the
    2262              * hidden registers (possible recompiler bug; see load_seg_vm) */
    2263             if (pCtx->csHid.Attr.n.u1Present == 0)
    2264                 return false;
    2265             if (pCtx->ssHid.Attr.n.u1Present == 0)
    2266                 return false;
    2267 
    2268             /* Windows XP: possible same as above, but new recompiler requires new heuristics?
    2269                VT-x doesn't seem to like something about the guest state and this stuff avoids it. */
    2270             /** @todo This check is actually wrong, it doesn't take the direction of the
    2271              *        stack segment into account. But, it does the job for now. */
    2272             if (pCtx->rsp >= pCtx->ssHid.u32Limit)
    2273                 return false;
    2274 #if 0
    2275             if (    pCtx->cs >= pCtx->gdtr.cbGdt
    2276                 ||  pCtx->ss >= pCtx->gdtr.cbGdt
    2277                 ||  pCtx->ds >= pCtx->gdtr.cbGdt
    2278                 ||  pCtx->es >= pCtx->gdtr.cbGdt
    2279                 ||  pCtx->fs >= pCtx->gdtr.cbGdt
    2280                 ||  pCtx->gs >= pCtx->gdtr.cbGdt)
    2281                 return false;
    2282 #endif
     2297            /* Note: We ignore the PE & PG bits here on purpose; we emulate real and protected mode without paging. */
     2298            mask &= ~(X86_CR0_PG|X86_CR0_PE);
    22832299        }
    2284     }
    2285 
    2286     if (pVM->hwaccm.s.vmx.fEnabled)
    2287     {
    2288         uint32_t mask;
    2289 
    2290         if (!pVM->hwaccm.s.vmx.fUnrestrictedGuest)
     2300        else
    22912301        {
    2292             /* if bit N is set in cr0_fixed0, then it must be set in the guest's cr0. */
    2293             mask = (uint32_t)pVM->hwaccm.s.vmx.msr.vmx_cr0_fixed0;
    2294             /* Note: We ignore the NE bit here on purpose; see vmmr0\hwaccmr0.cpp for details. */
    2295             mask &= ~X86_CR0_NE;
    2296 
    2297 #ifdef HWACCM_VMX_EMULATE_REALMODE
    2298             if (fVMMDeviceHeapEnabled)
    2299             {
    2300                 /* Note: We ignore the PE & PG bits here on purpose; we emulate real and protected mode without paging. */
    2301                 mask &= ~(X86_CR0_PG|X86_CR0_PE);
    2302             }
    2303             else
    2304 #endif
    2305             {
    2306                 /* We support protected mode without paging using identity mapping. */
    2307                 mask &= ~X86_CR0_PG;
    2308             }
    2309             if ((pCtx->cr0 & mask) != mask)
    2310                 return false;
    2311 
    2312             /* if bit N is cleared in cr0_fixed1, then it must be zero in the guest's cr0. */
    2313             mask = (uint32_t)~pVM->hwaccm.s.vmx.msr.vmx_cr0_fixed1;
    2314             if ((pCtx->cr0 & mask) != 0)
    2315                 return false;
     2302            /* We support protected mode without paging using identity mapping. */
     2303            mask &= ~X86_CR0_PG;
    23162304        }
     2305        if ((pCtx->cr0 & mask) != mask)
     2306            return false;
     2307
     2308        /* if bit N is cleared in cr0_fixed1, then it must be zero in the guest's cr0. */
     2309        mask = (uint32_t)~pVM->hwaccm.s.vmx.msr.vmx_cr0_fixed1;
     2310        if ((pCtx->cr0 & mask) != 0)
     2311            return false;
    23172312
    23182313        /* if bit N is set in cr4_fixed0, then it must be set in the guest's cr4. */
  • trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp

    r29250 r29737  
    755755#endif
    756756
    757 #ifdef HWACCM_VMX_EMULATE_REALMODE
    758757    if (    CPUMIsGuestInRealModeEx(pCtx)
    759758        &&  pVM->hwaccm.s.vmx.pRealModeTSS)
     
    826825        return VINF_SUCCESS;
    827826    }
    828 #endif /* HWACCM_VMX_EMULATE_REALMODE */
    829827
    830828    /* Set event injection state. */
     
    12821280#endif
    12831281
    1284 # ifdef HWACCM_VMX_EMULATE_REALMODE
    12851282    /* Intercept all exceptions in real mode as none of them can be injected directly (#GP otherwise). */
    12861283    if (    CPUMIsGuestInRealModeEx(pCtx)
    12871284        &&  pVM->hwaccm.s.vmx.pRealModeTSS)
    12881285        u32TrapMask |= HWACCM_VMX_TRAP_MASK_REALMODE;
    1289 # endif /* HWACCM_VMX_EMULATE_REALMODE */
    12901286
    12911287    int rc = VMXWriteVMCS(VMX_VMCS_CTRL_EXCEPTION_BITMAP, u32TrapMask);
     
    13511347    if (pVCpu->hwaccm.s.fContextUseFlags & HWACCM_CHANGED_GUEST_SEGMENT_REGS)
    13521348    {
    1353 #ifdef HWACCM_VMX_EMULATE_REALMODE
    13541349        if (pVM->hwaccm.s.vmx.pRealModeTSS)
    13551350        {
     
    14211416            }
    14221417        }
    1423 #endif /* HWACCM_VMX_EMULATE_REALMODE */
    14241418
    14251419        VMX_WRITE_SELREG(ES, es);
     
    14651459    if (pVCpu->hwaccm.s.fContextUseFlags & HWACCM_CHANGED_GUEST_TR)
    14661460    {
    1467 #ifdef HWACCM_VMX_EMULATE_REALMODE
    14681461        /* Real mode emulation using v86 mode with CR4.VME (interrupt redirection using the int bitmap in the TSS) */
    14691462        if (    CPUMIsGuestInRealModeEx(pCtx)
     
    14881481        }
    14891482        else
    1490 #endif /* HWACCM_VMX_EMULATE_REALMODE */
    14911483        {
    14921484            rc =  VMXWriteVMCS(VMX_VMCS16_GUEST_FIELD_TR,         pCtx->tr);
     
    16461638        }
    16471639
    1648 #ifdef HWACCM_VMX_EMULATE_REALMODE
    16491640        /* Turn off VME if we're in emulated real mode. */
    16501641        if (    CPUMIsGuestInRealModeEx(pCtx)
    16511642            &&  pVM->hwaccm.s.vmx.pRealModeTSS)
    16521643            val &= ~X86_CR4_VME;
    1653 #endif /* HWACCM_VMX_EMULATE_REALMODE */
    16541644
    16551645        rc |= VMXWriteVMCS64(VMX_VMCS64_GUEST_CR4,            val);
     
    17871777    eflags.u32 |= VMX_EFLAGS_RESERVED_1;
    17881778
    1789 #ifdef HWACCM_VMX_EMULATE_REALMODE
    17901779    /* Real mode emulation using v86 mode. */
    17911780    if (    CPUMIsGuestInRealModeEx(pCtx)
     
    17971786        eflags.Bits.u2IOPL = 0; /* must always be 0 or else certain instructions won't cause faults. */
    17981787    }
    1799 #endif /* HWACCM_VMX_EMULATE_REALMODE */
    18001788    rc   = VMXWriteVMCS(VMX_VMCS_GUEST_RFLAGS,           eflags.u32);
    18011789    AssertRC(rc);
     
    20182006    pCtx->idtr.pIdt         = val;
    20192007
    2020 #ifdef HWACCM_VMX_EMULATE_REALMODE
    20212008    /* Real mode emulation using v86 mode. */
    20222009    if (    CPUMIsGuestInRealModeEx(pCtx)
     
    20332020    }
    20342021    else
    2035 #endif /* HWACCM_VMX_EMULATE_REALMODE */
    20362022    {
    20372023        /* In real mode we have a fake TSS, so only sync it back when it's supposed to be valid. */
     
    33203306#endif
    33213307            default:
    3322 #ifdef HWACCM_VMX_EMULATE_REALMODE
    33233308                if (    CPUMIsGuestInRealModeEx(pCtx)
    33243309                    &&  pVM->hwaccm.s.vmx.pRealModeTSS)
     
    33363321                    goto ResumeExecution;
    33373322                }
    3338 #endif
    33393323                AssertMsgFailed(("Unexpected vm-exit caused by exception %x\n", vector));
    33403324                rc = VERR_VMX_UNEXPECTED_EXCEPTION;
Note: See TracChangeset for help on using the changeset viewer.

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