VirtualBox

Ignore:
Timestamp:
Jul 11, 2018 4:19:48 PM (7 years ago)
Author:
vboxsync
Message:

PGM/DBG: Optimize page scanning to speed up 'detect'.

File:
1 edited

Legend:

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

    r72265 r73073  
    14311431 * @param   pVCpu       The cross context virtual CPU structure of the calling EMT.
    14321432 * @param   GCPtr       The guest virtual address to walk by.
    1433  * @param   pWalk       Where to return the walk result. This is valid on some
     1433 * @param   pWalk       Where to return the walk result. This is valid for some
    14341434 *                      error codes as well.
    14351435 */
     
    14711471            return VERR_PGM_NOT_USED_IN_MODE;
    14721472    }
     1473}
     1474
     1475
     1476/**
     1477 * Tries to continue the previous walk.
     1478 *
     1479 * @note    Requires the caller to hold the PGM lock from the first
     1480 *          pgmGstPtWalk() call to the last pgmGstPtWalkNext() call.  Otherwise
     1481 *          we cannot use the pointers.
     1482 *
     1483 * @returns VBox status code.
     1484 * @retval  VINF_SUCCESS on success.
     1485 * @retval  VERR_PAGE_TABLE_NOT_PRESENT on failure.  Check pWalk for details.
     1486 * @retval  VERR_PGM_NOT_USED_IN_MODE if not paging isn't enabled. @a pWalk is
     1487 *          not valid, except enmType is PGMPTWALKGSTTYPE_INVALID.
     1488 *
     1489 * @param   pVCpu       The cross context virtual CPU structure of the calling EMT.
     1490 * @param   GCPtr       The guest virtual address to walk by.
     1491 * @param   pWalk       Pointer to the previous walk result and where to return
     1492 *                      the result of this walk.  This is valid for some error
     1493 *                      codes as well.
     1494 */
     1495int pgmGstPtWalkNext(PVMCPU pVCpu, RTGCPTR GCPtr, PPGMPTWALKGST pWalk)
     1496{
     1497    /*
     1498     * We can only handle successfully walks.
     1499     * We also limit ourselves to the next page.
     1500     */
     1501    if (   pWalk->u.Core.fSucceeded
     1502        && GCPtr - pWalk->u.Core.GCPtr == PAGE_SIZE)
     1503    {
     1504        Assert(pWalk->u.Core.uLevel == 0);
     1505        if (pWalk->enmType == PGMPTWALKGSTTYPE_AMD64)
     1506        {
     1507            /*
     1508             * AMD64
     1509             */
     1510            if (!pWalk->u.Core.fGigantPage && !pWalk->u.Core.fBigPage)
     1511            {
     1512                /*
     1513                 * We fall back to full walk if the PDE table changes, if any
     1514                 * reserved bits are set, or if the effective page access changes.
     1515                 */
     1516                const uint64_t fPteSame = X86_PTE_P   | X86_PTE_RW | X86_PTE_US     | X86_PTE_PWT
     1517                                        | X86_PTE_PCD | X86_PTE_A  | X86_PTE_PAE_NX;
     1518                const uint64_t fPdeSame = X86_PDE_P   | X86_PDE_RW | X86_PDE_US     | X86_PDE_PWT
     1519                                        | X86_PDE_PCD | X86_PDE_A  | X86_PDE_PAE_NX | X86_PDE_PS;
     1520
     1521                if ((GCPtr >> X86_PD_PAE_SHIFT) == (pWalk->u.Core.GCPtr >> X86_PD_PAE_SHIFT))
     1522                {
     1523                    if (pWalk->u.Amd64.pPte)
     1524                    {
     1525                        X86PTEPAE Pte;
     1526                        Pte.u = pWalk->u.Amd64.pPte[1].u;
     1527                        if (   (Pte.u & fPteSame) == (pWalk->u.Amd64.Pte.u & fPteSame)
     1528                            && !(Pte.u & (pVCpu)->pgm.s.fGstAmd64MbzPteMask))
     1529                        {
     1530
     1531                            pWalk->u.Core.GCPtr  = GCPtr;
     1532                            pWalk->u.Core.GCPhys = Pte.u & X86_PTE_PAE_PG_MASK;
     1533                            pWalk->u.Amd64.Pte.u = Pte.u;
     1534                            pWalk->u.Amd64.pPte++;
     1535                            return VINF_SUCCESS;
     1536                        }
     1537                    }
     1538                }
     1539                else if ((GCPtr >> X86_PDPT_SHIFT) == (pWalk->u.Core.GCPtr >> X86_PDPT_SHIFT))
     1540                {
     1541                    Assert(!((GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK)); /* Must be first PT entry. */
     1542                    if (pWalk->u.Amd64.pPde)
     1543                    {
     1544                        X86PDEPAE Pde;
     1545                        Pde.u = pWalk->u.Amd64.pPde[1].u;
     1546                        if (   (Pde.u & fPdeSame) == (Pde.u & fPdeSame)
     1547                            && !(Pde.u & (pVCpu)->pgm.s.fGstAmd64MbzPdeMask))
     1548                        {
     1549                            /* Get the new PTE and check out the first entry. */
     1550                            int rc = PGM_GCPHYS_2_PTR_BY_VMCPU(pVCpu, PGM_A20_APPLY(pVCpu, (Pde.u & X86_PDE_PAE_PG_MASK)),
     1551                                                               &pWalk->u.Amd64.pPt);
     1552                            if (RT_SUCCESS(rc))
     1553                            {
     1554                                pWalk->u.Amd64.pPte = &pWalk->u.Amd64.pPt->a[0];
     1555                                X86PTEPAE Pte;
     1556                                Pte.u = pWalk->u.Amd64.pPte->u;
     1557                                if (   (Pte.u & fPteSame) == (pWalk->u.Amd64.Pte.u & fPteSame)
     1558                                    && !(Pte.u & (pVCpu)->pgm.s.fGstAmd64MbzPteMask))
     1559                                {
     1560                                    pWalk->u.Core.GCPtr  = GCPtr;
     1561                                    pWalk->u.Core.GCPhys = Pte.u & X86_PTE_PAE_PG_MASK;
     1562                                    pWalk->u.Amd64.Pte.u = Pte.u;
     1563                                    pWalk->u.Amd64.Pde.u = Pde.u;
     1564                                    pWalk->u.Amd64.pPde++;
     1565                                    return VINF_SUCCESS;
     1566                                }
     1567                            }
     1568                        }
     1569                    }
     1570                }
     1571            }
     1572            else if (!pWalk->u.Core.fGigantPage)
     1573            {
     1574                if ((GCPtr & X86_PAGE_2M_BASE_MASK) == (pWalk->u.Core.GCPtr & X86_PAGE_2M_BASE_MASK))
     1575                {
     1576                    pWalk->u.Core.GCPtr   = GCPtr;
     1577                    pWalk->u.Core.GCPhys += PAGE_SIZE;
     1578                    return VINF_SUCCESS;
     1579                }
     1580            }
     1581            else
     1582            {
     1583                if ((GCPtr & X86_PAGE_1G_BASE_MASK) == (pWalk->u.Core.GCPtr & X86_PAGE_1G_BASE_MASK))
     1584                {
     1585                    pWalk->u.Core.GCPtr   = GCPtr;
     1586                    pWalk->u.Core.GCPhys += PAGE_SIZE;
     1587                    return VINF_SUCCESS;
     1588                }
     1589            }
     1590        }
     1591    }
     1592    /* Case we don't handle.  Do full walk. */
     1593    return pgmGstPtWalk(pVCpu, GCPtr, pWalk);
    14731594}
    14741595
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