VirtualBox

Changeset 6906 in vbox


Ignore:
Timestamp:
Feb 11, 2008 6:17:52 PM (17 years ago)
Author:
vboxsync
Message:

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

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/PGMInternal.h

    r6902 r6906  
    24792479int             pgmHandlerVirtualFindByPhysAddr(PVM pVM, RTGCPHYS GCPhys, PPGMVIRTHANDLER *ppVirt, unsigned *piPage);
    24802480DECLCALLBACK(int) pgmHandlerVirtualResetOne(PAVLROGCPTRNODECORE pNode, void *pvUser);
    2481 #ifdef VBOX_STRICT
     2481#if defined(VBOX_STRICT) || defined(LOG_ENABLED)
    24822482void            pgmHandlerVirtualDumpPhysPages(PVM pVM);
    24832483#else
  • 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 *
  • trunk/src/VBox/VMM/VMMAll/PGMAllHandler.cpp

    r6902 r6906  
    863863    pgmUnlock(pVM);
    864864    return rc;
     865}
     866
     867
     868/**
     869 * Temporarily turns off the access monitoring of a page within a monitored
     870 * physical write/all page access handler region.
     871 *
     872 * Use this when no further \#PFs are required for that page. Be aware that
     873 * a page directory sync might reset the flags, and turn on access monitoring
     874 * for the page.
     875 *
     876 * The caller must do required page table modifications.
     877 *
     878 * @returns VBox status code.
     879 * @param   pVM         VM Handle
     880 * @param   GCPhys      Start physical address earlier passed to PGMR3HandlerPhysicalRegister().
     881 *                      This must be a fully page aligned range or we risk messing up other
     882 *                      handlers installed for the start and end pages.
     883 * @param   GCPhysPage  Physical address of the page to turn off access monitoring for.
     884 */
     885PGMDECL(int)  PGMHandlerPhysicalPageTempOff(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS GCPhysPage)
     886{
     887    /*
     888     * Validate the range.
     889     */
     890    PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTXSUFF(pTrees)->PhysHandlers, GCPhys);
     891    if (pCur)
     892    {
     893        if (    GCPhysPage >= pCur->Core.Key
     894            &&  GCPhysPage <= pCur->Core.KeyLast)
     895        {
     896            Assert(!(pCur->Core.Key & PAGE_OFFSET_MASK));
     897            Assert((pCur->Core.KeyLast & PAGE_OFFSET_MASK) == PAGE_OFFSET_MASK);
     898
     899            AssertReturn(   pCur->enmType == PGMPHYSHANDLERTYPE_PHYSICAL_WRITE
     900                         || pCur->enmType == PGMPHYSHANDLERTYPE_PHYSICAL_ALL,
     901                         VERR_ACCESS_DENIED);
     902
     903            /*
     904             * Change the page status.
     905             */
     906            PPGMPAGE pPage;
     907            int rc = pgmPhysGetPageEx(&pVM->pgm.s, GCPhysPage, &pPage);
     908            AssertRCReturn(rc, rc);
     909            PGM_PAGE_SET_HNDL_PHYS_STATE(pPage, PGM_PAGE_HNDL_PHYS_STATE_DISABLED);
     910            return VINF_SUCCESS;
     911        }
     912
     913        AssertMsgFailed(("The page %#x is outside the range %#x-%#x\n",
     914                         GCPhysPage, pCur->Core.Key, pCur->Core.KeyLast));
     915        return VERR_INVALID_PARAMETER;
     916    }
     917
     918    AssertMsgFailed(("Specified physical handler start address %#x is invalid.\n", GCPhys));
     919    return VERR_PGM_HANDLER_NOT_FOUND;
     920}
     921
     922
     923/**
     924 * Turns access monitoring of a page within a monitored
     925 * physical write/all page access handler regio back on.
     926 *
     927 * The caller must do required page table modifications.
     928 *
     929 * @returns VBox status code.
     930 * @param   pVM         VM Handle
     931 * @param   GCPhys      Start physical address earlier passed to PGMR3HandlerPhysicalRegister().
     932 *                      This must be a fully page aligned range or we risk messing up other
     933 *                      handlers installed for the start and end pages.
     934 * @param   GCPhysPage  Physical address of the page to turn on access monitoring for.
     935 */
     936PGMDECL(int)  PGMHandlerPhysicalPageReset(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS GCPhysPage)
     937{
     938    /*
     939     * Validate the range.
     940     */
     941    PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysGet(&pVM->pgm.s.CTXSUFF(pTrees)->PhysHandlers, GCPhys);
     942    if (pCur)
     943    {
     944        if (    GCPhysPage >= pCur->Core.Key
     945            &&  GCPhysPage <= pCur->Core.KeyLast)
     946        {
     947            Assert(!(pCur->Core.Key & PAGE_OFFSET_MASK));
     948            Assert((pCur->Core.KeyLast & PAGE_OFFSET_MASK) == PAGE_OFFSET_MASK);
     949
     950            AssertReturn(   pCur->enmType == PGMPHYSHANDLERTYPE_PHYSICAL_WRITE
     951                         || pCur->enmType == PGMPHYSHANDLERTYPE_PHYSICAL_ALL,
     952                         VERR_ACCESS_DENIED);
     953
     954            /*
     955             * Change the page status.
     956             */
     957            PPGMPAGE pPage;
     958            int rc = pgmPhysGetPageEx(&pVM->pgm.s, GCPhysPage, &pPage);
     959            AssertRCReturn(rc, rc);
     960            PGM_PAGE_SET_HNDL_PHYS_STATE(pPage, pgmHandlerPhysicalCalcState(pCur));
     961            return VINF_SUCCESS;
     962        }
     963
     964        AssertMsgFailed(("The page %#x is outside the range %#x-%#x\n",
     965                         GCPhysPage, pCur->Core.Key, pCur->Core.KeyLast));
     966        return VERR_INVALID_PARAMETER;
     967    }
     968
     969    AssertMsgFailed(("Specified physical handler start address %#x is invalid.\n", GCPhys));
     970    return VERR_PGM_HANDLER_NOT_FOUND;
     971}
     972
     973
     974/**
     975 * Checks if a physical range is handled
     976 *
     977 * @returns boolean
     978 * @param   pVM         VM Handle
     979 * @param   GCPhys      Start physical address earlier passed to PGMR3HandlerPhysicalRegister().
     980 */
     981PGMDECL(bool) PGMHandlerPhysicalIsRegistered(PVM pVM, RTGCPHYS GCPhys)
     982{
     983    /*
     984     * Find the handler.
     985     */
     986    PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysRangeGet(&pVM->pgm.s.CTXSUFF(pTrees)->PhysHandlers, GCPhys);
     987    if (pCur)
     988    {
     989        if (    GCPhys >= pCur->Core.Key
     990            &&  GCPhys <= pCur->Core.KeyLast)
     991        {
     992            Assert(     pCur->enmType == PGMPHYSHANDLERTYPE_PHYSICAL_WRITE
     993                   ||   pCur->enmType == PGMPHYSHANDLERTYPE_PHYSICAL_ALL
     994                   ||   pCur->enmType == PGMPHYSHANDLERTYPE_MMIO);
     995            return true;
     996        }
     997    }
     998
     999    return false;
    8651000}
    8661001
     
    10271162}
    10281163
     1164
     1165#if defined(VBOX_STRICT) || defined(LOG_ENABLED)
     1166/**
     1167 * Worker for pgmHandlerVirtualDumpPhysPages.
     1168 *
     1169 * @returns 0 (continue enumeration).
     1170 * @param   pNode       The virtual handler node.
     1171 * @param   pvUser      User argument, unused.
     1172 */
     1173static DECLCALLBACK(int) pgmHandlerVirtualDumpPhysPagesCallback(PAVLROGCPHYSNODECORE pNode, void *pvUser)
     1174{
     1175    PPGMPHYS2VIRTHANDLER pCur = (PPGMPHYS2VIRTHANDLER)pNode;
     1176    PPGMVIRTHANDLER      pVirt = (PPGMVIRTHANDLER)((uintptr_t)pCur + pCur->offVirtHandler);
     1177    Log(("PHYS2VIRT: Range %VGp-%VGp for virtual handler: %s\n", pCur->Core.Key, pCur->Core.KeyLast, pVirt->pszDesc));
     1178    return 0;
     1179}
     1180
     1181
     1182/**
     1183 * Assertion / logging helper for dumping all the
     1184 * virtual handlers to the log.
     1185 *
     1186 * @param   pVM         Pointer to the shared VM structure.
     1187 */
     1188void pgmHandlerVirtualDumpPhysPages(PVM pVM)
     1189{
     1190    RTAvlroGCPhysDoWithAll(CTXSUFF(&pVM->pgm.s.pTrees)->PhysToVirtHandlers, true /* from left */,
     1191                           pgmHandlerVirtualDumpPhysPagesCallback, 0);
     1192}
     1193#endif /* VBOX_STRICT || LOG_ENABLED */
     1194
     1195#ifdef VBOX_STRICT
     1196
     1197/**
     1198 * State structure used by the PGMAssertHandlerAndFlagsInSync() function
     1199 * and its AVL enumerators.
     1200 */
     1201typedef struct PGMAHAFIS
     1202{
     1203    /** The VM handle. */
     1204    PVM         pVM;
     1205    /** Number of errors. */
     1206    unsigned    cErrors;
     1207    /** The flags we've found. */
     1208    unsigned    fFlagsFound;
     1209    /** The flags we're matching up to.
     1210     * This is also on the stack as a const, thus only valid during enumeration. */
     1211    unsigned    fFlags;
     1212    /** The current physical address. */
     1213    RTGCPHYS    GCPhys;
     1214} PGMAHAFIS, *PPGMAHAFIS;
     1215
     1216/**
     1217 * Verify virtual handler by matching physical address.
     1218 *
     1219 * @returns 0
     1220 * @param   pNode   Pointer to a PGMVIRTHANDLER.
     1221 * @param   pvUser  Pointer to user parameter.
     1222 */
     1223static DECLCALLBACK(int) pgmVirtHandlerVerifyOneByPhysAddr(PAVLROGCPTRNODECORE pNode, void *pvUser)
     1224{
     1225    PPGMVIRTHANDLER pCur = (PPGMVIRTHANDLER)pNode;
     1226    PPGMAHAFIS      pState = (PPGMAHAFIS)pvUser;
     1227
     1228    for (unsigned iPage = 0; iPage < pCur->cPages; iPage++)
     1229    {
     1230        if ((pCur->aPhysToVirt[iPage].Core.Key & X86_PTE_PAE_PG_MASK) == pState->GCPhys)
     1231        {
     1232            switch (pCur->enmType)
     1233            {
     1234                case PGMVIRTHANDLERTYPE_EIP:
     1235                case PGMVIRTHANDLERTYPE_NORMAL:     pState->fFlagsFound |= MM_RAM_FLAGS_VIRTUAL_HANDLER; break;
     1236                case PGMVIRTHANDLERTYPE_WRITE:      pState->fFlagsFound |= MM_RAM_FLAGS_VIRTUAL_HANDLER | MM_RAM_FLAGS_VIRTUAL_WRITE; break;
     1237                case PGMVIRTHANDLERTYPE_ALL:        pState->fFlagsFound |= MM_RAM_FLAGS_VIRTUAL_HANDLER | MM_RAM_FLAGS_VIRTUAL_ALL; break;
     1238                /* hypervisor handlers need no flags and wouldn't have nowhere to put them in any case. */
     1239                case PGMVIRTHANDLERTYPE_HYPERVISOR:
     1240                    return 0;
     1241            }
     1242            if (    (pState->fFlags & (MM_RAM_FLAGS_VIRTUAL_HANDLER  | MM_RAM_FLAGS_VIRTUAL_WRITE  | MM_RAM_FLAGS_VIRTUAL_ALL))
     1243                ==  pState->fFlagsFound)
     1244                break;
     1245        }
     1246    }
     1247    return 0;
     1248}
     1249
     1250
     1251/**
     1252 * Verify a virtual handler.
     1253 *
     1254 * @returns 0
     1255 * @param   pNode   Pointer to a PGMVIRTHANDLER.
     1256 * @param   pvUser  Pointer to user parameter.
     1257 */
     1258static DECLCALLBACK(int) pgmVirtHandlerVerifyOne(PAVLROGCPTRNODECORE pNode, void *pvUser)
     1259{
     1260    PPGMVIRTHANDLER pVirt   = (PPGMVIRTHANDLER)pNode;
     1261    PPGMAHAFIS      pState = (PPGMAHAFIS)pvUser;
     1262    PVM             pVM     = pState->pVM;
     1263
     1264    if (    pVirt->aPhysToVirt[0].Core.Key != NIL_RTGCPHYS
     1265        &&  (pVirt->aPhysToVirt[0].Core.Key & PAGE_OFFSET_MASK) != ((RTGCUINTPTR)pVirt->GCPtr & PAGE_OFFSET_MASK))
     1266    {
     1267        AssertMsgFailed(("virt handler phys out has incorrect key! %VGp %VGv %s\n",
     1268                         pVirt->aPhysToVirt[0].Core.Key, pVirt->GCPtr, HCSTRING(pVirt->pszDesc)));
     1269        pState->cErrors++;
     1270    }
     1271
     1272    /*
     1273     * Calc flags.
     1274     */
     1275    unsigned    fFlags;
     1276    switch (pVirt->enmType)
     1277    {
     1278        case PGMVIRTHANDLERTYPE_EIP:
     1279        case PGMVIRTHANDLERTYPE_NORMAL:     fFlags = MM_RAM_FLAGS_VIRTUAL_HANDLER; break;
     1280        case PGMVIRTHANDLERTYPE_WRITE:      fFlags = MM_RAM_FLAGS_VIRTUAL_HANDLER | MM_RAM_FLAGS_VIRTUAL_WRITE; break;
     1281        case PGMVIRTHANDLERTYPE_ALL:        fFlags = MM_RAM_FLAGS_VIRTUAL_HANDLER | MM_RAM_FLAGS_VIRTUAL_ALL; break;
     1282        /* hypervisor handlers need no flags and wouldn't have nowhere to put them in any case. */
     1283        case PGMVIRTHANDLERTYPE_HYPERVISOR:
     1284            return 0;
     1285        default:
     1286            AssertMsgFailed(("unknown enmType=%d\n", pVirt->enmType));
     1287            return 0;
     1288    }
     1289
     1290    /*
     1291     * Check pages against flags.
     1292     */
     1293    RTGCUINTPTR   GCPtr = (RTGCUINTPTR)pVirt->GCPtr;
     1294    for (unsigned iPage = 0; iPage < pVirt->cPages; iPage++, GCPtr += PAGE_SIZE)
     1295    {
     1296        RTGCPHYS   GCPhysGst;
     1297        uint64_t   fGst;
     1298        int rc = PGMGstGetPage(pVM, (RTGCPTR)GCPtr, &fGst, &GCPhysGst);
     1299        if (    rc == VERR_PAGE_NOT_PRESENT
     1300            ||  rc == VERR_PAGE_TABLE_NOT_PRESENT)
     1301        {
     1302            if (pVirt->aPhysToVirt[iPage].Core.Key != NIL_RTGCPHYS)
     1303            {
     1304                AssertMsgFailed(("virt handler phys out of sync. %VGp GCPhysNew=~0 iPage=%#x %VGv %s\n",
     1305                                 pVirt->aPhysToVirt[iPage].Core.Key, iPage, GCPtr, HCSTRING(pVirt->pszDesc)));
     1306                pState->cErrors++;
     1307            }
     1308            continue;
     1309        }
     1310
     1311        AssertRCReturn(rc, 0);
     1312        if ((pVirt->aPhysToVirt[iPage].Core.Key & X86_PTE_PAE_PG_MASK) != GCPhysGst)
     1313        {
     1314            AssertMsgFailed(("virt handler phys out of sync. %VGp GCPhysGst=%VGp iPage=%#x %VGv %s\n",
     1315                             pVirt->aPhysToVirt[iPage].Core.Key, GCPhysGst, iPage, GCPtr, HCSTRING(pVirt->pszDesc)));
     1316            pState->cErrors++;
     1317            continue;
     1318        }
     1319
     1320        PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, GCPhysGst);
     1321        if (!pPage)
     1322        {
     1323            AssertMsgFailed(("virt handler getting ram flags. GCPhysGst=%VGp iPage=%#x %VGv %s\n",
     1324                             GCPhysGst, iPage, GCPtr, HCSTRING(pVirt->pszDesc)));
     1325            pState->cErrors++;
     1326            continue;
     1327        }
     1328
     1329        if ((pPage->HCPhys & fFlags) != fFlags) /** @todo PAGE FLAGS */
     1330        {
     1331            AssertMsgFailed(("virt handler flags mismatch. HCPhys=%VHp fFlags=%#x GCPhysGst=%VGp iPage=%#x %VGv %s\n",
     1332                             pPage->HCPhys, fFlags, GCPhysGst, iPage, GCPtr, HCSTRING(pVirt->pszDesc)));
     1333            pState->cErrors++;
     1334            continue;
     1335        }
     1336    } /* for pages in virtual mapping. */
     1337
     1338    return 0;
     1339}
     1340
     1341
     1342/**
     1343 * Asserts that the handlers+guest-page-tables == ramrange-flags and
     1344 * that the physical addresses associated with virtual handlers are correct.
     1345 *
     1346 * @returns Number of mismatches.
     1347 * @param   pVM     The VM handle.
     1348 */
     1349PGMDECL(unsigned) PGMAssertHandlerAndFlagsInSync(PVM pVM)
     1350{
     1351    PPGM        pPGM = &pVM->pgm.s;
     1352    PGMAHAFIS   State;
     1353    State.cErrors = 0;
     1354    State.pVM     = pVM;
     1355
     1356    /*
     1357     * Check the RAM flags against the handlers.
     1358     */
     1359    for (PPGMRAMRANGE pRam = CTXALLSUFF(pPGM->pRamRanges); pRam; pRam = CTXALLSUFF(pRam->pNext))
     1360    {
     1361        const unsigned cPages = pRam->cb >> PAGE_SHIFT;
     1362        for (unsigned iPage = 0; iPage < cPages; iPage++)
     1363        {
     1364            PGMPAGE const *pPage = &pRam->aPages[iPage];
     1365            if (PGM_PAGE_HAVE_ANY_HANDLERS(pPage))
     1366            {
     1367                State.GCPhys = pRam->GCPhys + (iPage << PAGE_SHIFT);
     1368                State.fFlagsFound = 0; /* build flags and compare. */
     1369
     1370                /*
     1371                 * Physical first - calculate the state based on the handlers
     1372                 *                  active on the page, then compare.
     1373                 */
     1374                if (PGM_PAGE_HAVE_ANY_PHYSICAL_HANDLERS(pPage))
     1375                {
     1376                    /* the first */
     1377                    PPGMPHYSHANDLER pPhys = (PPGMPHYSHANDLER)RTAvlroGCPhysRangeGet(&pPGM->CTXSUFF(pTrees)->PhysHandlers, State.GCPhys);
     1378                    if (!pPhys)
     1379                    {
     1380                        pPhys = (PPGMPHYSHANDLER)RTAvlroGCPhysGetBestFit(&pPGM->CTXSUFF(pTrees)->PhysHandlers, State.GCPhys, true);
     1381                        if (    pPhys
     1382                            &&  pPhys->Core.Key > (State.GCPhys + PAGE_SIZE - 1))
     1383                            pPhys = NULL;
     1384                        Assert(!pPhys || pPhys->Core.Key >= State.GCPhys);
     1385                    }
     1386                    if (pPhys)
     1387                    {
     1388                        unsigned uState = pgmHandlerPhysicalCalcState(pPhys);
     1389
     1390                        /* more? */
     1391                        while (pPhys->Core.KeyLast < (State.GCPhys | PAGE_OFFSET_MASK))
     1392                        {
     1393                            PPGMPHYSHANDLER pPhys2 = (PPGMPHYSHANDLER)RTAvlroGCPhysGetBestFit(&pPGM->CTXSUFF(pTrees)->PhysHandlers,
     1394                                                                                              pPhys->Core.KeyLast + 1, true);
     1395                            if (    !pPhys2
     1396                                ||  pPhys2->Core.Key > (State.GCPhys | PAGE_OFFSET_MASK))
     1397                                break;
     1398                            unsigned uState2 = pgmHandlerPhysicalCalcState(pPhys2);
     1399                            uState = RT_MAX(uState, uState2);
     1400                            pPhys = pPhys2;
     1401                        }
     1402
     1403                        /* compare.*/
     1404                        if (    PGM_PAGE_GET_HNDL_PHYS_STATE(pPage) != uState
     1405                            &&  PGM_PAGE_GET_HNDL_PHYS_STATE(pPage) != PGM_PAGE_HNDL_PHYS_STATE_DISABLED)
     1406                        {
     1407                            AssertMsgFailed(("ram range vs phys handler flags mismatch. GCPhys=%RGp state=%d expected=%d %s\n",
     1408                                             State.GCPhys, PGM_PAGE_GET_HNDL_PHYS_STATE(pPage), uState, pPhys->pszDesc));
     1409                            State.cErrors++;
     1410                        }
     1411
     1412#ifdef IN_RING3
     1413                        /* validate that REM is handling it. */
     1414                        if (    !REMR3IsPageAccessHandled(pVM, State.GCPhys)
     1415                                /* ignore shadowed ROM for the time being. */ /// @todo PAGE FLAGS
     1416                            &&  (pPage->HCPhys & (MM_RAM_FLAGS_ROM | MM_RAM_FLAGS_MMIO2)) != (MM_RAM_FLAGS_ROM | MM_RAM_FLAGS_MMIO2))
     1417                        {
     1418                            AssertMsgFailed(("ram range vs phys handler REM mismatch. GCPhys=%RGp state=%d %s\n",
     1419                                             State.GCPhys, PGM_PAGE_GET_HNDL_PHYS_STATE(pPage), pPhys->pszDesc));
     1420                            State.cErrors++;
     1421                        }
     1422#endif
     1423                    }
     1424                    else
     1425                    {
     1426                        AssertMsgFailed(("ram range vs phys handler mismatch. no handler for GCPhys=%RGp\n", State.GCPhys));
     1427                        State.cErrors++;
     1428                    }
     1429                }
     1430
     1431                /* virtual flags. */
     1432                if (PGM_PAGE_HAVE_ACTIVE_VIRTUAL_HANDLERS(pPage))
     1433                {
     1434                    State.fFlags = pPage->HCPhys & (MM_RAM_FLAGS_VIRTUAL_HANDLER  | MM_RAM_FLAGS_VIRTUAL_WRITE  | MM_RAM_FLAGS_VIRTUAL_ALL); /// @todo PAGE FLAGS
     1435                    RTAvlroGCPtrDoWithAll(CTXSUFF(&pVM->pgm.s.pTrees)->VirtHandlers, true, pgmVirtHandlerVerifyOneByPhysAddr, &State);
     1436                    if (State.fFlags !=  State.fFlagsFound)
     1437                    {
     1438                        AssertMsgFailed(("ram range vs virt handler flags mismatch. GCPhys=%RGp fFlags=%#x fFlagsFound=%#x\n",
     1439                                         State.GCPhys, State.fFlags, State.fFlagsFound));
     1440                        State.cErrors++;
     1441                    }
     1442
     1443                }
     1444            }
     1445        } /* foreach page in ram range. */
     1446    } /* foreach ram range. */
     1447
     1448    /*
     1449     * Check that the physical addresses of the virtual handlers matches up.
     1450     */
     1451    RTAvlroGCPtrDoWithAll(CTXSUFF(&pVM->pgm.s.pTrees)->VirtHandlers, true, pgmVirtHandlerVerifyOne, &State);
     1452
     1453    /*
     1454     * Do the reverse check for physical handlers.
     1455     */
     1456    /** @todo */
     1457
     1458    return State.cErrors;
     1459}
     1460
     1461#endif /* VBOX_STRICT */
     1462
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