Changeset 71222 in vbox for trunk/src/VBox/VMM/VMMAll
- Timestamp:
- Mar 5, 2018 10:07:48 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 121132
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/NEMAllNativeTemplate-win.cpp.h
r71184 r71222 40 40 NEM_TMPL_STATIC const char * const g_apszPageStates[4] = { "not-set", "unmapped", "readable", "writable" }; 41 41 42 /** HV_INTERCEPT_ACCESS_TYPE names. */ 43 static const char * const g_apszHvInterceptAccessTypes[4] = { "read", "write", "exec", "!undefined!" }; 44 42 45 43 46 /********************************************************************************************************************************* … … 67 70 PGVM pGVM = GVMMR0FastGetGVMByVM(pVM); 68 71 AssertReturn(pGVM, VERR_INVALID_VM_HANDLE); 69 return nemR0WinMapPages(pGVM, pVM, &pGVM->aCpus[pVCpu->idCpu], GCPhysSrc, GCPhysDst, 1, fFlags); 72 return nemR0WinMapPages(pGVM, pVM, &pGVM->aCpus[pVCpu->idCpu], 73 GCPhysSrc & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK, 74 GCPhysDst & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK, 75 1, fFlags); 70 76 #else 71 77 pVCpu->nem.s.Hypercall.MapPages.GCPhysSrc = GCPhysSrc & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK; … … 91 97 PGVM pGVM = GVMMR0FastGetGVMByVM(pVM); 92 98 AssertReturn(pGVM, VERR_INVALID_VM_HANDLE); 93 return nemR0WinUnmapPages(pGVM, &pGVM->aCpus[pVCpu->idCpu], GCPhys , 1);99 return nemR0WinUnmapPages(pGVM, &pGVM->aCpus[pVCpu->idCpu], GCPhys & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK, 1); 94 100 # else 95 101 pVCpu->nem.s.Hypercall.UnmapPages.GCPhys = GCPhys & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK; … … 100 106 101 107 #endif /* NEM_WIN_USE_HYPERCALLS_FOR_PAGES */ 102 103 104 108 #ifndef IN_RING0 105 109 106 110 NEM_TMPL_STATIC int nemHCWinCopyStateToHyperV(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx) 107 111 { 108 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS112 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS 109 113 NOREF(pCtx); 110 114 int rc = VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_NEM_EXPORT_STATE, 0, NULL); … … 112 116 return rc; 113 117 114 # else118 # else 115 119 WHV_REGISTER_NAME aenmNames[128]; 116 120 WHV_REGISTER_VALUE aValues[128]; … … 157 161 158 162 /* Segments */ 159 # define COPY_OUT_SEG(a_idx, a_enmName, a_SReg) \163 # define COPY_OUT_SEG(a_idx, a_enmName, a_SReg) \ 160 164 do { \ 161 165 aenmNames[a_idx] = a_enmName; \ … … 391 395 Assert(iReg < RT_ELEMENTS(aValues)); 392 396 Assert(iReg < RT_ELEMENTS(aenmNames)); 393 # ifdef NEM_WIN_INTERCEPT_NT_IO_CTLS397 # ifdef NEM_WIN_INTERCEPT_NT_IO_CTLS 394 398 Log12(("Calling WHvSetVirtualProcessorRegisters(%p, %u, %p, %u, %p)\n", 395 399 pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, iReg, aValues)); 396 # endif400 # endif 397 401 HRESULT hrc = WHvSetVirtualProcessorRegisters(pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, iReg, aValues); 398 402 if (SUCCEEDED(hrc)) … … 402 406 hrc, RTNtLastStatusValue(), RTNtLastErrorValue())); 403 407 return VERR_INTERNAL_ERROR; 404 # endif /* !NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS */408 # endif /* !NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS */ 405 409 } 406 410 … … 408 412 NEM_TMPL_STATIC int nemHCWinCopyStateFromHyperV(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, uint64_t fWhat) 409 413 { 410 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS414 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS 411 415 /* See NEMR0ImportState */ 412 416 NOREF(pCtx); … … 421 425 return rc; 422 426 423 # else427 # else 424 428 WHV_REGISTER_NAME aenmNames[128]; 425 429 … … 534 538 Assert(RT_ELEMENTS(aValues) >= cRegs); 535 539 Assert(RT_ELEMENTS(aenmNames) >= cRegs); 536 # ifdef NEM_WIN_INTERCEPT_NT_IO_CTLS540 # ifdef NEM_WIN_INTERCEPT_NT_IO_CTLS 537 541 Log12(("Calling WHvGetVirtualProcessorRegisters(%p, %u, %p, %u, %p)\n", 538 542 pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, cRegs, aValues)); 539 # endif543 # endif 540 544 HRESULT hrc = WHvGetVirtualProcessorRegisters(pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, cRegs, aValues); 541 545 if (SUCCEEDED(hrc)) … … 567 571 568 572 /* Segments */ 569 # define COPY_BACK_SEG(a_idx, a_enmName, a_SReg) \573 # define COPY_BACK_SEG(a_idx, a_enmName, a_SReg) \ 570 574 do { \ 571 575 Assert(aenmNames[a_idx] == a_enmName); \ … … 774 778 hrc, RTNtLastStatusValue(), RTNtLastErrorValue())); 775 779 return VERR_INTERNAL_ERROR; 776 #endif /* !NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS */ 777 } 780 # endif /* !NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS */ 781 } 782 783 #endif /* !IN_RING0 */ 778 784 779 785 … … 1172 1178 } 1173 1179 1174 #ifdef IN_RING3 1180 #ifdef IN_RING0 1181 /** 1182 * Wrapper around nemR0WinImportState that converts VERR_NEM_CHANGE_PGM_MODE and 1183 * VERR_NEM_FLUSH_TBL into informational status codes and logs+asserts statuses. 1184 * 1185 * @returns VBox strict status code. 1186 * @param pGVM The global (ring-0) VM structure. 1187 * @param pGVCpu The global (ring-0) per CPU structure. 1188 * @param pCtx The CPU context to import into. 1189 * @param fWhat What to import. 1190 * @param pszCaller Whoe is doing the importing. 1191 */ 1192 DECLINLINE(VBOXSTRICTRC) nemR0WinImportStateStrict(PGVM pGVM, PGVMCPU pGVCpu, PCPUMCTX pCtx, uint64_t fWhat, const char *pszCaller) 1193 { 1194 int rc = nemR0WinImportState(pGVM, pGVCpu, pCtx, fWhat); 1195 if (RT_SUCCESS(rc)) 1196 { 1197 Assert(rc == VINF_SUCCESS); 1198 return VINF_SUCCESS; 1199 } 1200 1201 if (rc == VERR_NEM_CHANGE_PGM_MODE || rc == VERR_NEM_FLUSH_TLB) 1202 { 1203 Log4(("%s/%u: nemR0WinImportState -> %Rrc\n", pszCaller, pGVCpu->idCpu, -rc)); 1204 return -rc; 1205 } 1206 AssertMsgFailedReturn(("%s/%u: nemR0WinImportState failed: %Rrc\n", pszCaller, pGVCpu->idCpu, rc), rc); 1207 } 1208 #endif /* IN_RING0 */ 1175 1209 1176 1210 /** … … 1201 1235 * @param pMsg The message. 1202 1236 * @param pCtx The register context. 1237 * @param pGVCpu The global (ring-0) per CPU structure (NULL in r3). 1203 1238 */ 1204 1239 NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinHandleMessageMemory(PVM pVM, PVMCPU pVCpu, HV_X64_MEMORY_INTERCEPT_MESSAGE const *pMsg, 1205 PCPUMCTX pCtx) 1206 { 1240 PCPUMCTX pCtx, PGVMCPU pGVCpu) 1241 { 1242 Assert( pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_READ 1243 || pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE 1244 || pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_EXECUTE); 1245 1207 1246 /* 1208 1247 * Whatever we do, we must clear pending event ejection upon resume. … … 1226 1265 if (State.fCanResume) 1227 1266 { 1228 Log4(("MemExit: %RGp (=>%RHp) %s fProt=%u%s%s%s; restarting (%s)\n", 1267 Log4(("MemExit/%u: %04x:%08RX64: %RGp (=>%RHp) %s fProt=%u%s%s%s; restarting (%s)\n", 1268 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, 1229 1269 pMsg->GuestPhysicalAddress, Info.HCPhys, g_apszPageStates[Info.u2NemState], Info.fNemProt, 1230 1270 Info.fHasHandlers ? " handlers" : "", Info.fZeroPage ? " zero-pg" : "", 1231 State.fDidSomething ? "" : " no-change", g_apsz WHvMemAccesstypes[pMsg->Header.InterceptAccessType]));1271 State.fDidSomething ? "" : " no-change", g_apszHvInterceptAccessTypes[pMsg->Header.InterceptAccessType])); 1232 1272 return VINF_SUCCESS; 1233 1273 } 1234 1274 } 1235 Log4(("MemExit: %RGp (=>%RHp) %s fProt=%u%s%s%s; emulating (%s)\n", 1275 Log4(("MemExit/%u: %04x:%08RX64: %RGp (=>%RHp) %s fProt=%u%s%s%s; emulating (%s)\n", 1276 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, 1236 1277 pMsg->GuestPhysicalAddress, Info.HCPhys, g_apszPageStates[Info.u2NemState], Info.fNemProt, 1237 1278 Info.fHasHandlers ? " handlers" : "", Info.fZeroPage ? " zero-pg" : "", 1238 State.fDidSomething ? "" : " no-change", g_apsz WHvMemAccesstypes[pMsg->Header.InterceptAccessType]));1279 State.fDidSomething ? "" : " no-change", g_apszHvInterceptAccessTypes[pMsg->Header.InterceptAccessType])); 1239 1280 } 1240 1281 else 1241 Log4(("MemExit: %RGp rc=%Rrc%s; emulating (%s)\n", pMsg->GuestPhysicalAddress, rc, 1242 State.fDidSomething ? " modified-backing" : "", g_apszWHvMemAccesstypes[pMsg->Header.InterceptAccessType])); 1282 Log4(("MemExit/%u: %04x:%08RX64: %RGp rc=%Rrc%s; emulating (%s)\n", 1283 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, pMsg->GuestPhysicalAddress, rc, 1284 State.fDidSomething ? " modified-backing" : "", g_apszHvInterceptAccessTypes[pMsg->Header.InterceptAccessType])); 1243 1285 1244 1286 /* … … 1246 1288 */ 1247 1289 nemHCWinCopyStateFromX64Header(pCtx, &pMsg->Header); 1290 VBOXSTRICTRC rcStrict; 1291 #ifdef IN_RING0 1292 rcStrict = nemR0WinImportStateStrict(pGVCpu->pGVM, pGVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM, "MemExit"); 1293 if (rcStrict != VINF_SUCCESS) 1294 return rcStrict; 1295 #else 1248 1296 rc = nemHCWinCopyStateFromHyperV(pVM, pVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM); 1249 1297 AssertRCReturn(rc, rc); 1250 1251 VBOXSTRICTRC rcStrict; 1298 NOREF(pGVCpu); 1299 #endif 1300 1252 1301 if (pMsg->InstructionByteCount > 0) 1253 1302 rcStrict = IEMExecOneWithPrefetchedByPC(pVCpu, CPUMCTX2CORE(pCtx), pMsg->Header.Rip, … … 1268 1317 * @param pVCpu The cross context per CPU structure. 1269 1318 * @param pMsg The message. 1319 * @param pGVCpu The global (ring-0) per CPU structure (NULL in r3). 1270 1320 */ 1271 1321 NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinHandleMessageIoPort(PVM pVM, PVMCPU pVCpu, HV_X64_IO_PORT_INTERCEPT_MESSAGE const *pMsg, 1272 PCPUMCTX pCtx )1322 PCPUMCTX pCtx, PGVMCPU pGVCpu) 1273 1323 { 1274 1324 Assert( pMsg->AccessInfo.AccessSize == 1 1275 1325 || pMsg->AccessInfo.AccessSize == 2 1276 1326 || pMsg->AccessInfo.AccessSize == 4); 1327 Assert( pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_READ 1328 || pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE); 1277 1329 1278 1330 /* … … 1294 1346 { 1295 1347 rcStrict = IOMIOPortWrite(pVM, pVCpu, pMsg->PortNumber, (uint32_t)pMsg->Rax & fAndMask, pMsg->AccessInfo.AccessSize); 1296 Log4(("IOExit: %04x:%08RX64: OUT %#x, %#x LB %u rcStrict=%Rrc\n", pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, 1297 pMsg->PortNumber, (uint32_t)pMsg->Rax & fAndMask, pMsg->AccessInfo.AccessSize, VBOXSTRICTRC_VAL(rcStrict) )); 1348 Log4(("IOExit/%u: %04x:%08RX64: OUT %#x, %#x LB %u rcStrict=%Rrc\n", 1349 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, pMsg->PortNumber, 1350 (uint32_t)pMsg->Rax & fAndMask, pMsg->AccessInfo.AccessSize, VBOXSTRICTRC_VAL(rcStrict) )); 1298 1351 if (IOM_SUCCESS(rcStrict)) 1299 1352 { … … 1306 1359 uint32_t uValue = 0; 1307 1360 rcStrict = IOMIOPortRead(pVM, pVCpu, pMsg->PortNumber, &uValue, pMsg->AccessInfo.AccessSize); 1308 Log4(("IOExit : %04x:%08RX64: IN %#x LB %u -> %#x, rcStrict=%Rrc\n", pMsg->Header.CsSegment.Selector, pMsg->Header.Rip,1309 pMsg-> PortNumber, pMsg->AccessInfo.AccessSize, uValue, VBOXSTRICTRC_VAL(rcStrict) ));1361 Log4(("IOExit/%u: %04x:%08RX64: IN %#x LB %u -> %#x, rcStrict=%Rrc\n", pVCpu->idCpu, pMsg->Header.CsSegment.Selector, 1362 pMsg->Header.Rip, pMsg->PortNumber, pMsg->AccessInfo.AccessSize, uValue, VBOXSTRICTRC_VAL(rcStrict) )); 1310 1363 if (IOM_SUCCESS(rcStrict)) 1311 1364 { … … 1315 1368 pCtx->rax = uValue; 1316 1369 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RAX; 1317 Log4(("IOExit : RAX %#RX64 -> %#RX64\n", pMsg->Rax, pCtx->rax));1370 Log4(("IOExit/%u: RAX %#RX64 -> %#RX64\n", pVCpu->idCpu, pMsg->Rax, pCtx->rax)); 1318 1371 nemHCWinCopyStateFromX64Header(pCtx, &pMsg->Header); 1319 1372 nemHCWinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pMsg->Header); … … 1346 1399 pCtx->rdi = pMsg->Rdi; 1347 1400 pCtx->rsi = pMsg->Rsi; 1401 #ifdef IN_RING0 1402 rcStrict = nemR0WinImportStateStrict(pGVCpu->pGVM, pGVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM, "IOExit"); 1403 if (rcStrict != VINF_SUCCESS) 1404 return rcStrict; 1405 #else 1348 1406 int rc = nemHCWinCopyStateFromHyperV(pVM, pVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM); 1349 1407 AssertRCReturn(rc, rc); 1350 1351 Log4(("IOExit: %04x:%08RX64: %s%s %#x LB %u (emulating)\n", pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, 1408 RT_NOREF(pGVCpu); 1409 #endif 1410 1411 Log4(("IOExit/%u: %04x:%08RX64: %s%s %#x LB %u (emulating)\n", 1412 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, 1352 1413 pMsg->AccessInfo.RepPrefix ? "REP " : "", 1353 1414 pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE ? "OUTS" : "INS", … … 1379 1440 * @param pMappingHeader The message slot mapping. 1380 1441 * @param pCtx The register context. 1442 * @param pGVCpu The global (ring-0) per CPU structure (NULL in r3). 1381 1443 */ 1382 1444 NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinHandleMessage(PVM pVM, PVMCPU pVCpu, VID_MESSAGE_MAPPING_HEADER volatile *pMappingHeader, 1383 PCPUMCTX pCtx )1445 PCPUMCTX pCtx, PGVMCPU pGVCpu) 1384 1446 { 1385 1447 if (pMappingHeader->enmVidMsgType == VidMessageHypervisorMessage) … … 1391 1453 case HvMessageTypeUnmappedGpa: 1392 1454 Assert(pMsg->Header.PayloadSize == RT_UOFFSETOF(HV_X64_MEMORY_INTERCEPT_MESSAGE, DsSegment)); 1393 return nemHCWinHandleMessageMemory(pVM, pVCpu, &pMsg->X64MemoryIntercept, pCtx );1455 return nemHCWinHandleMessageMemory(pVM, pVCpu, &pMsg->X64MemoryIntercept, pCtx, pGVCpu); 1394 1456 1395 1457 case HvMessageTypeGpaIntercept: 1396 1458 Assert(pMsg->Header.PayloadSize == RT_UOFFSETOF(HV_X64_MEMORY_INTERCEPT_MESSAGE, DsSegment)); 1397 return nemHCWinHandleMessageMemory(pVM, pVCpu, &pMsg->X64MemoryIntercept, pCtx );1459 return nemHCWinHandleMessageMemory(pVM, pVCpu, &pMsg->X64MemoryIntercept, pCtx, pGVCpu); 1398 1460 1399 1461 case HvMessageTypeX64IoPortIntercept: 1400 1462 Assert(pMsg->Header.PayloadSize == sizeof(pMsg->X64IoPortIntercept)); 1401 return nemHCWinHandleMessageIoPort(pVM, pVCpu, &pMsg->X64IoPortIntercept, pCtx );1463 return nemHCWinHandleMessageIoPort(pVM, pVCpu, &pMsg->X64IoPortIntercept, pCtx, pGVCpu); 1402 1464 1403 1465 case HvMessageTypeX64Halt: … … 1454 1516 * exit. 1455 1517 * @param pMappingHeader The message slot mapping. 1518 * @param pGVM The global (ring-0) VM structure (NULL in r3). 1519 * @param pGVCpu The global (ring-0) per CPU structure (NULL in r3). 1456 1520 */ 1457 1521 NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinStopCpu(PVM pVM, PVMCPU pVCpu, VBOXSTRICTRC rcStrict, 1458 VID_MESSAGE_MAPPING_HEADER volatile *pMappingHeader) 1522 VID_MESSAGE_MAPPING_HEADER volatile *pMappingHeader, 1523 PGVM pGVM, PGVMCPU pGVCpu) 1459 1524 { 1460 1525 /* … … 1462 1527 * does another VM exit. 1463 1528 */ 1529 #ifdef IN_RING0 1530 pVCpu->nem.s.uIoCtlBuf.idCpu = pGVCpu->idCpu; 1531 NTSTATUS rcNt = nemR0NtPerformIoControl(pGVM, pGVM->nem.s.IoCtlStopVirtualProcessor.uFunction, 1532 &pVCpu->nem.s.uIoCtlBuf.idCpu, sizeof(pVCpu->nem.s.uIoCtlBuf.idCpu), 1533 NULL, 0); 1534 if (NT_SUCCESS(rcNt)) 1535 { 1536 Log8(("nemHCWinStopCpu: Stopping CPU succeeded (cpu status %u)\n", nemHCWinCpuGetRunningStatus(pVCpu) )); 1537 return rcStrict; 1538 } 1539 #else 1464 1540 BOOL fRet = VidStopVirtualProcessor(pVM->nem.s.hPartitionDevice, pVCpu->idCpu); 1465 1541 if (fRet) … … 1468 1544 return rcStrict; 1469 1545 } 1546 RT_NOREF(pGVM, pGVCpu); 1547 #endif 1470 1548 1471 1549 /* 1472 1550 * Dang. The CPU stopped by itself and we got a couple of message to deal with. 1473 1551 */ 1552 #ifdef IN_RING0 1553 AssertLogRelMsgReturn(rcNt == ERROR_VID_STOP_PENDING, ("rcNt=%#x\n", rcNt), 1554 RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR_3 : rcStrict); 1555 #else 1474 1556 DWORD dwErr = RTNtLastErrorValue(); 1475 AssertLogRelMsgReturn(dwErr == ERROR_VID_STOP_PENDING, ("dwErr=%#u \n", dwErr),1557 AssertLogRelMsgReturn(dwErr == ERROR_VID_STOP_PENDING, ("dwErr=%#u (%#x)\n", dwErr, dwErr), 1476 1558 RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR_3 : rcStrict); 1559 #endif 1477 1560 Log8(("nemHCWinStopCpu: Stopping CPU pending...\n")); 1478 1561 … … 1481 1564 * Note! We can safely ASSUME that rcStrict isn't an important information one. 1482 1565 */ 1566 #ifdef IN_RING0 1567 pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.iCpu = pGVCpu->idCpu; 1568 pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.fFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE; 1569 pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.cMillies = 30000; /*ms*/ 1570 rcNt = nemR0NtPerformIoControl(pGVM, pGVM->nem.s.IoCtlMessageSlotHandleAndGetNext.uFunction, 1571 &pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext, 1572 sizeof(pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext), 1573 NULL, 0); 1574 AssertLogRelMsgReturn(NT_SUCCESS(rcNt), ("1st VidMessageSlotHandleAndGetNext after ERROR_VID_STOP_PENDING failed: %#x\n", rcNt), 1575 RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR_3 : rcStrict); 1576 #else 1483 1577 BOOL fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu, 1484 1578 VID_MSHAGN_F_GET_NEXT_MESSAGE, 30000 /*ms*/); 1485 AssertLogRelMsgReturn(fWait, 1486 ("1st VidMessageSlotHandleAndGetNext after ERROR_VID_STOP_PENDING failed: %u\n", RTNtLastErrorValue()), 1579 AssertLogRelMsgReturn(fWait, ("1st VidMessageSlotHandleAndGetNext after ERROR_VID_STOP_PENDING failed: %u\n", RTNtLastErrorValue()), 1487 1580 RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR_3 : rcStrict); 1581 #endif 1488 1582 1489 1583 /* It should be a hypervisor message and definitely not a stop request completed message. */ … … 1494 1588 RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR_3 : rcStrict); 1495 1589 1496 VBOXSTRICTRC rcStrict2 = nemHCWinHandleMessage(pVM, pVCpu, pMappingHeader, CPUMQueryGuestCtxPtr(pVCpu) );1590 VBOXSTRICTRC rcStrict2 = nemHCWinHandleMessage(pVM, pVCpu, pMappingHeader, CPUMQueryGuestCtxPtr(pVCpu), pGVCpu); 1497 1591 if (rcStrict2 != VINF_SUCCESS && RT_SUCCESS(rcStrict)) 1498 1592 rcStrict = rcStrict2; … … 1502 1596 * that as handled too. CPU is back into fully stopped stated then. 1503 1597 */ 1598 #ifdef IN_RING0 1599 pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.iCpu = pGVCpu->idCpu; 1600 pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.fFlags = VID_MSHAGN_F_HANDLE_MESSAGE | VID_MSHAGN_F_GET_NEXT_MESSAGE; 1601 pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.cMillies = 30000; /*ms*/ 1602 rcNt = nemR0NtPerformIoControl(pGVM, pGVM->nem.s.IoCtlMessageSlotHandleAndGetNext.uFunction, 1603 &pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext, 1604 sizeof(pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext), 1605 NULL, 0); 1606 AssertLogRelMsgReturn(NT_SUCCESS(rcNt), ("2st VidMessageSlotHandleAndGetNext after ERROR_VID_STOP_PENDING failed: %#x\n", rcNt), 1607 RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR_3 : rcStrict); 1608 #else 1504 1609 fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu, 1505 1610 VID_MSHAGN_F_HANDLE_MESSAGE | VID_MSHAGN_F_GET_NEXT_MESSAGE, 30000 /*ms*/); 1506 AssertLogRelMsgReturn(fWait, 1507 ("2nd VidMessageSlotHandleAndGetNext after ERROR_VID_STOP_PENDING failed: %u\n", RTNtLastErrorValue()), 1611 AssertLogRelMsgReturn(fWait, ("2nd VidMessageSlotHandleAndGetNext after ERROR_VID_STOP_PENDING failed: %u\n", RTNtLastErrorValue()), 1508 1612 RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR_3 : rcStrict); 1613 #endif 1509 1614 1510 1615 /* It should be a stop request completed message. */ … … 1516 1621 1517 1622 /* Mark this as handled. */ 1518 fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu, 1519 VID_MSHAGN_F_HANDLE_MESSAGE, 30000 /*ms*/); 1520 AssertLogRelMsgReturn(fWait, 1521 ("3rd VidMessageSlotHandleAndGetNext after ERROR_VID_STOP_PENDING failed: %u\n", RTNtLastErrorValue()), 1623 #ifdef IN_RING0 1624 pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.iCpu = pGVCpu->idCpu; 1625 pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.fFlags = VID_MSHAGN_F_HANDLE_MESSAGE; 1626 pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.cMillies = 30000; /*ms*/ 1627 rcNt = nemR0NtPerformIoControl(pGVM, pGVM->nem.s.IoCtlMessageSlotHandleAndGetNext.uFunction, 1628 &pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext, 1629 sizeof(pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext), 1630 NULL, 0); 1631 AssertLogRelMsgReturn(NT_SUCCESS(rcNt), ("3rd VidMessageSlotHandleAndGetNext after ERROR_VID_STOP_PENDING failed: %#x\n", rcNt), 1522 1632 RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR_3 : rcStrict); 1633 #else 1634 fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu, VID_MSHAGN_F_HANDLE_MESSAGE, 30000 /*ms*/); 1635 AssertLogRelMsgReturn(fWait, ("3rd VidMessageSlotHandleAndGetNext after ERROR_VID_STOP_PENDING failed: %u\n", RTNtLastErrorValue()), 1636 RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR_3 : rcStrict); 1637 #endif 1523 1638 Log8(("nemHCWinStopCpu: Stopped the CPU (rcStrict=%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict) )); 1524 1639 return rcStrict; … … 1526 1641 1527 1642 1528 NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinRunGC(PVM pVM, PVMCPU pVCpu )1643 NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinRunGC(PVM pVM, PVMCPU pVCpu, PGVM pGVM, PGVMCPU pGVCpu) 1529 1644 { 1530 1645 PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu); 1531 LogFlow((" nemHCWinRunGC: Entering #%u cs:rip=%04x:%08RX64 efl=%#08RX64\n", pVCpu->idCpu, pCtx->cs.Sel, pCtx->rip, pCtx->rflags));1646 LogFlow(("NEM/%u: %04x:%08RX64 efl=%#08RX64 <=\n", pVCpu->idCpu, pCtx->cs.Sel, pCtx->rip, pCtx->rflags)); 1532 1647 #ifdef LOG_ENABLED 1533 1648 if (LogIs3Enabled()) … … 1552 1667 if ((pCtx->fExtrn & (CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_NEM_WIN_MASK)) != (CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_NEM_WIN_MASK)) 1553 1668 { 1669 #ifdef IN_RING0 1670 int rc2 = nemR0WinExportState(pGVM, pGVCpu, pCtx); 1671 #else 1554 1672 int rc2 = nemHCWinCopyStateToHyperV(pVM, pVCpu, pCtx); 1673 RT_NOREF(pGVM, pGVCpu); 1674 #endif 1555 1675 AssertRCReturn(rc2, rc2); 1556 1676 } … … 1566 1686 else 1567 1687 { 1568 if (g_pfnVidStartVirtualProcessor(pVM->nem.s.hPartitionDevice, pVCpu->idCpu)) 1569 pVCpu->nem.s.fHandleAndGetFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE; 1570 else 1571 AssertLogRelMsgFailedReturn(("VidStartVirtualProcessor failed for CPU #%u: %u (%#x, rcNt=%#x)\n", 1572 pVCpu->idCpu, RTNtLastErrorValue(), RTNtLastErrorValue(), RTNtLastStatusValue()), 1573 VERR_INTERNAL_ERROR_3); 1688 #ifdef IN_RING0 1689 pVCpu->nem.s.uIoCtlBuf.idCpu = pGVCpu->idCpu; 1690 NTSTATUS rcNt = nemR0NtPerformIoControl(pGVM, pGVM->nem.s.IoCtlStartVirtualProcessor.uFunction, 1691 &pVCpu->nem.s.uIoCtlBuf.idCpu, sizeof(pVCpu->nem.s.uIoCtlBuf.idCpu), 1692 NULL, 0); 1693 LogFlow(("NEM/%u: IoCtlStartVirtualProcessor -> %#x\n", pVCpu->idCpu, rcNt)); 1694 AssertLogRelMsgReturn(NT_SUCCESS(rcNt), ("VidStartVirtualProcessor failed for CPU #%u: %#x\n", pGVCpu->idCpu, rcNt), 1695 VERR_INTERNAL_ERROR_3); 1696 #else 1697 AssertLogRelMsgReturn(g_pfnVidStartVirtualProcessor(pVM->nem.s.hPartitionDevice, pVCpu->idCpu), 1698 ("VidStartVirtualProcessor failed for CPU #%u: %u (%#x, rcNt=%#x)\n", 1699 pVCpu->idCpu, RTNtLastErrorValue(), RTNtLastErrorValue(), RTNtLastStatusValue()), 1700 VERR_INTERNAL_ERROR_3); 1701 #endif 1702 pVCpu->nem.s.fHandleAndGetFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE; 1574 1703 } 1575 1704 1576 if (VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM , VMCPUSTATE_STARTED))1705 if (VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM_WAIT, VMCPUSTATE_STARTED)) 1577 1706 { 1707 #ifdef IN_RING0 1708 pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.iCpu = pGVCpu->idCpu; 1709 pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.fFlags = pVCpu->nem.s.fHandleAndGetFlags; 1710 pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.cMillies = cMillies; 1711 NTSTATUS rcNt = nemR0NtPerformIoControl(pGVM, pGVM->nem.s.IoCtlMessageSlotHandleAndGetNext.uFunction, 1712 &pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext, 1713 sizeof(pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext), 1714 NULL, 0); 1715 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM_WAIT); 1716 if (rcNt == STATUS_SUCCESS) 1717 #else 1578 1718 BOOL fRet = VidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu, 1579 1719 pVCpu->nem.s.fHandleAndGetFlags, cMillies); 1580 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM );1720 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM_WAIT); 1581 1721 if (fRet) 1722 #endif 1582 1723 { 1583 1724 /* 1584 1725 * Deal with the message. 1585 1726 */ 1586 rcStrict = nemHCWinHandleMessage(pVM, pVCpu, pMappingHeader, pCtx );1727 rcStrict = nemHCWinHandleMessage(pVM, pVCpu, pMappingHeader, pCtx, pGVCpu); 1587 1728 pVCpu->nem.s.fHandleAndGetFlags |= VID_MSHAGN_F_HANDLE_MESSAGE; 1729 if (rcStrict == VINF_SUCCESS) 1730 { /* hopefully likely */ } 1731 else 1732 { 1733 LogFlow(("NEM/%u: breaking: nemHCWinHandleMessage -> %Rrc\n", pVCpu->idCpu, VBOXSTRICTRC_VAL(rcStrict) )); 1734 break; 1735 } 1588 1736 } 1589 1737 else … … 1592 1740 so after NtAlertThread we end up here with a STATUS_TIMEOUT. And yeah, 1593 1741 the error code conversion is into WAIT_XXX, i.e. NT status codes. */ 1594 DWORD dwErr = GetLastError(); 1595 if ( dwErr == STATUS_TIMEOUT 1596 || dwErr == STATUS_ALERTED /* just in case */ 1597 || dwErr == STATUS_USER_APC /* ditto */ ) 1598 pVCpu->nem.s.fHandleAndGetFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE; /* exits are likely */ 1599 else 1600 AssertLogRelMsgFailedReturn(("VidMessageSlotHandleAndGetNext failed for CPU #%u: %u (%#x, rcNt=%#x)\n", 1601 pVCpu->idCpu, dwErr, dwErr, RTNtLastStatusValue()), 1602 VERR_INTERNAL_ERROR_3); 1742 #ifndef IN_RING0 1743 DWORD rcNt = GetLastError(); 1744 #endif 1745 LogFlow(("NEM/%u: VidMessageSlotHandleAndGetNext -> %#x\n", pVCpu->idCpu, rcNt)); 1746 AssertLogRelMsgReturn( rcNt == STATUS_TIMEOUT 1747 || rcNt == STATUS_ALERTED /* just in case */ 1748 || rcNt == STATUS_USER_APC /* ditto */ 1749 , ("VidMessageSlotHandleAndGetNext failed for CPU #%u: %#x (%u)\n", pVCpu->idCpu, rcNt, rcNt), 1750 VERR_INTERNAL_ERROR_3); 1751 pVCpu->nem.s.fHandleAndGetFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE; /* exits are likely */ 1603 1752 } 1604 1753 … … 1612 1761 /** @todo Try handle pending flags, not just return to EM loops. Take care 1613 1762 * not to set important RCs here unless we've handled a message. */ 1614 LogFlow(("nemHCWinRunGC: returning: pending FF (%#x / %#x)\n", pVM->fGlobalForcedActions, pVCpu->fLocalForcedActions)); 1763 LogFlow(("NEM/%u: breaking: pending FF (%#x / %#x)\n", 1764 pVCpu->idCpu, pVM->fGlobalForcedActions, pVCpu->fLocalForcedActions)); 1615 1765 } 1616 1766 else 1617 LogFlow((" nemHCWinRunGC: returning: canceled %d (pre exec)\n", VMCPU_GET_STATE(pVCpu) ));1767 LogFlow(("NEM/%u: breaking: canceled %d (pre exec)\n", pVCpu->idCpu, VMCPU_GET_STATE(pVCpu) )); 1618 1768 } 1619 1769 else 1620 LogFlow((" nemHCWinRunGC: returning: pending FF (pre exec)\n"));1770 LogFlow(("NEM/%u: breaking: pending FF (pre exec)\n", pVCpu->idCpu)); 1621 1771 break; 1622 1772 } /* the run loop */ … … 1630 1780 { 1631 1781 pVCpu->nem.s.fHandleAndGetFlags = 0; 1632 rcStrict = nemHCWinStopCpu(pVM, pVCpu, rcStrict, pMappingHeader );1782 rcStrict = nemHCWinStopCpu(pVM, pVCpu, rcStrict, pMappingHeader, pGVM, pGVCpu); 1633 1783 } 1634 1784 … … 1637 1787 if (pCtx->fExtrn & (CPUMCTX_EXTRN_ALL | (CPUMCTX_EXTRN_NEM_WIN_MASK & ~CPUMCTX_EXTRN_NEM_WIN_EVENT_INJECT))) 1638 1788 { 1789 #ifdef IN_RING0 1790 int rc2 = nemR0WinImportState(pGVM, pGVCpu, pCtx, CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_NEM_WIN_MASK); 1791 if (RT_SUCCESS(rc2)) 1792 pCtx->fExtrn = 0; 1793 else if (rc2 == VERR_NEM_CHANGE_PGM_MODE || rc2 == VERR_NEM_FLUSH_TLB) 1794 { 1795 pCtx->fExtrn = 0; 1796 if (rcStrict == VINF_SUCCESS || rcStrict == -rc2) 1797 rcStrict = -rc2; 1798 else 1799 { 1800 pVCpu->nem.s.rcPgmPending = -rc2; 1801 LogFlow(("NEM/%u: rcPgmPending=%Rrc (rcStrict=%Rrc)\n", pVCpu->idCpu, rc2, VBOXSTRICTRC_VAL(rcStrict) )); 1802 } 1803 } 1804 #else 1639 1805 int rc2 = nemHCWinCopyStateFromHyperV(pVM, pVCpu, pCtx, CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_NEM_WIN_MASK); 1640 1806 if (RT_SUCCESS(rc2)) 1641 1807 pCtx->fExtrn = 0; 1808 #endif 1642 1809 else if (RT_SUCCESS(rcStrict)) 1643 1810 rcStrict = rc2; … … 1646 1813 pCtx->fExtrn = 0; 1647 1814 1648 LogFlow(("nemHCWinRunGC: Leaving #%u cs:rip=%04x:%08RX64 efl=%#08RX64\n", pVCpu->idCpu, pCtx->cs.Sel, pCtx->rip, pCtx->rflags)); 1815 LogFlow(("NEM/%u: %04x:%08RX64 efl=%#08RX64 => %Rrc\n", 1816 pVCpu->idCpu, pCtx->cs.Sel, pCtx->rip, pCtx->rflags, VBOXSTRICTRC_VAL(rcStrict) )); 1649 1817 return rcStrict; 1650 1818 } 1651 #endif 1652 1653 #endif /* IN_RING0 */ 1819 1654 1820 1655 1821
Note:
See TracChangeset
for help on using the changeset viewer.