VirtualBox

Changeset 94838 in vbox for trunk/src/VBox


Ignore:
Timestamp:
May 5, 2022 10:29:49 AM (3 years ago)
Author:
vboxsync
Message:

VMM/IEM: More TLB work. bugref:9898

Location:
trunk/src/VBox/VMM
Files:
5 edited

Legend:

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

    r94800 r94838  
    605605 * @param   pVCpu       The cross context virtual CPU structure of the calling
    606606 *                      thread.
    607  * @note    Currently not used. 
     607 * @note    Currently not used.
    608608 */
    609609VMM_INT_DECL(void) IEMTlbInvalidateAllPhysical(PVMCPUCC pVCpu)
     
    41384138    return iemRaiseXcptOrInt(pVCpu, 0, X86_XCPT_AC, IEM_XCPT_FLAGS_T_CPU_XCPT, 0, 0);
    41394139}
     4140
     4141#ifdef IEM_WITH_SETJMP
     4142/** \#AC(0) - 11, longjmp.  */
     4143DECL_NO_RETURN(void) iemRaiseAlignmentCheckExceptionJmp(PVMCPUCC pVCpu) RT_NOEXCEPT
     4144{
     4145    longjmp(*CTX_SUFF(pVCpu->iem.s.pJmpBuf), VBOXSTRICTRC_VAL(iemRaiseAlignmentCheckException(pVCpu)));
     4146}
     4147#endif
    41404148
    41414149
     
    59115919     */
    59125920    /** @todo testcase: check when A and D bits are actually set by the CPU.  */
    5913     uint64_t const fTlbAccessedDirty = (fAccess & IEM_ACCESS_TYPE_WRITE ? IEMTLBE_F_PT_NO_DIRTY : 0) | IEMTLBE_F_PG_NO_ACCESSED;
     5921    uint64_t const fTlbAccessedDirty = (fAccess & IEM_ACCESS_TYPE_WRITE ? IEMTLBE_F_PT_NO_DIRTY : 0) | IEMTLBE_F_PT_NO_ACCESSED;
    59145922    if (pTlbe->fFlagsAndPhysRev & fTlbAccessedDirty)
    59155923    {
     
    61756183            && (fAccess & IEM_ACCESS_TYPE_WRITE)
    61766184            && (   (    pVCpu->iem.s.uCpl == 3
    6177                     && !(fAccess & IEM_ACCESS_WHAT_SYS))
     6185                    && !(fAccess & IEM_ACCESS_WHAT_SYS)) /** @todo check this. Not sure WP applies to all SYS writes... */
    61786186                || (pVCpu->cpum.GstCtx.cr0 & X86_CR0_WP)))
    61796187        {
     
    62056213     */
    62066214    /** @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_PG_NO_ACCESSED;
     6215    uint64_t const fTlbAccessedDirty = (fAccess & IEM_ACCESS_TYPE_WRITE ? IEMTLBE_F_PT_NO_DIRTY : 0) | IEMTLBE_F_PT_NO_ACCESSED;
    62086216    if (pTlbe->fFlagsAndPhysRev & fTlbAccessedDirty)
    62096217    {
     
    66006608uint32_t iemMemFetchDataU32Jmp(PVMCPUCC pVCpu, uint8_t iSegReg, RTGCPTR GCPtrMem) RT_NOEXCEPT
    66016609{
    6602 # if 0 //def IEM_WITH_DATA_TLB
     6610# if defined(IEM_WITH_DATA_TLB) && defined(IN_RING3)
     6611    /*
     6612     * Convert from segmented to flat address and check that it doesn't cross a page boundrary.
     6613     */
    66036614    RTGCPTR GCPtrEff = iemMemApplySegmentToReadJmp(pVCpu, iSegReg, sizeof(uint32_t), GCPtrMem);
    6604     if (RT_LIKELY((GCPtrEff & X86_PAGE_OFFSET_MASK) <= X86_PAGE_SIZE - sizeof(uint32_t)))
    6605     {
    6606         /// @todo more soon...
    6607     }
    6608 
     6615    if (RT_LIKELY((GCPtrEff & GUEST_PAGE_OFFSET_MASK) <= GUEST_PAGE_SIZE - sizeof(uint32_t)))
     6616    {
     6617        /*
     6618         * TLB lookup.
     6619         */
     6620        uint64_t uTag = ((GCPtrEff << 16) >> (X86_PAGE_SHIFT + 16));
     6621        Assert(!(uTag >> (48 - X86_PAGE_SHIFT)));
     6622        uTag         |= pVCpu->iem.s.DataTlb.uTlbRevision;
     6623        AssertCompile(RT_ELEMENTS(pVCpu->iem.s.DataTlb.aEntries) == 256);
     6624        PIEMTLBENTRY const pTlbe = &pVCpu->iem.s.DataTlb.aEntries[(uint8_t)uTag];
     6625        if (pTlbe->uTag == uTag)
     6626        {
     6627            /*
     6628             * Check TLB page table level access flags.
     6629             */
     6630            uint64_t const fNoUser = pVCpu->iem.s.uCpl == 3 ? IEMTLBE_F_PT_NO_USER : 0;
     6631            if (   (pTlbe->fFlagsAndPhysRev & (  IEMTLBE_F_PHYS_REV       | IEMTLBE_F_PG_UNASSIGNED | IEMTLBE_F_PG_NO_READ
     6632                                               | IEMTLBE_F_PT_NO_ACCESSED | IEMTLBE_F_NO_MAPPINGR3  | fNoUser))
     6633                == pVCpu->iem.s.DataTlb.uTlbPhysRev)
     6634            {
     6635                STAM_STATS({pVCpu->iem.s.DataTlb.cTlbHits++;});
     6636
     6637                /*
     6638                 * Alignment check:
     6639                 */
     6640                /** @todo check priority \#AC vs \#PF */
     6641                if (   !(GCPtrEff & (sizeof(uint32_t) - 1))
     6642                    || !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_AM)
     6643                    || !pVCpu->cpum.GstCtx.eflags.Bits.u1AC
     6644                    || pVCpu->iem.s.uCpl != 3)
     6645                {
     6646                    /*
     6647                     * Fetch and return the dword
     6648                     */
     6649                    Assert(pTlbe->pbMappingR3); /* (Only ever cleared by the owning EMT.) */
     6650                    Assert(!((uintptr_t)pTlbe->pbMappingR3 & GUEST_PAGE_OFFSET_MASK));
     6651                    return *(uint32_t const *)&pTlbe->pbMappingR3[GCPtrEff & GUEST_PAGE_OFFSET_MASK];
     6652                }
     6653                Log10(("iemMemFetchDataU32Jmp: Raising #AC for %RGv\n", GCPtrEff));
     6654                iemRaiseAlignmentCheckExceptionJmp(pVCpu);
     6655            }
     6656        }
     6657    }
     6658
     6659    /* Fall back on the slow careful approach in case of TLB miss, MMIO, exception
     6660       outdated page pointer, or other troubles. */
     6661    Log10(("iemMemFetchDataU32Jmp: %u:%RGv fallback\n", iSegReg, GCPtrMem));
    66096662    return iemMemFetchDataU32SafeJmp(pVCpu, iSegReg, GCPtrMem);
     6663
    66106664# else
    66116665    /* The lazy approach. */
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp

    r94800 r94838  
    6464#  define IEM_DISP_GET_S32_SX_U64(a_pVCpu, a_u64Disp, a_offDisp)  do { a_u64Disp = 0; RT_NOREF(a_offDisp); } while (0)
    6565#  define IEM_DISP_GET_S8_SX_U64(a_pVCpu, a_u64Disp, a_offDisp)   do { a_u64Disp = 0; RT_NOREF(a_offDisp); } while (0)
    66 #  if 1
     66#  if 0
    6767#   error "Implement me: Getting ModR/M, SIB, displacement needs to work even when instruction crosses a page boundary."
    6868#  endif
  • trunk/src/VBox/VMM/VMMR3/IEMR3.cpp

    r94801 r94838  
    232232                    pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_EXEC      ? "NX" : " X",
    233233                    pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_WRITE     ? "RO" : "RW",
    234                     pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PG_NO_ACCESSED  ? "-"  : "A",
     234                    pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_ACCESSED  ? "-"  : "A",
    235235                    pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_DIRTY     ? "-"  : "D",
    236236                    pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PG_NO_WRITE     ? "-"  : "w",
  • trunk/src/VBox/VMM/include/IEMInline.h

    r94800 r94838  
    23392339    if (pVCpu->iem.s.enmCpuMode == IEMMODE_64BIT)
    23402340    {
    2341         if (iSegReg >= X86_SREG_FS)
     2341        if (iSegReg >= X86_SREG_FS && iSegReg != UINT8_MAX)
    23422342        {
    23432343            IEM_CTX_IMPORT_JMP(pVCpu, CPUMCTX_EXTRN_SREG_FROM_IDX(iSegReg));
     
    23482348        if (RT_LIKELY(X86_IS_CANONICAL(GCPtrMem) && X86_IS_CANONICAL(GCPtrMem + cbMem - 1)))
    23492349            return GCPtrMem;
     2350        iemRaiseGeneralProtectionFault0Jmp(pVCpu);
    23502351    }
    23512352    /*
    23522353     * 16-bit and 32-bit segmentation.
    23532354     */
    2354     else
    2355     {
     2355    else if (iSegReg != UINT8_MAX)
     2356    {
     2357        /** @todo Does this apply to segments with 4G-1 limit? */
    23562358        uint32_t const GCPtrLast32 = (uint32_t)GCPtrMem + (uint32_t)cbMem - 1;
    23572359        if (RT_LIKELY(GCPtrLast32 >= (uint32_t)GCPtrMem))
     
    23592361            IEM_CTX_IMPORT_JMP(pVCpu, CPUMCTX_EXTRN_SREG_FROM_IDX(iSegReg));
    23602362            PCPUMSELREGHID const pSel = iemSRegGetHid(pVCpu, iSegReg);
    2361             switch (pSel->Attr.u & (X86DESCATTR_P | X86DESCATTR_UNUSABLE | X86_SEL_TYPE_CODE | X86_SEL_TYPE_DOWN))
     2363            switch (pSel->Attr.u & (  X86DESCATTR_P     | X86DESCATTR_UNUSABLE
     2364                                    | X86_SEL_TYPE_READ | X86_SEL_TYPE_WRITE /* same as read */
     2365                                    | X86_SEL_TYPE_DOWN | X86_SEL_TYPE_CONF  /* same as down */
     2366                                    | X86_SEL_TYPE_CODE))
    23622367            {
    2363                 case X86DESCATTR_P:                                         /* data, expand up */
     2368                case X86DESCATTR_P:                                         /* readonly data, expand up */
     2369                case X86DESCATTR_P | X86_SEL_TYPE_WRITE:                    /* writable data, expand up */
    23642370                case X86DESCATTR_P | X86_SEL_TYPE_CODE | X86_SEL_TYPE_READ: /* code, read-only */
     2371                case X86DESCATTR_P | X86_SEL_TYPE_CODE | X86_SEL_TYPE_READ | X86_SEL_TYPE_CONF: /* conforming code, read-only */
    23652372                    /* expand up */
    23662373                    if (RT_LIKELY(GCPtrLast32 <= pSel->u32Limit))
    23672374                        return (uint32_t)GCPtrMem + (uint32_t)pSel->u64Base;
     2375                    Log10(("iemMemApplySegmentToReadJmp: out of bounds %#x..%#x vs %#x\n",
     2376                           (uint32_t)GCPtrMem, GCPtrLast32, pSel->u32Limit));
    23682377                    break;
    23692378
    2370                 case X86DESCATTR_P | X86_SEL_TYPE_DOWN:                     /* data, expand down */
     2379                case X86DESCATTR_P | X86_SEL_TYPE_DOWN:                         /* readonly data, expand down */
     2380                case X86DESCATTR_P | X86_SEL_TYPE_DOWN | X86_SEL_TYPE_WRITE:    /* writable data, expand down */
    23712381                    /* expand down */
    23722382                    if (RT_LIKELY(   (uint32_t)GCPtrMem > pSel->u32Limit
     
    23742384                                      || GCPtrLast32 <= UINT32_C(0xffff)) ))
    23752385                        return (uint32_t)GCPtrMem + (uint32_t)pSel->u64Base;
     2386                    Log10(("iemMemApplySegmentToReadJmp: expand down out of bounds %#x..%#x vs %#x..%#x\n",
     2387                           (uint32_t)GCPtrMem, GCPtrLast32, pSel->u32Limit, pSel->Attr.n.u1DefBig ? UINT32_MAX : UINT16_MAX));
    23762388                    break;
    23772389
    23782390                default:
     2391                    Log10(("iemMemApplySegmentToReadJmp: bad selector %#x\n", pSel->Attr.u));
    23792392                    iemRaiseSelectorInvalidAccessJmp(pVCpu, iSegReg, IEM_ACCESS_DATA_R);
    23802393                    break;
    23812394            }
    23822395        }
     2396        Log10(("iemMemApplySegmentToReadJmp: out of bounds %#x..%#x\n",(uint32_t)GCPtrMem, GCPtrLast32));
    23832397        iemRaiseSelectorBoundsJmp(pVCpu, iSegReg, IEM_ACCESS_DATA_R);
    23842398    }
    2385     iemRaiseGeneralProtectionFault0Jmp(pVCpu);
     2399    /*
     2400     * 32-bit flat address.
     2401     */
     2402    else
     2403        return GCPtrMem;
    23862404}
    23872405
  • trunk/src/VBox/VMM/include/IEMInternal.h

    r94800 r94838  
    320320#define IEMTLBE_F_PG_NO_WRITE       RT_BIT_64(3) /**< Phys page:   Not writable (access handler, ROM, whatever). */
    321321#define IEMTLBE_F_PG_NO_READ        RT_BIT_64(4) /**< Phys page:   Not readable (MMIO / access handler, ROM) */
    322 #define IEMTLBE_F_PG_NO_ACCESSED    RT_BIT_64(5) /**< Phys tables: Not accessed (need to be marked accessed). */
     322#define IEMTLBE_F_PT_NO_ACCESSED    RT_BIT_64(5) /**< Phys tables: Not accessed (need to be marked accessed). */
    323323#define IEMTLBE_F_PT_NO_DIRTY       RT_BIT_64(6) /**< Page tables: Not dirty (needs to be made dirty on write). */
    324324#define IEMTLBE_F_NO_MAPPINGR3      RT_BIT_64(7) /**< TLB entry:   The IEMTLBENTRY::pMappingR3 member is invalid. */
     
    25472547VBOXSTRICTRC            iemRaiseMathFault(PVMCPUCC pVCpu);
    25482548VBOXSTRICTRC            iemRaiseAlignmentCheckException(PVMCPUCC pVCpu);
     2549#ifdef IEM_WITH_SETJMP
     2550DECL_NO_RETURN(void)    iemRaiseAlignmentCheckExceptionJmp(PVMCPUCC pVCpu)  RT_NOEXCEPT;
     2551#endif
    25492552
    25502553IEM_CIMPL_DEF_0(iemCImplRaiseDivideError);
Note: See TracChangeset for help on using the changeset viewer.

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