Changeset 94868 in vbox
- Timestamp:
- May 5, 2022 8:47:25 PM (3 years ago)
- svn:sync-xref-src-repo-rev:
- 151268
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
r94845 r94868 6137 6137 PIEMTLBENTRY const pTlbe = IEMTLB_TAG_TO_ENTRY(&pVCpu->iem.s.DataTlb, uTag); 6138 6138 if (pTlbe->uTag == uTag) 6139 { 6140 # ifdef VBOX_WITH_STATISTICS 6141 pVCpu->iem.s.DataTlb.cTlbHits++; 6142 # endif 6143 } 6139 STAM_STATS({pVCpu->iem.s.DataTlb.cTlbHits++;}); 6144 6140 else 6145 6141 { … … 6165 6161 6166 6162 /* 6167 * Check TLB page table level access flags.6163 * Check the flags and physical revision. 6168 6164 */ 6169 /* If the page is either supervisor only or non-writable, we need to do 6170 more careful access checks. */ 6171 if (pTlbe->fFlagsAndPhysRev & (IEMTLBE_F_PT_NO_USER | IEMTLBE_F_PT_NO_WRITE)) 6172 { 6165 /** @todo make the caller pass these in with fAccess. */ 6166 uint64_t const fNoUser = (fAccess & IEM_ACCESS_WHAT_MASK) != IEM_ACCESS_WHAT_SYS && pVCpu->iem.s.uCpl == 3 6167 ? IEMTLBE_F_PT_NO_USER : 0; 6168 uint64_t const fNoWriteNoDirty = fAccess & IEM_ACCESS_TYPE_WRITE 6169 ? IEMTLBE_F_PG_NO_WRITE | IEMTLBE_F_PT_NO_DIRTY 6170 | ( (pVCpu->cpum.GstCtx.cr0 & X86_CR0_WP) 6171 || (pVCpu->iem.s.uCpl == 3 && (fAccess & IEM_ACCESS_WHAT_MASK) != IEM_ACCESS_WHAT_SYS) 6172 ? IEMTLBE_F_PT_NO_WRITE : 0) 6173 : 0; 6174 uint64_t const fNoRead = fAccess & IEM_ACCESS_TYPE_READ ? IEMTLBE_F_PG_NO_READ : 0; 6175 uint8_t *pbMem = NULL; 6176 if ( (pTlbe->fFlagsAndPhysRev & (IEMTLBE_F_PHYS_REV | IEMTLBE_F_PT_NO_ACCESSED | fNoRead | fNoWriteNoDirty | fNoUser)) 6177 == pVCpu->iem.s.DataTlb.uTlbPhysRev) 6178 # ifdef IN_RING3 6179 pbMem = pTlbe->pbMappingR3; 6180 # else 6181 pbMem = NULL; 6182 # endif 6183 else 6184 { 6185 /* 6186 * Okay, something isn't quite right or needs refreshing. 6187 */ 6173 6188 /* Write to read only memory? */ 6174 if ( (pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_WRITE) 6175 && (fAccess & IEM_ACCESS_TYPE_WRITE) 6176 && ( ( pVCpu->iem.s.uCpl == 3 6177 && !(fAccess & IEM_ACCESS_WHAT_SYS)) /** @todo check this. Not sure WP applies to all SYS writes... */ 6178 || (pVCpu->cpum.GstCtx.cr0 & X86_CR0_WP))) 6189 if (pTlbe->fFlagsAndPhysRev & fNoWriteNoDirty & IEMTLBE_F_PT_NO_WRITE) 6179 6190 { 6180 6191 Log(("iemMemMapJmp: GCPtrMem=%RGv - read-only page -> #PF\n", GCPtrMem)); … … 6187 6198 6188 6199 /* Kernel memory accessed by userland? */ 6189 if ( (pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_USER) 6190 && pVCpu->iem.s.uCpl == 3 6191 && !(fAccess & IEM_ACCESS_WHAT_SYS)) 6200 if (pTlbe->fFlagsAndPhysRev & fNoUser & IEMTLBE_F_PT_NO_USER) 6192 6201 { 6193 6202 Log(("iemMemMapJmp: GCPtrMem=%RGv - user access to kernel page -> #PF\n", GCPtrMem)); … … 6198 6207 iemRaisePageFaultJmp(pVCpu, GCPtrMem, fAccess, VERR_ACCESS_DENIED); 6199 6208 } 6200 } 6201 6202 /* 6203 * Set the dirty / access flags. 6204 * ASSUMES this is set when the address is translated rather than on commit... 6205 */ 6206 /** @todo testcase: check when A and D bits are actually set by the CPU. */ 6207 uint64_t const fTlbAccessedDirty = (fAccess & IEM_ACCESS_TYPE_WRITE ? IEMTLBE_F_PT_NO_DIRTY : 0) | IEMTLBE_F_PT_NO_ACCESSED; 6208 if (pTlbe->fFlagsAndPhysRev & fTlbAccessedDirty) 6209 { 6210 uint32_t const fAccessedDirty = fAccess & IEM_ACCESS_TYPE_WRITE ? X86_PTE_D | X86_PTE_A : X86_PTE_A; 6211 int rc2 = PGMGstModifyPage(pVCpu, GCPtrMem, 1, fAccessedDirty, ~(uint64_t)fAccessedDirty); 6212 AssertRC(rc2); 6213 /** @todo Nested VMX: Accessed/dirty bit currently not supported, asserted below. */ 6214 Assert(!(CPUMGetGuestIa32VmxEptVpidCap(pVCpu) & VMX_BF_EPT_VPID_CAP_ACCESS_DIRTY_MASK)); 6215 pTlbe->fFlagsAndPhysRev &= ~fTlbAccessedDirty; 6216 } 6217 6218 /* 6219 * Look up the physical page info if necessary. 6220 */ 6221 uint8_t *pbMem = NULL; 6222 if ((pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PHYS_REV) == pVCpu->iem.s.DataTlb.uTlbPhysRev) 6209 6210 /* Set the dirty / access flags. 6211 ASSUMES this is set when the address is translated rather than on commit... */ 6212 /** @todo testcase: check when A and D bits are actually set by the CPU. */ 6213 if (pTlbe->fFlagsAndPhysRev & ((fNoWriteNoDirty & IEMTLBE_F_PT_NO_DIRTY) | IEMTLBE_F_PT_NO_ACCESSED)) 6214 { 6215 uint32_t const fAccessedDirty = fAccess & IEM_ACCESS_TYPE_WRITE ? X86_PTE_D | X86_PTE_A : X86_PTE_A; 6216 int rc2 = PGMGstModifyPage(pVCpu, GCPtrMem, 1, fAccessedDirty, ~(uint64_t)fAccessedDirty); 6217 AssertRC(rc2); 6218 /** @todo Nested VMX: Accessed/dirty bit currently not supported, asserted below. */ 6219 Assert(!(CPUMGetGuestIa32VmxEptVpidCap(pVCpu) & VMX_BF_EPT_VPID_CAP_ACCESS_DIRTY_MASK)); 6220 pTlbe->fFlagsAndPhysRev &= ~((fNoWriteNoDirty & IEMTLBE_F_PT_NO_DIRTY) | IEMTLBE_F_PT_NO_ACCESSED); 6221 } 6222 6223 /* 6224 * Check if the physical page info needs updating. 6225 */ 6226 if ((pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PHYS_REV) == pVCpu->iem.s.DataTlb.uTlbPhysRev) 6223 6227 # ifdef IN_RING3 6224 pbMem = pTlbe->pbMappingR3;6228 pbMem = pTlbe->pbMappingR3; 6225 6229 # else 6226 pbMem = NULL;6230 pbMem = NULL; 6227 6231 # endif 6228 else6229 {6230 AssertCompile(PGMIEMGCPHYS2PTR_F_NO_WRITE == IEMTLBE_F_PG_NO_WRITE);6231 AssertCompile(PGMIEMGCPHYS2PTR_F_NO_READ == IEMTLBE_F_PG_NO_READ);6232 AssertCompile(PGMIEMGCPHYS2PTR_F_NO_MAPPINGR3 == IEMTLBE_F_NO_MAPPINGR3);6233 AssertCompile(PGMIEMGCPHYS2PTR_F_UNASSIGNED == IEMTLBE_F_PG_UNASSIGNED);6234 pTlbe->pbMappingR3 = NULL;6235 pTlbe->fFlagsAndPhysRev &= ~( IEMTLBE_F_PHYS_REV6236 | IEMTLBE_F_NO_MAPPINGR3 | IEMTLBE_F_PG_NO_READ | IEMTLBE_F_PG_NO_WRITE | IEMTLBE_F_PG_UNASSIGNED);6237 int rc = PGMPhysIemGCPhys2PtrNoLock(pVCpu->CTX_SUFF(pVM), pVCpu, pTlbe->GCPhys, &pVCpu->iem.s.DataTlb.uTlbPhysRev,6238 &pbMem, &pTlbe->fFlagsAndPhysRev);6239 AssertRCStmt(rc, longjmp(*CTX_SUFF(pVCpu->iem.s.pJmpBuf), rc));6232 else 6233 { 6234 AssertCompile(PGMIEMGCPHYS2PTR_F_NO_WRITE == IEMTLBE_F_PG_NO_WRITE); 6235 AssertCompile(PGMIEMGCPHYS2PTR_F_NO_READ == IEMTLBE_F_PG_NO_READ); 6236 AssertCompile(PGMIEMGCPHYS2PTR_F_NO_MAPPINGR3 == IEMTLBE_F_NO_MAPPINGR3); 6237 AssertCompile(PGMIEMGCPHYS2PTR_F_UNASSIGNED == IEMTLBE_F_PG_UNASSIGNED); 6238 pTlbe->pbMappingR3 = NULL; 6239 pTlbe->fFlagsAndPhysRev &= ~( IEMTLBE_F_PHYS_REV 6240 | IEMTLBE_F_NO_MAPPINGR3 | IEMTLBE_F_PG_NO_READ | IEMTLBE_F_PG_NO_WRITE | IEMTLBE_F_PG_UNASSIGNED); 6241 int rc = PGMPhysIemGCPhys2PtrNoLock(pVCpu->CTX_SUFF(pVM), pVCpu, pTlbe->GCPhys, &pVCpu->iem.s.DataTlb.uTlbPhysRev, 6242 &pbMem, &pTlbe->fFlagsAndPhysRev); 6243 AssertRCStmt(rc, longjmp(*CTX_SUFF(pVCpu->iem.s.pJmpBuf), rc)); 6240 6244 # ifdef IN_RING3 6241 pTlbe->pbMappingR3 = pbMem;6245 pTlbe->pbMappingR3 = pbMem; 6242 6246 # endif 6243 } 6244 6245 /* 6246 * Check the physical page level access and mapping. 6247 */ 6248 if ( !(pTlbe->fFlagsAndPhysRev & (IEMTLBE_F_PG_NO_WRITE | IEMTLBE_F_PG_NO_READ)) 6249 || !(pTlbe->fFlagsAndPhysRev & ( (fAccess & IEM_ACCESS_TYPE_WRITE ? IEMTLBE_F_PG_NO_WRITE : 0) 6250 | (fAccess & IEM_ACCESS_TYPE_READ ? IEMTLBE_F_PG_NO_READ : 0))) ) 6251 { /* probably likely */ } 6252 else 6253 { 6254 rcStrict = iemMemBounceBufferMapPhys(pVCpu, iMemMap, (void **)&pbMem, cbMem, 6255 pTlbe->GCPhys | (GCPtrMem & GUEST_PAGE_OFFSET_MASK), fAccess, 6256 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PG_UNASSIGNED ? VERR_PGM_PHYS_TLB_UNASSIGNED 6257 : pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PG_NO_READ ? VERR_PGM_PHYS_TLB_CATCH_ALL 6258 : VERR_PGM_PHYS_TLB_CATCH_WRITE); 6259 if (rcStrict == VINF_SUCCESS) 6260 return pbMem; 6261 longjmp(*pVCpu->iem.s.CTX_SUFF(pJmpBuf), VBOXSTRICTRC_VAL(rcStrict)); 6247 } 6248 6249 /* 6250 * Check the physical page level access and mapping. 6251 */ 6252 if (!(pTlbe->fFlagsAndPhysRev & ((fNoWriteNoDirty | fNoRead) & (IEMTLBE_F_PG_NO_WRITE | IEMTLBE_F_PG_NO_READ)))) 6253 { /* probably likely */ } 6254 else 6255 { 6256 rcStrict = iemMemBounceBufferMapPhys(pVCpu, iMemMap, (void **)&pbMem, cbMem, 6257 pTlbe->GCPhys | (GCPtrMem & GUEST_PAGE_OFFSET_MASK), fAccess, 6258 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PG_UNASSIGNED ? VERR_PGM_PHYS_TLB_UNASSIGNED 6259 : pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PG_NO_READ ? VERR_PGM_PHYS_TLB_CATCH_ALL 6260 : VERR_PGM_PHYS_TLB_CATCH_WRITE); 6261 if (rcStrict == VINF_SUCCESS) 6262 return pbMem; 6263 longjmp(*pVCpu->iem.s.CTX_SUFF(pJmpBuf), VBOXSTRICTRC_VAL(rcStrict)); 6264 } 6262 6265 } 6263 6266 Assert(!(pTlbe->fFlagsAndPhysRev & IEMTLBE_F_NO_MAPPINGR3)); /* ASSUMPTIONS about PGMPhysIemGCPhys2PtrNoLock behaviour. */
Note:
See TracChangeset
for help on using the changeset viewer.