VirtualBox

Changeset 46125 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
May 16, 2013 1:59:37 PM (12 years ago)
Author:
vboxsync
Message:

PGM: Optimized virtual memory searching by skipping empty tables.

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

Legend:

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

    r45826 r46125  
    14151415
    14161416/**
     1417 * Performs a guest page table walk.
     1418 *
     1419 * The guest should be in paged protect mode or long mode when making a call to
     1420 * this function.
     1421 *
     1422 * @returns VBox status code.
     1423 * @retval  VINF_SUCCESS on success.
     1424 * @retval  VERR_PAGE_TABLE_NOT_PRESENT on failure.  Check pWalk for details.
     1425 * @retval  VERR_PGM_NOT_USED_IN_MODE if not paging isn't enabled. @a pWalk is
     1426 *          not valid, except enmType is PGMPTWALKGSTTYPE_INVALID.
     1427 *
     1428 * @param   pVCpu       The current CPU.
     1429 * @param   GCPtr       The guest virtual address to walk by.
     1430 * @param   pWalk       Where to return the walk result. This is valid on some
     1431 *                      error codes as well.
     1432 */
     1433int pgmGstPtWalk(PVMCPU pVCpu, RTGCPTR GCPtr, PPGMPTWALKGST pWalk)
     1434{
     1435    VMCPU_ASSERT_EMT(pVCpu);
     1436    switch (pVCpu->pgm.s.enmGuestMode)
     1437    {
     1438        case PGMMODE_32_BIT:
     1439            pWalk->enmType = PGMPTWALKGSTTYPE_32BIT;
     1440            return PGM_GST_NAME_32BIT(Walk)(pVCpu, GCPtr, &pWalk->u.Legacy);
     1441
     1442        case PGMMODE_PAE:
     1443        case PGMMODE_PAE_NX:
     1444            pWalk->enmType = PGMPTWALKGSTTYPE_PAE;
     1445            return PGM_GST_NAME_PAE(Walk)(pVCpu, GCPtr, &pWalk->u.Pae);
     1446
     1447#if !defined(IN_RC)
     1448        case PGMMODE_AMD64:
     1449        case PGMMODE_AMD64_NX:
     1450            pWalk->enmType = PGMPTWALKGSTTYPE_AMD64;
     1451            return PGM_GST_NAME_AMD64(Walk)(pVCpu, GCPtr, &pWalk->u.Amd64);
     1452#endif
     1453
     1454        case PGMMODE_REAL:
     1455        case PGMMODE_PROTECTED:
     1456            pWalk->enmType = PGMPTWALKGSTTYPE_INVALID;
     1457            return VERR_PGM_NOT_USED_IN_MODE;
     1458
     1459#if defined(IN_RC)
     1460        case PGMMODE_AMD64:
     1461        case PGMMODE_AMD64_NX:
     1462#endif
     1463        case PGMMODE_NESTED:
     1464        case PGMMODE_EPT:
     1465        default:
     1466            AssertFailed();
     1467            pWalk->enmType = PGMPTWALKGSTTYPE_INVALID;
     1468            return VERR_PGM_NOT_USED_IN_MODE;
     1469    }
     1470}
     1471
     1472
     1473/**
    14171474 * Checks if the page is present.
    14181475 *
  • trunk/src/VBox/VMM/VMMR3/PGMDbg.cpp

    r46117 r46125  
    776776    }
    777777
     778    /* Only paged protected mode or long mode here, use the physical scan for
     779       the other modes. */
     780    PGMMODE enmMode   = PGMGetGuestMode(pVCpu);
     781    AssertReturn(PGMMODE_WITH_PAGING(enmMode), VERR_PGM_NOT_USED_IN_MODE);
     782
    778783    /*
    779784     * Search the memory - ignore MMIO, zero and not-present pages.
    780785     */
    781786    const bool      fAllZero  = ASMMemIsAll8(pabNeedle, cbNeedle, 0) == NULL;
    782     PGMMODE         enmMode   = PGMGetGuestMode(pVCpu);
    783787    RTGCPTR         GCPtrMask = PGMMODE_IS_LONG_MODE(enmMode) ? UINT64_MAX : UINT32_MAX;
    784788    uint8_t         abPrev[MAX_NEEDLE_SIZE];
     
    795799    for (;; offPage = 0)
    796800    {
    797         RTGCPHYS GCPhys;
    798         int rc = PGMPhysGCPtr2GCPhys(pVCpu, GCPtr, &GCPhys);
    799         if (RT_SUCCESS(rc))
    800         {
    801             PPGMPAGE pPage = pgmPhysGetPage(pVM, GCPhys);
     801        PGMPTWALKGST Walk;
     802        int rc = pgmGstPtWalk(pVCpu, GCPtr, &Walk);
     803        if (RT_SUCCESS(rc) && Walk.u.Core.fSucceeded)
     804        {
     805            PPGMPAGE pPage = pgmPhysGetPage(pVM, Walk.u.Core.GCPhys);
    802806            if (    pPage
    803807                &&  (   !PGM_PAGE_IS_ZERO(pPage)
     
    809813                void const *pvPage;
    810814                PGMPAGEMAPLOCK Lock;
    811                 rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, GCPhys, &pvPage, &Lock);
     815                rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, Walk.u.Core.GCPhys, &pvPage, &Lock);
    812816                if (RT_SUCCESS(rc))
    813817                {
     
    839843        }
    840844        else
     845        {
     846            Assert(Walk.enmType != PGMPTWALKGSTTYPE_INVALID);
     847            Assert(!Walk.u.Core.fSucceeded);
    841848            cbPrev = 0; /* ignore error. */
     849
     850            /*
     851             * Try skip as much as possible. No need to figure out that a PDE
     852             * is not present 512 times!
     853             */
     854            uint64_t cPagesCanSkip;
     855            switch (Walk.u.Core.uLevel)
     856            {
     857                case 1:
     858                    /* page level, use cIncPages */
     859                    cPagesCanSkip = 1;
     860                    break;
     861                case 2:
     862                    if (Walk.enmType == PGMPTWALKGSTTYPE_32BIT)
     863                    {
     864                        cPagesCanSkip = X86_PG_ENTRIES     - ((GCPtr >> X86_PT_SHIFT)     & X86_PT_MASK);
     865                        Assert(!((GCPtr + ((RTGCPTR)cPagesCanSkip << X86_PT_PAE_SHIFT)) & (RT_BIT_64(X86_PD_SHIFT) - 1)));
     866                    }
     867                    else
     868                    {
     869                        cPagesCanSkip = X86_PG_PAE_ENTRIES - ((GCPtr >> X86_PT_PAE_SHIFT) & X86_PT_PAE_MASK);
     870                        Assert(!((GCPtr + ((RTGCPTR)cPagesCanSkip << X86_PT_PAE_SHIFT)) & (RT_BIT_64(X86_PD_PAE_SHIFT) - 1)));
     871                    }
     872                    break;
     873                case 3:
     874                    cPagesCanSkip = (X86_PG_PAE_ENTRIES - ((GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK)) * X86_PG_PAE_ENTRIES
     875                                  - ((GCPtr >> X86_PT_PAE_SHIFT) & X86_PT_PAE_MASK);
     876                    Assert(!((GCPtr + ((RTGCPTR)cPagesCanSkip << X86_PT_PAE_SHIFT)) & (RT_BIT_64(X86_PDPT_SHIFT) - 1)));
     877                    break;
     878                case 4:
     879                    cPagesCanSkip =   (X86_PG_PAE_ENTRIES  - ((GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_AMD64))
     880                                    * X86_PG_PAE_ENTRIES * X86_PG_PAE_ENTRIES
     881                                  - ((((GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK)) * X86_PG_PAE_ENTRIES)
     882                                  - ((  GCPtr >> X86_PT_PAE_SHIFT) & X86_PT_PAE_MASK);
     883                    Assert(!((GCPtr + ((RTGCPTR)cPagesCanSkip << X86_PT_PAE_SHIFT)) & (RT_BIT_64(X86_PML4_SHIFT) - 1)));
     884                    break;
     885                case 8:
     886                    /* The CR3 value is bad, forget the whole search. */
     887                    cPagesCanSkip = cPages;
     888                    break;
     889                default:
     890                    AssertMsgFailed(("%d\n", Walk.u.Core.uLevel));
     891                    cPagesCanSkip = 0;
     892                    break;
     893            }
     894            if (cPages <= cPagesCanSkip)
     895                break;
     896            if (cPagesCanSkip >= cIncPages)
     897            {
     898                cPages -= cPagesCanSkip;
     899                GCPtr += (RTGCPTR)cPagesCanSkip << X86_PT_PAE_SHIFT;
     900                continue;
     901            }
     902        }
    842903
    843904        /* advance to the next page. */
     
    845906            break;
    846907        cPages -= cIncPages;
    847         GCPtr += (RTGCPTR)cIncPages << PAGE_SHIFT;
     908        GCPtr += (RTGCPTR)cIncPages << X86_PT_PAE_SHIFT;
    848909    }
    849910    return VERR_DBGF_MEM_NOT_FOUND;
  • trunk/src/VBox/VMM/include/PGMInternal.h

    r45826 r46125  
    26992699typedef PGMPTWALKGST32BIT const *PCPGMPTWALKGST32BIT;
    27002700
     2701/**
     2702 * Which part of PGMPTWALKGST that is valid.
     2703 */
     2704typedef enum PGMPTWALKGSTTYPE
     2705{
     2706    /** Customary invalid 0 value. */
     2707    PGMPTWALKGSTTYPE_INVALID = 0,
     2708    /**  PGMPTWALKGST::u.Amd64 is valid. */
     2709    PGMPTWALKGSTTYPE_AMD64,
     2710    /**  PGMPTWALKGST::u.Pae is valid. */
     2711    PGMPTWALKGSTTYPE_PAE,
     2712    /**  PGMPTWALKGST::u.Legacy is valid. */
     2713    PGMPTWALKGSTTYPE_32BIT,
     2714    /** Customary 32-bit type hack. */
     2715    PGMPTWALKGSTTYPE_32BIT_HACK = 0x7fff0000
     2716} PGMPTWALKGSTTYPE;
     2717
     2718/**
     2719 * Combined guest page table walk result.
     2720 */
     2721typedef struct PGMPTWALKGST
     2722{
     2723    union
     2724    {
     2725        /** The page walker core - always valid. */
     2726        PGMPTWALKCORE       Core;
     2727        /** The page walker for AMD64. */
     2728        PGMPTWALKGSTAMD64   Amd64;
     2729        /** The page walker for PAE (32-bit). */
     2730        PGMPTWALKGSTPAE     Pae;
     2731        /** The page walker for 32-bit paging (called legacy due to C naming
     2732         * convension). */
     2733        PGMPTWALKGST32BIT   Legacy;
     2734    } u;
     2735    /** Indicates which part of the union is valid. */
     2736    PGMPTWALKGSTTYPE        enmType;
     2737} PGMPTWALKGST;
     2738/** Pointer to a combined guest page table walk result. */
     2739typedef PGMPTWALKGST *PPGMPTWALKGST;
     2740/** Pointer to a read-only combined guest page table walk result. */
     2741typedef PGMPTWALKGST const *PCPGMPTWALKGST;
     2742
    27012743
    27022744/** @name Paging mode macros
     
    40354077int             pgmGstLazyMapPaePD(PVMCPU pVCpu, uint32_t iPdpt, PX86PDPAE *ppPd);
    40364078int             pgmGstLazyMapPml4(PVMCPU pVCpu, PX86PML4 *ppPml4);
     4079int             pgmGstPtWalk(PVMCPU pVCpu, RTGCPTR GCPtr, PPGMPTWALKGST pWalk);
    40374080
    40384081# if defined(VBOX_STRICT) && HC_ARCH_BITS == 64 && defined(IN_RING3)
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