Changeset 71031 in vbox for trunk/src/VBox/VMM/VMMR3
- Timestamp:
- Feb 15, 2018 4:47:13 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 120894
- Location:
- trunk/src/VBox/VMM/VMMR3
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/EMR3Nem.cpp
r70980 r71031 463 463 TMTimerPollVoid(pVM, pVCpu); 464 464 #endif 465 if ( 466 || 465 if ( VM_FF_IS_PENDING(pVM, VM_FF_ALL_MASK) 466 || VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_ALL_MASK)) 467 467 { 468 468 rcStrict = emR3ForcedActions(pVM, pVCpu, VBOXSTRICTRC_TODO(rcStrict)); -
trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp
r71020 r71031 2 2 /** @file 3 3 * NEM - Native execution manager, native ring-3 Windows backend. 4 * 5 * Log group 2: Exit logging. 6 * Log group 3: Log context on exit. 4 7 */ 5 8 … … 37 40 38 41 #include <VBox/vmm/nem.h> 42 #include <VBox/vmm/iem.h> 43 #include <VBox/vmm/em.h> 39 44 #include <VBox/vmm/apic.h> 40 45 #include "NEMInternal.h" … … 143 148 # define WHvSetVirtualProcessorRegisters g_pfnWHvSetVirtualProcessorRegisters 144 149 #endif 150 151 152 /********************************************************************************************************************************* 153 * Internal Functions * 154 *********************************************************************************************************************************/ 155 static int nemR3NativeSetPhysPage(PVM pVM, RTGCPHYS GCPhys, uint32_t fPageProt, uint8_t *pu2State, bool fBackingChanged); 145 156 146 157 … … 604 615 */ 605 616 /** 606 * @todo Someone at microsoft please explain another weird API:617 * @todo Someone at Microsoft please explain another weird API: 607 618 * - Why this API doesn't take the WHV_PARTITION_PROPERTY_CODE value as an 608 619 * argument rather than as part of the struct. That is so weird if you've … … 870 881 871 882 872 static int nemR3WinCopy OutState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)883 static int nemR3WinCopyStateToHyperV(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx) 873 884 { 874 885 WHV_REGISTER_NAME aenmNames[128]; … … 962 973 963 974 /* Debug registers. */ 964 /** @todo fixme */975 /** @todo fixme. Figure out what the hyper-v version of KVM_SET_GUEST_DEBUG would be. */ 965 976 aenmNames[iReg] = WHvX64RegisterDr0; 966 aValues[iReg].Reg64 = CPUMGetHyperDR0(pVCpu); 977 //aValues[iReg].Reg64 = CPUMGetHyperDR0(pVCpu); 978 aValues[iReg].Reg64 = pCtx->dr[0]; 967 979 iReg++; 968 980 aenmNames[iReg] = WHvX64RegisterDr1; 969 aValues[iReg].Reg64 = CPUMGetHyperDR1(pVCpu); 981 //aValues[iReg].Reg64 = CPUMGetHyperDR1(pVCpu); 982 aValues[iReg].Reg64 = pCtx->dr[1]; 970 983 iReg++; 971 984 aenmNames[iReg] = WHvX64RegisterDr2; 972 aValues[iReg].Reg64 = CPUMGetHyperDR2(pVCpu); 985 //aValues[iReg].Reg64 = CPUMGetHyperDR2(pVCpu); 986 aValues[iReg].Reg64 = pCtx->dr[2]; 973 987 iReg++; 974 988 aenmNames[iReg] = WHvX64RegisterDr3; 975 aValues[iReg].Reg64 = CPUMGetHyperDR3(pVCpu); 989 //aValues[iReg].Reg64 = CPUMGetHyperDR3(pVCpu); 990 aValues[iReg].Reg64 = pCtx->dr[3]; 976 991 iReg++; 977 992 aenmNames[iReg] = WHvX64RegisterDr6; 978 aValues[iReg].Reg64 = CPUMGetHyperDR6(pVCpu); 993 //aValues[iReg].Reg64 = CPUMGetHyperDR6(pVCpu); 994 aValues[iReg].Reg64 = pCtx->dr[6]; 979 995 iReg++; 980 996 aenmNames[iReg] = WHvX64RegisterDr7; 981 aValues[iReg].Reg64 = CPUMGetHyperDR7(pVCpu); 997 //aValues[iReg].Reg64 = CPUMGetHyperDR7(pVCpu); 998 aValues[iReg].Reg64 = pCtx->dr[7]; 982 999 iReg++; 983 1000 … … 1098 1115 | ((uint64_t)pCtx->pXStateR3->x87.Rsrvd2 << 48); 1099 1116 aValues[iReg].XmmControlStatus.XmmStatusControl = pCtx->pXStateR3->x87.MXCSR; 1100 aValues[iReg].XmmControlStatus.XmmStatusControlMask = pCtx->pXStateR3->x87.MXCSR_MASK; /* ??? (Isn't this an output field?) */1117 aValues[iReg].XmmControlStatus.XmmStatusControlMask = pCtx->pXStateR3->x87.MXCSR_MASK; /** @todo ??? (Isn't this an output field?) */ 1101 1118 iReg++; 1102 1119 … … 1155 1172 } 1156 1173 1174 static int nemR3WinCopyStateFromHyperV(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx) 1175 { 1176 WHV_REGISTER_NAME aenmNames[128]; 1177 1178 /* GPRs */ 1179 aenmNames[0] = WHvX64RegisterRax; 1180 aenmNames[1] = WHvX64RegisterRcx; 1181 aenmNames[2] = WHvX64RegisterRdx; 1182 aenmNames[3] = WHvX64RegisterRbx; 1183 aenmNames[4] = WHvX64RegisterRsp; 1184 aenmNames[5] = WHvX64RegisterRbp; 1185 aenmNames[6] = WHvX64RegisterRsi; 1186 aenmNames[7] = WHvX64RegisterRdi; 1187 aenmNames[8] = WHvX64RegisterR8; 1188 aenmNames[9] = WHvX64RegisterR9; 1189 aenmNames[10] = WHvX64RegisterR10; 1190 aenmNames[11] = WHvX64RegisterR11; 1191 aenmNames[12] = WHvX64RegisterR12; 1192 aenmNames[13] = WHvX64RegisterR13; 1193 aenmNames[14] = WHvX64RegisterR14; 1194 aenmNames[15] = WHvX64RegisterR15; 1195 1196 /* RIP & Flags */ 1197 aenmNames[16] = WHvX64RegisterRip; 1198 aenmNames[17] = WHvX64RegisterRflags; 1199 1200 /* Segments */ 1201 aenmNames[18] = WHvX64RegisterEs; 1202 aenmNames[19] = WHvX64RegisterCs; 1203 aenmNames[20] = WHvX64RegisterSs; 1204 aenmNames[21] = WHvX64RegisterDs; 1205 aenmNames[22] = WHvX64RegisterFs; 1206 aenmNames[23] = WHvX64RegisterGs; 1207 aenmNames[24] = WHvX64RegisterLdtr; 1208 aenmNames[25] = WHvX64RegisterTr; 1209 1210 /* Descriptor tables. */ 1211 aenmNames[26] = WHvX64RegisterIdtr; 1212 aenmNames[27] = WHvX64RegisterGdtr; 1213 1214 /* Control registers. */ 1215 aenmNames[28] = WHvX64RegisterCr0; 1216 aenmNames[29] = WHvX64RegisterCr2; 1217 aenmNames[30] = WHvX64RegisterCr3; 1218 aenmNames[31] = WHvX64RegisterCr4; 1219 aenmNames[32] = WHvX64RegisterCr8; 1220 1221 /* Debug registers. */ 1222 aenmNames[33] = WHvX64RegisterDr0; 1223 aenmNames[34] = WHvX64RegisterDr1; 1224 aenmNames[35] = WHvX64RegisterDr2; 1225 aenmNames[36] = WHvX64RegisterDr3; 1226 aenmNames[37] = WHvX64RegisterDr6; 1227 aenmNames[38] = WHvX64RegisterDr7; 1228 1229 /* Vector state. */ 1230 aenmNames[39] = WHvX64RegisterXmm0; 1231 aenmNames[40] = WHvX64RegisterXmm1; 1232 aenmNames[41] = WHvX64RegisterXmm2; 1233 aenmNames[42] = WHvX64RegisterXmm3; 1234 aenmNames[43] = WHvX64RegisterXmm4; 1235 aenmNames[44] = WHvX64RegisterXmm5; 1236 aenmNames[45] = WHvX64RegisterXmm6; 1237 aenmNames[46] = WHvX64RegisterXmm7; 1238 aenmNames[47] = WHvX64RegisterXmm8; 1239 aenmNames[48] = WHvX64RegisterXmm9; 1240 aenmNames[49] = WHvX64RegisterXmm10; 1241 aenmNames[50] = WHvX64RegisterXmm11; 1242 aenmNames[51] = WHvX64RegisterXmm12; 1243 aenmNames[52] = WHvX64RegisterXmm13; 1244 aenmNames[53] = WHvX64RegisterXmm14; 1245 aenmNames[54] = WHvX64RegisterXmm15; 1246 1247 /* Floating point state. */ 1248 aenmNames[55] = WHvX64RegisterFpMmx0; 1249 aenmNames[56] = WHvX64RegisterFpMmx1; 1250 aenmNames[57] = WHvX64RegisterFpMmx2; 1251 aenmNames[58] = WHvX64RegisterFpMmx3; 1252 aenmNames[59] = WHvX64RegisterFpMmx4; 1253 aenmNames[60] = WHvX64RegisterFpMmx5; 1254 aenmNames[61] = WHvX64RegisterFpMmx6; 1255 aenmNames[62] = WHvX64RegisterFpMmx7; 1256 aenmNames[63] = WHvX64RegisterFpControlStatus; 1257 aenmNames[64] = WHvX64RegisterXmmControlStatus; 1258 1259 /* MSRs */ 1260 // WHvX64RegisterTsc - don't touch 1261 aenmNames[65] = WHvX64RegisterEfer; 1262 aenmNames[66] = WHvX64RegisterKernelGsBase; 1263 aenmNames[67] = WHvX64RegisterApicBase; 1264 aenmNames[68] = WHvX64RegisterPat; 1265 aenmNames[69] = WHvX64RegisterSysenterCs; 1266 aenmNames[70] = WHvX64RegisterSysenterEip; 1267 aenmNames[71] = WHvX64RegisterSysenterEsp; 1268 aenmNames[72] = WHvX64RegisterStar; 1269 aenmNames[73] = WHvX64RegisterLstar; 1270 aenmNames[74] = WHvX64RegisterCstar; 1271 aenmNames[75] = WHvX64RegisterSfmask; 1272 1273 /* event injection */ 1274 aenmNames[76] = WHvRegisterPendingInterruption; 1275 aenmNames[77] = WHvRegisterPendingInterruption; 1276 aenmNames[78] = WHvRegisterInterruptState; 1277 aenmNames[79] = WHvRegisterPendingEvent0; 1278 aenmNames[80] = WHvRegisterPendingEvent1; 1279 unsigned const cRegs = 81; 1280 1281 /* 1282 * Get the registers. 1283 */ 1284 WHV_REGISTER_VALUE aValues[cRegs]; 1285 RT_ZERO(aValues); 1286 Assert(RT_ELEMENTS(aValues) >= cRegs); 1287 Assert(RT_ELEMENTS(aenmNames) >= cRegs); 1288 #ifdef NEM_WIN_INTERCEPT_NT_IO_CTLS 1289 Log6(("Calling WHvGetVirtualProcessorRegisters(%p, %u, %p, %u, %p)\n", 1290 pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, cRegs, aValues)); 1291 #endif 1292 HRESULT hrc = WHvGetVirtualProcessorRegisters(pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, cRegs, aValues); 1293 if (SUCCEEDED(hrc)) 1294 { 1295 /* GPRs */ 1296 Assert(aenmNames[0] == WHvX64RegisterRax); 1297 Assert(aenmNames[15] == WHvX64RegisterR15); 1298 pCtx->rax = aValues[0].Reg64; 1299 pCtx->rcx = aValues[1].Reg64; 1300 pCtx->rdx = aValues[2].Reg64; 1301 pCtx->rbx = aValues[3].Reg64; 1302 pCtx->rsp = aValues[4].Reg64; 1303 pCtx->rbp = aValues[5].Reg64; 1304 pCtx->rsi = aValues[6].Reg64; 1305 pCtx->rdi = aValues[7].Reg64; 1306 pCtx->r8 = aValues[8].Reg64; 1307 pCtx->r9 = aValues[9].Reg64; 1308 pCtx->r10 = aValues[10].Reg64; 1309 pCtx->r11 = aValues[11].Reg64; 1310 pCtx->r12 = aValues[12].Reg64; 1311 pCtx->r13 = aValues[13].Reg64; 1312 pCtx->r14 = aValues[14].Reg64; 1313 pCtx->r15 = aValues[15].Reg64; 1314 1315 /* RIP & Flags */ 1316 Assert(aenmNames[16] == WHvX64RegisterRip); 1317 pCtx->rip = aValues[16].Reg64; 1318 pCtx->rflags.u = aValues[17].Reg64; 1319 1320 /* Segments */ 1321 #define COPY_BACK_SEG(a_idx, a_enmName, a_SReg) \ 1322 do { \ 1323 Assert(aenmNames[a_idx] == a_enmName); \ 1324 (a_SReg).u64Base = aValues[a_idx].Segment.Base; \ 1325 (a_SReg).u32Limit = aValues[a_idx].Segment.Limit; \ 1326 (a_SReg).ValidSel = (a_SReg).Sel = aValues[a_idx].Segment.Selector; \ 1327 (a_SReg).Attr.u = aValues[a_idx].Segment.Attributes; \ 1328 (a_SReg).fFlags = CPUMSELREG_FLAGS_VALID; \ 1329 } while (0) 1330 COPY_BACK_SEG(18, WHvX64RegisterEs, pCtx->es); 1331 COPY_BACK_SEG(19, WHvX64RegisterCs, pCtx->cs); 1332 COPY_BACK_SEG(20, WHvX64RegisterSs, pCtx->ss); 1333 COPY_BACK_SEG(21, WHvX64RegisterDs, pCtx->ds); 1334 COPY_BACK_SEG(22, WHvX64RegisterFs, pCtx->fs); 1335 COPY_BACK_SEG(23, WHvX64RegisterGs, pCtx->gs); 1336 COPY_BACK_SEG(24, WHvX64RegisterLdtr, pCtx->ldtr); 1337 COPY_BACK_SEG(25, WHvX64RegisterTr, pCtx->tr); 1338 1339 /* Descriptor tables. */ 1340 Assert(aenmNames[26] == WHvX64RegisterIdtr); 1341 pCtx->idtr.cbIdt = aValues[26].Table.Limit; 1342 pCtx->idtr.pIdt = aValues[26].Table.Base; 1343 Assert(aenmNames[27] == WHvX64RegisterGdtr); 1344 pCtx->gdtr.cbGdt = aValues[27].Table.Limit; 1345 pCtx->gdtr.pGdt = aValues[27].Table.Base; 1346 1347 /* Control registers. */ 1348 Assert(aenmNames[28] == WHvX64RegisterCr0); 1349 if (pCtx->cr0 != aValues[28].Reg64) 1350 { 1351 CPUMSetGuestCR0(pVCpu, aValues[28].Reg64); 1352 /** @todo more to do here! */ 1353 } 1354 pCtx->cr2 = aValues[29].Reg64; 1355 if (pCtx->cr3 != aValues[30].Reg64) 1356 { 1357 CPUMSetGuestCR3(pVCpu, aValues[30].Reg64); 1358 /** @todo more to do here! */ 1359 } 1360 if (pCtx->cr4 != aValues[31].Reg64) 1361 { 1362 CPUMSetGuestCR4(pVCpu, aValues[31].Reg64); 1363 /** @todo more to do here! */ 1364 } 1365 APICSetTpr(pVCpu, (uint8_t)aValues[32].Reg64 << 4); 1366 1367 /* Debug registers. */ 1368 Assert(aenmNames[33] == WHvX64RegisterDr0); 1369 /** @todo fixme */ 1370 if (pCtx->dr[0] != aValues[33].Reg64) 1371 CPUMSetGuestDR0(pVCpu, aValues[33].Reg64); 1372 if (pCtx->dr[1] != aValues[34].Reg64) 1373 CPUMSetGuestDR1(pVCpu, aValues[34].Reg64); 1374 if (pCtx->dr[2] != aValues[35].Reg64) 1375 CPUMSetGuestDR2(pVCpu, aValues[35].Reg64); 1376 if (pCtx->dr[3] != aValues[36].Reg64) 1377 CPUMSetGuestDR3(pVCpu, aValues[36].Reg64); 1378 Assert(aenmNames[37] == WHvX64RegisterDr6); 1379 Assert(aenmNames[38] == WHvX64RegisterDr7); 1380 if (pCtx->dr[6] != aValues[37].Reg64) 1381 CPUMSetGuestDR6(pVCpu, aValues[37].Reg64); 1382 if (pCtx->dr[7] != aValues[38].Reg64) 1383 CPUMSetGuestDR6(pVCpu, aValues[38].Reg64); 1384 1385 /* Vector state. */ 1386 Assert(aenmNames[39] == WHvX64RegisterXmm0); 1387 Assert(aenmNames[54] == WHvX64RegisterXmm15); 1388 pCtx->pXStateR3->x87.aXMM[0].uXmm.s.Lo = aValues[39].Reg128.Low64; 1389 pCtx->pXStateR3->x87.aXMM[0].uXmm.s.Hi = aValues[39].Reg128.High64; 1390 pCtx->pXStateR3->x87.aXMM[1].uXmm.s.Lo = aValues[40].Reg128.Low64; 1391 pCtx->pXStateR3->x87.aXMM[1].uXmm.s.Hi = aValues[40].Reg128.High64; 1392 pCtx->pXStateR3->x87.aXMM[2].uXmm.s.Lo = aValues[41].Reg128.Low64; 1393 pCtx->pXStateR3->x87.aXMM[2].uXmm.s.Hi = aValues[41].Reg128.High64; 1394 pCtx->pXStateR3->x87.aXMM[3].uXmm.s.Lo = aValues[42].Reg128.Low64; 1395 pCtx->pXStateR3->x87.aXMM[3].uXmm.s.Hi = aValues[42].Reg128.High64; 1396 pCtx->pXStateR3->x87.aXMM[4].uXmm.s.Lo = aValues[43].Reg128.Low64; 1397 pCtx->pXStateR3->x87.aXMM[4].uXmm.s.Hi = aValues[43].Reg128.High64; 1398 pCtx->pXStateR3->x87.aXMM[5].uXmm.s.Lo = aValues[44].Reg128.Low64; 1399 pCtx->pXStateR3->x87.aXMM[5].uXmm.s.Hi = aValues[44].Reg128.High64; 1400 pCtx->pXStateR3->x87.aXMM[6].uXmm.s.Lo = aValues[45].Reg128.Low64; 1401 pCtx->pXStateR3->x87.aXMM[6].uXmm.s.Hi = aValues[45].Reg128.High64; 1402 pCtx->pXStateR3->x87.aXMM[7].uXmm.s.Lo = aValues[46].Reg128.Low64; 1403 pCtx->pXStateR3->x87.aXMM[7].uXmm.s.Hi = aValues[46].Reg128.High64; 1404 pCtx->pXStateR3->x87.aXMM[8].uXmm.s.Lo = aValues[47].Reg128.Low64; 1405 pCtx->pXStateR3->x87.aXMM[8].uXmm.s.Hi = aValues[47].Reg128.High64; 1406 pCtx->pXStateR3->x87.aXMM[9].uXmm.s.Lo = aValues[48].Reg128.Low64; 1407 pCtx->pXStateR3->x87.aXMM[9].uXmm.s.Hi = aValues[48].Reg128.High64; 1408 pCtx->pXStateR3->x87.aXMM[10].uXmm.s.Lo = aValues[49].Reg128.Low64; 1409 pCtx->pXStateR3->x87.aXMM[10].uXmm.s.Hi = aValues[49].Reg128.High64; 1410 pCtx->pXStateR3->x87.aXMM[11].uXmm.s.Lo = aValues[50].Reg128.Low64; 1411 pCtx->pXStateR3->x87.aXMM[11].uXmm.s.Hi = aValues[50].Reg128.High64; 1412 pCtx->pXStateR3->x87.aXMM[12].uXmm.s.Lo = aValues[51].Reg128.Low64; 1413 pCtx->pXStateR3->x87.aXMM[12].uXmm.s.Hi = aValues[51].Reg128.High64; 1414 pCtx->pXStateR3->x87.aXMM[13].uXmm.s.Lo = aValues[52].Reg128.Low64; 1415 pCtx->pXStateR3->x87.aXMM[13].uXmm.s.Hi = aValues[52].Reg128.High64; 1416 pCtx->pXStateR3->x87.aXMM[14].uXmm.s.Lo = aValues[53].Reg128.Low64; 1417 pCtx->pXStateR3->x87.aXMM[14].uXmm.s.Hi = aValues[53].Reg128.High64; 1418 pCtx->pXStateR3->x87.aXMM[15].uXmm.s.Lo = aValues[54].Reg128.Low64; 1419 pCtx->pXStateR3->x87.aXMM[15].uXmm.s.Hi = aValues[54].Reg128.High64; 1420 1421 /* Floating point state. */ 1422 Assert(aenmNames[55] == WHvX64RegisterFpMmx0); 1423 Assert(aenmNames[62] == WHvX64RegisterFpMmx7); 1424 pCtx->pXStateR3->x87.aRegs[0].au64[0] = aValues[55].Fp.AsUINT128.Low64; 1425 pCtx->pXStateR3->x87.aRegs[0].au64[1] = aValues[55].Fp.AsUINT128.High64; 1426 pCtx->pXStateR3->x87.aRegs[1].au64[0] = aValues[56].Fp.AsUINT128.Low64; 1427 pCtx->pXStateR3->x87.aRegs[1].au64[1] = aValues[56].Fp.AsUINT128.High64; 1428 pCtx->pXStateR3->x87.aRegs[2].au64[0] = aValues[57].Fp.AsUINT128.Low64; 1429 pCtx->pXStateR3->x87.aRegs[2].au64[1] = aValues[57].Fp.AsUINT128.High64; 1430 pCtx->pXStateR3->x87.aRegs[3].au64[0] = aValues[58].Fp.AsUINT128.Low64; 1431 pCtx->pXStateR3->x87.aRegs[3].au64[1] = aValues[58].Fp.AsUINT128.High64; 1432 pCtx->pXStateR3->x87.aRegs[4].au64[0] = aValues[59].Fp.AsUINT128.Low64; 1433 pCtx->pXStateR3->x87.aRegs[4].au64[1] = aValues[59].Fp.AsUINT128.High64; 1434 pCtx->pXStateR3->x87.aRegs[5].au64[0] = aValues[60].Fp.AsUINT128.Low64; 1435 pCtx->pXStateR3->x87.aRegs[5].au64[1] = aValues[60].Fp.AsUINT128.High64; 1436 pCtx->pXStateR3->x87.aRegs[6].au64[0] = aValues[61].Fp.AsUINT128.Low64; 1437 pCtx->pXStateR3->x87.aRegs[6].au64[1] = aValues[61].Fp.AsUINT128.High64; 1438 pCtx->pXStateR3->x87.aRegs[7].au64[0] = aValues[62].Fp.AsUINT128.Low64; 1439 pCtx->pXStateR3->x87.aRegs[7].au64[1] = aValues[62].Fp.AsUINT128.High64; 1440 1441 Assert(aenmNames[63] == WHvX64RegisterFpControlStatus); 1442 pCtx->pXStateR3->x87.FCW = aValues[63].FpControlStatus.FpControl; 1443 pCtx->pXStateR3->x87.FSW = aValues[63].FpControlStatus.FpStatus; 1444 pCtx->pXStateR3->x87.FTW = aValues[63].FpControlStatus.FpTag 1445 /*| (aValues[63].FpControlStatus.Reserved << 8)*/; 1446 pCtx->pXStateR3->x87.FOP = aValues[63].FpControlStatus.LastFpOp; 1447 pCtx->pXStateR3->x87.FPUIP = (uint32_t)aValues[63].FpControlStatus.LastFpRip; 1448 pCtx->pXStateR3->x87.CS = (uint16_t)(aValues[63].FpControlStatus.LastFpRip >> 32); 1449 pCtx->pXStateR3->x87.Rsrvd1 = (uint16_t)(aValues[63].FpControlStatus.LastFpRip >> 48); 1450 1451 Assert(aenmNames[64] == WHvX64RegisterXmmControlStatus); 1452 pCtx->pXStateR3->x87.FPUDP = (uint32_t)aValues[64].XmmControlStatus.LastFpRdp; 1453 pCtx->pXStateR3->x87.DS = (uint16_t)(aValues[64].XmmControlStatus.LastFpRdp >> 32); 1454 pCtx->pXStateR3->x87.Rsrvd2 = (uint16_t)(aValues[64].XmmControlStatus.LastFpRdp >> 48); 1455 pCtx->pXStateR3->x87.MXCSR = aValues[64].XmmControlStatus.XmmStatusControl; 1456 pCtx->pXStateR3->x87.MXCSR_MASK = aValues[64].XmmControlStatus.XmmStatusControlMask; /** @todo ??? (Isn't this an output field?) */ 1457 1458 /* MSRs */ 1459 // WHvX64RegisterTsc - don't touch 1460 Assert(aenmNames[65] == WHvX64RegisterEfer); 1461 if (aValues[65].Reg64 != pCtx->msrEFER) 1462 { 1463 pCtx->msrEFER = aValues[65].Reg64; 1464 /** @todo more to do here! */ 1465 } 1466 1467 Assert(aenmNames[66] == WHvX64RegisterKernelGsBase); 1468 pCtx->msrKERNELGSBASE = aValues[66].Reg64; 1469 1470 Assert(aenmNames[67] == WHvX64RegisterApicBase); 1471 if (aValues[67].Reg64 != APICGetBaseMsrNoCheck(pVCpu)) 1472 { 1473 VBOXSTRICTRC rc2 = APICSetBaseMsr(pVCpu, aValues[67].Reg64); 1474 Assert(rc2 == VINF_SUCCESS); NOREF(rc2); 1475 } 1476 1477 Assert(aenmNames[68] == WHvX64RegisterPat); 1478 pCtx->msrPAT = aValues[68].Reg64; 1479 /// @todo WHvX64RegisterSysenterCs 1480 /// @todo WHvX64RegisterSysenterEip 1481 /// @todo WHvX64RegisterSysenterEsp 1482 Assert(aenmNames[72] == WHvX64RegisterStar); 1483 pCtx->msrSTAR = aValues[72].Reg64; 1484 Assert(aenmNames[73] == WHvX64RegisterLstar); 1485 pCtx->msrLSTAR = aValues[73].Reg64; 1486 Assert(aenmNames[74] == WHvX64RegisterCstar); 1487 pCtx->msrCSTAR = aValues[74].Reg64; 1488 Assert(aenmNames[75] == WHvX64RegisterSfmask); 1489 pCtx->msrSFMASK = aValues[75].Reg64; 1490 1491 /* event injection */ 1492 /// @todo WHvRegisterPendingInterruption 1493 /// @todo WHvRegisterInterruptState 1494 /// @todo WHvRegisterPendingEvent0 1495 /// @todo WHvRegisterPendingEvent1 1496 1497 1498 return VINF_SUCCESS; 1499 } 1500 1501 AssertLogRelMsgFailed(("WHvGetVirtualProcessorRegisters(%p, %u,,%u,) -> %Rhrc (Last=%#x/%u)\n", 1502 pVM->nem.s.hPartition, pVCpu->idCpu, cRegs, 1503 hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue)); 1504 return VERR_INTERNAL_ERROR; 1505 } 1506 1157 1507 1158 1508 #ifdef LOG_ENABLED … … 1169 1519 { 1170 1520 case WHvRunVpExitReasonMemoryAccess: 1171 Log2(("Exit: Memory access GCPhys=%RGp GCVirt=%RGv %s %s %s\n",1521 Log2(("Exit: Memory access: GCPhys=%RGp GCVirt=%RGv %s %s %s\n", 1172 1522 pExitReason->MemoryAccess.Gpa, pExitReason->MemoryAccess.Gva, 1173 1523 pExitReason->MemoryAccess.AccessInfo.AccessType == WHvMemoryAccessRead ? "read" … … 1182 1532 1183 1533 case WHvRunVpExitReasonX64IoPortAccess: 1184 Log2(("Exit: Memory accessIoPort=%#x LB %u %s%s%s rax=%#RX64 rcx=%#RX64 rsi=%#RX64 rdi=%#RX64\n",1534 Log2(("Exit: I/O port access: IoPort=%#x LB %u %s%s%s rax=%#RX64 rcx=%#RX64 rsi=%#RX64 rdi=%#RX64\n", 1185 1535 pExitReason->IoPortAccess.PortNumber, 1186 1536 pExitReason->IoPortAccess.AccessInfo.AccessSize, … … 1192 1542 pExitReason->IoPortAccess.Rsi, 1193 1543 pExitReason->IoPortAccess.Rdi)); 1194 Log2(("Exit: ds=%#x:{%#RX64 LB %#RX32, %#x} es=%#x:{%#RX64 LB %#RX32, %#x}\n",1544 Log2(("Exit: + ds=%#x:{%#RX64 LB %#RX32, %#x} es=%#x:{%#RX64 LB %#RX32, %#x}\n", 1195 1545 pExitReason->IoPortAccess.Ds.Selector, 1196 1546 pExitReason->IoPortAccess.Ds.Base, … … 1247 1597 { 1248 1598 const WHV_VP_EXIT_CONTEXT *pVpCtx = &pExitReason->IoPortAccess.VpContext; 1249 Log2(("Exit: CS:RIP=%04x:%08RX64 RFLAGS=%06RX64 cbInstr=%u CS={%RX64 L %#RX32, %#x}\n",1599 Log2(("Exit: + CS:RIP=%04x:%08RX64 RFLAGS=%06RX64 cbInstr=%u CS={%RX64 L %#RX32, %#x}\n", 1250 1600 pVpCtx->Cs.Selector, 1251 1601 pVpCtx->Rip, … … 1253 1603 pVpCtx->InstructionLength, 1254 1604 pVpCtx->Cs.Base, pVpCtx->Cs.Limit, pVpCtx->Cs.Attributes)); 1255 Log2(("Exit: cpl=%d CR0.PE=%d CR0.AM=%d EFER.LMA=%d DebugActive=%d InterruptionPending=%d InterruptShadow=%d\n",1605 Log2(("Exit: + cpl=%d CR0.PE=%d CR0.AM=%d EFER.LMA=%d DebugActive=%d InterruptionPending=%d InterruptShadow=%d\n", 1256 1606 pVpCtx->ExecutionState.Cpl, 1257 1607 pVpCtx->ExecutionState.Cr0Pe, … … 1264 1614 ("ExecutionState.AsUINT16=%#x\n", pVpCtx->ExecutionState.AsUINT16)); 1265 1615 1266 /** @todo Someone please explain why the InstructionBytes fields are 16 bytes 1267 * long, when 15 would've been sufficent and saved 3-7 bytes of alignment 1268 * padding? Intel max length is 15, so is this sSome ARM stuff? Aren't ARM 1616 /** @todo Someone at Microsoft please explain why the InstructionBytes fields 1617 * are 16 bytes long, when 15 would've been sufficent and saved 3-7 bytes of 1618 * alignment padding? Intel max length is 15, so is this sSome ARM stuff? 1619 * Aren't ARM 1269 1620 * instructions max 32-bit wide? Confused. */ 1270 1621 if (fExitInstr && pExitReason->IoPortAccess.InstructionByteCount > 0) 1271 Log2(("Exit: Instruction %.*Rhxs\n",1622 Log2(("Exit: + Instruction %.*Rhxs\n", 1272 1623 pExitReason->IoPortAccess.InstructionByteCount, pExitReason->IoPortAccess.InstructionBytes)); 1273 1624 } 1274 1625 } 1626 1627 1628 /** 1629 * Logs the current CPU state. 1630 */ 1631 static void nemR3WinLogState(PVM pVM, PVMCPU pVCpu) 1632 { 1633 if (LogIs3Enabled()) 1634 { 1635 char szRegs[4096]; 1636 DBGFR3RegPrintf(pVM->pUVM, pVCpu->idCpu, &szRegs[0], sizeof(szRegs), 1637 "rax=%016VR{rax} rbx=%016VR{rbx} rcx=%016VR{rcx} rdx=%016VR{rdx}\n" 1638 "rsi=%016VR{rsi} rdi=%016VR{rdi} r8 =%016VR{r8} r9 =%016VR{r9}\n" 1639 "r10=%016VR{r10} r11=%016VR{r11} r12=%016VR{r12} r13=%016VR{r13}\n" 1640 "r14=%016VR{r14} r15=%016VR{r15} %VRF{rflags}\n" 1641 "rip=%016VR{rip} rsp=%016VR{rsp} rbp=%016VR{rbp}\n" 1642 "cs={%04VR{cs} base=%016VR{cs_base} limit=%08VR{cs_lim} flags=%04VR{cs_attr}} cr0=%016VR{cr0}\n" 1643 "ds={%04VR{ds} base=%016VR{ds_base} limit=%08VR{ds_lim} flags=%04VR{ds_attr}} cr2=%016VR{cr2}\n" 1644 "es={%04VR{es} base=%016VR{es_base} limit=%08VR{es_lim} flags=%04VR{es_attr}} cr3=%016VR{cr3}\n" 1645 "fs={%04VR{fs} base=%016VR{fs_base} limit=%08VR{fs_lim} flags=%04VR{fs_attr}} cr4=%016VR{cr4}\n" 1646 "gs={%04VR{gs} base=%016VR{gs_base} limit=%08VR{gs_lim} flags=%04VR{gs_attr}} cr8=%016VR{cr8}\n" 1647 "ss={%04VR{ss} base=%016VR{ss_base} limit=%08VR{ss_lim} flags=%04VR{ss_attr}}\n" 1648 "dr0=%016VR{dr0} dr1=%016VR{dr1} dr2=%016VR{dr2} dr3=%016VR{dr3}\n" 1649 "dr6=%016VR{dr6} dr7=%016VR{dr7}\n" 1650 "gdtr=%016VR{gdtr_base}:%04VR{gdtr_lim} idtr=%016VR{idtr_base}:%04VR{idtr_lim} rflags=%08VR{rflags}\n" 1651 "ldtr={%04VR{ldtr} base=%016VR{ldtr_base} limit=%08VR{ldtr_lim} flags=%08VR{ldtr_attr}}\n" 1652 "tr ={%04VR{tr} base=%016VR{tr_base} limit=%08VR{tr_lim} flags=%08VR{tr_attr}}\n" 1653 " sysenter={cs=%04VR{sysenter_cs} eip=%08VR{sysenter_eip} esp=%08VR{sysenter_esp}}\n" 1654 " efer=%016VR{efer}\n" 1655 " pat=%016VR{pat}\n" 1656 " sf_mask=%016VR{sf_mask}\n" 1657 "krnl_gs_base=%016VR{krnl_gs_base}\n" 1658 " lstar=%016VR{lstar}\n" 1659 " star=%016VR{star} cstar=%016VR{cstar}\n" 1660 "fcw=%04VR{fcw} fsw=%04VR{fsw} ftw=%04VR{ftw} mxcsr=%04VR{mxcsr} mxcsr_mask=%04VR{mxcsr_mask}\n" 1661 ); 1662 1663 char szInstr[256]; 1664 DBGFR3DisasInstrEx(pVM->pUVM, pVCpu->idCpu, 0, 0, 1665 DBGF_DISAS_FLAGS_CURRENT_GUEST | DBGF_DISAS_FLAGS_DEFAULT_MODE, 1666 szInstr, sizeof(szInstr), NULL); 1667 Log3(("%s%s\n", szRegs, szInstr)); 1668 } 1669 } 1670 1275 1671 #endif /* LOG_ENABLED */ 1276 1672 1673 1674 /** 1675 * Advances the guest RIP and clear EFLAGS.RF. 1676 * 1677 * This may clear VMCPU_FF_INHIBIT_INTERRUPTS. 1678 * 1679 * @param pVCpu The cross context virtual CPU structure. 1680 * @param pCtx The CPU context to update. 1681 * @param pExitCtx The exit context. 1682 */ 1683 DECLINLINE(void) nemR3WinAdvanceGuestRipAndClearRF(PVMCPU pVCpu, PCPUMCTX pCtx, WHV_VP_EXIT_CONTEXT const *pExitCtx) 1684 { 1685 /* Advance the RIP. */ 1686 Assert(pExitCtx->InstructionLength > 0 && pExitCtx->InstructionLength < 16); 1687 pCtx->rip += pExitCtx->InstructionLength; 1688 pCtx->rflags.Bits.u1RF = 0; 1689 1690 /* Update interrupt inhibition. */ 1691 if (!VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)) 1692 { /* likely */ } 1693 else if (pCtx->rip != EMGetInhibitInterruptsPC(pVCpu)) 1694 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS); 1695 } 1696 1697 1698 static VBOXSTRICTRC nemR3WinHandleHalt(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason) 1699 { 1700 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason); 1701 AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED); 1702 } 1703 1704 1705 /** 1706 * @callback_method_impl{FNPGMPHYSNEMQUERYCHECKER} 1707 */ 1708 static DECLCALLBACK(int) nemR3WinHandleMemoryAccessPageCheckerCallback(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, 1709 PPGMPHYSNEMPAGEINFO pInfo, void *pvUser) 1710 { 1711 uint8_t u2State = pInfo->u2NemState; 1712 int rc = nemR3NativeSetPhysPage(pVM, GCPhys, pInfo->fNemProt, &u2State, 1713 u2State <= NEM_WIN_PAGE_STATE_UNMAPPED /*fBackingChanged*/); 1714 pInfo->u2NemState = u2State; 1715 RT_NOREF(pVCpu, pvUser); 1716 return rc; 1717 } 1718 1719 1720 /** 1721 * Handles an memory access VMEXIT. 1722 * 1723 * This can be triggered by a number of things. 1724 * 1725 * @returns Strict VBox status code. 1726 * @param pVM The cross context VM structure. 1727 * @param pVCpu The cross context virtual CPU structure. 1728 * @param pCtx The CPU context to update. 1729 * @param pExitReason The exit reason information. 1730 */ 1731 static VBOXSTRICTRC nemR3WinHandleMemoryAccess(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_MEMORY_ACCESS_CONTEXT const *pMemCtx) 1732 { 1733 /* 1734 * Ask PGM for information about the given GCPhys. We need to check if we're 1735 * out of sync first. 1736 */ 1737 PGMPHYSNEMPAGEINFO Info; 1738 int rc = PGMPhysNemQueryPageInfo(pVM, pVCpu, pMemCtx->Gpa, &Info, nemR3WinHandleMemoryAccessPageCheckerCallback, NULL); 1739 if (RT_SUCCESS(rc)) 1740 { 1741 if (Info.fNemProt & (pMemCtx->AccessInfo.AccessType == WHvMemoryAccessWrite ? NEM_PAGE_PROT_WRITE :NEM_PAGE_PROT_READ)) 1742 return VINF_SUCCESS; 1743 } 1744 1745 /* 1746 * Emulate the memory access, either access handler or special memory. 1747 */ 1748 VBOXSTRICTRC rcStrict; 1749 if (pMemCtx->InstructionByteCount > 0) 1750 rcStrict = IEMExecOneWithPrefetchedByPC(pVCpu, CPUMCTX2CORE(pCtx), pMemCtx->VpContext.Rip, 1751 pMemCtx->InstructionBytes, pMemCtx->InstructionByteCount); 1752 else 1753 rcStrict = IEMExecOne(pVCpu); 1754 /** @todo do we need to do anything wrt debugging here? */ 1755 return rcStrict; 1756 } 1757 1758 1759 /** 1760 * Handles an I/O port access VMEXIT. 1761 * 1762 * We ASSUME that the hypervisor has don't I/O port access control. 1763 * 1764 * @returns Strict VBox status code. 1765 * @param pVM The cross context VM structure. 1766 * @param pVCpu The cross context virtual CPU structure. 1767 * @param pCtx The CPU context to update. 1768 * @param pExitReason The exit reason information. 1769 */ 1770 static VBOXSTRICTRC nemR3WinHandleIoPortAccess(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, 1771 WHV_X64_IO_PORT_ACCESS_CONTEXT const *pIoPortCtx) 1772 { 1773 VBOXSTRICTRC rcStrict; 1774 if (!pIoPortCtx->AccessInfo.StringOp) 1775 { 1776 /* 1777 * Simple port I/O. 1778 */ 1779 Assert(pCtx->rax == pIoPortCtx->Rax); 1780 1781 static uint32_t const s_fAndMask[8] = 1782 { UINT32_C(0xff), UINT32_C(0xffff), UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX }; 1783 uint32_t const fAndMask = s_fAndMask[pIoPortCtx->AccessInfo.AccessSize]; 1784 if (pIoPortCtx->AccessInfo.IsWrite) 1785 { 1786 rcStrict = IOMIOPortWrite(pVM, pVCpu, pIoPortCtx->PortNumber, (uint32_t)pIoPortCtx->Rax & fAndMask, 1787 pIoPortCtx->AccessInfo.AccessSize); 1788 if (IOM_SUCCESS(rcStrict)) 1789 nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pIoPortCtx->VpContext); 1790 } 1791 else 1792 { 1793 uint32_t uValue = 0; 1794 rcStrict = IOMIOPortRead(pVM, pVCpu, pIoPortCtx->PortNumber, &uValue, 1795 pIoPortCtx->AccessInfo.AccessSize); 1796 if (IOM_SUCCESS(rcStrict)) 1797 { 1798 pCtx->eax = (pCtx->eax & ~fAndMask) | (uValue & fAndMask); 1799 nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pIoPortCtx->VpContext); 1800 } 1801 } 1802 } 1803 else 1804 { 1805 /* 1806 * String port I/O. 1807 */ 1808 /** @todo Someone at Microsoft please explain how we can get the address mode 1809 * from the IoPortAccess.VpContext. CS.Attributes is only sufficient for 1810 * getting the default mode, it can always be overridden by a prefix. This 1811 * forces us to interpret the instruction from opcodes, which is suboptimal. 1812 * Both AMD-V and VT-x includes the address size in the exit info, at least on 1813 * CPUs that are reasonably new. */ 1814 Assert( pIoPortCtx->Ds.Base == pCtx->ds.u64Base 1815 && pIoPortCtx->Ds.Limit == pCtx->ds.u32Limit 1816 && pIoPortCtx->Ds.Selector == pCtx->ds.Sel); 1817 Assert( pIoPortCtx->Es.Base == pCtx->es.u64Base 1818 && pIoPortCtx->Es.Limit == pCtx->es.u32Limit 1819 && pIoPortCtx->Es.Selector == pCtx->es.Sel); 1820 Assert(pIoPortCtx->Rdi == pCtx->rdi); 1821 Assert(pIoPortCtx->Rsi == pCtx->rsi); 1822 Assert(pIoPortCtx->Rcx == pCtx->rcx); 1823 Assert(pIoPortCtx->Rcx == pCtx->rcx); 1824 1825 rcStrict = IEMExecOne(pVCpu); 1826 } 1827 if (IOM_SUCCESS(rcStrict)) 1828 { 1829 /* 1830 * Do debug checks. 1831 */ 1832 if ( pIoPortCtx->VpContext.ExecutionState.DebugActive /** @todo Microsoft: Does DebugActive this only reflext DR7? */ 1833 || (pIoPortCtx->VpContext.Rflags & X86_EFL_TF) 1834 || DBGFBpIsHwIoArmed(pVM) ) 1835 { 1836 /** @todo Debugging. */ 1837 } 1838 } 1839 return rcStrict; 1840 } 1841 1842 1843 static VBOXSTRICTRC nemR3WinHandleInterruptWindow(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason) 1844 { 1845 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason); 1846 AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED); 1847 } 1848 1849 1850 static VBOXSTRICTRC nemR3WinHandleMsrAccess(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason) 1851 { 1852 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason); 1853 AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED); 1854 } 1855 1856 1857 static VBOXSTRICTRC nemR3WinHandleCpuId(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason) 1858 { 1859 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason); 1860 AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED); 1861 } 1862 1863 1864 static VBOXSTRICTRC nemR3WinHandleException(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason) 1865 { 1866 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason); 1867 AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED); 1868 } 1869 1870 1871 static VBOXSTRICTRC nemR3WinHandleUD(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason) 1872 { 1873 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason); 1874 AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED); 1875 } 1876 1877 1878 static VBOXSTRICTRC nemR3WinHandleTripleFault(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason) 1879 { 1880 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason); 1881 AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED); 1882 } 1883 1884 1885 static VBOXSTRICTRC nemR3WinHandleInvalidState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason) 1886 { 1887 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason); 1888 AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED); 1889 } 1890 1891 1277 1892 VBOXSTRICTRC nemR3NativeRunGC(PVM pVM, PVMCPU pVCpu) 1278 1893 { 1279 /* 1280 * Just some simple experiment here that runs a couple of instructions. 1281 */ 1282 PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu); 1283 int rc = nemR3WinCopyOutState(pVM, pVCpu, pCtx); 1284 if (RT_SUCCESS(rc)) 1285 { 1894 #ifdef LOG_ENABLED 1895 if (LogIs3Enabled()) 1896 { 1897 Log3(("nemR3NativeRunGC: Entering #%u\n", pVCpu->idCpu)); 1898 nemR3WinLogState(pVM, pVCpu); 1899 } 1900 #endif 1901 1902 /* 1903 * The run loop. 1904 * 1905 * Current approach to state updating to use the sledgehammer and sync 1906 * everything every time. This will be optimized later. 1907 */ 1908 const bool fSingleStepping = false; /** @todo get this from somewhere. */ 1909 VBOXSTRICTRC rcStrict = VINF_SUCCESS; 1910 for (;;) 1911 { 1912 /* 1913 * Copy the state. 1914 */ 1915 PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu); 1916 int rc2 = nemR3WinCopyStateToHyperV(pVM, pVCpu, pCtx); 1917 AssertRCBreakStmt(rc2, rcStrict = rc2); 1918 1919 /* 1920 * Run a bit. 1921 */ 1286 1922 WHV_RUN_VP_EXIT_CONTEXT ExitReason; 1287 1923 RT_ZERO(ExitReason); 1288 HRESULT hrc = WHvRunVirtualProcessor(pVM->nem.s.hPartition, pVCpu->idCpu, &ExitReason, sizeof(ExitReason)); 1289 Log2(("WHvRunVirtualProcessor -> %#x; exit code %#x (%d)\n", hrc, ExitReason.ExitReason)); 1924 if ( !VM_FF_IS_PENDING(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC) 1925 && !VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_HM_TO_R3_MASK)) 1926 { 1927 HRESULT hrc = WHvRunVirtualProcessor(pVM->nem.s.hPartition, pVCpu->idCpu, &ExitReason, sizeof(ExitReason)); 1928 AssertLogRelMsgBreakStmt(SUCCEEDED(hrc), 1929 ("WHvRunVirtualProcessor(%p, %u,,) -> %Rhrc (Last=%#x/%u)\n", pVM->nem.s.hPartition, pVCpu->idCpu, 1930 hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue), 1931 rcStrict = VERR_INTERNAL_ERROR); 1932 Log2(("WHvRunVirtualProcessor -> %#x; exit code %#x (%d)\n", hrc, ExitReason.ExitReason, ExitReason.ExitReason)); 1933 } 1934 else 1935 { 1936 LogFlow(("nemR3NativeRunGC: returning: pending FF (pre exec)\n")); 1937 break; 1938 } 1939 1940 /* 1941 * Copy back the state. 1942 */ 1943 rc2 = nemR3WinCopyStateFromHyperV(pVM, pVCpu, pCtx); 1944 AssertRCBreakStmt(rc2, rcStrict = rc2); 1945 1946 #ifdef VBOX_STRICT 1947 /* Assert that the VpContext field makes sense. */ 1948 switch (ExitReason.ExitReason) 1949 { 1950 case WHvRunVpExitReasonMemoryAccess: 1951 case WHvRunVpExitReasonX64IoPortAccess: 1952 case WHvRunVpExitReasonX64MsrAccess: 1953 case WHvRunVpExitReasonX64Cpuid: 1954 case WHvRunVpExitReasonException: 1955 case WHvRunVpExitReasonUnrecoverableException: 1956 Assert(ExitReason.IoPortAccess.VpContext.InstructionLength > 0); 1957 Assert(ExitReason.IoPortAccess.VpContext.InstructionLength < 16); 1958 Assert(ExitReason.IoPortAccess.VpContext.ExecutionState.Cpl == CPUMGetGuestCPL(pVCpu)); 1959 Assert(ExitReason.IoPortAccess.VpContext.ExecutionState.Cr0Pe == RT_BOOL(pCtx->cr0 & X86_CR0_PE)); 1960 Assert(ExitReason.IoPortAccess.VpContext.ExecutionState.Cr0Am == RT_BOOL(pCtx->cr0 & X86_CR0_AM)); 1961 Assert(ExitReason.IoPortAccess.VpContext.ExecutionState.EferLma == RT_BOOL(pCtx->msrEFER & MSR_K6_EFER_LMA)); 1962 Assert(ExitReason.IoPortAccess.VpContext.ExecutionState.DebugActive == RT_BOOL(pCtx->dr[7] & X86_DR7_ENABLED_MASK)); 1963 Assert(ExitReason.IoPortAccess.VpContext.ExecutionState.Reserved0 == 0); 1964 Assert(ExitReason.IoPortAccess.VpContext.ExecutionState.Reserved1 == 0); 1965 Assert(ExitReason.IoPortAccess.VpContext.Rip == pCtx->rip); 1966 Assert(ExitReason.IoPortAccess.VpContext.Rflags == pCtx->rflags.u); 1967 Assert( ExitReason.IoPortAccess.VpContext.Cs.Base == pCtx->cs.u64Base 1968 && ExitReason.IoPortAccess.VpContext.Cs.Limit == pCtx->cs.u32Limit 1969 && ExitReason.IoPortAccess.VpContext.Cs.Selector == pCtx->cs.Sel); 1970 break; 1971 default: break; /* shut up compiler. */ 1972 } 1973 #endif 1974 1975 #ifdef LOG_ENABLED 1976 /* 1977 * Do some logging. 1978 */ 1290 1979 if (LogIs2Enabled()) 1291 1980 nemR3WinLogExitReason(&ExitReason); 1292 1293 rc = VERR_NOT_IMPLEMENTED; 1294 } 1295 return rc; 1981 if (LogIs3Enabled()) 1982 nemR3WinLogState(pVM, pVCpu); 1983 #endif 1984 1985 /* 1986 * Deal with the exit. 1987 */ 1988 switch (ExitReason.ExitReason) 1989 { 1990 /* Frequent exits: */ 1991 case WHvRunVpExitReasonCanceled: 1992 case WHvRunVpExitReasonAlerted: 1993 rcStrict = VINF_SUCCESS; 1994 break; 1995 1996 case WHvRunVpExitReasonX64Halt: 1997 rcStrict = nemR3WinHandleHalt(pVM, pVCpu, pCtx, &ExitReason); 1998 break; 1999 2000 case WHvRunVpExitReasonMemoryAccess: 2001 rcStrict = nemR3WinHandleMemoryAccess(pVM, pVCpu, pCtx, &ExitReason.MemoryAccess); 2002 break; 2003 2004 case WHvRunVpExitReasonX64IoPortAccess: 2005 rcStrict = nemR3WinHandleIoPortAccess(pVM, pVCpu, pCtx, &ExitReason.IoPortAccess); 2006 break; 2007 2008 case WHvRunVpExitReasonX64InterruptWindow: 2009 rcStrict = nemR3WinHandleInterruptWindow(pVM, pVCpu, pCtx, &ExitReason); 2010 break; 2011 2012 case WHvRunVpExitReasonX64MsrAccess: /* needs configuring */ 2013 rcStrict = nemR3WinHandleMsrAccess(pVM, pVCpu, pCtx, &ExitReason); 2014 break; 2015 2016 case WHvRunVpExitReasonX64Cpuid: /* needs configuring */ 2017 rcStrict = nemR3WinHandleCpuId(pVM, pVCpu, pCtx, &ExitReason); 2018 break; 2019 2020 case WHvRunVpExitReasonException: /* needs configuring */ 2021 rcStrict = nemR3WinHandleException(pVM, pVCpu, pCtx, &ExitReason); 2022 break; 2023 2024 /* Unlikely exits: */ 2025 case WHvRunVpExitReasonUnsupportedFeature: 2026 rcStrict = nemR3WinHandleUD(pVM, pVCpu, pCtx, &ExitReason); 2027 break; 2028 2029 case WHvRunVpExitReasonUnrecoverableException: 2030 rcStrict = nemR3WinHandleTripleFault(pVM, pVCpu, pCtx, &ExitReason); 2031 break; 2032 2033 case WHvRunVpExitReasonInvalidVpRegisterValue: 2034 rcStrict = nemR3WinHandleInvalidState(pVM, pVCpu, pCtx, &ExitReason); 2035 break; 2036 2037 /* Undesired exits: */ 2038 case WHvRunVpExitReasonNone: 2039 default: 2040 AssertLogRelMsgFailed(("Unknown ExitReason: %#x\n", ExitReason.ExitReason)); 2041 rcStrict = VERR_INTERNAL_ERROR_3; 2042 break; 2043 } 2044 if (rcStrict != VINF_SUCCESS) 2045 { 2046 LogFlow(("nemR3NativeRunGC: returning: %Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 2047 break; 2048 } 2049 2050 /* If any FF is pending, return to the EM loops. That's okay for the 2051 current sledgehammer approach. */ 2052 if ( VM_FF_IS_PENDING( pVM, !fSingleStepping ? VM_FF_HP_R0_PRE_HM_MASK : VM_FF_HP_R0_PRE_HM_STEP_MASK) 2053 || VMCPU_FF_IS_PENDING(pVCpu, !fSingleStepping ? VMCPU_FF_HP_R0_PRE_HM_MASK : VMCPU_FF_HP_R0_PRE_HM_STEP_MASK) ) 2054 { 2055 LogFlow(("nemR3NativeRunGC: returning: pending FF\n")); 2056 break; 2057 } 2058 } 2059 2060 return rcStrict; 1296 2061 } 1297 2062
Note:
See TracChangeset
for help on using the changeset viewer.