VirtualBox

Ignore:
Timestamp:
Feb 11, 2008 6:17:52 PM (17 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
28057
Message:

Moved PGMHandlerPhysicalPageTempOff, PGMHandlerPhysicalPageReset, PGMHandlerPhysicalIsRegistered,
pgmHandlerVirtualDumpPhysPages and PGMAssertHandlerAndFlagsInSync from PGMAll.cpp to PGMAllHandler.cpp.

File:
1 edited

Legend:

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

    r6905 r6906  
    779779
    780780/**
    781  * Temporarily turns off the access monitoring of a page within a monitored
    782  * physical write/all page access handler region.
    783  *
    784  * Use this when no further \#PFs are required for that page. Be aware that
    785  * a page directory sync might reset the flags, and turn on access monitoring
    786  * for the page.
    787  *
    788  * The caller must do required page table modifications.
    789  *
    790  * @returns VBox status code.
    791  * @param   pVM         VM Handle
    792  * @param   GCPhys      Start physical address earlier passed to PGMR3HandlerPhysicalRegister().
    793  *                      This must be a fully page aligned range or we risk messing up other
    794  *                      handlers installed for the start and end pages.
    795  * @param   GCPhysPage  Physical address of the page to turn off access monitoring for.
    796  * @todo move to PGMAllHandler.cpp
    797  */
    798 PGMDECL(int)  PGMHandlerPhysicalPageTempOff(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS GCPhysPage)
    799 {
    800     /*
    801      * Validate the range.
    802      */
    803     PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTXSUFF(pTrees)->PhysHandlers, GCPhys);
    804     if (pCur)
    805     {
    806         if (    GCPhysPage >= pCur->Core.Key
    807             &&  GCPhysPage <= pCur->Core.KeyLast)
    808         {
    809             Assert(!(pCur->Core.Key & PAGE_OFFSET_MASK));
    810             Assert((pCur->Core.KeyLast & PAGE_OFFSET_MASK) == PAGE_OFFSET_MASK);
    811 
    812             AssertReturn(   pCur->enmType == PGMPHYSHANDLERTYPE_PHYSICAL_WRITE
    813                          || pCur->enmType == PGMPHYSHANDLERTYPE_PHYSICAL_ALL,
    814                          VERR_ACCESS_DENIED);
    815 
    816             /*
    817              * Change the page status.
    818              */
    819             PPGMPAGE pPage;
    820             int rc = pgmPhysGetPageEx(&pVM->pgm.s, GCPhysPage, &pPage);
    821             AssertRCReturn(rc, rc);
    822             PGM_PAGE_SET_HNDL_PHYS_STATE(pPage, PGM_PAGE_HNDL_PHYS_STATE_DISABLED);
    823             return VINF_SUCCESS;
    824         }
    825 
    826         AssertMsgFailed(("The page %#x is outside the range %#x-%#x\n",
    827                          GCPhysPage, pCur->Core.Key, pCur->Core.KeyLast));
    828         return VERR_INVALID_PARAMETER;
    829     }
    830 
    831     AssertMsgFailed(("Specified physical handler start address %#x is invalid.\n", GCPhys));
    832     return VERR_PGM_HANDLER_NOT_FOUND;
    833 }
    834 
    835 
    836 /**
    837  * Turns access monitoring of a page within a monitored
    838  * physical write/all page access handler regio back on.
    839  *
    840  * The caller must do required page table modifications.
    841  *
    842  * @returns VBox status code.
    843  * @param   pVM         VM Handle
    844  * @param   GCPhys      Start physical address earlier passed to PGMR3HandlerPhysicalRegister().
    845  *                      This must be a fully page aligned range or we risk messing up other
    846  *                      handlers installed for the start and end pages.
    847  * @param   GCPhysPage  Physical address of the page to turn on access monitoring for.
    848  * @todo move to PGMAllHandler.cpp
    849  */
    850 PGMDECL(int)  PGMHandlerPhysicalPageReset(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS GCPhysPage)
    851 {
    852     /*
    853      * Validate the range.
    854      */
    855     PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTXSUFF(pTrees)->PhysHandlers, GCPhys);
    856     if (pCur)
    857     {
    858         if (    GCPhysPage >= pCur->Core.Key
    859             &&  GCPhysPage <= pCur->Core.KeyLast)
    860         {
    861             Assert(!(pCur->Core.Key & PAGE_OFFSET_MASK));
    862             Assert((pCur->Core.KeyLast & PAGE_OFFSET_MASK) == PAGE_OFFSET_MASK);
    863 
    864             AssertReturn(   pCur->enmType == PGMPHYSHANDLERTYPE_PHYSICAL_WRITE
    865                          || pCur->enmType == PGMPHYSHANDLERTYPE_PHYSICAL_ALL,
    866                          VERR_ACCESS_DENIED);
    867 
    868             /*
    869              * Change the page status.
    870              */
    871             PPGMPAGE pPage;
    872             int rc = pgmPhysGetPageEx(&pVM->pgm.s, GCPhysPage, &pPage);
    873             AssertRCReturn(rc, rc);
    874             PGM_PAGE_SET_HNDL_PHYS_STATE(pPage, pgmHandlerPhysicalCalcState(pCur));
    875             return VINF_SUCCESS;
    876         }
    877 
    878         AssertMsgFailed(("The page %#x is outside the range %#x-%#x\n",
    879                          GCPhysPage, pCur->Core.Key, pCur->Core.KeyLast));
    880         return VERR_INVALID_PARAMETER;
    881     }
    882 
    883     AssertMsgFailed(("Specified physical handler start address %#x is invalid.\n", GCPhys));
    884     return VERR_PGM_HANDLER_NOT_FOUND;
    885 }
    886 
    887 
    888 /**
    889  * Checks if a physical range is handled
    890  *
    891  * @returns boolean
    892  * @param   pVM         VM Handle
    893  * @param   GCPhys      Start physical address earlier passed to PGMR3HandlerPhysicalRegister().
    894  * @todo move to PGMAllHandler.cpp
    895  */
    896 PGMDECL(bool) PGMHandlerPhysicalIsRegistered(PVM pVM, RTGCPHYS GCPhys)
    897 {
    898     /*
    899      * Find the handler.
    900      */
    901     PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysRangeGet(&pVM->pgm.s.CTXSUFF(pTrees)->PhysHandlers, GCPhys);
    902     if (pCur)
    903     {
    904         if (    GCPhys >= pCur->Core.Key
    905             &&  GCPhys <= pCur->Core.KeyLast)
    906         {
    907             Assert(     pCur->enmType == PGMPHYSHANDLERTYPE_PHYSICAL_WRITE
    908                    ||   pCur->enmType == PGMPHYSHANDLERTYPE_PHYSICAL_ALL
    909                    ||   pCur->enmType == PGMPHYSHANDLERTYPE_MMIO);
    910             return true;
    911         }
    912     }
    913 
    914     return false;
    915 }
    916 
    917 
    918 #ifdef VBOX_STRICT
    919 DECLCALLBACK(int) pgmVirtHandlerDumpPhysRange(PAVLROGCPHYSNODECORE pNode, void *pvUser)
    920 {
    921     PPGMPHYS2VIRTHANDLER pCur = (PPGMPHYS2VIRTHANDLER)pNode;
    922     PPGMVIRTHANDLER      pVirt = (PPGMVIRTHANDLER)((uintptr_t)pCur + pCur->offVirtHandler);
    923     Log(("PHYS2VIRT: Range %VGp-%VGp for virtual handler: %s\n", pCur->Core.Key, pCur->Core.KeyLast, pVirt->pszDesc));
    924     return 0;
    925 }
    926 
    927 
    928 void pgmHandlerVirtualDumpPhysPages(PVM pVM)
    929 {
    930     RTAvlroGCPhysDoWithAll(CTXSUFF(&pVM->pgm.s.pTrees)->PhysToVirtHandlers, true, pgmVirtHandlerDumpPhysRange, 0);
    931 }
    932 #endif /* VBOX_STRICT */
    933 
    934 
    935 /**
    936781 * Gets the current CR3 register value for the shadow memory context.
    937782 * @returns CR3 value.
     
    13761221
    13771222/**
    1378  * State structure used by the PGMAssertHandlerAndFlagsInSync() function
    1379  * and its AVL enumerators.
    1380  */
    1381 typedef struct PGMAHAFIS
    1382 {
    1383     /** The VM handle. */
    1384     PVM         pVM;
    1385     /** Number of errors. */
    1386     unsigned    cErrors;
    1387     /** The flags we've found. */
    1388     unsigned    fFlagsFound;
    1389     /** The flags we're matching up to.
    1390      * This is also on the stack as a const, thus only valid during enumeration. */
    1391     unsigned    fFlags;
    1392     /** The current physical address. */
    1393     RTGCPHYS    GCPhys;
    1394 } PGMAHAFIS, *PPGMAHAFIS;
    1395 
    1396 /**
    1397  * Verify virtual handler by matching physical address.
    1398  *
    1399  * @returns 0
    1400  * @param   pNode   Pointer to a PGMVIRTHANDLER.
    1401  * @param   pvUser  Pointer to user parameter.
    1402  */
    1403 static DECLCALLBACK(int) pgmVirtHandlerVerifyOneByPhysAddr(PAVLROGCPTRNODECORE pNode, void *pvUser)
    1404 {
    1405     PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)pNode;
    1406     PPGMAHAFIS      pState = (PPGMAHAFIS)pvUser;
    1407 
    1408     for (unsigned iPage = 0; iPage < pCur->cPages; iPage++)
    1409     {
    1410         if ((pCur->aPhysToVirt[iPage].Core.Key & X86_PTE_PAE_PG_MASK) == pState->GCPhys)
    1411         {
    1412             switch (pCur->enmType)
    1413             {
    1414                 case PGMVIRTHANDLERTYPE_EIP:
    1415                 case PGMVIRTHANDLERTYPE_NORMAL:     pState->fFlagsFound |= MM_RAM_FLAGS_VIRTUAL_HANDLER; break;
    1416                 case PGMVIRTHANDLERTYPE_WRITE:      pState->fFlagsFound |= MM_RAM_FLAGS_VIRTUAL_HANDLER | MM_RAM_FLAGS_VIRTUAL_WRITE; break;
    1417                 case PGMVIRTHANDLERTYPE_ALL:        pState->fFlagsFound |= MM_RAM_FLAGS_VIRTUAL_HANDLER | MM_RAM_FLAGS_VIRTUAL_ALL; break;
    1418                 /* hypervisor handlers need no flags and wouldn't have nowhere to put them in any case. */
    1419                 case PGMVIRTHANDLERTYPE_HYPERVISOR:
    1420                     return 0;
    1421             }
    1422             if (    (pState->fFlags & (MM_RAM_FLAGS_VIRTUAL_HANDLER  | MM_RAM_FLAGS_VIRTUAL_WRITE  | MM_RAM_FLAGS_VIRTUAL_ALL))
    1423                 ==  pState->fFlagsFound)
    1424                 break;
    1425         }
    1426     }
    1427     return 0;
    1428 }
    1429 
    1430 
    1431 /**
    1432  * Verify a virtual handler.
    1433  *
    1434  * @returns 0
    1435  * @param   pNode   Pointer to a PGMVIRTHANDLER.
    1436  * @param   pvUser  Pointer to user parameter.
    1437  */
    1438 static DECLCALLBACK(int) pgmVirtHandlerVerifyOne(PAVLROGCPTRNODECORE pNode, void *pvUser)
    1439 {
    1440     PPGMVIRTHANDLER pVirt   = (PPGMVIRTHANDLER)pNode;
    1441     PPGMAHAFIS      pState = (PPGMAHAFIS)pvUser;
    1442     PVM             pVM     = pState->pVM;
    1443 
    1444     if (    pVirt->aPhysToVirt[0].Core.Key != NIL_RTGCPHYS
    1445         &&  (pVirt->aPhysToVirt[0].Core.Key & PAGE_OFFSET_MASK) != ((RTGCUINTPTR)pVirt->GCPtr & PAGE_OFFSET_MASK))
    1446     {
    1447         AssertMsgFailed(("virt handler phys out has incorrect key! %VGp %VGv %s\n",
    1448                          pVirt->aPhysToVirt[0].Core.Key, pVirt->GCPtr, HCSTRING(pVirt->pszDesc)));
    1449         pState->cErrors++;
    1450     }
    1451 
    1452     /*
    1453      * Calc flags.
    1454      */
    1455     unsigned    fFlags;
    1456     switch (pVirt->enmType)
    1457     {
    1458         case PGMVIRTHANDLERTYPE_EIP:
    1459         case PGMVIRTHANDLERTYPE_NORMAL:     fFlags = MM_RAM_FLAGS_VIRTUAL_HANDLER; break;
    1460         case PGMVIRTHANDLERTYPE_WRITE:      fFlags = MM_RAM_FLAGS_VIRTUAL_HANDLER | MM_RAM_FLAGS_VIRTUAL_WRITE; break;
    1461         case PGMVIRTHANDLERTYPE_ALL:        fFlags = MM_RAM_FLAGS_VIRTUAL_HANDLER | MM_RAM_FLAGS_VIRTUAL_ALL; break;
    1462         /* hypervisor handlers need no flags and wouldn't have nowhere to put them in any case. */
    1463         case PGMVIRTHANDLERTYPE_HYPERVISOR:
    1464             return 0;
    1465         default:
    1466             AssertMsgFailed(("unknown enmType=%d\n", pVirt->enmType));
    1467             return 0;
    1468     }
    1469 
    1470     /*
    1471      * Check pages against flags.
    1472      */
    1473     RTGCUINTPTR   GCPtr = (RTGCUINTPTR)pVirt->GCPtr;
    1474     for (unsigned iPage = 0; iPage < pVirt->cPages; iPage++, GCPtr += PAGE_SIZE)
    1475     {
    1476         RTGCPHYS   GCPhysGst;
    1477         uint64_t   fGst;
    1478         int rc = PGMGstGetPage(pVM, (RTGCPTR)GCPtr, &fGst, &GCPhysGst);
    1479         if (    rc == VERR_PAGE_NOT_PRESENT
    1480             ||  rc == VERR_PAGE_TABLE_NOT_PRESENT)
    1481         {
    1482             if (pVirt->aPhysToVirt[iPage].Core.Key != NIL_RTGCPHYS)
    1483             {
    1484                 AssertMsgFailed(("virt handler phys out of sync. %VGp GCPhysNew=~0 iPage=%#x %VGv %s\n",
    1485                                  pVirt->aPhysToVirt[iPage].Core.Key, iPage, GCPtr, HCSTRING(pVirt->pszDesc)));
    1486                 pState->cErrors++;
    1487             }
    1488             continue;
    1489         }
    1490 
    1491         AssertRCReturn(rc, 0);
    1492         if ((pVirt->aPhysToVirt[iPage].Core.Key & X86_PTE_PAE_PG_MASK) != GCPhysGst)
    1493         {
    1494             AssertMsgFailed(("virt handler phys out of sync. %VGp GCPhysGst=%VGp iPage=%#x %VGv %s\n",
    1495                              pVirt->aPhysToVirt[iPage].Core.Key, GCPhysGst, iPage, GCPtr, HCSTRING(pVirt->pszDesc)));
    1496             pState->cErrors++;
    1497             continue;
    1498         }
    1499 
    1500         PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, GCPhysGst);
    1501         if (!pPage)
    1502         {
    1503             AssertMsgFailed(("virt handler getting ram flags. GCPhysGst=%VGp iPage=%#x %VGv %s\n",
    1504                              GCPhysGst, iPage, GCPtr, HCSTRING(pVirt->pszDesc)));
    1505             pState->cErrors++;
    1506             continue;
    1507         }
    1508 
    1509         if ((pPage->HCPhys & fFlags) != fFlags) /** @todo PAGE FLAGS */
    1510         {
    1511             AssertMsgFailed(("virt handler flags mismatch. HCPhys=%VHp fFlags=%#x GCPhysGst=%VGp iPage=%#x %VGv %s\n",
    1512                              pPage->HCPhys, fFlags, GCPhysGst, iPage, GCPtr, HCSTRING(pVirt->pszDesc)));
    1513             pState->cErrors++;
    1514             continue;
    1515         }
    1516     } /* for pages in virtual mapping. */
    1517 
    1518     return 0;
    1519 }
    1520 
    1521 
    1522 /**
    1523  * Asserts that the handlers+guest-page-tables == ramrange-flags and
    1524  * that the physical addresses associated with virtual handlers are correct.
    1525  *
    1526  * @returns Number of mismatches.
    1527  * @param   pVM     The VM handle.
    1528  */
    1529 PGMDECL(unsigned) PGMAssertHandlerAndFlagsInSync(PVM pVM)
    1530 {
    1531     PPGM        pPGM = &pVM->pgm.s;
    1532     PGMAHAFIS   State;
    1533     State.cErrors = 0;
    1534     State.pVM     = pVM;
    1535 
    1536     /*
    1537      * Check the RAM flags against the handlers.
    1538      */
    1539     for (PPGMRAMRANGE pRam = CTXALLSUFF(pPGM->pRamRanges); pRam; pRam = CTXALLSUFF(pRam->pNext))
    1540     {
    1541         const unsigned cPages = pRam->cb >> PAGE_SHIFT;
    1542         for (unsigned iPage = 0; iPage < cPages; iPage++)
    1543         {
    1544             PGMPAGE const *pPage = &pRam->aPages[iPage];
    1545             if (PGM_PAGE_HAVE_ANY_HANDLERS(pPage))
    1546             {
    1547                 State.GCPhys = pRam->GCPhys + (iPage << PAGE_SHIFT);
    1548                 State.fFlagsFound = 0; /* build flags and compare. */
    1549 
    1550                 /*
    1551                  * Physical first - calculate the state based on the handlers
    1552                  *                  active on the page, then compare.
    1553                  */
    1554                 if (PGM_PAGE_HAVE_ANY_PHYSICAL_HANDLERS(pPage))
    1555                 {
    1556                     /* the first */
    1557                     PPGMPHYSHANDLER pPhys = (PPGMPHYSHANDLER)RTAvlroGCPhysRangeGet(&pPGM->CTXSUFF(pTrees)->PhysHandlers, State.GCPhys);
    1558                     if (!pPhys)
    1559                     {
    1560                         pPhys = (PPGMPHYSHANDLER)RTAvlroGCPhysGetBestFit(&pPGM->CTXSUFF(pTrees)->PhysHandlers, State.GCPhys, true);
    1561                         if (    pPhys
    1562                             &&  pPhys->Core.Key > (State.GCPhys + PAGE_SIZE - 1))
    1563                             pPhys = NULL;
    1564                         Assert(!pPhys || pPhys->Core.Key >= State.GCPhys);
    1565                     }
    1566                     if (pPhys)
    1567                     {
    1568                         unsigned uState = pgmHandlerPhysicalCalcState(pPhys);
    1569 
    1570                         /* more? */
    1571                         while (pPhys->Core.KeyLast < (State.GCPhys | PAGE_OFFSET_MASK))
    1572                         {
    1573                             PPGMPHYSHANDLER pPhys2 = (PPGMPHYSHANDLER)RTAvlroGCPhysGetBestFit(&pPGM->CTXSUFF(pTrees)->PhysHandlers,
    1574                                                                                               pPhys->Core.KeyLast + 1, true);
    1575                             if (    !pPhys2
    1576                                 ||  pPhys2->Core.Key > (State.GCPhys | PAGE_OFFSET_MASK))
    1577                                 break;
    1578                             unsigned uState2 = pgmHandlerPhysicalCalcState(pPhys2);
    1579                             uState = RT_MAX(uState, uState2);
    1580                             pPhys = pPhys2;
    1581                         }
    1582 
    1583                         /* compare.*/
    1584                         if (    PGM_PAGE_GET_HNDL_PHYS_STATE(pPage) != uState
    1585                             &&  PGM_PAGE_GET_HNDL_PHYS_STATE(pPage) != PGM_PAGE_HNDL_PHYS_STATE_DISABLED)
    1586                         {
    1587                             AssertMsgFailed(("ram range vs phys handler flags mismatch. GCPhys=%RGp state=%d expected=%d %s\n",
    1588                                              State.GCPhys, PGM_PAGE_GET_HNDL_PHYS_STATE(pPage), uState, pPhys->pszDesc));
    1589                             State.cErrors++;
    1590                         }
    1591 
    1592 #ifdef IN_RING3
    1593                         /* validate that REM is handling it. */
    1594                         if (    !REMR3IsPageAccessHandled(pVM, State.GCPhys)
    1595                                 /* ignore shadowed ROM for the time being. */ /// @todo PAGE FLAGS
    1596                             &&  (pPage->HCPhys & (MM_RAM_FLAGS_ROM | MM_RAM_FLAGS_MMIO2)) != (MM_RAM_FLAGS_ROM | MM_RAM_FLAGS_MMIO2))
    1597                         {
    1598                             AssertMsgFailed(("ram range vs phys handler REM mismatch. GCPhys=%RGp state=%d %s\n",
    1599                                              State.GCPhys, PGM_PAGE_GET_HNDL_PHYS_STATE(pPage), pPhys->pszDesc));
    1600                             State.cErrors++;
    1601                         }
    1602 #endif
    1603                     }
    1604                     else
    1605                     {
    1606                         AssertMsgFailed(("ram range vs phys handler mismatch. no handler for GCPhys=%RGp\n", State.GCPhys));
    1607                         State.cErrors++;
    1608                     }
    1609                 }
    1610 
    1611                 /* virtual flags. */
    1612                 if (PGM_PAGE_HAVE_ACTIVE_VIRTUAL_HANDLERS(pPage))
    1613                 {
    1614                     State.fFlags = pPage->HCPhys & (MM_RAM_FLAGS_VIRTUAL_HANDLER  | MM_RAM_FLAGS_VIRTUAL_WRITE  | MM_RAM_FLAGS_VIRTUAL_ALL); /// @todo PAGE FLAGS
    1615                     RTAvlroGCPtrDoWithAll(CTXSUFF(&pVM->pgm.s.pTrees)->VirtHandlers, true, pgmVirtHandlerVerifyOneByPhysAddr, &State);
    1616                     if (State.fFlags !=  State.fFlagsFound)
    1617                     {
    1618                         AssertMsgFailed(("ram range vs virt handler flags mismatch. GCPhys=%RGp fFlags=%#x fFlagsFound=%#x\n",
    1619                                          State.GCPhys, State.fFlags, State.fFlagsFound));
    1620                         State.cErrors++;
    1621                     }
    1622 
    1623                 }
    1624             }
    1625         } /* foreach page in ram range. */
    1626     } /* foreach ram range. */
    1627 
    1628     /*
    1629      * Check that the physical addresses of the virtual handlers matches up.
    1630      */
    1631     RTAvlroGCPtrDoWithAll(CTXSUFF(&pVM->pgm.s.pTrees)->VirtHandlers, true, pgmVirtHandlerVerifyOne, &State);
    1632 
    1633     /*
    1634      * Do the reverse check for physical handlers.
    1635      */
    1636     /** @todo */
    1637 
    1638     return State.cErrors;
    1639 }
    1640 
    1641 
    1642 /**
    16431223 * Asserts that there are no mapping conflicts.
    16441224 *
Note: See TracChangeset for help on using the changeset viewer.

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