- Timestamp:
- Nov 11, 2021 8:43:34 AM (3 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/pgm.h
r92186 r92344 337 337 VMMDECL(int) PGMTrap0eHandler(PVMCPUCC pVCpu, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault); 338 338 VMMDECL(int) PGMPrefetchPage(PVMCPUCC pVCpu, RTGCPTR GCPtrPage); 339 VMMDECL(int) PGMVerifyAccess(PVMCPUCC pVCpu, RTGCPTR Addr, uint32_t cbSize, uint32_t fAccess);340 VMMDECL(int) PGMIsValidAccess(PVMCPUCC pVCpu, RTGCPTR Addr, uint32_t cbSize, uint32_t fAccess);341 339 VMMDECL(VBOXSTRICTRC) PGMInterpretInstruction(PVMCC pVM, PVMCPUCC pVCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault); 342 340 VMMDECL(int) PGMShwGetPage(PVMCPUCC pVCpu, RTGCPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys); -
trunk/src/VBox/VMM/VMMAll/PGMAll.cpp
r92286 r92344 1011 1011 STAM_PROFILE_STOP(&pVCpu->pgm.s.Stats.CTX_MID_Z(Stat,Prefetch), a); 1012 1012 AssertMsg(rc == VINF_SUCCESS || rc == VINF_PGM_SYNC_CR3 || RT_FAILURE(rc), ("rc=%Rrc\n", rc)); 1013 return rc;1014 }1015 1016 1017 /**1018 * Verifies a range of pages for read or write access1019 *1020 * Only checks the guest's page tables1021 *1022 * @returns VBox status code.1023 * @param pVCpu The cross context virtual CPU structure.1024 * @param Addr Guest virtual address to check1025 * @param cbSize Access size1026 * @param fAccess Access type (r/w, user/supervisor (X86_PTE_*))1027 * @remarks Current not in use.1028 */1029 VMMDECL(int) PGMIsValidAccess(PVMCPUCC pVCpu, RTGCPTR Addr, uint32_t cbSize, uint32_t fAccess)1030 {1031 /*1032 * Validate input.1033 */1034 if (fAccess & ~(X86_PTE_US | X86_PTE_RW))1035 {1036 AssertMsgFailed(("PGMIsValidAccess: invalid access type %08x\n", fAccess));1037 return VERR_INVALID_PARAMETER;1038 }1039 1040 uint64_t fPage;1041 int rc = PGMGstGetPage(pVCpu, (RTGCPTR)Addr, &fPage, NULL);1042 if (RT_FAILURE(rc))1043 {1044 Log(("PGMIsValidAccess: access violation for %RGv rc=%d\n", Addr, rc));1045 return VINF_EM_RAW_GUEST_TRAP;1046 }1047 1048 /*1049 * Check if the access would cause a page fault1050 *1051 * Note that hypervisor page directories are not present in the guest's tables, so this check1052 * is sufficient.1053 */1054 bool fWrite = !!(fAccess & X86_PTE_RW);1055 bool fUser = !!(fAccess & X86_PTE_US);1056 if ( !(fPage & X86_PTE_P)1057 || (fWrite && !(fPage & X86_PTE_RW))1058 || (fUser && !(fPage & X86_PTE_US)) )1059 {1060 Log(("PGMIsValidAccess: access violation for %RGv attr %#llx vs %d:%d\n", Addr, fPage, fWrite, fUser));1061 return VINF_EM_RAW_GUEST_TRAP;1062 }1063 if ( RT_SUCCESS(rc)1064 && PAGE_ADDRESS(Addr) != PAGE_ADDRESS(Addr + cbSize))1065 return PGMIsValidAccess(pVCpu, Addr + PAGE_SIZE, (cbSize > PAGE_SIZE) ? cbSize - PAGE_SIZE : 1, fAccess);1066 return rc;1067 }1068 1069 1070 /**1071 * Verifies a range of pages for read or write access1072 *1073 * Supports handling of pages marked for dirty bit tracking and CSAM1074 *1075 * @returns VBox status code.1076 * @param pVCpu The cross context virtual CPU structure.1077 * @param Addr Guest virtual address to check1078 * @param cbSize Access size1079 * @param fAccess Access type (r/w, user/supervisor (X86_PTE_*))1080 */1081 VMMDECL(int) PGMVerifyAccess(PVMCPUCC pVCpu, RTGCPTR Addr, uint32_t cbSize, uint32_t fAccess)1082 {1083 PVM pVM = pVCpu->CTX_SUFF(pVM);1084 1085 AssertMsg(!(fAccess & ~(X86_PTE_US | X86_PTE_RW)), ("PGMVerifyAccess: invalid access type %08x\n", fAccess));1086 1087 /*1088 * Get going.1089 */1090 uint64_t fPageGst;1091 int rc = PGMGstGetPage(pVCpu, (RTGCPTR)Addr, &fPageGst, NULL);1092 if (RT_FAILURE(rc))1093 {1094 Log(("PGMVerifyAccess: access violation for %RGv rc=%d\n", Addr, rc));1095 return VINF_EM_RAW_GUEST_TRAP;1096 }1097 1098 /*1099 * Check if the access would cause a page fault1100 *1101 * Note that hypervisor page directories are not present in the guest's tables, so this check1102 * is sufficient.1103 */1104 const bool fWrite = !!(fAccess & X86_PTE_RW);1105 const bool fUser = !!(fAccess & X86_PTE_US);1106 if ( !(fPageGst & X86_PTE_P)1107 || (fWrite && !(fPageGst & X86_PTE_RW))1108 || (fUser && !(fPageGst & X86_PTE_US)) )1109 {1110 Log(("PGMVerifyAccess: access violation for %RGv attr %#llx vs %d:%d\n", Addr, fPageGst, fWrite, fUser));1111 return VINF_EM_RAW_GUEST_TRAP;1112 }1113 1114 if (!pVM->pgm.s.fNestedPaging)1115 {1116 /*1117 * Next step is to verify if we protected this page for dirty bit tracking or for CSAM scanning1118 */1119 rc = PGMShwGetPage(pVCpu, (RTGCPTR)Addr, NULL, NULL);1120 if ( rc == VERR_PAGE_NOT_PRESENT1121 || rc == VERR_PAGE_TABLE_NOT_PRESENT)1122 {1123 /*1124 * Page is not present in our page tables.1125 * Try to sync it!1126 */1127 Assert(X86_TRAP_PF_RW == X86_PTE_RW && X86_TRAP_PF_US == X86_PTE_US);1128 uint32_t const uErr = fAccess & (X86_TRAP_PF_RW | X86_TRAP_PF_US);1129 uintptr_t const idxBth = pVCpu->pgm.s.idxBothModeData;1130 AssertReturn(idxBth < RT_ELEMENTS(g_aPgmBothModeData), VERR_PGM_MODE_IPE);1131 AssertReturn(g_aPgmBothModeData[idxBth].pfnVerifyAccessSyncPage, VERR_PGM_MODE_IPE);1132 rc = g_aPgmBothModeData[idxBth].pfnVerifyAccessSyncPage(pVCpu, Addr, fPageGst, uErr);1133 if (rc != VINF_SUCCESS)1134 return rc;1135 }1136 else1137 AssertMsg(rc == VINF_SUCCESS, ("PGMShwGetPage %RGv failed with %Rrc\n", Addr, rc));1138 }1139 1140 #if 0 /* def VBOX_STRICT; triggers too often now */1141 /*1142 * This check is a bit paranoid, but useful.1143 */1144 /* Note! This will assert when writing to monitored pages (a bit annoying actually). */1145 uint64_t fPageShw;1146 rc = PGMShwGetPage(pVCpu, (RTGCPTR)Addr, &fPageShw, NULL);1147 if ( (rc == VERR_PAGE_NOT_PRESENT || RT_FAILURE(rc))1148 || (fWrite && !(fPageShw & X86_PTE_RW))1149 || (fUser && !(fPageShw & X86_PTE_US)) )1150 {1151 AssertMsgFailed(("Unexpected access violation for %RGv! rc=%Rrc write=%d user=%d\n",1152 Addr, rc, fWrite && !(fPageShw & X86_PTE_RW), fUser && !(fPageShw & X86_PTE_US)));1153 return VINF_EM_RAW_GUEST_TRAP;1154 }1155 #endif1156 1157 if ( RT_SUCCESS(rc)1158 && ( PAGE_ADDRESS(Addr) != PAGE_ADDRESS(Addr + cbSize - 1)1159 || Addr + cbSize < Addr))1160 {1161 /* Don't recursively call PGMVerifyAccess as we might run out of stack. */1162 for (;;)1163 {1164 Addr += PAGE_SIZE;1165 if (cbSize > PAGE_SIZE)1166 cbSize -= PAGE_SIZE;1167 else1168 cbSize = 1;1169 rc = PGMVerifyAccess(pVCpu, Addr, 1, fAccess);1170 if (rc != VINF_SUCCESS)1171 break;1172 if (PAGE_ADDRESS(Addr) == PAGE_ADDRESS(Addr + cbSize - 1))1173 break;1174 }1175 }1176 1013 return rc; 1177 1014 }
Note:
See TracChangeset
for help on using the changeset viewer.