Changeset 85974 in vbox
- Timestamp:
- Sep 1, 2020 10:03:09 AM (5 years ago)
- svn:sync-xref-src-repo-rev:
- 140169
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/hm_vmx.h
r82968 r85974 1757 1757 #define VMX_VMCS16_GUEST_FS_SEL 0x0808 1758 1758 #define VMX_VMCS16_GUEST_GS_SEL 0x080a 1759 #define VMX_VMCS16_GUEST_SEG_SEL(a_iSegReg) (VMX_VMCS16_GUEST_ES_SEL + (a_iSegReg) * 2) 1759 1760 #define VMX_VMCS16_GUEST_LDTR_SEL 0x080c 1760 1761 #define VMX_VMCS16_GUEST_TR_SEL 0x080e … … 1894 1895 #define VMX_VMCS32_GUEST_FS_LIMIT 0x4808 1895 1896 #define VMX_VMCS32_GUEST_GS_LIMIT 0x480a 1897 #define VMX_VMCS32_GUEST_SEG_LIMIT(a_iSegReg) (VMX_VMCS32_GUEST_ES_LIMIT + (a_iSegReg) * 2) 1896 1898 #define VMX_VMCS32_GUEST_LDTR_LIMIT 0x480c 1897 1899 #define VMX_VMCS32_GUEST_TR_LIMIT 0x480e … … 1904 1906 #define VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS 0x481c 1905 1907 #define VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS 0x481e 1908 #define VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(a_iSegReg) (VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS + (a_iSegReg) * 2) 1906 1909 #define VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS 0x4820 1907 1910 #define VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS 0x4822 … … 1943 1946 #define VMX_VMCS_GUEST_FS_BASE 0x680e 1944 1947 #define VMX_VMCS_GUEST_GS_BASE 0x6810 1948 #define VMX_VMCS_GUEST_SEG_BASE(a_iSegReg) (VMX_VMCS_GUEST_ES_BASE + (a_iSegReg) * 2) 1945 1949 #define VMX_VMCS_GUEST_LDTR_BASE 0x6812 1946 1950 #define VMX_VMCS_GUEST_TR_BASE 0x6814 -
trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp
r85970 r85974 691 691 #endif /* VBOX_WITH_NESTED_HWVIRT_VMX */ 692 692 693 #ifdef VBOX_STRICT 693 694 static const uint32_t g_aVmcsSegBase[] = 694 695 { … … 731 732 AssertCompile(RT_ELEMENTS(g_aVmcsSegBase) == X86_SREG_COUNT); 732 733 AssertCompile(RT_ELEMENTS(g_aVmcsSegAttr) == X86_SREG_COUNT); 734 #endif /* VBOX_STRICT */ 733 735 734 736 #ifdef HMVMX_USE_FUNCTION_TABLE … … 6262 6264 * @remarks No-long-jump zone!!! 6263 6265 */ 6264 static int hmR0VmxExportGuestSegReg(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, uint 8_t iSegReg, PCCPUMSELREG pSelReg)6266 static int hmR0VmxExportGuestSegReg(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, uint32_t iSegReg, PCCPUMSELREG pSelReg) 6265 6267 { 6266 6268 Assert(iSegReg < X86_SREG_COUNT); 6267 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];6268 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];6269 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];6270 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];6271 6269 6272 6270 uint32_t u32Access = pSelReg->Attr.u; 6273 if (pVmcsInfo->RealMode.fRealOnV86Active) 6274 { 6275 /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */ 6276 u32Access = 0xf3; 6277 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS); 6278 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM))); 6279 RT_NOREF_PV(pVCpu); 6280 } 6281 else 6271 if (!pVmcsInfo->RealMode.fRealOnV86Active) 6282 6272 { 6283 6273 /* … … 6288 6278 * NULL selectors loaded in protected-mode have their attribute as 0. 6289 6279 */ 6290 if (!u32Access) 6280 if (u32Access) 6281 { } 6282 else 6291 6283 u32Access = X86DESCATTR_UNUSABLE; 6284 } 6285 else 6286 { 6287 /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */ 6288 u32Access = 0xf3; 6289 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS); 6290 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM))); 6291 RT_NOREF_PV(pVCpu); 6292 6292 } 6293 6293 6294 6294 /* Validate segment access rights. Refer to Intel spec. "26.3.1.2 Checks on Guest Segment Registers". */ 6295 6295 AssertMsg((u32Access & X86DESCATTR_UNUSABLE) || (u32Access & X86_SEL_TYPE_ACCESSED), 6296 ("Access bit not set for usable segment. idx=%#x sel=%#x attr %#x\n", idxBase, pSelReg, pSelReg->Attr.u));6296 ("Access bit not set for usable segment. %.2s sel=%#x attr %#x\n", "ESCSSSDSFSGS" + iSegReg * 2, pSelReg, pSelReg->Attr.u)); 6297 6297 6298 6298 /* 6299 6299 * Commit it to the VMCS. 6300 6300 */ 6301 int rc = VMXWriteVmcs32(idxSel, pSelReg->Sel); AssertRC(rc); 6302 rc = VMXWriteVmcs32(idxLimit, pSelReg->u32Limit); AssertRC(rc); 6303 rc = VMXWriteVmcsNw(idxBase, pSelReg->u64Base); AssertRC(rc); 6304 rc = VMXWriteVmcs32(idxAttr, u32Access); AssertRC(rc); 6301 Assert((uint32_t)VMX_VMCS16_GUEST_SEG_SEL(iSegReg) == g_aVmcsSegSel[iSegReg]); 6302 Assert((uint32_t)VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg) == g_aVmcsSegLimit[iSegReg]); 6303 Assert((uint32_t)VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg) == g_aVmcsSegAttr[iSegReg]); 6304 Assert((uint32_t)VMX_VMCS_GUEST_SEG_BASE(iSegReg) == g_aVmcsSegBase[iSegReg]); 6305 int rc = VMXWriteVmcs32(VMX_VMCS16_GUEST_SEG_SEL(iSegReg), pSelReg->Sel); AssertRC(rc); 6306 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg), pSelReg->u32Limit); AssertRC(rc); 6307 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SEG_BASE(iSegReg), pSelReg->u64Base); AssertRC(rc); 6308 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg), u32Access); AssertRC(rc); 6305 6309 return VINF_SUCCESS; 6306 6310 } … … 7227 7231 * @param pVCpu The cross context virtual CPU structure. 7228 7232 * @param pSelReg The segment register that needs fixing. 7229 * @param idxSel The VMCS field for the corresponding segment register.7230 */ 7231 static void hmR0VmxFixUnusableSegRegAttr(PVMCPUCC pVCpu, PCPUMSELREG pSelReg, uint32_t idxSel)7233 * @param pszRegName The register name (for logging and assertions). 7234 */ 7235 static void hmR0VmxFixUnusableSegRegAttr(PVMCPUCC pVCpu, PCPUMSELREG pSelReg, const char *pszRegName) 7232 7236 { 7233 7237 Assert(pSelReg->Attr.u & X86DESCATTR_UNUSABLE); … … 7261 7265 #ifdef VBOX_STRICT 7262 7266 VMMRZCallRing3Disable(pVCpu); 7263 Log4Func(("Unusable % #x: sel=%#x attr=%#x -> %#x\n", idxSel, pSelReg->Sel, uAttr, pSelReg->Attr.u));7267 Log4Func(("Unusable %s: sel=%#x attr=%#x -> %#x\n", pszRegName, pSelReg->Sel, uAttr, pSelReg->Attr.u)); 7264 7268 # ifdef DEBUG_bird 7265 7269 AssertMsg((uAttr & ~X86DESCATTR_P) == pSelReg->Attr.u, 7266 ("% #x: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n",7267 idxSel, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit));7270 ("%s: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n", 7271 pszRegName, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit)); 7268 7272 # endif 7269 7273 VMMRZCallRing3Enable(pVCpu); 7270 7274 NOREF(uAttr); 7271 7275 #endif 7272 RT_NOREF2(pVCpu, idxSel);7276 RT_NOREF2(pVCpu, pszRegName); 7273 7277 } 7274 7278 … … 7283 7287 * @remarks Called with interrupts and/or preemption disabled. 7284 7288 */ 7285 static void hmR0VmxImportGuestSegReg(PVMCPUCC pVCpu, uint 8_t iSegReg)7289 static void hmR0VmxImportGuestSegReg(PVMCPUCC pVCpu, uint32_t iSegReg) 7286 7290 { 7287 7291 Assert(iSegReg < X86_SREG_COUNT); 7288 7289 /** @todo r=bird: Aren't these translation tables a complete wast of time and 7290 * memory accesses? As far as I can tell, the constants are in segment 7291 * order with a 2+ stepping. Adding 4 macro functions to hm_vmx.h that 7292 * does the translation, like: @code 7293 * #define VMX_VMCS_GUEST_SEG_BASE(a_iSegReg) \ 7294 * (VMX_VMCS_GUEST_ES_BASE + (a_iSegReg) * 2) 7295 * @endcode 7296 * The tables are in two different cache lines two, due to their size, so not 7297 * great for locality either. 7298 */ 7299 uint32_t const idxSel = g_aVmcsSegSel[iSegReg]; 7300 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg]; 7301 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg]; 7302 uint32_t const idxBase = g_aVmcsSegBase[iSegReg]; 7292 Assert((uint32_t)VMX_VMCS16_GUEST_SEG_SEL(iSegReg) == g_aVmcsSegSel[iSegReg]); 7293 Assert((uint32_t)VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg) == g_aVmcsSegLimit[iSegReg]); 7294 Assert((uint32_t)VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg) == g_aVmcsSegAttr[iSegReg]); 7295 Assert((uint32_t)VMX_VMCS_GUEST_SEG_BASE(iSegReg) == g_aVmcsSegBase[iSegReg]); 7296 7297 PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg]; 7303 7298 7304 7299 uint16_t u16Sel; 7305 uint64_t u64Base; 7306 uint32_t u32Limit, u32Attr; 7307 int rc = VMXReadVmcs16(idxSel, &u16Sel); AssertRC(rc); 7308 rc = VMXReadVmcs32(idxLimit, &u32Limit); AssertRC(rc); 7309 rc = VMXReadVmcs32(idxAttr, &u32Attr); AssertRC(rc); 7310 rc = VMXReadVmcsNw(idxBase, &u64Base); AssertRC(rc); 7311 7312 PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg]; 7300 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_SEG_SEL(iSegReg), &u16Sel); AssertRC(rc); 7313 7301 pSelReg->Sel = u16Sel; 7314 7302 pSelReg->ValidSel = u16Sel; 7315 pSelReg->fFlags = CPUMSELREG_FLAGS_VALID; 7316 pSelReg->u32Limit = u32Limit; 7317 #ifdef DEBUG_bird 7318 if (pSelReg->u64Base != u64Base) 7319 Log7(("HM: %.2s: base %RX64 -> %RX64\n", "ESCSSSDSFSGS" + iSegReg * 2, pSelReg->u64Base, u64Base)); 7320 #endif 7321 pSelReg->u64Base = u64Base; 7303 7304 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg), &pSelReg->u32Limit); AssertRC(rc); 7305 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SEG_BASE(iSegReg), &pSelReg->u64Base); AssertRC(rc); 7306 7307 uint32_t u32Attr; 7308 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg), &u32Attr); AssertRC(rc); 7322 7309 pSelReg->Attr.u = u32Attr; 7323 7310 if (u32Attr & X86DESCATTR_UNUSABLE) 7324 hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, idxSel); 7311 hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, "ES\0CS\0SS\0DS\0FS\0GS" + iSegReg * 3); 7312 7313 pSelReg->fFlags = CPUMSELREG_FLAGS_VALID; 7325 7314 } 7326 7315 … … 7350 7339 pVCpu->cpum.GstCtx.ldtr.Attr.u = u32Attr; 7351 7340 if (u32Attr & X86DESCATTR_UNUSABLE) 7352 hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, VMX_VMCS16_GUEST_LDTR_SEL);7341 hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, "LDTR"); 7353 7342 } 7354 7343
Note:
See TracChangeset
for help on using the changeset viewer.