Changeset 15584 in vbox
- Timestamp:
- Dec 16, 2008 1:59:05 PM (16 years ago)
- svn:sync-xref-src-repo-rev:
- 41093
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/HWACCM.cpp
r15578 r15584 783 783 /* Allocate three pages for the TSS we need for real mode emulation. (2 page for the IO bitmap) */ 784 784 rc = PDMR3VMMDevHeapAlloc(pVM, HWACCM_VTX_TOTAL_DEVHEAP_MEM, (RTR3PTR *)&pVM->hwaccm.s.vmx.pRealModeTSS); 785 AssertRC(rc); 786 if (RT_FAILURE(rc)) 787 return rc; 788 789 /* The I/O bitmap starts right after the virtual interrupt redirection bitmap. */ 790 ASMMemZero32(pVM->hwaccm.s.vmx.pRealModeTSS, sizeof(*pVM->hwaccm.s.vmx.pRealModeTSS)); 791 pVM->hwaccm.s.vmx.pRealModeTSS->offIoBitmap = sizeof(*pVM->hwaccm.s.vmx.pRealModeTSS); 792 /* Bit set to 0 means redirection enabled. */ 793 memset(pVM->hwaccm.s.vmx.pRealModeTSS->IntRedirBitmap, 0x0, sizeof(pVM->hwaccm.s.vmx.pRealModeTSS->IntRedirBitmap)); 794 /* Allow all port IO, so the VT-x IO intercepts do their job. */ 795 memset(pVM->hwaccm.s.vmx.pRealModeTSS + 1, 0, PAGE_SIZE*2); 796 *((unsigned char *)pVM->hwaccm.s.vmx.pRealModeTSS + HWACCM_VTX_TSS_SIZE - 2) = 0xff; 797 798 /* Construct a 1024 element page directory with 4 MB pages for the identity mapped page table used in 799 * real and protected mode without paging with EPT. 800 */ 801 pVM->hwaccm.s.vmx.pNonPagingModeEPTPageTable = (PX86PD)((char *)pVM->hwaccm.s.vmx.pRealModeTSS + PAGE_SIZE * 3); 802 for (unsigned i=0;i<X86_PG_ENTRIES;i++) 785 if (RT_SUCCESS(rc)) 803 786 { 804 pVM->hwaccm.s.vmx.pNonPagingModeEPTPageTable->a[i].u = _4M * i; 805 pVM->hwaccm.s.vmx.pNonPagingModeEPTPageTable->a[i].u |= X86_PDE4M_P | X86_PDE4M_RW | X86_PDE4M_US | X86_PDE4M_A | X86_PDE4M_D | X86_PDE4M_PS | X86_PDE4M_G; 787 788 /* The I/O bitmap starts right after the virtual interrupt redirection bitmap. */ 789 ASMMemZero32(pVM->hwaccm.s.vmx.pRealModeTSS, sizeof(*pVM->hwaccm.s.vmx.pRealModeTSS)); 790 pVM->hwaccm.s.vmx.pRealModeTSS->offIoBitmap = sizeof(*pVM->hwaccm.s.vmx.pRealModeTSS); 791 /* Bit set to 0 means redirection enabled. */ 792 memset(pVM->hwaccm.s.vmx.pRealModeTSS->IntRedirBitmap, 0x0, sizeof(pVM->hwaccm.s.vmx.pRealModeTSS->IntRedirBitmap)); 793 /* Allow all port IO, so the VT-x IO intercepts do their job. */ 794 memset(pVM->hwaccm.s.vmx.pRealModeTSS + 1, 0, PAGE_SIZE*2); 795 *((unsigned char *)pVM->hwaccm.s.vmx.pRealModeTSS + HWACCM_VTX_TSS_SIZE - 2) = 0xff; 796 797 /* Construct a 1024 element page directory with 4 MB pages for the identity mapped page table used in 798 * real and protected mode without paging with EPT. 799 */ 800 pVM->hwaccm.s.vmx.pNonPagingModeEPTPageTable = (PX86PD)((char *)pVM->hwaccm.s.vmx.pRealModeTSS + PAGE_SIZE * 3); 801 for (unsigned i=0;i<X86_PG_ENTRIES;i++) 802 { 803 pVM->hwaccm.s.vmx.pNonPagingModeEPTPageTable->a[i].u = _4M * i; 804 pVM->hwaccm.s.vmx.pNonPagingModeEPTPageTable->a[i].u |= X86_PDE4M_P | X86_PDE4M_RW | X86_PDE4M_US | X86_PDE4M_A | X86_PDE4M_D | X86_PDE4M_PS | X86_PDE4M_G; 805 } 806 807 /* We convert it here every time as pci regions could be reconfigured. */ 808 rc = PDMVMMDevHeapR3ToGCPhys(pVM, pVM->hwaccm.s.vmx.pRealModeTSS, &GCPhys); 809 AssertRC(rc); 810 LogRel(("HWACCM: Real Mode TSS guest physaddr = %RGp\n", GCPhys)); 811 812 rc = PDMVMMDevHeapR3ToGCPhys(pVM, pVM->hwaccm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys); 813 AssertRC(rc); 814 LogRel(("HWACCM: Non-Paging Mode EPT CR3 = %RGp\n", GCPhys)); 806 815 } 807 808 /* We convert it here every time as pci regions could be reconfigured. */ 809 rc = PDMVMMDevHeapR3ToGCPhys(pVM, pVM->hwaccm.s.vmx.pRealModeTSS, &GCPhys); 810 AssertRC(rc); 811 LogRel(("HWACCM: Real Mode TSS guest physaddr = %RGp\n", GCPhys)); 812 813 rc = PDMVMMDevHeapR3ToGCPhys(pVM, pVM->hwaccm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys); 814 AssertRC(rc); 815 LogRel(("HWACCM: Non-Paging Mode EPT CR3 = %RGp\n", GCPhys)); 816 else 817 { 818 LogRel(("HWACCM: No real mode VT-x support (PDMR3VMMDevHeapAlloc returned %Rrc)\n", rc)); 819 pVM->hwaccm.s.vmx.pRealModeTSS = NULL; 820 pVM->hwaccm.s.vmx.pNonPagingModeEPTPageTable = NULL; 821 } 816 822 817 823 rc = SUPCallVMMR0Ex(pVM->pVMR0, VMMR0_DO_HWACC_SETUP_VM, 0, NULL); … … 1193 1199 /* Note! The context supplied by REM is partial. If we add more checks here, be sure to verify that REM provides this info! */ 1194 1200 #ifdef HWACCM_VMX_EMULATE_REALMODE 1195 if (CPUMIsGuestInRealModeEx(pCtx)) 1196 { 1197 /* VT-x will not allow high selector bases in v86 mode; fall back to the recompiler in that case. 1198 * The base must also be equal to (sel << 4). 1199 */ 1200 if ( ( pCtx->cs != (pCtx->csHid.u64Base >> 4) 1201 && pCtx->csHid.u64Base != 0xffff0000 /* we can deal with the BIOS code as it's also mapped into the lower region. */) 1202 || pCtx->ds != (pCtx->dsHid.u64Base >> 4) 1203 || pCtx->es != (pCtx->esHid.u64Base >> 4) 1204 || pCtx->fs != (pCtx->fsHid.u64Base >> 4) 1205 || pCtx->gs != (pCtx->gsHid.u64Base >> 4) 1206 || pCtx->ss != (pCtx->ssHid.u64Base >> 4)) 1207 { 1208 return false; 1209 } 1210 } 1211 else 1212 { 1213 PGMMODE enmGuestMode = PGMGetGuestMode(pVM); 1214 /* Verify the requirements for executing code in protected mode. VT-x can't handle the CPU state right after a switch 1215 * from real to protected mode. (all sorts of RPL & DPL assumptions) 1216 */ 1217 PVMCPU pVCpu = VMMGetCpu(pVM); 1218 1219 if ( pVCpu->hwaccm.s.vmx.enmLastSeenGuestMode == PGMMODE_REAL 1220 && enmGuestMode >= PGMMODE_PROTECTED) 1221 { 1222 if ( (pCtx->cs & X86_SEL_RPL) 1223 || (pCtx->ds & X86_SEL_RPL) 1224 || (pCtx->es & X86_SEL_RPL) 1225 || (pCtx->fs & X86_SEL_RPL) 1226 || (pCtx->gs & X86_SEL_RPL) 1227 || (pCtx->ss & X86_SEL_RPL)) 1201 if (pVM->hwaccm.s.vmx.pRealModeTSS) 1202 { 1203 if (CPUMIsGuestInRealModeEx(pCtx)) 1204 { 1205 /* VT-x will not allow high selector bases in v86 mode; fall back to the recompiler in that case. 1206 * The base must also be equal to (sel << 4). 1207 */ 1208 if ( ( pCtx->cs != (pCtx->csHid.u64Base >> 4) 1209 && pCtx->csHid.u64Base != 0xffff0000 /* we can deal with the BIOS code as it's also mapped into the lower region. */) 1210 || pCtx->ds != (pCtx->dsHid.u64Base >> 4) 1211 || pCtx->es != (pCtx->esHid.u64Base >> 4) 1212 || pCtx->fs != (pCtx->fsHid.u64Base >> 4) 1213 || pCtx->gs != (pCtx->gsHid.u64Base >> 4) 1214 || pCtx->ss != (pCtx->ssHid.u64Base >> 4)) 1228 1215 { 1229 1216 return false; 1230 1217 } 1231 1218 } 1232 } 1233 #else 1234 if (!CPUMIsGuestInLongModeEx(pCtx)) 1235 { 1236 /* Too early for VT-x; Solaris guests will fail with a guru meditation otherwise; same for XP. */ 1237 if (pCtx->idtr.pIdt == 0 || pCtx->idtr.cbIdt == 0 || pCtx->tr == 0) 1238 return false; 1239 1240 /* The guest is about to complete the switch to protected mode. Wait a bit longer. */ 1241 /* Windows XP; switch to protected mode; all selectors are marked not present in the 1242 * hidden registers (possible recompiler bug; see load_seg_vm) */ 1243 if (pCtx->csHid.Attr.n.u1Present == 0) 1244 return false; 1245 if (pCtx->ssHid.Attr.n.u1Present == 0) 1246 return false; 1247 } 1248 #endif 1219 else 1220 { 1221 PGMMODE enmGuestMode = PGMGetGuestMode(pVM); 1222 /* Verify the requirements for executing code in protected mode. VT-x can't handle the CPU state right after a switch 1223 * from real to protected mode. (all sorts of RPL & DPL assumptions) 1224 */ 1225 PVMCPU pVCpu = VMMGetCpu(pVM); 1226 1227 if ( pVCpu->hwaccm.s.vmx.enmLastSeenGuestMode == PGMMODE_REAL 1228 && enmGuestMode >= PGMMODE_PROTECTED) 1229 { 1230 if ( (pCtx->cs & X86_SEL_RPL) 1231 || (pCtx->ds & X86_SEL_RPL) 1232 || (pCtx->es & X86_SEL_RPL) 1233 || (pCtx->fs & X86_SEL_RPL) 1234 || (pCtx->gs & X86_SEL_RPL) 1235 || (pCtx->ss & X86_SEL_RPL)) 1236 { 1237 return false; 1238 } 1239 } 1240 } 1241 } 1242 else 1243 #endif /* HWACCM_VMX_EMULATE_REALMODE */ 1244 { 1245 if (!CPUMIsGuestInLongModeEx(pCtx)) 1246 { 1247 /* Too early for VT-x; Solaris guests will fail with a guru meditation otherwise; same for XP. */ 1248 if (pCtx->idtr.pIdt == 0 || pCtx->idtr.cbIdt == 0 || pCtx->tr == 0) 1249 return false; 1250 1251 /* The guest is about to complete the switch to protected mode. Wait a bit longer. */ 1252 /* Windows XP; switch to protected mode; all selectors are marked not present in the 1253 * hidden registers (possible recompiler bug; see load_seg_vm) */ 1254 if (pCtx->csHid.Attr.n.u1Present == 0) 1255 return false; 1256 if (pCtx->ssHid.Attr.n.u1Present == 0) 1257 return false; 1258 } 1259 } 1249 1260 1250 1261 if (pVM->hwaccm.s.vmx.fEnabled) … … 1258 1269 1259 1270 #ifdef HWACCM_VMX_EMULATE_REALMODE 1260 /* Note: We ignore the PE & PG bits here on purpose; we emulate real and protected mode without paging. */ 1261 mask &= ~(X86_CR0_PG|X86_CR0_PE); 1262 #else 1263 /* We support protected mode without paging using identity mapping. */ 1264 mask &= ~X86_CR0_PG; 1271 if (pVM->hwaccm.s.vmx.pRealModeTSS) 1272 { 1273 /* Note: We ignore the PE & PG bits here on purpose; we emulate real and protected mode without paging. */ 1274 mask &= ~(X86_CR0_PG|X86_CR0_PE); 1275 } 1276 else 1265 1277 #endif 1278 { 1279 /* We support protected mode without paging using identity mapping. */ 1280 mask &= ~X86_CR0_PG; 1281 } 1266 1282 if ((pCtx->cr0 & mask) != mask) 1267 1283 return false;
Note:
See TracChangeset
for help on using the changeset viewer.