VirtualBox

Changeset 94868 in vbox


Ignore:
Timestamp:
May 5, 2022 8:47:25 PM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
151268
Message:

VMM/IEM: More TLB work. bugref:9898

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IEMAll.cpp

    r94845 r94868  
    61376137    PIEMTLBENTRY const pTlbe = IEMTLB_TAG_TO_ENTRY(&pVCpu->iem.s.DataTlb, uTag);
    61386138    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++;});
    61446140    else
    61456141    {
     
    61656161
    61666162    /*
    6167      * Check TLB page table level access flags.
     6163     * Check the flags and physical revision.
    61686164     */
    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         */
    61736188        /* 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)
    61796190        {
    61806191            Log(("iemMemMapJmp: GCPtrMem=%RGv - read-only page -> #PF\n", GCPtrMem));
     
    61876198
    61886199        /* 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)
    61926201        {
    61936202            Log(("iemMemMapJmp: GCPtrMem=%RGv - user access to kernel page -> #PF\n", GCPtrMem));
     
    61986207            iemRaisePageFaultJmp(pVCpu, GCPtrMem, fAccess, VERR_ACCESS_DENIED);
    61996208        }
    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)
    62236227# ifdef IN_RING3
    6224         pbMem = pTlbe->pbMappingR3;
     6228            pbMem = pTlbe->pbMappingR3;
    62256229# else
    6226         pbMem = NULL;
     6230            pbMem = NULL;
    62276231# endif
    6228     else
    6229     {
    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_REV
    6236                                      | 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));
    62406244# ifdef IN_RING3
    6241         pTlbe->pbMappingR3 = pbMem;
     6245            pTlbe->pbMappingR3 = pbMem;
    62426246# 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        }
    62626265    }
    62636266    Assert(!(pTlbe->fFlagsAndPhysRev & IEMTLBE_F_NO_MAPPINGR3)); /* ASSUMPTIONS about PGMPhysIemGCPhys2PtrNoLock behaviour. */
Note: See TracChangeset for help on using the changeset viewer.

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