Changeset 49227 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Oct 22, 2013 11:57:45 AM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp
r49209 r49227 63 63 /** Use the function table. */ 64 64 #define HMVMX_USE_FUNCTION_TABLE 65 66 /** 67 * The maximum number of MSRs we are willing to swap during a world-switch. 68 * Intel claims 512/check capability MSR, we don't want to do anywhere close 69 * to that. See Intel spec. 24.7.2 "VM-Exit Controls for MSRs" 70 * 71 * Bump this count as and when required, there's no backward compatibility 72 * requirement. 73 */ 74 #define HMVMX_MAX_SWAP_MSR_COUNT 5 65 75 66 76 /** Determine which tagged-TLB flush handler to use. */ … … 1150 1160 ASMBitClear(pbMsrBitmap + 0x800, iBit); 1151 1161 } 1162 1163 1164 #ifdef VBOX_WITH_AUTO_MSR_LOAD_RESTORE 1165 /** 1166 * Updates the VMCS with the number of effective MSRs in the auto-load/store MSR 1167 * area. 1168 * 1169 * @returns VBox status code. 1170 * @param pVCpu Pointer to the VMCPU. 1171 * @param cMsrs The number of MSRs. 1172 */ 1173 DECLINLINE(int) hmR0VmxSetAutoLoadStoreMsrCount(PVMCPU pVCpu, uint32_t cMsrs) 1174 { 1175 /* Update the VCPU's copy of the guest MSR count. */ 1176 pVCpu->hm.s.vmx.cGuestMsrs = cMsrs; 1177 1178 /* Update number of guest MSRs to load/store across the world-switch. */ 1179 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, cMsrs); AssertRCReturn(rc, rc); 1180 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, cMsrs); AssertRCReturn(rc, rc); 1181 1182 /* Update number of host MSRs to load after the world-switch. Identical to guest-MSR count as it's always paired. */ 1183 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, cMsrs); AssertRCReturn(rc, rc); 1184 return VINF_SUCCESS; 1185 } 1186 1187 1188 /** 1189 * Adds a guest/host MSR pair to be swapped during the world-switch as 1190 * part of the auto-load/store MSR area in the VMCS. 1191 * 1192 * @returns VBox status code. 1193 * @param pVCpu Pointer to the VMCPU. 1194 * @param uMsr The MSR. 1195 * @param uGuestMsr Value of the guest MSR. 1196 * @param uHostMsr Value of the host MSR. 1197 */ 1198 static int hmR0VmxAddAutoLoadStoreMsr(PVMCPU pVCpu, uint32_t uMsr, uint64_t uGuestMsrValue, uint64_t uHostMsrValue) 1199 { 1200 AssertMsg(HMVMX_MAX_SWAP_MSR_COUNT < MSR_IA32_VMX_MISC_MAX_MSR(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc), 1201 ("MSR swap count exceeded. Cpu reports %#RX32, our limit %#RX32\n", 1202 MSR_IA32_VMX_MISC_MAX_MSR(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc), HMVMX_MAX_SWAP_MSR_COUNT)); 1203 1204 PVMXAUTOMSR pGuestMsr = (PVMXAUTOMSR)pVCpu->hm.s.vmx.pvGuestMsr; 1205 uint32_t cGuestMsrs = pVCpu->hm.s.vmx.cGuestMsrs; 1206 uint32_t i; 1207 for (i = 0; i < cGuestMsrs; i++) 1208 { 1209 if (pGuestMsr->u32Msr == uMsr) 1210 break; 1211 pGuestMsr++; 1212 } 1213 1214 AssertReturn(i < HMVMX_MAX_SWAP_MSR_COUNT, VERR_HM_MSR_SWAP_COUNT_EXCEEDED); 1215 if (i == cGuestMsrs) 1216 { 1217 ++cGuestMsrs; 1218 /* Shouldn't ever happen but there -is- a number. We're well within the recommended 512. */ 1219 if (RT_UNLIKELY(cGuestMsrs > MSR_IA32_VMX_MISC_MAX_MSR(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc))) 1220 { 1221 LogRel(("CPU autoload/store MSR count in VMCS exceeded cGuestMsrs=%u.\n", cGuestMsrs)); 1222 pVCpu->hm.s.u32HMError = VMX_UFC_INSUFFICIENT_GUEST_MSR_STORAGE; 1223 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO; 1224 } 1225 1226 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, cGuestMsrs); 1227 AssertRCReturn(rc, rc); 1228 } 1229 1230 /* Update the MSR values in the auto-load/store MSR area. */ 1231 pGuestMsr->u32Msr = uMsr; 1232 pGuestMsr->u64Value = uGuestMsrValue; 1233 1234 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVCpu->hm.s.vmx.pvHostMsr; 1235 pHostMsr += i; 1236 pHostMsr->u32Msr = uMsr; 1237 pHostMsr->u64Value = uHostMsrValue; 1238 1239 /* Now that we're swapping MSRs during the world-switch, allow the guest to read/write them without causing VM-exits. */ 1240 Assert(pVCpu->hm.s.vmx.u32ProcCtls & VMX_VMCS_CTRL_PROC_EXEC_USE_MSR_BITMAPS); 1241 hmR0VmxSetMsrPermission(pVCpu, uMsr, VMXMSREXIT_PASSTHRU_READ, VMXMSREXIT_PASSTHRU_WRITE); 1242 return VINF_SUCCESS; 1243 } 1244 1245 1246 /** 1247 * Removes a guest/shost MSR pair to be swapped during the world-switch from the 1248 * auto-load/store MSR area in the VMCS. 1249 * 1250 * Does not fail if the MSR in @a uMsr is not found in the auto-load/store MSR 1251 * area. 1252 * 1253 * @returns VBox status code. 1254 * @param pVCpu Pointer to the VMCPU. 1255 * @param uMsr The MSR. 1256 */ 1257 static int hmR0VmxRemoveAutoLoadStoreMsr(PVMCPU pVCpu, uint32_t uMsr) 1258 { 1259 PVMXAUTOMSR pGuestMsr = (PVMXAUTOMSR)pVCpu->hm.s.vmx.pvGuestMsr; 1260 uint32_t cGuestMsrs = pVCpu->hm.s.vmx.cGuestMsrs; 1261 uint32_t i; 1262 for (i = 0; i < cGuestMsrs; i++) 1263 { 1264 /* Find the MSR. */ 1265 if (pGuestMsr->u32Msr == uMsr) 1266 { 1267 /* If it's the last MSR, simply reduce the count. */ 1268 if (i == cGuestMsrs - 1) 1269 { 1270 --cGuestMsrs; 1271 break; 1272 } 1273 1274 /* Remove it by swapping the last MSR in place of it, and reducing the count. */ 1275 PVMXAUTOMSR pLastGuestMsr = (PVMXAUTOMSR)pVCpu->hm.s.vmx.pvGuestMsr; 1276 pLastGuestMsr += cGuestMsrs; 1277 pGuestMsr->u32Msr = pLastGuestMsr->u32Msr; 1278 pGuestMsr->u64Value = pLastGuestMsr->u64Value; 1279 1280 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVCpu->hm.s.vmx.pvHostMsr; 1281 PVMXAUTOMSR pLastHostMsr = (PVMXAUTOMSR)pVCpu->hm.s.vmx.pvHostMsr; 1282 pLastHostMsr += cGuestMsrs; 1283 pHostMsr->u32Msr = pLastHostMsr->u32Msr; 1284 pHostMsr->u64Value = pLastHostMsr->u64Value; 1285 --cGuestMsrs; 1286 break; 1287 } 1288 pGuestMsr++; 1289 } 1290 1291 /* Update the VMCS if the count changed (meaning the MSR was found). */ 1292 if (cGuestMsrs != pVCpu->hm.s.vmx.cGuestMsrs) 1293 { 1294 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, cGuestMsrs); 1295 AssertRCReturn(rc, rc); 1296 } 1297 1298 /* We're no longer swapping MSRs during the world-switch, intercept guest read/writes to them. */ 1299 hmR0VmxSetMsrPermission(pVCpu, uMsr, VMXMSREXIT_INTERCEPT_READ, VMXMSREXIT_INTERCEPT_WRITE); 1300 return VINF_SUCCESS; 1301 } 1302 1303 1304 /** 1305 * Updates the value of a host MSR in the auto-load/store area in the VMCS. 1306 * 1307 * @returns VBox status code. 1308 * @param pVCpu Pointer to the VMCPU. 1309 * @param uMsr The MSR. 1310 */ 1311 static int hmR0VmxUpdateAutoLoadStoreHostMsr(PVMCPU pVCpu, uint32_t uMsr) 1312 { 1313 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVCpu->hm.s.vmx.pvHostMsr; 1314 uint32_t cMsrs = pVCpu->hm.s.vmx.cGuestMsrs; 1315 1316 for (uint32_t i = 0; i < cMsrs; i++) 1317 { 1318 if (pHostMsr->u32Msr == uMsr) 1319 { 1320 pHostMsr->u64Value = ASMRdMsr(pHostMsr->u32Msr); 1321 return VINF_SUCCESS; 1322 } 1323 } 1324 1325 return VERR_NOT_FOUND; 1326 } 1327 1328 #endif /* VBOX_WITH_AUTO_MSR_LOAD_RESTORE */ 1152 1329 1153 1330
Note:
See TracChangeset
for help on using the changeset viewer.