Changeset 6906 in vbox for trunk/src/VBox/VMM/VMMAll/PGMAll.cpp
- Timestamp:
- Feb 11, 2008 6:17:52 PM (17 years ago)
- svn:sync-xref-src-repo-rev:
- 28057
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/PGMAll.cpp
r6905 r6906 779 779 780 780 /** 781 * Temporarily turns off the access monitoring of a page within a monitored782 * physical write/all page access handler region.783 *784 * Use this when no further \#PFs are required for that page. Be aware that785 * a page directory sync might reset the flags, and turn on access monitoring786 * for the page.787 *788 * The caller must do required page table modifications.789 *790 * @returns VBox status code.791 * @param pVM VM Handle792 * @param GCPhys Start physical address earlier passed to PGMR3HandlerPhysicalRegister().793 * This must be a fully page aligned range or we risk messing up other794 * 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.cpp797 */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.Key807 && 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_WRITE813 || 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 monitored838 * 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 Handle844 * @param GCPhys Start physical address earlier passed to PGMR3HandlerPhysicalRegister().845 * This must be a fully page aligned range or we risk messing up other846 * 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.cpp849 */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.Key859 && 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_WRITE865 || 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 handled890 *891 * @returns boolean892 * @param pVM VM Handle893 * @param GCPhys Start physical address earlier passed to PGMR3HandlerPhysicalRegister().894 * @todo move to PGMAllHandler.cpp895 */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.Key905 && GCPhys <= pCur->Core.KeyLast)906 {907 Assert( pCur->enmType == PGMPHYSHANDLERTYPE_PHYSICAL_WRITE908 || pCur->enmType == PGMPHYSHANDLERTYPE_PHYSICAL_ALL909 || pCur->enmType == PGMPHYSHANDLERTYPE_MMIO);910 return true;911 }912 }913 914 return false;915 }916 917 918 #ifdef VBOX_STRICT919 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 /**936 781 * Gets the current CR3 register value for the shadow memory context. 937 782 * @returns CR3 value. … … 1376 1221 1377 1222 /** 1378 * State structure used by the PGMAssertHandlerAndFlagsInSync() function1379 * and its AVL enumerators.1380 */1381 typedef struct PGMAHAFIS1382 {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 01400 * @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 01435 * @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_RTGCPHYS1445 && (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_PRESENT1480 || 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 and1524 * 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 handlers1552 * 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 ( pPhys1562 && 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 ( !pPhys21576 || 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) != uState1585 && 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_RING31593 /* validate that REM is handling it. */1594 if ( !REMR3IsPageAccessHandled(pVM, State.GCPhys)1595 /* ignore shadowed ROM for the time being. */ /// @todo PAGE FLAGS1596 && (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 #endif1603 }1604 else1605 {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 FLAGS1615 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 /**1643 1223 * Asserts that there are no mapping conflicts. 1644 1224 *
Note:
See TracChangeset
for help on using the changeset viewer.