VirtualBox

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


Ignore:
Timestamp:
Oct 14, 2022 6:05:15 AM (2 years ago)
Author:
vboxsync
Message:

VMM/PGM: Nested VMX: bugref:10092 Implemented large (2M) page support for EPT PDEs.

Location:
trunk/src/VBox/VMM/VMMR3
Files:
2 edited

Legend:

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

    r97043 r97145  
    17261726               && !(fEptVpidCap & MSR_IA32_VMX_EPT_VPID_CAP_ACCESS_DIRTY));
    17271727        /* We need to shadow reserved bits as guest EPT tables can set them to trigger EPT misconfigs.  */
    1728         pVCpu->pgm.s.fGstEptShadowedPteMask   = GCPhysRsvdAddrMask | EPT_PRESENT_MASK | EPT_E_MEMTYPE_MASK | EPT_E_IGNORE_PAT;
    1729         pVCpu->pgm.s.fGstEptShadowedPdeMask   = GCPhysRsvdAddrMask | EPT_PRESENT_MASK | EPT_E_MEMTYPE_MASK | EPT_E_IGNORE_PAT | EPT_E_LEAF;
    1730         pVCpu->pgm.s.fGstEptShadowedPdpteMask = GCPhysRsvdAddrMask | EPT_PRESENT_MASK | EPT_E_MEMTYPE_MASK | EPT_E_IGNORE_PAT | EPT_E_LEAF;
    1731         pVCpu->pgm.s.fGstEptShadowedPml4eMask = GCPhysRsvdAddrMask | EPT_PRESENT_MASK | EPT_PML4E_MBZ_MASK;
     1728        pVCpu->pgm.s.fGstEptShadowedPteMask    = GCPhysRsvdAddrMask | EPT_PRESENT_MASK | EPT_E_MEMTYPE_MASK | EPT_E_IGNORE_PAT;
     1729        pVCpu->pgm.s.fGstEptShadowedPdeMask    = GCPhysRsvdAddrMask | EPT_PRESENT_MASK;
     1730        pVCpu->pgm.s.fGstEptShadowedBigPdeMask = GCPhysRsvdAddrMask | EPT_PRESENT_MASK | EPT_E_MEMTYPE_MASK | EPT_E_IGNORE_PAT | EPT_E_LEAF;
     1731        pVCpu->pgm.s.fGstEptShadowedPdpteMask  = GCPhysRsvdAddrMask | EPT_PRESENT_MASK | EPT_E_MEMTYPE_MASK | EPT_E_IGNORE_PAT | EPT_E_LEAF;
     1732        pVCpu->pgm.s.fGstEptShadowedPml4eMask  = GCPhysRsvdAddrMask | EPT_PRESENT_MASK | EPT_PML4E_MBZ_MASK;
    17321733        /* If mode-based execute control for EPT is enabled, we would need to include bit 10 in the present mask. */
    17331734        pVCpu->pgm.s.fGstEptPresentMask       = EPT_PRESENT_MASK;
  • trunk/src/VBox/VMM/VMMR3/PGMPool.cpp

    r96957 r97145  
    600600                    }
    601601                    goto default_case;
     602
     603# ifdef VBOX_WITH_NESTED_HWVIRT_VMX_EPT
     604                case PGMPOOLKIND_EPT_PD_FOR_EPT_PD: /* Large pages reference 2 MB of physical memory, so we must clear them. */
     605                    if (pPage->cPresent)
     606                    {
     607                        PEPTPD pShwPD = (PEPTPD)PGMPOOL_PAGE_2_PTR_V2(pPool->CTX_SUFF(pVM), pVCpu, pPage);
     608                        for (unsigned i = 0; i < RT_ELEMENTS(pShwPD->a); i++)
     609                        {
     610                            if (   (pShwPD->a[i].u & EPT_PRESENT_MASK)
     611                                && (pShwPD->a[i].u & EPT_E_LEAF))
     612                            {
     613                                pShwPD->a[i].u = 0;
     614                                Assert(pPage->cPresent);
     615                                pPage->cPresent--;
     616                            }
     617                        }
     618                        if (pPage->cPresent == 0)
     619                            pPage->iFirstPresent = NIL_PGMPOOL_PRESENT_INDEX;
     620                    }
     621                    goto default_case;
     622# endif /* VBOX_WITH_NESTED_HWVIRT_VMX_EPT */
    602623#endif /* PGM_WITH_LARGE_PAGES */
    603624
     
    613634#ifdef VBOX_WITH_NESTED_HWVIRT_VMX_EPT
    614635                case PGMPOOLKIND_EPT_PT_FOR_EPT_PT:
    615                 case PGMPOOLKIND_EPT_PD_FOR_EPT_PD:
     636                case PGMPOOLKIND_EPT_PT_FOR_EPT_2MB:
    616637                case PGMPOOLKIND_EPT_PDPT_FOR_EPT_PDPT:
    617638                case PGMPOOLKIND_EPT_PML4_FOR_EPT_PML4:
     
    622643                        void *pvShw = PGMPOOL_PAGE_2_PTR_V2(pPool->CTX_SUFF(pVM), pVCpu, pPage);
    623644                        STAM_PROFILE_START(&pPool->StatZeroPage, z);
    624 #ifdef VBOX_STRICT
    625                         if (PGMPOOL_PAGE_IS_NESTED(pPage))
    626                         {
    627                             PEPTPT pPT = (PEPTPT)pvShw;
    628                             for (unsigned idxPt = 0; idxPt < RT_ELEMENTS(pPT->a); idxPt++)
    629                                 if (pPT->a[idxPt].u & EPT_PRESENT_MASK)
    630                                     Assert(!(pPT->a[idxPt].u & EPT_E_LEAF));  /* We don't support large pages as of yet. */
    631                         }
    632 #endif
    633645#if 0
    634646                        /* Useful check for leaking references; *very* expensive though. */
     
    792804    AssertRC(rc);
    793805}
     806
     807
     808/**
     809 * Stringifies a PGMPOOLACCESS value.
     810 */
     811static const char *pgmPoolPoolAccessToStr(uint8_t enmAccess)
     812{
     813    switch ((PGMPOOLACCESS)enmAccess)
     814    {
     815        case PGMPOOLACCESS_DONTCARE:         return "DONTCARE";
     816        case PGMPOOLACCESS_USER_RW:          return "USER_RW";
     817        case PGMPOOLACCESS_USER_R:           return "USER_R";
     818        case PGMPOOLACCESS_USER_RW_NX:       return "USER_RW_NX";
     819        case PGMPOOLACCESS_USER_R_NX:        return "USER_R_NX";
     820        case PGMPOOLACCESS_SUPERVISOR_RW:    return "SUPERVISOR_RW";
     821        case PGMPOOLACCESS_SUPERVISOR_R:     return "SUPERVISOR_R";
     822        case PGMPOOLACCESS_SUPERVISOR_RW_NX: return "SUPERVISOR_RW_NX";
     823        case PGMPOOLACCESS_SUPERVISOR_R_NX:  return "SUPERVISOR_R_NX";
     824    }
     825    return "Unknown Access";
     826}
     827
    794828
    795829/**
     
    862896        case PGMPOOLKIND_EPT_PT_FOR_EPT_PT:
    863897            return "EPT_PT_FOR_EPT_PT";
     898        case PGMPOOLKIND_EPT_PT_FOR_EPT_2MB:
     899            return "EPT_PT_FOR_EPT_2MB";
    864900        case PGMPOOLKIND_EPT_PD_FOR_EPT_PD:
    865901            return "EPT_PD_FOR_EPT_PD";
     
    958994            && enmKind != PGMPOOLKIND_FREE)
    959995        {
    960             pHlp->pfnPrintf(pHlp, "#%04x: HCPhys=%RHp GCPhys=%RGp %s %s%s%s\n",
     996            pHlp->pfnPrintf(pHlp, "#%04x: HCPhys=%RHp GCPhys=%RGp %s %s %s%s%s\n",
    961997                            iPage, pPage->Core.Key, GCPhys, pPage->fA20Enabled ? "A20 " : "!A20",
    962998                            pgmPoolPoolKindToStr(enmKind),
    963                             pPage->fCached ? " cached" : "",
    964                             pPage->fMonitored ? " monitored" : "");
     999                            pPage->enmAccess == PGMPOOLACCESS_DONTCARE ? "" : pgmPoolPoolAccessToStr(pPage->enmAccess),
     1000                            pPage->fCached ? " cached" : "", pPage->fMonitored ? " monitored" : "");
    9651001            if (!--cLeft)
    9661002                break;
     
    11261162                                || ((uShw & EPT_E_EXECUTE) && !(uGst & EPT_E_EXECUTE)) ) )
    11271163                            pgmR3PoolCheckError(&State, "Mismatch r/w/x: idx=%#x guest %RX64 shw=%RX64\n", j, uGst, uShw);
     1164                    }
     1165                }
     1166                break;
     1167            }
     1168
     1169            case PGMPOOLKIND_EPT_PT_FOR_EPT_2MB:
     1170            {
     1171                PCEPTPT const pShwPT = (PCEPTPT)PGMPOOL_PAGE_2_PTR(pPool->CTX_SUFF(pVM), pPage);
     1172                for (unsigned j = 0; j < RT_ELEMENTS(pShwPT->a); j++)
     1173                {
     1174                    uint64_t const uShw = pShwPT->a[j].u;
     1175                    if (uShw & EPT_E_LEAF)
     1176                        pgmR3PoolCheckError(&State, "Leafness-error: idx=%#x shw=%RX64 (2MB)\n", j, uShw);
     1177                    else if (uShw & EPT_PRESENT_MASK)
     1178                    {
     1179                        RTGCPHYS const GCPhysSubPage = pPage->GCPhys | (j << PAGE_SHIFT);
     1180                        RTHCPHYS       HCPhys        = NIL_RTHCPHYS;
     1181                        int rc = PGMPhysGCPhys2HCPhys(pPool->CTX_SUFF(pVM), GCPhysSubPage, &HCPhys);
     1182                        if (   rc != VINF_SUCCESS
     1183                            || (uShw & EPT_E_PG_MASK) != HCPhys)
     1184                            pgmR3PoolCheckError(&State, "Mismatch HCPhys: rc=%Rrc idx=%#x guest %RX64 shw=%RX64 vs %RHp\n",
     1185                                                rc, j, GCPhysSubPage, uShw, HCPhys);
    11281186                    }
    11291187                }
     
    11601218                            if (pSubPage)
    11611219                            {
    1162                                 /** @todo adjust for 2M page to shadow PT mapping.   */
    1163                                 if (pSubPage->enmKind != PGMPOOLKIND_EPT_PT_FOR_EPT_PT)
     1220                                if (   pSubPage->enmKind != PGMPOOLKIND_EPT_PT_FOR_EPT_PT
     1221                                    && pSubPage->enmKind != PGMPOOLKIND_EPT_PT_FOR_EPT_2MB)
    11641222                                    pgmR3PoolCheckError(&State, "Wrong sub-table type: idx=%#x guest %RX64 shw=%RX64: idxSub=%#x %s\n",
    11651223                                                        j, uGst, uShw, pSubPage->idx, pgmPoolPoolKindToStr(pSubPage->enmKind));
     
    11731231                            else
    11741232                                pgmR3PoolCheckError(&State, "sub table not found: idx=%#x shw=%RX64\n", j, uShw);
    1175 
    11761233                        }
    11771234                        if (      (uShw & (EPT_E_READ | EPT_E_WRITE | EPT_E_EXECUTE))
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