Changeset 96949 in vbox for trunk/src/VBox/VMM/VMMR3
- Timestamp:
- Sep 30, 2022 9:24:29 AM (2 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/PGMPool.cpp
r96939 r96949 123 123 124 124 /********************************************************************************************************************************* 125 * Structures and Typedefs * 126 *********************************************************************************************************************************/ 127 typedef struct PGMPOOLCHECKERSTATE 128 { 129 PDBGCCMDHLP pCmdHlp; 130 PVM pVM; 131 PPGMPOOL pPool; 132 PPGMPOOLPAGE pPage; 133 bool fFirstMsg; 134 uint32_t cErrors; 135 } PGMPOOLCHECKERSTATE; 136 typedef PGMPOOLCHECKERSTATE *PPGMPOOLCHECKERSTATE; 137 138 139 140 /********************************************************************************************************************************* 125 141 * Internal Functions * 126 142 *********************************************************************************************************************************/ 143 static FNDBGFHANDLERINT pgmR3PoolInfoPages; 127 144 static FNDBGFHANDLERINT pgmR3PoolInfoRoots; 128 145 … … 451 468 #endif /* VBOX_WITH_STATISTICS */ 452 469 470 DBGFR3InfoRegisterInternalEx(pVM, "pgmpoolpages", "Lists page pool pages.", pgmR3PoolInfoPages, 0); 453 471 DBGFR3InfoRegisterInternalEx(pVM, "pgmpoolroots", "Lists page pool roots.", pgmR3PoolInfoRoots, 0); 454 472 … … 775 793 } 776 794 795 /** 796 * Stringifies a PGMPOOLKIND value. 797 */ 798 static const char *pgmPoolPoolKindToStr(uint8_t enmKind) 799 { 800 switch ((PGMPOOLKIND)enmKind) 801 { 802 case PGMPOOLKIND_INVALID: 803 return "INVALID"; 804 case PGMPOOLKIND_FREE: 805 return "FREE"; 806 case PGMPOOLKIND_32BIT_PT_FOR_PHYS: 807 return "32BIT_PT_FOR_PHYS"; 808 case PGMPOOLKIND_32BIT_PT_FOR_32BIT_PT: 809 return "32BIT_PT_FOR_32BIT_PT"; 810 case PGMPOOLKIND_32BIT_PT_FOR_32BIT_4MB: 811 return "32BIT_PT_FOR_32BIT_4MB"; 812 case PGMPOOLKIND_PAE_PT_FOR_PHYS: 813 return "PAE_PT_FOR_PHYS"; 814 case PGMPOOLKIND_PAE_PT_FOR_32BIT_PT: 815 return "PAE_PT_FOR_32BIT_PT"; 816 case PGMPOOLKIND_PAE_PT_FOR_32BIT_4MB: 817 return "PAE_PT_FOR_32BIT_4MB"; 818 case PGMPOOLKIND_PAE_PT_FOR_PAE_PT: 819 return "PAE_PT_FOR_PAE_PT"; 820 case PGMPOOLKIND_PAE_PT_FOR_PAE_2MB: 821 return "PAE_PT_FOR_PAE_2MB"; 822 case PGMPOOLKIND_32BIT_PD: 823 return "32BIT_PD"; 824 case PGMPOOLKIND_32BIT_PD_PHYS: 825 return "32BIT_PD_PHYS"; 826 case PGMPOOLKIND_PAE_PD0_FOR_32BIT_PD: 827 return "PAE_PD0_FOR_32BIT_PD"; 828 case PGMPOOLKIND_PAE_PD1_FOR_32BIT_PD: 829 return "PAE_PD1_FOR_32BIT_PD"; 830 case PGMPOOLKIND_PAE_PD2_FOR_32BIT_PD: 831 return "PAE_PD2_FOR_32BIT_PD"; 832 case PGMPOOLKIND_PAE_PD3_FOR_32BIT_PD: 833 return "PAE_PD3_FOR_32BIT_PD"; 834 case PGMPOOLKIND_PAE_PD_FOR_PAE_PD: 835 return "PAE_PD_FOR_PAE_PD"; 836 case PGMPOOLKIND_PAE_PD_PHYS: 837 return "PAE_PD_PHYS"; 838 case PGMPOOLKIND_PAE_PDPT_FOR_32BIT: 839 return "PAE_PDPT_FOR_32BIT"; 840 case PGMPOOLKIND_PAE_PDPT: 841 return "PAE_PDPT"; 842 case PGMPOOLKIND_PAE_PDPT_PHYS: 843 return "PAE_PDPT_PHYS"; 844 case PGMPOOLKIND_64BIT_PDPT_FOR_64BIT_PDPT: 845 return "64BIT_PDPT_FOR_64BIT_PDPT"; 846 case PGMPOOLKIND_64BIT_PDPT_FOR_PHYS: 847 return "64BIT_PDPT_FOR_PHYS"; 848 case PGMPOOLKIND_64BIT_PD_FOR_64BIT_PD: 849 return "64BIT_PD_FOR_64BIT_PD"; 850 case PGMPOOLKIND_64BIT_PD_FOR_PHYS: 851 return "64BIT_PD_FOR_PHYS"; 852 case PGMPOOLKIND_64BIT_PML4: 853 return "64BIT_PML4"; 854 case PGMPOOLKIND_EPT_PDPT_FOR_PHYS: 855 return "EPT_PDPT_FOR_PHYS"; 856 case PGMPOOLKIND_EPT_PD_FOR_PHYS: 857 return "EPT_PD_FOR_PHYS"; 858 case PGMPOOLKIND_EPT_PT_FOR_PHYS: 859 return "EPT_PT_FOR_PHYS"; 860 case PGMPOOLKIND_ROOT_NESTED: 861 return "ROOT_NESTED"; 862 case PGMPOOLKIND_EPT_PT_FOR_EPT_PT: 863 return "EPT_PT_FOR_EPT_PT"; 864 case PGMPOOLKIND_EPT_PD_FOR_EPT_PD: 865 return "EPT_PD_FOR_EPT_PD"; 866 case PGMPOOLKIND_EPT_PDPT_FOR_EPT_PDPT: 867 return "EPT_PDPT_FOR_EPT_PDPT"; 868 case PGMPOOLKIND_EPT_PML4_FOR_EPT_PML4: 869 return "EPT_PML4_FOR_EPT_PML4"; 870 } 871 return "Unknown kind!"; 872 } 873 777 874 778 875 /** … … 844 941 845 942 /** 943 * @callback_method_impl{FNDBGFHANDLERINT, pgmpoolpages} 944 */ 945 static DECLCALLBACK(void) pgmR3PoolInfoPages(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs) 946 { 947 RT_NOREF(pszArgs); 948 949 PPGMPOOL const pPool = pVM->pgm.s.CTX_SUFF(pPool); 950 unsigned const cPages = pPool->cCurPages; 951 unsigned cLeft = pPool->cUsedPages; 952 for (unsigned iPage = 0; iPage < cPages; iPage++) 953 { 954 PGMPOOLPAGE volatile const *pPage = (PGMPOOLPAGE volatile const *)&pPool->aPages[iPage]; 955 RTGCPHYS const GCPhys = pPage->GCPhys; 956 uint8_t const enmKind = pPage->enmKind; 957 if ( enmKind != PGMPOOLKIND_INVALID 958 && enmKind != PGMPOOLKIND_FREE) 959 { 960 pHlp->pfnPrintf(pHlp, "#%04x: HCPhys=%RHp GCPhys=%RGp %s %s%s%s\n", 961 iPage, pPage->Core.Key, GCPhys, pPage->fA20Enabled ? "A20 " : "!A20", 962 pgmPoolPoolKindToStr(enmKind), 963 pPage->fCached ? " cached" : "", 964 pPage->fMonitored ? " monitored" : ""); 965 if (!--cLeft) 966 break; 967 } 968 } 969 } 970 971 972 /** 846 973 * @callback_method_impl{FNDBGFHANDLERINT, pgmpoolroots} 847 974 */ … … 850 977 RT_NOREF(pszArgs); 851 978 852 PPGMPOOL pPool= pVM->pgm.s.CTX_SUFF(pPool);853 unsigned c Left = pPool->cUsedPages;854 unsigned iPage = pPool->cCurPages;855 while (--iPage >= PGMPOOL_IDX_FIRST)979 PPGMPOOL const pPool = pVM->pgm.s.CTX_SUFF(pPool); 980 unsigned const cPages = pPool->cCurPages; 981 unsigned cLeft = pPool->cUsedPages; 982 for (unsigned iPage = 0; iPage < cPages; iPage++) 856 983 { 857 984 PGMPOOLPAGE volatile const *pPage = (PGMPOOLPAGE volatile const *)&pPool->aPages[iPage]; … … 871 998 case PGMPOOLKIND_ROOT_NESTED: 872 999 case PGMPOOLKIND_EPT_PML4_FOR_EPT_PML4: 873 {874 const char *pszKind = "wtf!";875 switch (enmKind)876 {877 case PGMPOOLKIND_PAE_PDPT_FOR_32BIT: pszKind = "PAE_PDPT_FOR_32BIT"; break;878 case PGMPOOLKIND_PAE_PDPT: pszKind = "PAE_PDPT"; break;879 case PGMPOOLKIND_PAE_PDPT_PHYS: pszKind = "PAE_PDPT_PHYS"; break;880 case PGMPOOLKIND_64BIT_PML4: pszKind = "64BIT_PML4"; break;881 case PGMPOOLKIND_ROOT_NESTED: pszKind = "ROOT_NESTED"; break;882 case PGMPOOLKIND_EPT_PML4_FOR_EPT_PML4: pszKind = "EPT_PML4_FOR_EPT_PML4"; break;883 }884 1000 pHlp->pfnPrintf(pHlp, "#%04x: HCPhys=%RHp GCPhys=%RGp %s %s %s\n", 885 1001 iPage, pPage->Core.Key, GCPhys, pPage->fA20Enabled ? "A20 " : "!A20", 886 p szKind, pPage->fMonitored ? " monitored" : "");1002 pgmPoolPoolKindToStr(enmKind), pPage->fMonitored ? " monitored" : ""); 887 1003 break; 888 }889 1004 } 890 1005 if (!--cLeft) … … 894 1009 } 895 1010 896 897 1011 #ifdef VBOX_WITH_DEBUGGER 1012 1013 /** 1014 * Helper for pgmR3PoolCmdCheck that reports an error. 1015 */ 1016 static void pgmR3PoolCheckError(PPGMPOOLCHECKERSTATE pState, const char *pszFormat, ...) 1017 { 1018 if (pState->fFirstMsg) 1019 { 1020 DBGCCmdHlpPrintf(pState->pCmdHlp, "Checking pool page #%i for %RGp %s\n", 1021 pState->pPage->idx, pState->pPage->GCPhys, pgmPoolPoolKindToStr(pState->pPage->enmKind)); 1022 pState->fFirstMsg = false; 1023 } 1024 1025 va_list va; 1026 va_start(va, pszFormat); 1027 pState->pCmdHlp->pfnPrintfV(pState->pCmdHlp, NULL, pszFormat, va); 1028 va_end(va); 1029 } 1030 1031 898 1032 /** 899 1033 * @callback_method_impl{FNDBGCCMD, The '.pgmpoolcheck' command.} … … 905 1039 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE); 906 1040 DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, -1, cArgs == 0); 907 uint32_t cErrors = 0;908 1041 NOREF(paArgs); 909 1042 910 PPGMPOOL pPool = pVM->pgm.s.CTX_SUFF(pPool); 1043 PGM_LOCK_VOID(pVM); 1044 PPGMPOOL pPool = pVM->pgm.s.CTX_SUFF(pPool); 1045 PGMPOOLCHECKERSTATE State = { pCmdHlp, pVM, pPool, NULL, true, 0 }; 911 1046 for (unsigned i = 0; i < pPool->cCurPages; i++) 912 1047 { 913 PPGMPOOLPAGE pPage = &pPool->aPages[i]; 914 bool fFirstMsg = true; 915 916 /** @todo cover other paging modes too. */ 917 if (pPage->enmKind == PGMPOOLKIND_PAE_PT_FOR_PAE_PT) 1048 PPGMPOOLPAGE pPage = &pPool->aPages[i]; 1049 State.pPage = pPage; 1050 State.fFirstMsg = true; 1051 1052 if (pPage->enmKind == PGMPOOLKIND_FREE) 1053 continue; 1054 if (pPage->enmKind > PGMPOOLKIND_LAST || pPage->enmKind <= PGMPOOLKIND_INVALID) 918 1055 { 919 PPGMSHWPTPAE pShwPT = (PPGMSHWPTPAE)PGMPOOL_PAGE_2_PTR(pPool->CTX_SUFF(pVM), pPage); 1056 pgmR3PoolCheckError(&State, "Invalid enmKind value: %#x\n", pPage->enmKind); 1057 continue; 1058 } 1059 1060 void const *pvGuestPage = NULL; 1061 PGMPAGEMAPLOCK LockPage; 1062 if ( pPage->enmKind != PGMPOOLKIND_EPT_PDPT_FOR_PHYS 1063 && pPage->enmKind != PGMPOOLKIND_EPT_PD_FOR_PHYS 1064 && pPage->enmKind != PGMPOOLKIND_EPT_PT_FOR_PHYS 1065 && pPage->enmKind != PGMPOOLKIND_ROOT_NESTED) 1066 { 1067 int rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, pPage->GCPhys, &pvGuestPage, &LockPage); 1068 if (RT_FAILURE(rc)) 920 1069 { 921 PX86PTPAE pGstPT; 922 PGMPAGEMAPLOCK LockPage; 923 int rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, pPage->GCPhys, (const void **)&pGstPT, &LockPage); AssertReleaseRC(rc); 924 925 /* Check if any PTEs are out of sync. */ 1070 pgmR3PoolCheckError(&State, "PGMPhysGCPhys2CCPtrReadOnly failed for %RGp: %Rrc\n", pPage->GCPhys, rc); 1071 continue; 1072 } 1073 } 1074 1075 /* 1076 * Check if something obvious is out of sync. 1077 */ 1078 switch (pPage->enmKind) 1079 { 1080 case PGMPOOLKIND_PAE_PT_FOR_PAE_PT: 1081 { 1082 PCPGMSHWPTPAE const pShwPT = (PCPGMSHWPTPAE)PGMPOOL_PAGE_2_PTR(pPool->CTX_SUFF(pVM), pPage); 1083 PCX86PDPAE const pGstPT = (PCX86PDPAE)pvGuestPage; 926 1084 for (unsigned j = 0; j < RT_ELEMENTS(pShwPT->a); j++) 927 {928 1085 if (PGMSHWPTEPAE_IS_P(pShwPT->a[j])) 929 1086 { 930 1087 RTHCPHYS HCPhys = NIL_RTHCPHYS; 931 rc = PGMPhysGCPhys2HCPhys(pPool->CTX_SUFF(pVM), pGstPT->a[j].u & X86_PTE_PAE_PG_MASK, &HCPhys);1088 int rc = PGMPhysGCPhys2HCPhys(pPool->CTX_SUFF(pVM), pGstPT->a[j].u & X86_PTE_PAE_PG_MASK, &HCPhys); 932 1089 if ( rc != VINF_SUCCESS 933 1090 || PGMSHWPTEPAE_GET_HCPHYS(pShwPT->a[j]) != HCPhys) 934 { 935 if (fFirstMsg) 936 { 937 DBGCCmdHlpPrintf(pCmdHlp, "Check pool page %RGp\n", pPage->GCPhys); 938 fFirstMsg = false; 939 } 940 DBGCCmdHlpPrintf(pCmdHlp, "Mismatch HCPhys: rc=%Rrc idx=%d guest %RX64 shw=%RX64 vs %RHp\n", rc, j, pGstPT->a[j].u, PGMSHWPTEPAE_GET_LOG(pShwPT->a[j]), HCPhys); 941 cErrors++; 942 } 1091 pgmR3PoolCheckError(&State, "Mismatch HCPhys: rc=%Rrc idx=%#x guest %RX64 shw=%RX64 vs %RHp\n", 1092 rc, j, pGstPT->a[j].u, PGMSHWPTEPAE_GET_LOG(pShwPT->a[j]), HCPhys); 943 1093 else if ( PGMSHWPTEPAE_IS_RW(pShwPT->a[j]) 944 1094 && !(pGstPT->a[j].u & X86_PTE_RW)) 945 { 946 if (fFirstMsg) 947 { 948 DBGCCmdHlpPrintf(pCmdHlp, "Check pool page %RGp\n", pPage->GCPhys); 949 fFirstMsg = false; 950 } 951 DBGCCmdHlpPrintf(pCmdHlp, "Mismatch r/w gst/shw: idx=%d guest %RX64 shw=%RX64 vs %RHp\n", j, pGstPT->a[j].u, PGMSHWPTEPAE_GET_LOG(pShwPT->a[j]), HCPhys); 952 cErrors++; 953 } 1095 pgmR3PoolCheckError(&State, "Mismatch r/w gst/shw: idx=%#x guest %RX64 shw=%RX64 vs %RHp\n", 1096 j, pGstPT->a[j].u, PGMSHWPTEPAE_GET_LOG(pShwPT->a[j]), HCPhys); 954 1097 } 955 } 956 PGMPhysReleasePageMappingLock(pVM, &LockPage); 1098 break; 957 1099 } 958 1100 959 /* Make sure this page table can't be written to from any shadow mapping. */ 960 RTHCPHYS HCPhysPT = NIL_RTHCPHYS; 961 int rc = PGMPhysGCPhys2HCPhys(pPool->CTX_SUFF(pVM), pPage->GCPhys, &HCPhysPT); 962 AssertMsgRC(rc, ("PGMPhysGCPhys2HCPhys failed with rc=%d for %RGp\n", rc, pPage->GCPhys)); 963 if (rc == VINF_SUCCESS) 1101 case PGMPOOLKIND_EPT_PT_FOR_EPT_PT: 964 1102 { 965 for (unsigned j = 0; j < pPool->cCurPages; j++) 966 { 967 PPGMPOOLPAGE pTempPage = &pPool->aPages[j]; 968 969 if (pTempPage->enmKind == PGMPOOLKIND_PAE_PT_FOR_PAE_PT) 1103 PCEPTPT const pShwPT = (PCEPTPT)PGMPOOL_PAGE_2_PTR(pPool->CTX_SUFF(pVM), pPage); 1104 PCEPTPT const pGstPT = (PCEPTPT)pvGuestPage; 1105 for (unsigned j = 0; j < RT_ELEMENTS(pShwPT->a); j++) 1106 if (pShwPT->a[j].u & EPT_PRESENT_MASK) 970 1107 { 971 PPGMSHWPTPAE pShwPT2 = (PPGMSHWPTPAE)PGMPOOL_PAGE_2_PTR(pPool->CTX_SUFF(pVM), pTempPage); 972 973 for (unsigned k = 0; k < RT_ELEMENTS(pShwPT->a); k++) 974 { 975 if ( PGMSHWPTEPAE_IS_P_RW(pShwPT2->a[k]) 976 # ifdef PGMPOOL_WITH_OPTIMIZED_DIRTY_PT 977 && !pPage->fDirty 978 # endif 979 && PGMSHWPTEPAE_GET_HCPHYS(pShwPT2->a[k]) == HCPhysPT) 980 { 981 if (fFirstMsg) 982 { 983 DBGCCmdHlpPrintf(pCmdHlp, "Check pool page %RGp\n", pPage->GCPhys); 984 fFirstMsg = false; 985 } 986 DBGCCmdHlpPrintf(pCmdHlp, "Mismatch: r/w: GCPhys=%RGp idx=%d shw %RX64 %RX64\n", pTempPage->GCPhys, k, PGMSHWPTEPAE_GET_LOG(pShwPT->a[k]), PGMSHWPTEPAE_GET_LOG(pShwPT2->a[k])); 987 cErrors++; 988 } 989 } 1108 RTHCPHYS HCPhys = NIL_RTHCPHYS; 1109 int rc = PGMPhysGCPhys2HCPhys(pPool->CTX_SUFF(pVM), pGstPT->a[j].u & X86_PTE_PAE_PG_MASK, &HCPhys); 1110 if ( rc != VINF_SUCCESS 1111 || (pShwPT->a[j].u & EPT_E_PG_MASK) != HCPhys) 1112 pgmR3PoolCheckError(&State, "Mismatch HCPhys: rc=%Rrc idx=%#x guest %RX64 shw=%RX64 vs %RHp\n", 1113 rc, j, pGstPT->a[j].u, pShwPT->a[j].u, HCPhys); 1114 else if ( (pShwPT->a[j].u & (EPT_E_READ | EPT_E_WRITE | EPT_E_EXECUTE)) 1115 != (EPT_E_READ | EPT_E_WRITE | EPT_E_EXECUTE) 1116 && ( ((pShwPT->a[j].u & EPT_E_READ) && !(pGstPT->a[j].u & EPT_E_READ)) 1117 || ((pShwPT->a[j].u & EPT_E_WRITE) && !(pGstPT->a[j].u & EPT_E_WRITE)) 1118 || ((pShwPT->a[j].u & EPT_E_EXECUTE) && !(pGstPT->a[j].u & EPT_E_EXECUTE)) ) ) 1119 pgmR3PoolCheckError(&State, "Mismatch r/w/x: idx=%#x guest %RX64 shw=%RX64\n", 1120 j, pGstPT->a[j].u, pShwPT->a[j].u); 990 1121 } 991 }1122 break; 992 1123 } 993 1124 } 994 } 995 if (cErrors > 0) 996 return DBGCCmdHlpFail(pCmdHlp, pCmd, "Found %#x errors", cErrors); 1125 1126 if (pvGuestPage) 1127 PGMPhysReleasePageMappingLock(pVM, &LockPage); 1128 } 1129 PGM_UNLOCK(pVM); 1130 1131 if (State.cErrors > 0) 1132 return DBGCCmdHlpFail(pCmdHlp, pCmd, "Found %#x errors", State.cErrors); 997 1133 return VINF_SUCCESS; 998 1134 } 1135 999 1136 #endif /* VBOX_WITH_DEBUGGER */
Note:
See TracChangeset
for help on using the changeset viewer.