VirtualBox

Changeset 96949 in vbox for trunk/src/VBox/VMM/VMMR3


Ignore:
Timestamp:
Sep 30, 2022 9:24:29 AM (2 years ago)
Author:
vboxsync
Message:

VMM/PGMPool: Extended the .pgmpoolcheck command to cover shadow guest EPT PTs too. Added a 'pgmpoolpages' info item. bugref:10092

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/PGMPool.cpp

    r96939 r96949  
    123123
    124124/*********************************************************************************************************************************
     125*   Structures and Typedefs                                                                                                      *
     126*********************************************************************************************************************************/
     127typedef struct PGMPOOLCHECKERSTATE
     128{
     129    PDBGCCMDHLP     pCmdHlp;
     130    PVM             pVM;
     131    PPGMPOOL        pPool;
     132    PPGMPOOLPAGE    pPage;
     133    bool            fFirstMsg;
     134    uint32_t        cErrors;
     135} PGMPOOLCHECKERSTATE;
     136typedef PGMPOOLCHECKERSTATE *PPGMPOOLCHECKERSTATE;
     137
     138
     139
     140/*********************************************************************************************************************************
    125141*   Internal Functions                                                                                                           *
    126142*********************************************************************************************************************************/
     143static FNDBGFHANDLERINT pgmR3PoolInfoPages;
    127144static FNDBGFHANDLERINT pgmR3PoolInfoRoots;
    128145
     
    451468#endif /* VBOX_WITH_STATISTICS */
    452469
     470    DBGFR3InfoRegisterInternalEx(pVM, "pgmpoolpages", "Lists page pool pages.", pgmR3PoolInfoPages, 0);
    453471    DBGFR3InfoRegisterInternalEx(pVM, "pgmpoolroots", "Lists page pool roots.", pgmR3PoolInfoRoots, 0);
    454472
     
    775793}
    776794
     795/**
     796 * Stringifies a PGMPOOLKIND value.
     797 */
     798static const char *pgmPoolPoolKindToStr(uint8_t enmKind)
     799{
     800    switch ((PGMPOOLKIND)enmKind)
     801    {
     802        case PGMPOOLKIND_INVALID:
     803            return "INVALID";
     804        case PGMPOOLKIND_FREE:
     805            return "FREE";
     806        case PGMPOOLKIND_32BIT_PT_FOR_PHYS:
     807            return "32BIT_PT_FOR_PHYS";
     808        case PGMPOOLKIND_32BIT_PT_FOR_32BIT_PT:
     809            return "32BIT_PT_FOR_32BIT_PT";
     810        case PGMPOOLKIND_32BIT_PT_FOR_32BIT_4MB:
     811            return "32BIT_PT_FOR_32BIT_4MB";
     812        case PGMPOOLKIND_PAE_PT_FOR_PHYS:
     813            return "PAE_PT_FOR_PHYS";
     814        case PGMPOOLKIND_PAE_PT_FOR_32BIT_PT:
     815            return "PAE_PT_FOR_32BIT_PT";
     816        case PGMPOOLKIND_PAE_PT_FOR_32BIT_4MB:
     817            return "PAE_PT_FOR_32BIT_4MB";
     818        case PGMPOOLKIND_PAE_PT_FOR_PAE_PT:
     819            return "PAE_PT_FOR_PAE_PT";
     820        case PGMPOOLKIND_PAE_PT_FOR_PAE_2MB:
     821            return "PAE_PT_FOR_PAE_2MB";
     822        case PGMPOOLKIND_32BIT_PD:
     823            return "32BIT_PD";
     824        case PGMPOOLKIND_32BIT_PD_PHYS:
     825            return "32BIT_PD_PHYS";
     826        case PGMPOOLKIND_PAE_PD0_FOR_32BIT_PD:
     827            return "PAE_PD0_FOR_32BIT_PD";
     828        case PGMPOOLKIND_PAE_PD1_FOR_32BIT_PD:
     829            return "PAE_PD1_FOR_32BIT_PD";
     830        case PGMPOOLKIND_PAE_PD2_FOR_32BIT_PD:
     831            return "PAE_PD2_FOR_32BIT_PD";
     832        case PGMPOOLKIND_PAE_PD3_FOR_32BIT_PD:
     833            return "PAE_PD3_FOR_32BIT_PD";
     834        case PGMPOOLKIND_PAE_PD_FOR_PAE_PD:
     835            return "PAE_PD_FOR_PAE_PD";
     836        case PGMPOOLKIND_PAE_PD_PHYS:
     837            return "PAE_PD_PHYS";
     838        case PGMPOOLKIND_PAE_PDPT_FOR_32BIT:
     839            return "PAE_PDPT_FOR_32BIT";
     840        case PGMPOOLKIND_PAE_PDPT:
     841            return "PAE_PDPT";
     842        case PGMPOOLKIND_PAE_PDPT_PHYS:
     843            return "PAE_PDPT_PHYS";
     844        case PGMPOOLKIND_64BIT_PDPT_FOR_64BIT_PDPT:
     845            return "64BIT_PDPT_FOR_64BIT_PDPT";
     846        case PGMPOOLKIND_64BIT_PDPT_FOR_PHYS:
     847            return "64BIT_PDPT_FOR_PHYS";
     848        case PGMPOOLKIND_64BIT_PD_FOR_64BIT_PD:
     849            return "64BIT_PD_FOR_64BIT_PD";
     850        case PGMPOOLKIND_64BIT_PD_FOR_PHYS:
     851            return "64BIT_PD_FOR_PHYS";
     852        case PGMPOOLKIND_64BIT_PML4:
     853            return "64BIT_PML4";
     854        case PGMPOOLKIND_EPT_PDPT_FOR_PHYS:
     855            return "EPT_PDPT_FOR_PHYS";
     856        case PGMPOOLKIND_EPT_PD_FOR_PHYS:
     857            return "EPT_PD_FOR_PHYS";
     858        case PGMPOOLKIND_EPT_PT_FOR_PHYS:
     859            return "EPT_PT_FOR_PHYS";
     860        case PGMPOOLKIND_ROOT_NESTED:
     861            return "ROOT_NESTED";
     862        case PGMPOOLKIND_EPT_PT_FOR_EPT_PT:
     863            return "EPT_PT_FOR_EPT_PT";
     864        case PGMPOOLKIND_EPT_PD_FOR_EPT_PD:
     865            return "EPT_PD_FOR_EPT_PD";
     866        case PGMPOOLKIND_EPT_PDPT_FOR_EPT_PDPT:
     867            return "EPT_PDPT_FOR_EPT_PDPT";
     868        case PGMPOOLKIND_EPT_PML4_FOR_EPT_PML4:
     869            return "EPT_PML4_FOR_EPT_PML4";
     870    }
     871    return "Unknown kind!";
     872}
     873
    777874
    778875/**
     
    844941
    845942/**
     943 * @callback_method_impl{FNDBGFHANDLERINT, pgmpoolpages}
     944 */
     945static DECLCALLBACK(void) pgmR3PoolInfoPages(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
     946{
     947    RT_NOREF(pszArgs);
     948
     949    PPGMPOOL const pPool  = pVM->pgm.s.CTX_SUFF(pPool);
     950    unsigned const cPages = pPool->cCurPages;
     951    unsigned       cLeft  = pPool->cUsedPages;
     952    for (unsigned iPage = 0; iPage < cPages; iPage++)
     953    {
     954        PGMPOOLPAGE volatile const *pPage = (PGMPOOLPAGE volatile const *)&pPool->aPages[iPage];
     955        RTGCPHYS const GCPhys = pPage->GCPhys;
     956        uint8_t const enmKind = pPage->enmKind;
     957        if (   enmKind != PGMPOOLKIND_INVALID
     958            && enmKind != PGMPOOLKIND_FREE)
     959        {
     960            pHlp->pfnPrintf(pHlp, "#%04x: HCPhys=%RHp GCPhys=%RGp %s %s%s%s\n",
     961                            iPage, pPage->Core.Key, GCPhys, pPage->fA20Enabled ? "A20 " : "!A20",
     962                            pgmPoolPoolKindToStr(enmKind),
     963                            pPage->fCached ? " cached" : "",
     964                            pPage->fMonitored ? " monitored" : "");
     965            if (!--cLeft)
     966                break;
     967        }
     968    }
     969}
     970
     971
     972/**
    846973 * @callback_method_impl{FNDBGFHANDLERINT, pgmpoolroots}
    847974 */
     
    850977    RT_NOREF(pszArgs);
    851978
    852     PPGMPOOL pPool = pVM->pgm.s.CTX_SUFF(pPool);
    853     unsigned cLeft = pPool->cUsedPages;
    854     unsigned iPage = pPool->cCurPages;
    855     while (--iPage >= PGMPOOL_IDX_FIRST)
     979    PPGMPOOL const pPool = pVM->pgm.s.CTX_SUFF(pPool);
     980    unsigned const cPages = pPool->cCurPages;
     981    unsigned       cLeft  = pPool->cUsedPages;
     982    for (unsigned iPage = 0; iPage < cPages; iPage++)
    856983    {
    857984        PGMPOOLPAGE volatile const *pPage = (PGMPOOLPAGE volatile const *)&pPool->aPages[iPage];
     
    871998                case PGMPOOLKIND_ROOT_NESTED:
    872999                case PGMPOOLKIND_EPT_PML4_FOR_EPT_PML4:
    873                 {
    874                     const char *pszKind = "wtf!";
    875                     switch (enmKind)
    876                     {
    877                         case PGMPOOLKIND_PAE_PDPT_FOR_32BIT:    pszKind = "PAE_PDPT_FOR_32BIT"; break;
    878                         case PGMPOOLKIND_PAE_PDPT:              pszKind = "PAE_PDPT"; break;
    879                         case PGMPOOLKIND_PAE_PDPT_PHYS:         pszKind = "PAE_PDPT_PHYS"; break;
    880                         case PGMPOOLKIND_64BIT_PML4:            pszKind = "64BIT_PML4"; break;
    881                         case PGMPOOLKIND_ROOT_NESTED:           pszKind = "ROOT_NESTED"; break;
    882                         case PGMPOOLKIND_EPT_PML4_FOR_EPT_PML4: pszKind = "EPT_PML4_FOR_EPT_PML4"; break;
    883                     }
    8841000                    pHlp->pfnPrintf(pHlp, "#%04x: HCPhys=%RHp GCPhys=%RGp %s %s %s\n",
    8851001                                    iPage, pPage->Core.Key, GCPhys, pPage->fA20Enabled ? "A20 " : "!A20",
    886                                     pszKind, pPage->fMonitored ? " monitored" : "");
     1002                                    pgmPoolPoolKindToStr(enmKind), pPage->fMonitored ? " monitored" : "");
    8871003                    break;
    888                 }
    8891004            }
    8901005            if (!--cLeft)
     
    8941009}
    8951010
    896 
    8971011#ifdef VBOX_WITH_DEBUGGER
     1012
     1013/**
     1014 * Helper for pgmR3PoolCmdCheck that reports an error.
     1015 */
     1016static void pgmR3PoolCheckError(PPGMPOOLCHECKERSTATE pState, const char *pszFormat, ...)
     1017{
     1018    if (pState->fFirstMsg)
     1019    {
     1020        DBGCCmdHlpPrintf(pState->pCmdHlp, "Checking pool page #%i for %RGp %s\n",
     1021                         pState->pPage->idx, pState->pPage->GCPhys, pgmPoolPoolKindToStr(pState->pPage->enmKind));
     1022        pState->fFirstMsg = false;
     1023    }
     1024
     1025    va_list va;
     1026    va_start(va, pszFormat);
     1027    pState->pCmdHlp->pfnPrintfV(pState->pCmdHlp, NULL, pszFormat, va);
     1028    va_end(va);
     1029}
     1030
     1031
    8981032/**
    8991033 * @callback_method_impl{FNDBGCCMD, The '.pgmpoolcheck' command.}
     
    9051039    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    9061040    DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, -1, cArgs == 0);
    907     uint32_t cErrors = 0;
    9081041    NOREF(paArgs);
    9091042
    910     PPGMPOOL pPool = pVM->pgm.s.CTX_SUFF(pPool);
     1043    PGM_LOCK_VOID(pVM);
     1044    PPGMPOOL            pPool = pVM->pgm.s.CTX_SUFF(pPool);
     1045    PGMPOOLCHECKERSTATE State = { pCmdHlp, pVM, pPool, NULL, true, 0 };
    9111046    for (unsigned i = 0; i < pPool->cCurPages; i++)
    9121047    {
    913         PPGMPOOLPAGE    pPage     = &pPool->aPages[i];
    914         bool            fFirstMsg = true;
    915 
    916         /** @todo cover other paging modes too. */
    917         if (pPage->enmKind == PGMPOOLKIND_PAE_PT_FOR_PAE_PT)
     1048        PPGMPOOLPAGE pPage = &pPool->aPages[i];
     1049        State.pPage     = pPage;
     1050        State.fFirstMsg = true;
     1051
     1052        if (pPage->enmKind == PGMPOOLKIND_FREE)
     1053            continue;
     1054        if (pPage->enmKind > PGMPOOLKIND_LAST || pPage->enmKind <= PGMPOOLKIND_INVALID)
    9181055        {
    919             PPGMSHWPTPAE pShwPT = (PPGMSHWPTPAE)PGMPOOL_PAGE_2_PTR(pPool->CTX_SUFF(pVM), pPage);
     1056            pgmR3PoolCheckError(&State, "Invalid enmKind value: %#x\n", pPage->enmKind);
     1057            continue;
     1058        }
     1059
     1060        void const     *pvGuestPage = NULL;
     1061        PGMPAGEMAPLOCK  LockPage;
     1062        if (   pPage->enmKind != PGMPOOLKIND_EPT_PDPT_FOR_PHYS
     1063            && pPage->enmKind != PGMPOOLKIND_EPT_PD_FOR_PHYS
     1064            && pPage->enmKind != PGMPOOLKIND_EPT_PT_FOR_PHYS
     1065            && pPage->enmKind != PGMPOOLKIND_ROOT_NESTED)
     1066        {
     1067            int rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, pPage->GCPhys, &pvGuestPage, &LockPage);
     1068            if (RT_FAILURE(rc))
    9201069            {
    921                 PX86PTPAE       pGstPT;
    922                 PGMPAGEMAPLOCK  LockPage;
    923                 int rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, pPage->GCPhys, (const void **)&pGstPT, &LockPage);     AssertReleaseRC(rc);
    924 
    925                 /* Check if any PTEs are out of sync. */
     1070                pgmR3PoolCheckError(&State, "PGMPhysGCPhys2CCPtrReadOnly failed for %RGp: %Rrc\n", pPage->GCPhys, rc);
     1071                continue;
     1072            }
     1073        }
     1074
     1075        /*
     1076         * Check if something obvious is out of sync.
     1077         */
     1078        switch (pPage->enmKind)
     1079        {
     1080            case PGMPOOLKIND_PAE_PT_FOR_PAE_PT:
     1081            {
     1082                PCPGMSHWPTPAE const pShwPT = (PCPGMSHWPTPAE)PGMPOOL_PAGE_2_PTR(pPool->CTX_SUFF(pVM), pPage);
     1083                PCX86PDPAE const    pGstPT = (PCX86PDPAE)pvGuestPage;
    9261084                for (unsigned j = 0; j < RT_ELEMENTS(pShwPT->a); j++)
    927                 {
    9281085                    if (PGMSHWPTEPAE_IS_P(pShwPT->a[j]))
    9291086                    {
    9301087                        RTHCPHYS HCPhys = NIL_RTHCPHYS;
    931                         rc = PGMPhysGCPhys2HCPhys(pPool->CTX_SUFF(pVM), pGstPT->a[j].u & X86_PTE_PAE_PG_MASK, &HCPhys);
     1088                        int rc = PGMPhysGCPhys2HCPhys(pPool->CTX_SUFF(pVM), pGstPT->a[j].u & X86_PTE_PAE_PG_MASK, &HCPhys);
    9321089                        if (   rc != VINF_SUCCESS
    9331090                            || PGMSHWPTEPAE_GET_HCPHYS(pShwPT->a[j]) != HCPhys)
    934                         {
    935                             if (fFirstMsg)
    936                             {
    937                                 DBGCCmdHlpPrintf(pCmdHlp, "Check pool page %RGp\n", pPage->GCPhys);
    938                                 fFirstMsg = false;
    939                             }
    940                             DBGCCmdHlpPrintf(pCmdHlp, "Mismatch HCPhys: rc=%Rrc idx=%d guest %RX64 shw=%RX64 vs %RHp\n", rc, j, pGstPT->a[j].u, PGMSHWPTEPAE_GET_LOG(pShwPT->a[j]), HCPhys);
    941                             cErrors++;
    942                         }
     1091                            pgmR3PoolCheckError(&State, "Mismatch HCPhys: rc=%Rrc idx=%#x guest %RX64 shw=%RX64 vs %RHp\n",
     1092                                                rc, j, pGstPT->a[j].u, PGMSHWPTEPAE_GET_LOG(pShwPT->a[j]), HCPhys);
    9431093                        else if (   PGMSHWPTEPAE_IS_RW(pShwPT->a[j])
    9441094                                 && !(pGstPT->a[j].u & X86_PTE_RW))
    945                         {
    946                             if (fFirstMsg)
    947                             {
    948                                 DBGCCmdHlpPrintf(pCmdHlp, "Check pool page %RGp\n", pPage->GCPhys);
    949                                 fFirstMsg = false;
    950                             }
    951                             DBGCCmdHlpPrintf(pCmdHlp, "Mismatch r/w gst/shw: idx=%d guest %RX64 shw=%RX64 vs %RHp\n", j, pGstPT->a[j].u, PGMSHWPTEPAE_GET_LOG(pShwPT->a[j]), HCPhys);
    952                             cErrors++;
    953                         }
     1095                            pgmR3PoolCheckError(&State, "Mismatch r/w gst/shw: idx=%#x guest %RX64 shw=%RX64 vs %RHp\n",
     1096                                                j, pGstPT->a[j].u, PGMSHWPTEPAE_GET_LOG(pShwPT->a[j]), HCPhys);
    9541097                    }
    955                 }
    956                 PGMPhysReleasePageMappingLock(pVM, &LockPage);
     1098                break;
    9571099            }
    9581100
    959             /* Make sure this page table can't be written to from any shadow mapping. */
    960             RTHCPHYS HCPhysPT = NIL_RTHCPHYS;
    961             int rc = PGMPhysGCPhys2HCPhys(pPool->CTX_SUFF(pVM), pPage->GCPhys, &HCPhysPT);
    962             AssertMsgRC(rc, ("PGMPhysGCPhys2HCPhys failed with rc=%d for %RGp\n", rc, pPage->GCPhys));
    963             if (rc == VINF_SUCCESS)
     1101            case PGMPOOLKIND_EPT_PT_FOR_EPT_PT:
    9641102            {
    965                 for (unsigned j = 0; j < pPool->cCurPages; j++)
    966                 {
    967                     PPGMPOOLPAGE pTempPage = &pPool->aPages[j];
    968 
    969                     if (pTempPage->enmKind == PGMPOOLKIND_PAE_PT_FOR_PAE_PT)
     1103                PCEPTPT const pShwPT = (PCEPTPT)PGMPOOL_PAGE_2_PTR(pPool->CTX_SUFF(pVM), pPage);
     1104                PCEPTPT const pGstPT = (PCEPTPT)pvGuestPage;
     1105                for (unsigned j = 0; j < RT_ELEMENTS(pShwPT->a); j++)
     1106                    if (pShwPT->a[j].u & EPT_PRESENT_MASK)
    9701107                    {
    971                         PPGMSHWPTPAE pShwPT2 = (PPGMSHWPTPAE)PGMPOOL_PAGE_2_PTR(pPool->CTX_SUFF(pVM), pTempPage);
    972 
    973                         for (unsigned k = 0; k < RT_ELEMENTS(pShwPT->a); k++)
    974                         {
    975                             if (    PGMSHWPTEPAE_IS_P_RW(pShwPT2->a[k])
    976 # ifdef PGMPOOL_WITH_OPTIMIZED_DIRTY_PT
    977                                 &&  !pPage->fDirty
    978 # endif
    979                                 &&  PGMSHWPTEPAE_GET_HCPHYS(pShwPT2->a[k]) == HCPhysPT)
    980                             {
    981                                 if (fFirstMsg)
    982                                 {
    983                                     DBGCCmdHlpPrintf(pCmdHlp, "Check pool page %RGp\n", pPage->GCPhys);
    984                                     fFirstMsg = false;
    985                                 }
    986                                 DBGCCmdHlpPrintf(pCmdHlp, "Mismatch: r/w: GCPhys=%RGp idx=%d shw %RX64 %RX64\n", pTempPage->GCPhys, k, PGMSHWPTEPAE_GET_LOG(pShwPT->a[k]), PGMSHWPTEPAE_GET_LOG(pShwPT2->a[k]));
    987                                 cErrors++;
    988                             }
    989                         }
     1108                        RTHCPHYS HCPhys = NIL_RTHCPHYS;
     1109                        int rc = PGMPhysGCPhys2HCPhys(pPool->CTX_SUFF(pVM), pGstPT->a[j].u & X86_PTE_PAE_PG_MASK, &HCPhys);
     1110                        if (   rc != VINF_SUCCESS
     1111                            || (pShwPT->a[j].u & EPT_E_PG_MASK) != HCPhys)
     1112                            pgmR3PoolCheckError(&State, "Mismatch HCPhys: rc=%Rrc idx=%#x guest %RX64 shw=%RX64 vs %RHp\n",
     1113                                                rc, j, pGstPT->a[j].u, pShwPT->a[j].u, HCPhys);
     1114                        else if (      (pShwPT->a[j].u & (EPT_E_READ | EPT_E_WRITE | EPT_E_EXECUTE))
     1115                                    != (EPT_E_READ | EPT_E_WRITE | EPT_E_EXECUTE)
     1116                                 && (   ((pShwPT->a[j].u & EPT_E_READ)    && !(pGstPT->a[j].u & EPT_E_READ))
     1117                                     || ((pShwPT->a[j].u & EPT_E_WRITE)   && !(pGstPT->a[j].u & EPT_E_WRITE))
     1118                                     || ((pShwPT->a[j].u & EPT_E_EXECUTE) && !(pGstPT->a[j].u & EPT_E_EXECUTE)) ) )
     1119                            pgmR3PoolCheckError(&State, "Mismatch r/w/x: idx=%#x guest %RX64 shw=%RX64\n",
     1120                                                j, pGstPT->a[j].u, pShwPT->a[j].u);
    9901121                    }
    991                 }
     1122                break;
    9921123            }
    9931124        }
    994     }
    995     if (cErrors > 0)
    996         return DBGCCmdHlpFail(pCmdHlp, pCmd, "Found %#x errors", cErrors);
     1125
     1126        if (pvGuestPage)
     1127            PGMPhysReleasePageMappingLock(pVM, &LockPage);
     1128    }
     1129    PGM_UNLOCK(pVM);
     1130
     1131    if (State.cErrors > 0)
     1132        return DBGCCmdHlpFail(pCmdHlp, pCmd, "Found %#x errors", State.cErrors);
    9971133    return VINF_SUCCESS;
    9981134}
     1135
    9991136#endif /* VBOX_WITH_DEBUGGER */
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