Changeset 29737 in vbox for trunk/src/VBox/VMM
- Timestamp:
- May 21, 2010 2:07:52 PM (15 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/HWACCM.cpp
r29250 r29737 2192 2192 2193 2193 /* 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_REALMODE2195 bool fVMMDeviceHeapEnabled = PDMVMMDevHeapIsEnabled(pVM);2196 2197 2194 Assert((pVM->hwaccm.s.vmx.fUnrestrictedGuest && !pVM->hwaccm.s.vmx.pRealModeTSS) || (!pVM->hwaccm.s.vmx.fUnrestrictedGuest && pVM->hwaccm.s.vmx.pRealModeTSS)); 2198 2195 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) 2203 2201 { 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)) 2214 2203 { 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 } 2216 2237 } 2217 2238 } 2218 2239 else 2219 2240 { 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) 2226 2243 { 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 */ 2234 2253 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 2236 2282 } 2237 2283 } 2238 2284 } 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) 2244 2296 { 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); 2283 2299 } 2284 } 2285 2286 if (pVM->hwaccm.s.vmx.fEnabled) 2287 { 2288 uint32_t mask; 2289 2290 if (!pVM->hwaccm.s.vmx.fUnrestrictedGuest) 2300 else 2291 2301 { 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; 2316 2304 } 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; 2317 2312 2318 2313 /* 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 755 755 #endif 756 756 757 #ifdef HWACCM_VMX_EMULATE_REALMODE758 757 if ( CPUMIsGuestInRealModeEx(pCtx) 759 758 && pVM->hwaccm.s.vmx.pRealModeTSS) … … 826 825 return VINF_SUCCESS; 827 826 } 828 #endif /* HWACCM_VMX_EMULATE_REALMODE */829 827 830 828 /* Set event injection state. */ … … 1282 1280 #endif 1283 1281 1284 # ifdef HWACCM_VMX_EMULATE_REALMODE1285 1282 /* Intercept all exceptions in real mode as none of them can be injected directly (#GP otherwise). */ 1286 1283 if ( CPUMIsGuestInRealModeEx(pCtx) 1287 1284 && pVM->hwaccm.s.vmx.pRealModeTSS) 1288 1285 u32TrapMask |= HWACCM_VMX_TRAP_MASK_REALMODE; 1289 # endif /* HWACCM_VMX_EMULATE_REALMODE */1290 1286 1291 1287 int rc = VMXWriteVMCS(VMX_VMCS_CTRL_EXCEPTION_BITMAP, u32TrapMask); … … 1351 1347 if (pVCpu->hwaccm.s.fContextUseFlags & HWACCM_CHANGED_GUEST_SEGMENT_REGS) 1352 1348 { 1353 #ifdef HWACCM_VMX_EMULATE_REALMODE1354 1349 if (pVM->hwaccm.s.vmx.pRealModeTSS) 1355 1350 { … … 1421 1416 } 1422 1417 } 1423 #endif /* HWACCM_VMX_EMULATE_REALMODE */1424 1418 1425 1419 VMX_WRITE_SELREG(ES, es); … … 1465 1459 if (pVCpu->hwaccm.s.fContextUseFlags & HWACCM_CHANGED_GUEST_TR) 1466 1460 { 1467 #ifdef HWACCM_VMX_EMULATE_REALMODE1468 1461 /* Real mode emulation using v86 mode with CR4.VME (interrupt redirection using the int bitmap in the TSS) */ 1469 1462 if ( CPUMIsGuestInRealModeEx(pCtx) … … 1488 1481 } 1489 1482 else 1490 #endif /* HWACCM_VMX_EMULATE_REALMODE */1491 1483 { 1492 1484 rc = VMXWriteVMCS(VMX_VMCS16_GUEST_FIELD_TR, pCtx->tr); … … 1646 1638 } 1647 1639 1648 #ifdef HWACCM_VMX_EMULATE_REALMODE1649 1640 /* Turn off VME if we're in emulated real mode. */ 1650 1641 if ( CPUMIsGuestInRealModeEx(pCtx) 1651 1642 && pVM->hwaccm.s.vmx.pRealModeTSS) 1652 1643 val &= ~X86_CR4_VME; 1653 #endif /* HWACCM_VMX_EMULATE_REALMODE */1654 1644 1655 1645 rc |= VMXWriteVMCS64(VMX_VMCS64_GUEST_CR4, val); … … 1787 1777 eflags.u32 |= VMX_EFLAGS_RESERVED_1; 1788 1778 1789 #ifdef HWACCM_VMX_EMULATE_REALMODE1790 1779 /* Real mode emulation using v86 mode. */ 1791 1780 if ( CPUMIsGuestInRealModeEx(pCtx) … … 1797 1786 eflags.Bits.u2IOPL = 0; /* must always be 0 or else certain instructions won't cause faults. */ 1798 1787 } 1799 #endif /* HWACCM_VMX_EMULATE_REALMODE */1800 1788 rc = VMXWriteVMCS(VMX_VMCS_GUEST_RFLAGS, eflags.u32); 1801 1789 AssertRC(rc); … … 2018 2006 pCtx->idtr.pIdt = val; 2019 2007 2020 #ifdef HWACCM_VMX_EMULATE_REALMODE2021 2008 /* Real mode emulation using v86 mode. */ 2022 2009 if ( CPUMIsGuestInRealModeEx(pCtx) … … 2033 2020 } 2034 2021 else 2035 #endif /* HWACCM_VMX_EMULATE_REALMODE */2036 2022 { 2037 2023 /* In real mode we have a fake TSS, so only sync it back when it's supposed to be valid. */ … … 3320 3306 #endif 3321 3307 default: 3322 #ifdef HWACCM_VMX_EMULATE_REALMODE3323 3308 if ( CPUMIsGuestInRealModeEx(pCtx) 3324 3309 && pVM->hwaccm.s.vmx.pRealModeTSS) … … 3336 3321 goto ResumeExecution; 3337 3322 } 3338 #endif3339 3323 AssertMsgFailed(("Unexpected vm-exit caused by exception %x\n", vector)); 3340 3324 rc = VERR_VMX_UNEXPECTED_EXCEPTION;
Note:
See TracChangeset
for help on using the changeset viewer.