Changeset 93351 in vbox for trunk/src/VBox/VMM/VMMAll/NEMAllNativeTemplate-win.cpp.h
- Timestamp:
- Jan 19, 2022 11:35:13 PM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/NEMAllNativeTemplate-win.cpp.h
r93305 r93351 105 105 106 106 107 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES108 109 /**110 * Wrapper around VMMR0_DO_NEM_MAP_PAGES for a single page.111 *112 * @returns VBox status code.113 * @param pVM The cross context VM structure.114 * @param pVCpu The cross context virtual CPU structure of the caller.115 * @param GCPhysSrc The source page. Does not need to be page aligned.116 * @param GCPhysDst The destination page. Same as @a GCPhysSrc except for117 * when A20 is disabled.118 * @param fFlags HV_MAP_GPA_XXX.119 */120 DECLINLINE(int) nemHCWinHypercallMapPage(PVMCC pVM, PVMCPUCC pVCpu, RTGCPHYS GCPhysSrc, RTGCPHYS GCPhysDst, uint32_t fFlags)121 {122 #ifdef IN_RING0123 /** @todo optimize further, caller generally has the physical address. */124 return nemR0WinMapPages(pVM, pVCpu,125 GCPhysSrc & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK,126 GCPhysDst & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK,127 1, fFlags);128 #else129 pVCpu->nem.s.Hypercall.MapPages.GCPhysSrc = GCPhysSrc & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK;130 pVCpu->nem.s.Hypercall.MapPages.GCPhysDst = GCPhysDst & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK;131 pVCpu->nem.s.Hypercall.MapPages.cPages = 1;132 pVCpu->nem.s.Hypercall.MapPages.fFlags = fFlags;133 return VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_NEM_MAP_PAGES, 0, NULL);134 #endif135 }136 137 138 /**139 * Wrapper around VMMR0_DO_NEM_UNMAP_PAGES for a single page.140 *141 * @returns VBox status code.142 * @param pVM The cross context VM structure.143 * @param pVCpu The cross context virtual CPU structure of the caller.144 * @param GCPhys The page to unmap. Does not need to be page aligned.145 */146 DECLINLINE(int) nemHCWinHypercallUnmapPage(PVMCC pVM, PVMCPUCC pVCpu, RTGCPHYS GCPhys)147 {148 # ifdef IN_RING0149 return nemR0WinUnmapPages(pVM, pVCpu, GCPhys & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK, 1);150 # else151 pVCpu->nem.s.Hypercall.UnmapPages.GCPhys = GCPhys & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK;152 pVCpu->nem.s.Hypercall.UnmapPages.cPages = 1;153 return VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_NEM_UNMAP_PAGES, 0, NULL);154 # endif155 }156 157 #endif /* NEM_WIN_USE_HYPERCALLS_FOR_PAGES */158 107 #ifndef IN_RING0 159 108 160 109 NEM_TMPL_STATIC int nemHCWinCopyStateToHyperV(PVMCC pVM, PVMCPUCC pVCpu) 161 110 { 162 # if defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS) || defined(NEM_WIN_WITH_RING0_RUNLOOP)163 # if !defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS) && defined(NEM_WIN_WITH_RING0_RUNLOOP)164 if (pVM->nem.s.fUseRing0Runloop)165 # endif166 {167 int rc = VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_NEM_EXPORT_STATE, 0, NULL);168 AssertLogRelRCReturn(rc, rc);169 return rc;170 }171 # endif172 # ifndef NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS173 174 111 /* 175 112 * The following is very similar to what nemR0WinExportState() does. … … 492 429 # undef ADD_REG128 493 430 # undef ADD_SEG 494 495 # endif /* !NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS */496 431 } 497 432 … … 499 434 NEM_TMPL_STATIC int nemHCWinCopyStateFromHyperV(PVMCC pVM, PVMCPUCC pVCpu, uint64_t fWhat) 500 435 { 501 # if defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS) || defined(NEM_WIN_WITH_RING0_RUNLOOP)502 # if !defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS) && defined(NEM_WIN_WITH_RING0_RUNLOOP)503 if (pVM->nem.s.fUseRing0Runloop)504 # endif505 {506 /* See NEMR0ImportState */507 int rc = VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_NEM_IMPORT_STATE, fWhat, NULL);508 if (RT_SUCCESS(rc))509 return rc;510 if (rc == VERR_NEM_FLUSH_TLB)511 {512 rc = PGMFlushTLB(pVCpu, pVCpu->cpum.GstCtx.cr3, true /*fGlobal*/);513 return rc;514 }515 AssertLogRelRCReturn(rc, rc);516 return rc;517 }518 # endif519 # ifndef NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS520 436 WHV_REGISTER_NAME aenmNames[128]; 521 437 … … 1138 1054 1139 1055 return VINF_SUCCESS; 1140 # endif /* !NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS */1141 1056 } 1142 1057 … … 1156 1071 1157 1072 #ifdef IN_RING0 1158 # ifdef NEM_WIN_WITH_RING0_RUNLOOP1159 return nemR0WinImportState(pVCpu->pGVM, pVCpu, &pVCpu->cpum.GstCtx, fWhat, true /*fCanUpdateCr3*/);1160 # else1161 1073 RT_NOREF(pVCpu, fWhat); 1162 1074 return VERR_NOT_IMPLEMENTED; 1163 # endif1164 1075 #else 1165 1076 return nemHCWinCopyStateFromHyperV(pVCpu->pVMR3, pVCpu, fWhat); … … 1185 1096 AssertReturn(VM_IS_NEM_ENABLED(pVM), VERR_NEM_IPE_9); 1186 1097 1187 # if defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS) || defined(NEM_WIN_WITH_RING0_RUNLOOP)1188 # if !defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS) && defined(NEM_WIN_WITH_RING0_RUNLOOP)1189 if (pVM->nem.s.fUseRing0Runloop)1190 # endif1191 {1192 /* Call ring-0 and get the values. */1193 int rc = VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_NEM_QUERY_CPU_TICK, 0, NULL);1194 AssertLogRelRCReturn(rc, rc);1195 *pcTicks = pVCpu->nem.s.Hypercall.QueryCpuTick.cTicks;1196 if (puAux)1197 *puAux = pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_TSC_AUX1198 ? pVCpu->nem.s.Hypercall.QueryCpuTick.uAux : CPUMGetGuestTscAux(pVCpu);1199 return VINF_SUCCESS;1200 }1201 # endif1202 # ifndef NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS1203 1098 /* Call the offical API. */ 1204 1099 WHV_REGISTER_NAME aenmNames[2] = { WHvX64RegisterTsc, WHvX64RegisterTscAux }; … … 1214 1109 *pcTicks = pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_TSC_AUX ? aValues[0].Reg64 : CPUMGetGuestTscAux(pVCpu); 1215 1110 return VINF_SUCCESS; 1216 # endif /* !NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS */1217 1111 #else /* IN_RING0 */ 1218 # ifdef NEM_WIN_WITH_RING0_RUNLOOP1219 int rc = nemR0WinQueryCpuTick(pVCpu->pGVM, pVCpu, pcTicks, puAux);1220 if (RT_SUCCESS(rc) && puAux && !(pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_TSC_AUX))1221 *puAux = CPUMGetGuestTscAux(pVCpu);1222 return rc;1223 # else1224 1112 RT_NOREF(pVCpu, pcTicks, puAux); 1225 1113 return VERR_NOT_IMPLEMENTED; 1226 # endif1227 1114 #endif /* IN_RING0 */ 1228 1115 } … … 1242 1129 { 1243 1130 #ifdef IN_RING0 1244 # ifdef NEM_WIN_WITH_RING0_RUNLOOP1245 return nemR0WinResumeCpuTickOnAll(pVM, pVCpu, uPausedTscValue);1246 # else1247 1131 RT_NOREF(pVM, pVCpu, uPausedTscValue); 1248 1132 return VERR_NOT_IMPLEMENTED; 1249 # endif1250 1133 #else /* IN_RING3 */ 1251 1134 VMCPU_ASSERT_EMT_RETURN(pVCpu, VERR_VM_THREAD_NOT_EMT); 1252 1135 AssertReturn(VM_IS_NEM_ENABLED(pVM), VERR_NEM_IPE_9); 1253 1136 1254 # if defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS) || defined(NEM_WIN_WITH_RING0_RUNLOOP)1255 # if !defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS) && defined(NEM_WIN_WITH_RING0_RUNLOOP)1256 if (pVM->nem.s.fUseRing0Runloop)1257 # endif1258 {1259 /* Call ring-0 and do it all there. */1260 return VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_NEM_RESUME_CPU_TICK_ON_ALL, uPausedTscValue, NULL);1261 }1262 # endif1263 # ifndef NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS1264 1137 /* 1265 1138 * Call the offical API to do the job. … … 1294 1167 1295 1168 return VINF_SUCCESS; 1296 # endif /* !NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS */1297 1169 #endif /* IN_RING3 */ 1298 1170 } 1299 1300 #ifdef NEMWIN_NEED_GET_REGISTER1301 # if defined(IN_RING0) || defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS)1302 /** Worker for assertion macro. */1303 NEM_TMPL_STATIC int nemHCWinGetRegister(PVMCPUCC pVCpu, PGVMCPU pGVCpu, uint32_t enmReg, HV_REGISTER_VALUE *pRetValue)1304 {1305 RT_ZERO(*pRetValue);1306 # ifdef IN_RING31307 RT_NOREF(pVCpu, pGVCpu, enmReg);1308 return VERR_NOT_IMPLEMENTED;1309 # else1310 NOREF(pVCpu);1311 1312 /*1313 * Hypercall parameters.1314 */1315 HV_INPUT_GET_VP_REGISTERS *pInput = (HV_INPUT_GET_VP_REGISTERS *)pGVCpu->nem.s.HypercallData.pbPage;1316 AssertPtrReturn(pInput, VERR_INTERNAL_ERROR_3);1317 AssertReturn(g_pfnHvlInvokeHypercall, VERR_NEM_MISSING_KERNEL_API);1318 1319 pInput->PartitionId = pVCpu->pGVM->nemr0.s.idHvPartition;1320 pInput->VpIndex = pVCpu->idCpu;1321 pInput->fFlags = 0;1322 pInput->Names[0] = (HV_REGISTER_NAME)enmReg;1323 1324 size_t const cbInput = RT_ALIGN_Z(RT_UOFFSETOF(HV_INPUT_GET_VP_REGISTERS, Names[1]), 32);1325 HV_REGISTER_VALUE *paValues = (HV_REGISTER_VALUE *)((uint8_t *)pInput + cbInput);1326 RT_BZERO(paValues, sizeof(paValues[0]) * 1);1327 1328 /*1329 * Make the hypercall and copy out the value.1330 */1331 uint64_t uResult = g_pfnHvlInvokeHypercall(HV_MAKE_CALL_INFO(HvCallGetVpRegisters, 1),1332 pGVCpu->nem.s.HypercallData.HCPhysPage,1333 pGVCpu->nem.s.HypercallData.HCPhysPage + cbInput);1334 AssertLogRelMsgReturn(uResult == HV_MAKE_CALL_REP_RET(1), ("uResult=%RX64 cRegs=%#x\n", uResult, 1),1335 VERR_NEM_GET_REGISTERS_FAILED);1336 1337 *pRetValue = paValues[0];1338 return VINF_SUCCESS;1339 # endif1340 }1341 # else1342 /** Worker for assertion macro. */1343 NEM_TMPL_STATIC int nemR3WinGetRegister(PVMCPUCC a_pVCpu, uint32_t a_enmReg, WHV_REGISTER_VALUE pValue)1344 {1345 RT_ZERO(*pRetValue);1346 RT_NOREF(pVCpu, pGVCpu, enmReg);1347 return VERR_NOT_IMPLEMENTED;1348 }1349 # endif1350 #endif1351 1171 1352 1172 … … 1379 1199 1380 1200 1381 #if defined(NEM_WIN_USE_OUR_OWN_RUN_API) || defined(NEM_WIN_WITH_RING0_RUNLOOP)1382 # ifdef IN_RING3 /* hopefully not needed in ring-0, as we'd need K THREADs and KeAlertThread. */1201 #if defined(NEM_WIN_USE_OUR_OWN_RUN_API) 1202 # ifdef IN_RING3 /* hopefully not needed in ring-0, as we'd need KETHREADs and KeAlertThread. */ 1383 1203 /** 1384 1204 * Our own WHvCancelRunVirtualProcessor that can later be moved to ring-0. … … 1446 1266 } 1447 1267 # endif /* IN_RING3 */ 1448 #endif /* NEM_WIN_USE_OUR_OWN_RUN_API || NEM_WIN_WITH_RING0_RUNLOOP*/1268 #endif /* NEM_WIN_USE_OUR_OWN_RUN_API */ 1449 1269 1450 1270 … … 1612 1432 #endif /* IN_RING3 && !NEM_WIN_TEMPLATE_MODE_OWN_RUN_API */ 1613 1433 1614 #if defined( NEM_WIN_USE_HYPERCALLS_FOR_PAGES) || defined(IN_RING3)1434 #if defined(IN_RING3) 1615 1435 1616 1436 NEM_TMPL_STATIC DECLCALLBACK(int) 1617 1437 nemHCWinUnmapOnePageCallback(PVMCC pVM, PVMCPUCC pVCpu, RTGCPHYS GCPhys, uint8_t *pu2NemState, void *pvUser) 1618 1438 { 1619 RT_NOREF_PV(pvUser); 1620 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES 1621 int rc = nemHCWinHypercallUnmapPage(pVM, pVCpu, GCPhys); 1622 AssertRC(rc); 1623 if (RT_SUCCESS(rc)) 1624 # else 1625 RT_NOREF_PV(pVCpu); 1439 RT_NOREF(pvUser, pVCpu); 1626 1440 STAM_REL_PROFILE_START(&pVM->nem.s.StatProfUnmapGpaRangePage, a); 1627 1441 HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhys, X86_PAGE_SIZE); 1628 1442 STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfUnmapGpaRangePage, a); 1629 1443 if (SUCCEEDED(hrc)) 1630 # endif1631 1444 { 1632 1445 Log5(("NEM GPA unmap all: %RGp (cMappedPages=%u)\n", GCPhys, pVM->nem.s.cMappedPages - 1)); … … 1636 1449 else 1637 1450 { 1638 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES1639 LogRel(("nemHCWinUnmapOnePageCallback: GCPhys=%RGp rc=%Rrc\n", GCPhys, rc));1640 # else1641 1451 LogRel(("nemHCWinUnmapOnePageCallback: GCPhys=%RGp %s hrc=%Rhrc (%#x) Last=%#x/%u (cMappedPages=%u)\n", 1642 1452 GCPhys, g_apszPageStates[*pu2NemState], hrc, hrc, RTNtLastStatusValue(), 1643 1453 RTNtLastErrorValue(), pVM->nem.s.cMappedPages)); 1644 # endif1645 1454 *pu2NemState = NEM_WIN_PAGE_STATE_NOT_SET; 1646 1455 STAM_REL_COUNTER_INC(&pVM->nem.s.StatUnmapPageFailed); … … 1704 1513 * We don't really consider downgrades here, as they shouldn't happen. 1705 1514 */ 1706 # ifndef NEM_WIN_USE_HYPERCALLS_FOR_PAGES1707 1515 /** @todo Someone at microsoft please explain: 1708 1516 * I'm not sure WTF was going on, but I ended up in a loop if I remapped a … … 1713 1521 * with new protection or backing. 1714 1522 */ 1715 # endif1716 1523 int rc; 1717 1524 switch (u2State) … … 1756 1563 } 1757 1564 1758 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES1759 /* Upgrade page to writable. */1760 /** @todo test this*/1761 if ( (pInfo->fNemProt & NEM_PAGE_PROT_WRITE)1762 && pState->fWriteAccess)1763 {1764 rc = nemHCWinHypercallMapPage(pVM, pVCpu, GCPhysSrc, GCPhys,1765 HV_MAP_GPA_READABLE | HV_MAP_GPA_WRITABLE1766 | HV_MAP_GPA_EXECUTABLE | HV_MAP_GPA_EXECUTABLE_AGAIN);1767 AssertRC(rc);1768 if (RT_SUCCESS(rc))1769 {1770 STAM_REL_COUNTER_INC(&pVM->nem.s.StatRemapPage);1771 pInfo->u2NemState = NEM_WIN_PAGE_STATE_WRITABLE;1772 pState->fDidSomething = true;1773 pState->fCanResume = true;1774 Log5(("NEM GPA write-upgrade/exit: %RGp (was %s, cMappedPages=%u)\n",1775 GCPhys, g_apszPageStates[u2State], pVM->nem.s.cMappedPages));1776 }1777 else1778 STAM_REL_COUNTER_INC(&pVM->nem.s.StatRemapPageFailed);1779 }1780 else1781 {1782 /* Need to emulate the acces. */1783 AssertBreak(pInfo->fNemProt != NEM_PAGE_PROT_NONE); /* There should be no downgrades. */1784 rc = VINF_SUCCESS;1785 }1786 return rc;1787 # else1788 1565 break; 1789 # endif1790 1566 1791 1567 case NEM_WIN_PAGE_STATE_WRITABLE: … … 1802 1578 return VINF_SUCCESS; 1803 1579 } 1804 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES1805 AssertFailed(); /* There should be no downgrades. */1806 # endif1807 1580 break; 1808 1581 … … 1815 1588 * If this fails, which it does every so often, just unmap everything for now. 1816 1589 */ 1817 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES1818 rc = nemHCWinHypercallUnmapPage(pVM, pVCpu, GCPhys);1819 AssertRC(rc);1820 if (RT_SUCCESS(rc))1821 # else1822 1590 /** @todo figure out whether we mess up the state or if it's WHv. */ 1823 1591 STAM_REL_PROFILE_START(&pVM->nem.s.StatProfUnmapGpaRangePage, a); … … 1825 1593 STAM_REL_PROFILE_STOP(&pVM->nem.s.StatProfUnmapGpaRangePage, a); 1826 1594 if (SUCCEEDED(hrc)) 1827 # endif1828 1595 { 1829 1596 pState->fDidSomething = true; … … 1836 1603 } 1837 1604 STAM_REL_COUNTER_INC(&pVM->nem.s.StatUnmapPageFailed); 1838 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES 1839 LogRel(("nemHCWinHandleMemoryAccessPageCheckerCallback/unmap: GCPhysDst=%RGp rc=%Rrc\n", GCPhys, rc)); 1840 return rc; 1841 # elif defined(VBOX_WITH_PGM_NEM_MODE) 1605 # if defined(VBOX_WITH_PGM_NEM_MODE) 1842 1606 LogRel(("nemHCWinHandleMemoryAccessPageCheckerCallback/unmap: GCPhysDst=%RGp %s hrc=%Rhrc (%#x)\n", 1843 1607 GCPhys, g_apszPageStates[u2State], hrc, hrc)); … … 1859 1623 } 1860 1624 1861 #endif /* defined( NEM_WIN_USE_HYPERCALLS_FOR_PAGES) || defined(IN_RING3) */1625 #endif /* defined(IN_RING3) */ 1862 1626 1863 1627 … … 3877 3641 3878 3642 3879 #if defined(IN_RING0) && defined(NEM_WIN_WITH_RING0_RUNLOOP)3880 /**3881 * Perform an I/O control operation on the partition handle (VID.SYS),3882 * restarting on alert-like behaviour.3883 *3884 * @returns NT status code.3885 * @param pGVM The ring-0 VM structure.3886 * @param pGVCpu The global (ring-0) per CPU structure.3887 * @param fFlags The wait flags.3888 * @param cMillies The timeout in milliseconds3889 */3890 static NTSTATUS nemR0NtPerformIoCtlMessageSlotHandleAndGetNext(PGVM pGVM, PGVMCPU pGVCpu, uint32_t fFlags, uint32_t cMillies)3891 {3892 pGVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.iCpu = pGVCpu->idCpu;3893 pGVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.fFlags = fFlags;3894 pGVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.cMillies = cMillies;3895 NTSTATUS rcNt = nemR0NtPerformIoControl(pGVM, pGVCpu, pGVM->nemr0.s.IoCtlMessageSlotHandleAndGetNext.uFunction,3896 &pGVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext,3897 pGVM->nemr0.s.IoCtlMessageSlotHandleAndGetNext.cbInput,3898 NULL, 0);3899 if (rcNt == STATUS_SUCCESS)3900 { /* likely */ }3901 /*3902 * Generally, if we get down here, we have been interrupted between ACK'ing3903 * a message and waiting for the next due to a NtAlertThread call. So, we3904 * should stop ACK'ing the previous message and get on waiting on the next.3905 * See similar stuff in nemHCWinRunGC().3906 */3907 else if ( rcNt == STATUS_TIMEOUT3908 || rcNt == STATUS_ALERTED /* just in case */3909 || rcNt == STATUS_KERNEL_APC /* just in case */3910 || rcNt == STATUS_USER_APC /* just in case */)3911 {3912 DBGFTRACE_CUSTOM(pGVCpu->CTX_SUFF(pVM), "IoCtlMessageSlotHandleAndGetNextRestart/1 %#x (f=%#x)", rcNt, fFlags);3913 STAM_REL_COUNTER_INC(&pGVCpu->nem.s.StatStopCpuPendingAlerts);3914 Assert(fFlags & VID_MSHAGN_F_GET_NEXT_MESSAGE);3915 3916 pGVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.iCpu = pGVCpu->idCpu;3917 pGVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.fFlags = fFlags & ~VID_MSHAGN_F_HANDLE_MESSAGE;3918 pGVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.cMillies = cMillies;3919 rcNt = nemR0NtPerformIoControl(pGVM, pGVCpu, pGVM->nemr0.s.IoCtlMessageSlotHandleAndGetNext.uFunction,3920 &pGVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext,3921 pGVM->nemr0.s.IoCtlMessageSlotHandleAndGetNext.cbInput,3922 NULL, 0);3923 DBGFTRACE_CUSTOM(pGVM, "IoCtlMessageSlotHandleAndGetNextRestart/2 %#x", rcNt);3924 }3925 return rcNt;3926 }3927 #endif /* IN_RING0 */3928 3929 3930 3643 #ifdef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API 3931 3644 /** … … 4252 3965 for (unsigned iLoop = 0;; iLoop++) 4253 3966 { 4254 # if !defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES) && !defined(VBOX_WITH_PGM_NEM_MODE)3967 # ifndef VBOX_WITH_PGM_NEM_MODE 4255 3968 /* 4256 3969 * Hack alert! … … 4598 4311 4599 4312 #endif /* defined(NEM_WIN_TEMPLATE_MODE_OWN_RUN_API) || defined(IN_RING3) */ 4600 #if defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES) || defined(IN_RING3)4313 #ifdef IN_RING3 4601 4314 4602 4315 /** … … 4609 4322 if (pInfo->u2NemState > NEM_WIN_PAGE_STATE_UNMAPPED) 4610 4323 { 4611 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES4612 int rc = nemHCWinHypercallUnmapPage(pVM, pVCpu, GCPhys);4613 AssertRC(rc);4614 if (RT_SUCCESS(rc))4615 # else4616 4324 HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhys, X86_PAGE_SIZE); 4617 4325 if (SUCCEEDED(hrc)) 4618 # endif4619 4326 { 4620 4327 STAM_REL_COUNTER_INC(&pVM->nem.s.StatUnmapPage); … … 4626 4333 { 4627 4334 STAM_REL_COUNTER_INC(&pVM->nem.s.StatUnmapPageFailed); 4628 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES4629 LogRel(("nemHCWinUnsetForA20CheckerCallback/unmap: GCPhys=%RGp rc=%Rrc\n", GCPhys, rc));4630 return rc;4631 # else4632 4335 LogRel(("nemHCWinUnsetForA20CheckerCallback/unmap: GCPhys=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n", 4633 4336 GCPhys, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue())); 4634 4337 return VERR_NEM_IPE_2; 4635 # endif4636 4338 } 4637 4339 } … … 4672 4374 4673 4375 *pu2State = UINT8_MAX; 4674 #if !defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES) &&defined(VBOX_WITH_PGM_NEM_MODE) && defined(IN_RING3)4376 #if defined(VBOX_WITH_PGM_NEM_MODE) && defined(IN_RING3) 4675 4377 if (pvMemR3) 4676 4378 { … … 4701 4403 4702 4404 4703 #if defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES) || defined(IN_RING3)4405 #ifdef IN_RING3 4704 4406 /** 4705 4407 * Worker that maps pages into Hyper-V. … … 4723 4425 uint32_t fPageProt, uint8_t *pu2State, bool fBackingChanged) 4724 4426 { 4725 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES4726 /*4727 * When using the hypercalls instead of the ring-3 APIs, we don't need to4728 * unmap memory before modifying it. We still want to track the state though,4729 * since unmap will fail when called an unmapped page and we don't want to redo4730 * upgrades/downgrades.4731 */4732 uint8_t const u2OldState = *pu2State;4733 int rc;4734 if (fPageProt == NEM_PAGE_PROT_NONE)4735 {4736 if (u2OldState > NEM_WIN_PAGE_STATE_UNMAPPED)4737 {4738 rc = nemHCWinHypercallUnmapPage(pVM, pVCpu, GCPhysDst);4739 if (RT_SUCCESS(rc))4740 {4741 *pu2State = NEM_WIN_PAGE_STATE_UNMAPPED;4742 STAM_REL_COUNTER_INC(&pVM->nem.s.StatUnmapPage);4743 uint32_t cMappedPages = ASMAtomicDecU32(&pVM->nem.s.cMappedPages); NOREF(cMappedPages);4744 Log5(("NEM GPA unmapped/set: %RGp (was %s, cMappedPages=%u)\n", GCPhysDst, g_apszPageStates[u2OldState], cMappedPages));4745 }4746 else4747 {4748 STAM_REL_COUNTER_INC(&pVM->nem.s.StatUnmapPageFailed);4749 AssertLogRelMsgFailed(("nemHCNativeSetPhysPage/unmap: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));4750 }4751 }4752 else4753 rc = VINF_SUCCESS;4754 }4755 else if (fPageProt & NEM_PAGE_PROT_WRITE)4756 {4757 if (u2OldState != NEM_WIN_PAGE_STATE_WRITABLE || fBackingChanged)4758 {4759 rc = nemHCWinHypercallMapPage(pVM, pVCpu, GCPhysSrc, GCPhysDst,4760 HV_MAP_GPA_READABLE | HV_MAP_GPA_WRITABLE4761 | HV_MAP_GPA_EXECUTABLE | HV_MAP_GPA_EXECUTABLE_AGAIN);4762 if (RT_SUCCESS(rc))4763 {4764 *pu2State = NEM_WIN_PAGE_STATE_WRITABLE;4765 STAM_REL_COUNTER_INC(&pVM->nem.s.StatMapPage);4766 uint32_t cMappedPages = u2OldState <= NEM_WIN_PAGE_STATE_UNMAPPED4767 ? ASMAtomicIncU32(&pVM->nem.s.cMappedPages) : pVM->nem.s.cMappedPages;4768 Log5(("NEM GPA writable/set: %RGp (was %s, cMappedPages=%u)\n", GCPhysDst, g_apszPageStates[u2OldState], cMappedPages));4769 NOREF(cMappedPages);4770 }4771 else4772 {4773 STAM_REL_COUNTER_INC(&pVM->nem.s.StatMapPageFailed);4774 AssertLogRelMsgFailed(("nemHCNativeSetPhysPage/writable: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));4775 }4776 }4777 else4778 rc = VINF_SUCCESS;4779 }4780 else4781 {4782 if (u2OldState != NEM_WIN_PAGE_STATE_READABLE || fBackingChanged)4783 {4784 rc = nemHCWinHypercallMapPage(pVM, pVCpu, GCPhysSrc, GCPhysDst,4785 HV_MAP_GPA_READABLE | HV_MAP_GPA_EXECUTABLE | HV_MAP_GPA_EXECUTABLE_AGAIN);4786 if (RT_SUCCESS(rc))4787 {4788 *pu2State = NEM_WIN_PAGE_STATE_READABLE;4789 STAM_REL_COUNTER_INC(&pVM->nem.s.StatMapPage);4790 uint32_t cMappedPages = u2OldState <= NEM_WIN_PAGE_STATE_UNMAPPED4791 ? ASMAtomicIncU32(&pVM->nem.s.cMappedPages) : pVM->nem.s.cMappedPages;4792 Log5(("NEM GPA read+exec/set: %RGp (was %s, cMappedPages=%u)\n", GCPhysDst, g_apszPageStates[u2OldState], cMappedPages));4793 NOREF(cMappedPages);4794 }4795 else4796 {4797 STAM_REL_COUNTER_INC(&pVM->nem.s.StatMapPageFailed);4798 AssertLogRelMsgFailed(("nemHCNativeSetPhysPage/writable: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));4799 }4800 }4801 else4802 rc = VINF_SUCCESS;4803 }4804 4805 return VINF_SUCCESS;4806 4807 # else /* !NEM_WIN_USE_HYPERCALLS_FOR_PAGES */4808 4427 /* 4809 4428 * Looks like we need to unmap a page before we can change the backing … … 4820 4439 if (u2OldState > NEM_WIN_PAGE_STATE_UNMAPPED) 4821 4440 { 4822 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES4823 int rc = nemHCWinHypercallUnmapPage(pVM, pVCpu, GCPhysDst);4824 AssertRC(rc);4825 if (RT_SUCCESS(rc))4826 {4827 *pu2State = NEM_WIN_PAGE_STATE_UNMAPPED;4828 STAM_REL_COUNTER_INC(&pVM->nem.s.StatUnmapPage);4829 uint32_t cMappedPages = ASMAtomicDecU32(&pVM->nem.s.cMappedPages); NOREF(cMappedPages);4830 if (u2NewState == NEM_WIN_PAGE_STATE_UNMAPPED)4831 {4832 Log5(("NEM GPA unmapped/set: %RGp (was %s, cMappedPages=%u)\n",4833 GCPhysDst, g_apszPageStates[u2OldState], cMappedPages));4834 return VINF_SUCCESS;4835 }4836 }4837 else4838 {4839 STAM_REL_COUNTER_INC(&pVM->nem.s.StatUnmapPageFailed);4840 LogRel(("nemHCNativeSetPhysPage/unmap: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));4841 return rc;4842 }4843 # else4844 4441 STAM_REL_PROFILE_START(&pVM->nem.s.StatProfUnmapGpaRangePage, a); 4845 4442 HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhysDst, X86_PAGE_SIZE); … … 4864 4461 return VERR_NEM_INIT_FAILED; 4865 4462 } 4866 # endif4867 4463 } 4868 4464 } … … 4873 4469 if (fPageProt & NEM_PAGE_PROT_WRITE) 4874 4470 { 4875 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES4876 int rc = nemHCWinHypercallMapPage(pVM, pVCpu, GCPhysSrc, GCPhysDst,4877 HV_MAP_GPA_READABLE | HV_MAP_GPA_WRITABLE4878 | HV_MAP_GPA_EXECUTABLE | HV_MAP_GPA_EXECUTABLE_AGAIN);4879 AssertRC(rc);4880 if (RT_SUCCESS(rc))4881 {4882 *pu2State = NEM_WIN_PAGE_STATE_WRITABLE;4883 STAM_REL_COUNTER_INC(&pVM->nem.s.StatMapPage);4884 uint32_t cMappedPages = ASMAtomicIncU32(&pVM->nem.s.cMappedPages); NOREF(cMappedPages);4885 Log5(("NEM GPA mapped/set: %RGp %s (was %s, cMappedPages=%u)\n",4886 GCPhysDst, g_apszPageStates[u2NewState], g_apszPageStates[u2OldState], cMappedPages));4887 return VINF_SUCCESS;4888 }4889 STAM_REL_COUNTER_INC(&pVM->nem.s.StatMapPageFailed);4890 LogRel(("nemHCNativeSetPhysPage/writable: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));4891 return rc;4892 # else4893 4471 void *pvPage; 4894 4472 int rc = nemR3NativeGCPhys2R3PtrWriteable(pVM, GCPhysSrc, &pvPage); … … 4913 4491 LogRel(("nemHCNativeSetPhysPage/writable: GCPhysSrc=%RGp rc=%Rrc\n", GCPhysSrc, rc)); 4914 4492 return rc; 4915 # endif4916 4493 } 4917 4494 4918 4495 if (fPageProt & NEM_PAGE_PROT_READ) 4919 4496 { 4920 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES4921 int rc = nemHCWinHypercallMapPage(pVM, pVCpu, GCPhysSrc, GCPhysDst,4922 HV_MAP_GPA_READABLE | HV_MAP_GPA_EXECUTABLE | HV_MAP_GPA_EXECUTABLE_AGAIN);4923 AssertRC(rc);4924 if (RT_SUCCESS(rc))4925 {4926 *pu2State = NEM_WIN_PAGE_STATE_READABLE;4927 STAM_REL_COUNTER_INC(&pVM->nem.s.StatMapPage);4928 uint32_t cMappedPages = ASMAtomicIncU32(&pVM->nem.s.cMappedPages); NOREF(cMappedPages);4929 Log5(("NEM GPA mapped/set: %RGp %s (was %s, cMappedPages=%u)\n",4930 GCPhysDst, g_apszPageStates[u2NewState], g_apszPageStates[u2OldState], cMappedPages));4931 return VINF_SUCCESS;4932 }4933 STAM_REL_COUNTER_INC(&pVM->nem.s.StatMapPageFailed);4934 LogRel(("nemHCNativeSetPhysPage/readonly: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));4935 return rc;4936 # else4937 4497 const void *pvPage; 4938 4498 int rc = nemR3NativeGCPhys2R3PtrReadOnly(pVM, GCPhysSrc, &pvPage); … … 4959 4519 LogRel(("nemHCNativeSetPhysPage/readonly: GCPhysSrc=%RGp rc=%Rrc\n", GCPhysSrc, rc)); 4960 4520 return rc; 4961 # endif4962 4521 } 4963 4522 … … 4965 4524 *pu2State = NEM_WIN_PAGE_STATE_UNMAPPED; 4966 4525 return VINF_SUCCESS; 4967 # endif /* !NEM_WIN_USE_HYPERCALLS_FOR_PAGES */ 4968 } 4969 #endif /* defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES) || defined(IN_RING3) */ 4526 } 4527 #endif /* IN_RING3 */ 4970 4528 4971 4529 … … 4979 4537 } 4980 4538 4981 #if defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES) 4982 PVMCPUCC pVCpu = VMMGetCpu(pVM); 4983 int rc = nemHCWinHypercallUnmapPage(pVM, pVCpu, GCPhysDst); 4984 AssertRC(rc); 4985 if (RT_SUCCESS(rc)) 4986 { 4987 STAM_REL_COUNTER_INC(&pVM->nem.s.StatUnmapPage); 4988 uint32_t cMappedPages = ASMAtomicDecU32(&pVM->nem.s.cMappedPages); NOREF(cMappedPages); 4989 Log5(("NEM GPA unmapped/just: %RGp (was %s, cMappedPages=%u)\n", GCPhysDst, g_apszPageStates[*pu2State], cMappedPages)); 4990 *pu2State = NEM_WIN_PAGE_STATE_UNMAPPED; 4991 return VINF_SUCCESS; 4992 } 4993 STAM_REL_COUNTER_INC(&pVM->nem.s.StatUnmapPageFailed); 4994 LogRel(("nemHCJustUnmapPageFromHyperV/unmap: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc)); 4995 return rc; 4996 4997 #elif defined(IN_RING3) 4539 #if defined(IN_RING3) 4998 4540 STAM_REL_PROFILE_START(&pVM->nem.s.StatProfUnmapGpaRangePage, a); 4999 4541 HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhysDst & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK, X86_PAGE_SIZE); … … 5027 4569 5028 4570 int rc; 5029 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES 5030 PVMCPUCC pVCpu = VMMGetCpu(pVM); 5031 # ifdef NEM_WIN_WITH_A20 4571 RT_NOREF_PV(fPageProt); 4572 #ifdef NEM_WIN_WITH_A20 5032 4573 if ( pVM->nem.s.fA20Enabled 5033 4574 || !NEM_WIN_IS_RELEVANT_TO_A20(GCPhys)) 5034 # endif 5035 rc = nemHCNativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/); 5036 # ifdef NEM_WIN_WITH_A20 5037 else 5038 { 5039 /* To keep effort at a minimum, we unmap the HMA page alias and resync it lazily when needed. */ 5040 rc = nemHCWinUnmapPageForA20Gate(pVM, pVCpu, GCPhys | RT_BIT_32(20)); 5041 if (!NEM_WIN_IS_SUBJECT_TO_A20(GCPhys) && RT_SUCCESS(rc)) 5042 rc = nemHCNativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/); 5043 5044 } 5045 # endif 5046 #else 5047 RT_NOREF_PV(fPageProt); 5048 # ifdef NEM_WIN_WITH_A20 5049 if ( pVM->nem.s.fA20Enabled 5050 || !NEM_WIN_IS_RELEVANT_TO_A20(GCPhys)) 5051 # endif 4575 #endif 5052 4576 rc = nemHCJustUnmapPageFromHyperV(pVM, GCPhys, pu2State); 5053 # 4577 #ifdef NEM_WIN_WITH_A20 5054 4578 else if (!NEM_WIN_IS_SUBJECT_TO_A20(GCPhys)) 5055 4579 rc = nemHCJustUnmapPageFromHyperV(pVM, GCPhys, pu2State); 5056 4580 else 5057 4581 rc = VINF_SUCCESS; /* ignore since we've got the alias page at this address. */ 5058 # endif5059 4582 #endif 5060 4583 return rc; … … 5070 4593 RT_NOREF(HCPhys, enmType, pvR3); 5071 4594 5072 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES 5073 PVMCPUCC pVCpu = VMMGetCpu(pVM); 5074 # ifdef NEM_WIN_WITH_A20 4595 RT_NOREF_PV(fPageProt); 4596 #ifdef NEM_WIN_WITH_A20 5075 4597 if ( pVM->nem.s.fA20Enabled 5076 4598 || !NEM_WIN_IS_RELEVANT_TO_A20(GCPhys)) 5077 # endif 5078 nemHCNativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, false /*fBackingChanged*/); 5079 # ifdef NEM_WIN_WITH_A20 5080 else 5081 { 5082 /* To keep effort at a minimum, we unmap the HMA page alias and resync it lazily when needed. */ 5083 nemHCWinUnmapPageForA20Gate(pVM, pVCpu, GCPhys | RT_BIT_32(20)); 5084 if (!NEM_WIN_IS_SUBJECT_TO_A20(GCPhys)) 5085 nemHCNativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, false /*fBackingChanged*/); 5086 } 5087 # endif 5088 #else 5089 RT_NOREF_PV(fPageProt); 5090 # ifdef NEM_WIN_WITH_A20 5091 if ( pVM->nem.s.fA20Enabled 5092 || !NEM_WIN_IS_RELEVANT_TO_A20(GCPhys)) 5093 # endif 4599 #endif 5094 4600 nemHCJustUnmapPageFromHyperV(pVM, GCPhys, pu2State); 5095 # 4601 #ifdef NEM_WIN_WITH_A20 5096 4602 else if (!NEM_WIN_IS_SUBJECT_TO_A20(GCPhys)) 5097 4603 nemHCJustUnmapPageFromHyperV(pVM, GCPhys, pu2State); 5098 4604 /* else: ignore since we've got the alias page at this address. */ 5099 # endif5100 4605 #endif 5101 4606 } … … 5110 4615 RT_NOREF(HCPhysPrev, HCPhysNew, pvNewR3, enmType); 5111 4616 5112 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES 5113 PVMCPUCC pVCpu = VMMGetCpu(pVM); 5114 # ifdef NEM_WIN_WITH_A20 4617 RT_NOREF_PV(fPageProt); 4618 #ifdef NEM_WIN_WITH_A20 5115 4619 if ( pVM->nem.s.fA20Enabled 5116 4620 || !NEM_WIN_IS_RELEVANT_TO_A20(GCPhys)) 5117 # endif 5118 nemHCNativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/); 5119 # ifdef NEM_WIN_WITH_A20 5120 else 5121 { 5122 /* To keep effort at a minimum, we unmap the HMA page alias and resync it lazily when needed. */ 5123 nemHCWinUnmapPageForA20Gate(pVM, pVCpu, GCPhys | RT_BIT_32(20)); 5124 if (!NEM_WIN_IS_SUBJECT_TO_A20(GCPhys)) 5125 nemHCNativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/); 5126 } 5127 # endif 5128 #else 5129 RT_NOREF_PV(fPageProt); 5130 # ifdef NEM_WIN_WITH_A20 5131 if ( pVM->nem.s.fA20Enabled 5132 || !NEM_WIN_IS_RELEVANT_TO_A20(GCPhys)) 5133 # endif 4621 #endif 5134 4622 nemHCJustUnmapPageFromHyperV(pVM, GCPhys, pu2State); 5135 # 4623 #ifdef NEM_WIN_WITH_A20 5136 4624 else if (!NEM_WIN_IS_SUBJECT_TO_A20(GCPhys)) 5137 4625 nemHCJustUnmapPageFromHyperV(pVM, GCPhys, pu2State); 5138 4626 /* else: ignore since we've got the alias page at this address. */ 5139 # endif5140 4627 #endif 5141 4628 }
Note:
See TracChangeset
for help on using the changeset viewer.