Changeset 71152 in vbox for trunk/src/VBox/VMM/VMMAll
- Timestamp:
- Feb 28, 2018 12:36:04 PM (7 years ago)
- Location:
- trunk/src/VBox/VMM/VMMAll
- Files:
-
- 1 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/NEMAll.cpp
r70977 r71152 41 41 #if defined(VBOX_WITH_NATIVE_NEM) && defined(IN_RING3) 42 42 if (VM_IS_NEM_ENABLED(pVM)) 43 nem R3NativeNotifyHandlerPhysicalRegister(pVM, enmKind, GCPhys, cb);43 nemHCNativeNotifyHandlerPhysicalRegister(pVM, enmKind, GCPhys, cb); 44 44 #else 45 45 RT_NOREF(pVM, enmKind, GCPhys, cb); … … 53 53 #if defined(VBOX_WITH_NATIVE_NEM) && defined(IN_RING3) 54 54 if (VM_IS_NEM_ENABLED(pVM)) 55 nem R3NativeNotifyHandlerPhysicalDeregister(pVM, enmKind, GCPhys, cb, fRestoreAsRAM, fRestoreAsRAM2);55 nemHCNativeNotifyHandlerPhysicalDeregister(pVM, enmKind, GCPhys, cb, fRestoreAsRAM, fRestoreAsRAM2); 56 56 #else 57 57 RT_NOREF(pVM, enmKind, GCPhys, cb, fRestoreAsRAM, fRestoreAsRAM2); … … 65 65 #if defined(VBOX_WITH_NATIVE_NEM) && defined(IN_RING3) 66 66 if (VM_IS_NEM_ENABLED(pVM)) 67 nem R3NativeNotifyHandlerPhysicalModify(pVM, enmKind, GCPhysOld, GCPhysNew, cb, fRestoreAsRAM);67 nemHCNativeNotifyHandlerPhysicalModify(pVM, enmKind, GCPhysOld, GCPhysNew, cb, fRestoreAsRAM); 68 68 #else 69 69 RT_NOREF(pVM, enmKind, GCPhysOld, GCPhysNew, cb, fRestoreAsRAM); … … 77 77 Assert(VM_IS_NEM_ENABLED(pVM)); 78 78 #if defined(VBOX_WITH_NATIVE_NEM) && defined(IN_RING3) 79 return nem R3NativeNotifyPhysPageAllocated(pVM, GCPhys, HCPhys, fPageProt, enmType, pu2State);79 return nemHCNativeNotifyPhysPageAllocated(pVM, GCPhys, HCPhys, fPageProt, enmType, pu2State); 80 80 #else 81 81 RT_NOREF(pVM, GCPhys, HCPhys, fPageProt, enmType, pu2State); … … 89 89 { 90 90 Assert(VM_IS_NEM_ENABLED(pVM)); 91 #if defined(VBOX_WITH_NATIVE_NEM) && defined(IN_RING3)92 nem R3NativeNotifyPhysPageProtChanged(pVM, GCPhys, HCPhys, fPageProt, enmType, pu2State);91 #if defined(VBOX_WITH_NATIVE_NEM) 92 nemHCNativeNotifyPhysPageProtChanged(pVM, GCPhys, HCPhys, fPageProt, enmType, pu2State); 93 93 #else 94 94 RT_NOREF(pVM, GCPhys, HCPhys, fPageProt, enmType, pu2State); … … 101 101 { 102 102 Assert(VM_IS_NEM_ENABLED(pVM)); 103 #if defined(VBOX_WITH_NATIVE_NEM) && defined(IN_RING3)104 nem R3NativeNotifyPhysPageChanged(pVM, GCPhys, HCPhysPrev, HCPhysNew, fPageProt, enmType, pu2State);103 #if defined(VBOX_WITH_NATIVE_NEM) 104 nemHCNativeNotifyPhysPageChanged(pVM, GCPhys, HCPhysPrev, HCPhysNew, fPageProt, enmType, pu2State); 105 105 #else 106 106 RT_NOREF(pVM, GCPhys, HCPhysPrev, HCPhysNew, fPageProt, enmType, pu2State); -
trunk/src/VBox/VMM/VMMAll/NEMAllNativeTemplate-win.cpp.h
r71136 r71152 1 1 /* $Id$ */ 2 2 /** @file 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. 7 * Log group 5: Ring-3 memory management 8 * Log group 6: Ring-0 memory management 9 * Log group 12: API intercepts. 3 * NEM - Native execution manager, Windows code template ring-0/3. 10 4 */ 11 5 … … 24 18 25 19 /********************************************************************************************************************************* 26 * Header Files *27 *********************************************************************************************************************************/28 #define LOG_GROUP LOG_GROUP_NEM29 #include <iprt/nt/nt-and-windows.h>30 #include <iprt/nt/hyperv.h>31 #include <iprt/nt/vid.h>32 #include <WinHvPlatform.h>33 34 #ifndef _WIN32_WINNT_WIN1035 # error "Missing _WIN32_WINNT_WIN10"36 #endif37 #ifndef _WIN32_WINNT_WIN10_RS1 /* Missing define, causing trouble for us. */38 # define _WIN32_WINNT_WIN10_RS1 (_WIN32_WINNT_WIN10 + 1)39 #endif40 #include <sysinfoapi.h>41 #include <debugapi.h>42 #include <errhandlingapi.h>43 #include <fileapi.h>44 #include <winerror.h> /* no api header for this. */45 46 #include <VBox/vmm/nem.h>47 #include <VBox/vmm/iem.h>48 #include <VBox/vmm/em.h>49 #include <VBox/vmm/apic.h>50 #include "NEMInternal.h"51 #include <VBox/vmm/vm.h>52 53 #include <iprt/ldr.h>54 #include <iprt/path.h>55 #include <iprt/string.h>56 57 58 /*********************************************************************************************************************************59 * Defined Constants And Macros *60 *********************************************************************************************************************************/61 #ifdef LOG_ENABLED62 # define NEM_WIN_INTERCEPT_NT_IO_CTLS63 #endif64 65 /** @name Our two-bit physical page state for PGMPAGE66 * @{ */67 #define NEM_WIN_PAGE_STATE_NOT_SET 068 #define NEM_WIN_PAGE_STATE_UNMAPPED 169 #define NEM_WIN_PAGE_STATE_READABLE 270 #define NEM_WIN_PAGE_STATE_WRITABLE 371 /** @} */72 73 /** Checks if a_GCPhys is subject to the limited A20 gate emulation. */74 #define NEM_WIN_IS_SUBJECT_TO_A20(a_GCPhys) ((RTGCPHYS)((a_GCPhys) - _1M) < (RTGCPHYS)_64K)75 76 /** Checks if a_GCPhys is relevant to the limited A20 gate emulation. */77 #define NEM_WIN_IS_RELEVANT_TO_A20(a_GCPhys) \78 ( ((RTGCPHYS)((a_GCPhys) - _1M) < (RTGCPHYS)_64K) || ((RTGCPHYS)(a_GCPhys) < (RTGCPHYS)_64K) )79 80 /** VID I/O control detection: Fake partition handle input. */81 #define NEM_WIN_IOCTL_DETECTOR_FAKE_HANDLE ((HANDLE)(uintptr_t)38479125)82 /** VID I/O control detection: Fake partition ID return. */83 #define NEM_WIN_IOCTL_DETECTOR_FAKE_PARTITION_ID UINT64_C(0xfa1e000042424242)84 /** VID I/O control detection: Fake CPU index input. */85 #define NEM_WIN_IOCTL_DETECTOR_FAKE_VP_INDEX UINT32_C(42)86 /** VID I/O control detection: Fake timeout input. */87 #define NEM_WIN_IOCTL_DETECTOR_FAKE_TIMEOUT UINT32_C(0x00080286)88 89 90 /*********************************************************************************************************************************91 20 * Global Variables * 92 21 *********************************************************************************************************************************/ 93 /** @name APIs imported from WinHvPlatform.dll94 * @{ */95 static decltype(WHvGetCapability) * g_pfnWHvGetCapability;96 static decltype(WHvCreatePartition) * g_pfnWHvCreatePartition;97 static decltype(WHvSetupPartition) * g_pfnWHvSetupPartition;98 static decltype(WHvDeletePartition) * g_pfnWHvDeletePartition;99 static decltype(WHvGetPartitionProperty) * g_pfnWHvGetPartitionProperty;100 static decltype(WHvSetPartitionProperty) * g_pfnWHvSetPartitionProperty;101 static decltype(WHvMapGpaRange) * g_pfnWHvMapGpaRange;102 static decltype(WHvUnmapGpaRange) * g_pfnWHvUnmapGpaRange;103 static decltype(WHvTranslateGva) * g_pfnWHvTranslateGva;104 #ifndef NEM_WIN_USE_OUR_OWN_RUN_API105 static decltype(WHvCreateVirtualProcessor) * g_pfnWHvCreateVirtualProcessor;106 static decltype(WHvDeleteVirtualProcessor) * g_pfnWHvDeleteVirtualProcessor;107 static decltype(WHvRunVirtualProcessor) * g_pfnWHvRunVirtualProcessor;108 static decltype(WHvGetRunExitContextSize) * g_pfnWHvGetRunExitContextSize;109 static decltype(WHvCancelRunVirtualProcessor) * g_pfnWHvCancelRunVirtualProcessor;110 static decltype(WHvGetVirtualProcessorRegisters) * g_pfnWHvGetVirtualProcessorRegisters;111 static decltype(WHvSetVirtualProcessorRegisters) * g_pfnWHvSetVirtualProcessorRegisters;112 #endif113 /** @} */114 115 /** @name APIs imported from Vid.dll116 * @{ */117 static decltype(VidGetHvPartitionId) *g_pfnVidGetHvPartitionId;118 static decltype(VidStartVirtualProcessor) *g_pfnVidStartVirtualProcessor;119 static decltype(VidStopVirtualProcessor) *g_pfnVidStopVirtualProcessor;120 static decltype(VidMessageSlotMap) *g_pfnVidMessageSlotMap;121 static decltype(VidMessageSlotHandleAndGetNext) *g_pfnVidMessageSlotHandleAndGetNext;122 #ifdef LOG_ENABLED123 static decltype(VidGetVirtualProcessorState) *g_pfnVidGetVirtualProcessorState;124 static decltype(VidSetVirtualProcessorState) *g_pfnVidSetVirtualProcessorState;125 static decltype(VidGetVirtualProcessorRunningStatus) *g_pfnVidGetVirtualProcessorRunningStatus;126 #endif127 /** @} */128 129 130 /**131 * Import instructions.132 */133 static const struct134 {135 uint8_t idxDll; /**< 0 for WinHvPlatform.dll, 1 for vid.dll. */136 bool fOptional; /**< Set if import is optional. */137 PFNRT *ppfn; /**< The function pointer variable. */138 const char *pszName; /**< The function name. */139 } g_aImports[] =140 {141 #define NEM_WIN_IMPORT(a_idxDll, a_fOptional, a_Name) { (a_idxDll), (a_fOptional), (PFNRT *)&RT_CONCAT(g_pfn,a_Name), #a_Name }142 NEM_WIN_IMPORT(0, false, WHvGetCapability),143 NEM_WIN_IMPORT(0, false, WHvCreatePartition),144 NEM_WIN_IMPORT(0, false, WHvSetupPartition),145 NEM_WIN_IMPORT(0, false, WHvDeletePartition),146 NEM_WIN_IMPORT(0, false, WHvGetPartitionProperty),147 NEM_WIN_IMPORT(0, false, WHvSetPartitionProperty),148 NEM_WIN_IMPORT(0, false, WHvMapGpaRange),149 NEM_WIN_IMPORT(0, false, WHvUnmapGpaRange),150 NEM_WIN_IMPORT(0, false, WHvTranslateGva),151 #ifndef NEM_WIN_USE_OUR_OWN_RUN_API152 NEM_WIN_IMPORT(0, false, WHvCreateVirtualProcessor),153 NEM_WIN_IMPORT(0, false, WHvDeleteVirtualProcessor),154 NEM_WIN_IMPORT(0, false, WHvRunVirtualProcessor),155 NEM_WIN_IMPORT(0, false, WHvCancelRunVirtualProcessor),156 NEM_WIN_IMPORT(0, false, WHvGetRunExitContextSize),157 NEM_WIN_IMPORT(0, false, WHvGetVirtualProcessorRegisters),158 NEM_WIN_IMPORT(0, false, WHvSetVirtualProcessorRegisters),159 #endif160 NEM_WIN_IMPORT(1, false, VidGetHvPartitionId),161 NEM_WIN_IMPORT(1, false, VidMessageSlotMap),162 NEM_WIN_IMPORT(1, false, VidMessageSlotHandleAndGetNext),163 NEM_WIN_IMPORT(1, false, VidStartVirtualProcessor),164 NEM_WIN_IMPORT(1, false, VidStopVirtualProcessor),165 #ifdef LOG_ENABLED166 NEM_WIN_IMPORT(1, false, VidGetVirtualProcessorState),167 NEM_WIN_IMPORT(1, false, VidSetVirtualProcessorState),168 NEM_WIN_IMPORT(1, false, VidGetVirtualProcessorRunningStatus),169 #endif170 #undef NEM_WIN_IMPORT171 };172 173 174 /** The real NtDeviceIoControlFile API in NTDLL. */175 static decltype(NtDeviceIoControlFile) *g_pfnNtDeviceIoControlFile;176 /** Pointer to the NtDeviceIoControlFile import table entry. */177 static decltype(NtDeviceIoControlFile) **g_ppfnVidNtDeviceIoControlFile;178 /** Info about the VidGetHvPartitionId I/O control interface. */179 static NEMWINIOCTL g_IoCtlGetHvPartitionId;180 /** Info about the VidStartVirtualProcessor I/O control interface. */181 static NEMWINIOCTL g_IoCtlStartVirtualProcessor;182 /** Info about the VidStopVirtualProcessor I/O control interface. */183 static NEMWINIOCTL g_IoCtlStopVirtualProcessor;184 /** Info about the VidMessageSlotHandleAndGetNext I/O control interface. */185 static NEMWINIOCTL g_IoCtlMessageSlotHandleAndGetNext;186 #ifdef LOG_ENABLED187 /** Info about the VidMessageSlotMap I/O control interface - for logging. */188 static NEMWINIOCTL g_IoCtlMessageSlotMap;189 /* Info about the VidGetVirtualProcessorState I/O control interface - for logging. */190 static NEMWINIOCTL g_IoCtlGetVirtualProcessorState;191 /* Info about the VidSetVirtualProcessorState I/O control interface - for logging. */192 static NEMWINIOCTL g_IoCtlSetVirtualProcessorState;193 /** Pointer to what nemR3WinIoctlDetector_ForLogging should fill in. */194 static NEMWINIOCTL *g_pIoCtlDetectForLogging;195 #endif196 197 #ifdef NEM_WIN_INTERCEPT_NT_IO_CTLS198 /** Mapping slot for CPU #0.199 * @{ */200 static VID_MESSAGE_MAPPING_HEADER *g_pMsgSlotMapping = NULL;201 static const HV_MESSAGE_HEADER *g_pHvMsgHdr;202 static const HV_X64_INTERCEPT_MESSAGE_HEADER *g_pX64MsgHdr;203 /** @} */204 #endif205 206 207 /*208 * Let the preprocessor alias the APIs to import variables for better autocompletion.209 */210 #ifndef IN_SLICKEDIT211 # define WHvGetCapability g_pfnWHvGetCapability212 # define WHvCreatePartition g_pfnWHvCreatePartition213 # define WHvSetupPartition g_pfnWHvSetupPartition214 # define WHvDeletePartition g_pfnWHvDeletePartition215 # define WHvGetPartitionProperty g_pfnWHvGetPartitionProperty216 # define WHvSetPartitionProperty g_pfnWHvSetPartitionProperty217 # define WHvMapGpaRange g_pfnWHvMapGpaRange218 # define WHvUnmapGpaRange g_pfnWHvUnmapGpaRange219 # define WHvTranslateGva g_pfnWHvTranslateGva220 # define WHvCreateVirtualProcessor g_pfnWHvCreateVirtualProcessor221 # define WHvDeleteVirtualProcessor g_pfnWHvDeleteVirtualProcessor222 # define WHvRunVirtualProcessor g_pfnWHvRunVirtualProcessor223 # define WHvGetRunExitContextSize g_pfnWHvGetRunExitContextSize224 # define WHvCancelRunVirtualProcessor g_pfnWHvCancelRunVirtualProcessor225 # define WHvGetVirtualProcessorRegisters g_pfnWHvGetVirtualProcessorRegisters226 # define WHvSetVirtualProcessorRegisters g_pfnWHvSetVirtualProcessorRegisters227 #endif228 229 22 /** NEM_WIN_PAGE_STATE_XXX names. */ 230 static const char * const g_apszPageStates[4] = { "not-set", "unmapped", "readable", "writable" }; 231 /** WHV_MEMORY_ACCESS_TYPE names */ 232 static const char * const g_apszWHvMemAccesstypes[4] = { "read", "write", "exec", "!undefined!" }; 23 NEM_TMPL_STATIC const char * const g_apszPageStates[4] = { "not-set", "unmapped", "readable", "writable" }; 233 24 234 25 … … 236 27 * Internal Functions * 237 28 *********************************************************************************************************************************/ 238 static int nemR3NativeSetPhysPage(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhysSrc, RTGCPHYS GCPhysDst, uint32_t fPageProt, 239 uint8_t *pu2State, bool fBackingChanged); 240 241 242 243 #ifdef NEM_WIN_INTERCEPT_NT_IO_CTLS 244 /** 245 * Wrapper that logs the call from VID.DLL. 246 * 247 * This is very handy for figuring out why an API call fails. 248 */ 249 static NTSTATUS WINAPI 250 nemR3WinLogWrapper_NtDeviceIoControlFile(HANDLE hFile, HANDLE hEvt, PIO_APC_ROUTINE pfnApcCallback, PVOID pvApcCtx, 251 PIO_STATUS_BLOCK pIos, ULONG uFunction, PVOID pvInput, ULONG cbInput, 252 PVOID pvOutput, ULONG cbOutput) 253 { 254 255 char szFunction[32]; 256 const char *pszFunction; 257 if (uFunction == g_IoCtlMessageSlotHandleAndGetNext.uFunction) 258 pszFunction = "VidMessageSlotHandleAndGetNext"; 259 else if (uFunction == g_IoCtlStartVirtualProcessor.uFunction) 260 pszFunction = "VidStartVirtualProcessor"; 261 else if (uFunction == g_IoCtlStopVirtualProcessor.uFunction) 262 pszFunction = "VidStopVirtualProcessor"; 263 else if (uFunction == g_IoCtlMessageSlotMap.uFunction) 264 pszFunction = "VidMessageSlotMap"; 265 else if (uFunction == g_IoCtlGetVirtualProcessorState.uFunction) 266 pszFunction = "VidGetVirtualProcessorState"; 267 else if (uFunction == g_IoCtlSetVirtualProcessorState.uFunction) 268 pszFunction = "VidSetVirtualProcessorState"; 269 else 270 { 271 RTStrPrintf(szFunction, sizeof(szFunction), "%#x", uFunction); 272 pszFunction = szFunction; 273 } 274 275 if (cbInput > 0 && pvInput) 276 Log12(("VID!NtDeviceIoControlFile: %s/input: %.*Rhxs\n", pszFunction, RT_MIN(cbInput, 32), pvInput)); 277 NTSTATUS rcNt = g_pfnNtDeviceIoControlFile(hFile, hEvt, pfnApcCallback, pvApcCtx, pIos, uFunction, 278 pvInput, cbInput, pvOutput, cbOutput); 279 if (!hEvt && !pfnApcCallback && !pvApcCtx) 280 Log12(("VID!NtDeviceIoControlFile: hFile=%#zx pIos=%p->{s:%#x, i:%#zx} uFunction=%s Input=%p LB %#x Output=%p LB %#x) -> %#x; Caller=%p\n", 281 hFile, pIos, pIos->Status, pIos->Information, pszFunction, pvInput, cbInput, pvOutput, cbOutput, rcNt, ASMReturnAddress())); 282 else 283 Log12(("VID!NtDeviceIoControlFile: hFile=%#zx hEvt=%#zx Apc=%p/%p pIos=%p->{s:%#x, i:%#zx} uFunction=%s Input=%p LB %#x Output=%p LB %#x) -> %#x; Caller=%p\n", 284 hFile, hEvt, pfnApcCallback, pvApcCtx, pIos, pIos->Status, pIos->Information, pszFunction, 285 pvInput, cbInput, pvOutput, cbOutput, rcNt, ASMReturnAddress())); 286 if (cbOutput > 0 && pvOutput) 287 { 288 Log12(("VID!NtDeviceIoControlFile: %s/output: %.*Rhxs\n", pszFunction, RT_MIN(cbOutput, 32), pvOutput)); 289 if (uFunction == 0x2210cc && g_pMsgSlotMapping == NULL && cbOutput >= sizeof(void *)) 290 { 291 g_pMsgSlotMapping = *(VID_MESSAGE_MAPPING_HEADER **)pvOutput; 292 g_pHvMsgHdr = (const HV_MESSAGE_HEADER *)(g_pMsgSlotMapping + 1); 293 g_pX64MsgHdr = (const HV_X64_INTERCEPT_MESSAGE_HEADER *)(g_pHvMsgHdr + 1); 294 Log12(("VID!NtDeviceIoControlFile: Message slot mapping: %p\n", g_pMsgSlotMapping)); 295 } 296 } 297 if ( g_pMsgSlotMapping 298 && ( uFunction == g_IoCtlMessageSlotHandleAndGetNext.uFunction 299 || uFunction == g_IoCtlStopVirtualProcessor.uFunction 300 || uFunction == g_IoCtlMessageSlotMap.uFunction 301 )) 302 Log12(("VID!NtDeviceIoControlFile: enmVidMsgType=%#x cb=%#x msg=%#x payload=%u cs:rip=%04x:%08RX64 (%s)\n", 303 g_pMsgSlotMapping->enmVidMsgType, g_pMsgSlotMapping->cbMessage, 304 g_pHvMsgHdr->MessageType, g_pHvMsgHdr->PayloadSize, 305 g_pX64MsgHdr->CsSegment.Selector, g_pX64MsgHdr->Rip, pszFunction)); 306 307 return rcNt; 308 } 309 #endif /* NEM_WIN_INTERCEPT_NT_IO_CTLS */ 310 311 312 /** 313 * Patches the call table of VID.DLL so we can intercept NtDeviceIoControlFile. 314 * 315 * This is for used to figure out the I/O control codes and in logging builds 316 * for logging API calls that WinHvPlatform.dll does. 317 * 318 * @returns VBox status code. 319 * @param hLdrModVid The VID module handle. 320 * @param pErrInfo Where to return additional error information. 321 */ 322 static int nemR3WinInitVidIntercepts(RTLDRMOD hLdrModVid, PRTERRINFO pErrInfo) 323 { 324 /* 325 * Locate the real API. 326 */ 327 g_pfnNtDeviceIoControlFile = (decltype(NtDeviceIoControlFile) *)RTLdrGetSystemSymbol("NTDLL.DLL", "NtDeviceIoControlFile"); 328 AssertReturn(g_pfnNtDeviceIoControlFile != NULL, 329 RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, "Failed to resolve NtDeviceIoControlFile from NTDLL.DLL")); 330 331 /* 332 * Locate the PE header and get what we need from it. 333 */ 334 uint8_t const *pbImage = (uint8_t const *)RTLdrGetNativeHandle(hLdrModVid); 335 IMAGE_DOS_HEADER const *pMzHdr = (IMAGE_DOS_HEADER const *)pbImage; 336 AssertReturn(pMzHdr->e_magic == IMAGE_DOS_SIGNATURE, 337 RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, "VID.DLL mapping doesn't start with MZ signature: %#x", pMzHdr->e_magic)); 338 IMAGE_NT_HEADERS const *pNtHdrs = (IMAGE_NT_HEADERS const *)&pbImage[pMzHdr->e_lfanew]; 339 AssertReturn(pNtHdrs->Signature == IMAGE_NT_SIGNATURE, 340 RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, "VID.DLL has invalid PE signaturre: %#x @%#x", 341 pNtHdrs->Signature, pMzHdr->e_lfanew)); 342 343 uint32_t const cbImage = pNtHdrs->OptionalHeader.SizeOfImage; 344 IMAGE_DATA_DIRECTORY const ImportDir = pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; 345 346 /* 347 * Walk the import descriptor table looking for NTDLL.DLL. 348 */ 349 AssertReturn( ImportDir.Size > 0 350 && ImportDir.Size < cbImage, 351 RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, "VID.DLL bad import directory size: %#x", ImportDir.Size)); 352 AssertReturn( ImportDir.VirtualAddress > 0 353 && ImportDir.VirtualAddress <= cbImage - ImportDir.Size, 354 RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, "VID.DLL bad import directory RVA: %#x", ImportDir.VirtualAddress)); 355 356 for (PIMAGE_IMPORT_DESCRIPTOR pImps = (PIMAGE_IMPORT_DESCRIPTOR)&pbImage[ImportDir.VirtualAddress]; 357 pImps->Name != 0 && pImps->FirstThunk != 0; 358 pImps++) 359 { 360 AssertReturn(pImps->Name < cbImage, 361 RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, "VID.DLL bad import directory entry name: %#x", pImps->Name)); 362 const char *pszModName = (const char *)&pbImage[pImps->Name]; 363 if (RTStrICmpAscii(pszModName, "ntdll.dll")) 364 continue; 365 AssertReturn(pImps->FirstThunk < cbImage, 366 RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, "VID.DLL bad FirstThunk: %#x", pImps->FirstThunk)); 367 AssertReturn(pImps->OriginalFirstThunk < cbImage, 368 RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, "VID.DLL bad FirstThunk: %#x", pImps->FirstThunk)); 369 370 /* 371 * Walk the thunks table(s) looking for NtDeviceIoControlFile. 372 */ 373 PIMAGE_THUNK_DATA pFirstThunk = (PIMAGE_THUNK_DATA)&pbImage[pImps->FirstThunk]; /* update this. */ 374 PIMAGE_THUNK_DATA pThunk = pImps->OriginalFirstThunk == 0 /* read from this. */ 375 ? (PIMAGE_THUNK_DATA)&pbImage[pImps->FirstThunk] 376 : (PIMAGE_THUNK_DATA)&pbImage[pImps->OriginalFirstThunk]; 377 while (pThunk->u1.Ordinal != 0) 378 { 379 if (!(pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG32)) 380 { 381 AssertReturn(pThunk->u1.Ordinal > 0 && pThunk->u1.Ordinal < cbImage, 382 RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, "VID.DLL bad FirstThunk: %#x", pImps->FirstThunk)); 383 384 const char *pszSymbol = (const char *)&pbImage[(uintptr_t)pThunk->u1.AddressOfData + 2]; 385 if (strcmp(pszSymbol, "NtDeviceIoControlFile") == 0) 386 { 387 DWORD fOldProt = PAGE_READONLY; 388 VirtualProtect(&pFirstThunk->u1.Function, sizeof(uintptr_t), PAGE_EXECUTE_READWRITE, &fOldProt); 389 g_ppfnVidNtDeviceIoControlFile = (decltype(NtDeviceIoControlFile) **)&pFirstThunk->u1.Function; 390 /* Don't restore the protection here, so we modify the NtDeviceIoControlFile pointer later. */ 391 } 392 } 393 394 pThunk++; 395 pFirstThunk++; 396 } 397 } 398 399 if (*g_ppfnVidNtDeviceIoControlFile) 400 { 401 #ifdef NEM_WIN_INTERCEPT_NT_IO_CTLS 402 *g_ppfnVidNtDeviceIoControlFile = nemR3WinLogWrapper_NtDeviceIoControlFile; 403 #endif 404 return VINF_SUCCESS; 405 } 406 return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, "Failed to patch NtDeviceIoControlFile import in VID.DLL!"); 407 } 408 409 410 /** 411 * Worker for nemR3NativeInit that probes and load the native API. 412 * 413 * @returns VBox status code. 414 * @param fForced Whether the HMForced flag is set and we should 415 * fail if we cannot initialize. 416 * @param pErrInfo Where to always return error info. 417 */ 418 static int nemR3WinInitProbeAndLoad(bool fForced, PRTERRINFO pErrInfo) 419 { 420 /* 421 * Check that the DLL files we need are present, but without loading them. 422 * We'd like to avoid loading them unnecessarily. 423 */ 424 WCHAR wszPath[MAX_PATH + 64]; 425 UINT cwcPath = GetSystemDirectoryW(wszPath, MAX_PATH); 426 if (cwcPath >= MAX_PATH || cwcPath < 2) 427 return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, "GetSystemDirectoryW failed (%#x / %u)", cwcPath, GetLastError()); 428 429 if (wszPath[cwcPath - 1] != '\\' || wszPath[cwcPath - 1] != '/') 430 wszPath[cwcPath++] = '\\'; 431 RTUtf16CopyAscii(&wszPath[cwcPath], RT_ELEMENTS(wszPath) - cwcPath, "WinHvPlatform.dll"); 432 if (GetFileAttributesW(wszPath) == INVALID_FILE_ATTRIBUTES) 433 return RTErrInfoSetF(pErrInfo, VERR_NEM_NOT_AVAILABLE, "The native API dll was not found (%ls)", wszPath); 434 435 /* 436 * Check that we're in a VM and that the hypervisor identifies itself as Hyper-V. 437 */ 438 if (!ASMHasCpuId()) 439 return RTErrInfoSet(pErrInfo, VERR_NEM_NOT_AVAILABLE, "No CPUID support"); 440 if (!ASMIsValidStdRange(ASMCpuId_EAX(0))) 441 return RTErrInfoSet(pErrInfo, VERR_NEM_NOT_AVAILABLE, "No CPUID leaf #1"); 442 if (!(ASMCpuId_ECX(1) & X86_CPUID_FEATURE_ECX_HVP)) 443 return RTErrInfoSet(pErrInfo, VERR_NEM_NOT_AVAILABLE, "Not in a hypervisor partition (HVP=0)"); 444 445 uint32_t cMaxHyperLeaf = 0; 446 uint32_t uEbx = 0; 447 uint32_t uEcx = 0; 448 uint32_t uEdx = 0; 449 ASMCpuIdExSlow(0x40000000, 0, 0, 0, &cMaxHyperLeaf, &uEbx, &uEcx, &uEdx); 450 if (!ASMIsValidHypervisorRange(cMaxHyperLeaf)) 451 return RTErrInfoSetF(pErrInfo, VERR_NEM_NOT_AVAILABLE, "Invalid hypervisor CPUID range (%#x %#x %#x %#x)", 452 cMaxHyperLeaf, uEbx, uEcx, uEdx); 453 if ( uEbx != UINT32_C(0x7263694d) /* Micr */ 454 || uEcx != UINT32_C(0x666f736f) /* osof */ 455 || uEdx != UINT32_C(0x76482074) /* t Hv */) 456 return RTErrInfoSetF(pErrInfo, VERR_NEM_NOT_AVAILABLE, 457 "Not Hyper-V CPUID signature: %#x %#x %#x (expected %#x %#x %#x)", 458 uEbx, uEcx, uEdx, UINT32_C(0x7263694d), UINT32_C(0x666f736f), UINT32_C(0x76482074)); 459 if (cMaxHyperLeaf < UINT32_C(0x40000005)) 460 return RTErrInfoSetF(pErrInfo, VERR_NEM_NOT_AVAILABLE, "Too narrow hypervisor CPUID range (%#x)", cMaxHyperLeaf); 461 462 /** @todo would be great if we could recognize a root partition from the 463 * CPUID info, but I currently don't dare do that. */ 464 465 /* 466 * Now try load the DLLs and resolve the APIs. 467 */ 468 static const char * const s_apszDllNames[2] = { "WinHvPlatform.dll", "vid.dll" }; 469 RTLDRMOD ahMods[2] = { NIL_RTLDRMOD, NIL_RTLDRMOD }; 470 int rc = VINF_SUCCESS; 471 for (unsigned i = 0; i < RT_ELEMENTS(s_apszDllNames); i++) 472 { 473 int rc2 = RTLdrLoadSystem(s_apszDllNames[i], true /*fNoUnload*/, &ahMods[i]); 474 if (RT_FAILURE(rc2)) 475 { 476 if (!RTErrInfoIsSet(pErrInfo)) 477 RTErrInfoSetF(pErrInfo, rc2, "Failed to load API DLL: %s: %Rrc", s_apszDllNames[i], rc2); 478 else 479 RTErrInfoAddF(pErrInfo, rc2, "; %s: %Rrc", s_apszDllNames[i], rc2); 480 ahMods[i] = NIL_RTLDRMOD; 481 rc = VERR_NEM_INIT_FAILED; 482 } 483 } 484 if (RT_SUCCESS(rc)) 485 rc = nemR3WinInitVidIntercepts(ahMods[1], pErrInfo); 486 if (RT_SUCCESS(rc)) 487 { 488 for (unsigned i = 0; i < RT_ELEMENTS(g_aImports); i++) 489 { 490 int rc2 = RTLdrGetSymbol(ahMods[g_aImports[i].idxDll], g_aImports[i].pszName, (void **)g_aImports[i].ppfn); 491 if (RT_FAILURE(rc2)) 492 { 493 *g_aImports[i].ppfn = NULL; 494 495 LogRel(("NEM: %s: Failed to import %s!%s: %Rrc", 496 g_aImports[i].fOptional ? "info" : fForced ? "fatal" : "error", 497 s_apszDllNames[g_aImports[i].idxDll], g_aImports[i].pszName, rc2)); 498 if (!g_aImports[i].fOptional) 499 { 500 if (RTErrInfoIsSet(pErrInfo)) 501 RTErrInfoAddF(pErrInfo, rc2, ", %s!%s", 502 s_apszDllNames[g_aImports[i].idxDll], g_aImports[i].pszName); 503 else 504 rc = RTErrInfoSetF(pErrInfo, rc2, "Failed to import: %s!%s", 505 s_apszDllNames[g_aImports[i].idxDll], g_aImports[i].pszName); 506 Assert(RT_FAILURE(rc)); 507 } 508 } 509 } 510 if (RT_SUCCESS(rc)) 511 { 512 Assert(!RTErrInfoIsSet(pErrInfo)); 513 } 514 } 515 516 for (unsigned i = 0; i < RT_ELEMENTS(ahMods); i++) 517 RTLdrClose(ahMods[i]); 518 return rc; 519 } 520 521 522 /** 523 * Worker for nemR3NativeInit that gets the hypervisor capabilities. 524 * 525 * @returns VBox status code. 526 * @param pVM The cross context VM structure. 527 * @param pErrInfo Where to always return error info. 528 */ 529 static int nemR3WinInitCheckCapabilities(PVM pVM, PRTERRINFO pErrInfo) 530 { 531 #define NEM_LOG_REL_CAP_EX(a_szField, a_szFmt, a_Value) LogRel(("NEM: %-38s= " a_szFmt "\n", a_szField, a_Value)) 532 #define NEM_LOG_REL_CAP_SUB_EX(a_szField, a_szFmt, a_Value) LogRel(("NEM: %36s: " a_szFmt "\n", a_szField, a_Value)) 533 #define NEM_LOG_REL_CAP_SUB(a_szField, a_Value) NEM_LOG_REL_CAP_SUB_EX(a_szField, "%d", a_Value) 534 535 /* 536 * Is the hypervisor present with the desired capability? 537 * 538 * In build 17083 this translates into: 539 * - CPUID[0x00000001].HVP is set 540 * - CPUID[0x40000000] == "Microsoft Hv" 541 * - CPUID[0x40000001].eax == "Hv#1" 542 * - CPUID[0x40000003].ebx[12] is set. 543 * - VidGetExoPartitionProperty(INVALID_HANDLE_VALUE, 0x60000, &Ignored) returns 544 * a non-zero value. 545 */ 546 /** 547 * @todo Someone at Microsoft please explain weird API design: 548 * 1. Pointless CapabilityCode duplication int the output; 549 * 2. No output size. 550 */ 551 WHV_CAPABILITY Caps; 552 RT_ZERO(Caps); 553 SetLastError(0); 554 HRESULT hrc = WHvGetCapability(WHvCapabilityCodeHypervisorPresent, &Caps, sizeof(Caps)); 555 DWORD rcWin = GetLastError(); 556 if (FAILED(hrc)) 557 return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, 558 "WHvGetCapability/WHvCapabilityCodeHypervisorPresent failed: %Rhrc (Last=%#x/%u)", 559 hrc, RTNtLastStatusValue(), RTNtLastErrorValue()); 560 if (!Caps.HypervisorPresent) 561 { 562 if (!RTPathExists(RTPATH_NT_PASSTHRU_PREFIX "Device\\VidExo")) 563 return RTErrInfoSetF(pErrInfo, VERR_NEM_NOT_AVAILABLE, 564 "WHvCapabilityCodeHypervisorPresent is FALSE! Make sure you have enabled the 'Windows Hypervisor Platform' feature."); 565 return RTErrInfoSetF(pErrInfo, VERR_NEM_NOT_AVAILABLE, "WHvCapabilityCodeHypervisorPresent is FALSE! (%u)", rcWin); 566 } 567 LogRel(("NEM: WHvCapabilityCodeHypervisorPresent is TRUE, so this might work...\n")); 568 569 570 /* 571 * Check what extended VM exits are supported. 572 */ 573 RT_ZERO(Caps); 574 hrc = WHvGetCapability(WHvCapabilityCodeExtendedVmExits, &Caps, sizeof(Caps)); 575 if (FAILED(hrc)) 576 return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, 577 "WHvGetCapability/WHvCapabilityCodeExtendedVmExits failed: %Rhrc (Last=%#x/%u)", 578 hrc, RTNtLastStatusValue(), RTNtLastErrorValue()); 579 NEM_LOG_REL_CAP_EX("WHvCapabilityCodeExtendedVmExits", "%'#018RX64", Caps.ExtendedVmExits.AsUINT64); 580 pVM->nem.s.fExtendedMsrExit = RT_BOOL(Caps.ExtendedVmExits.X64MsrExit); 581 pVM->nem.s.fExtendedCpuIdExit = RT_BOOL(Caps.ExtendedVmExits.X64CpuidExit); 582 pVM->nem.s.fExtendedXcptExit = RT_BOOL(Caps.ExtendedVmExits.ExceptionExit); 583 NEM_LOG_REL_CAP_SUB("fExtendedMsrExit", pVM->nem.s.fExtendedMsrExit); 584 NEM_LOG_REL_CAP_SUB("fExtendedCpuIdExit", pVM->nem.s.fExtendedCpuIdExit); 585 NEM_LOG_REL_CAP_SUB("fExtendedXcptExit", pVM->nem.s.fExtendedXcptExit); 586 if (Caps.ExtendedVmExits.AsUINT64 & ~(uint64_t)7) 587 LogRel(("NEM: Warning! Unknown VM exit definitions: %#RX64\n", Caps.ExtendedVmExits.AsUINT64)); 588 /** @todo RECHECK: WHV_EXTENDED_VM_EXITS typedef. */ 589 590 /* 591 * Check features in case they end up defining any. 592 */ 593 RT_ZERO(Caps); 594 hrc = WHvGetCapability(WHvCapabilityCodeFeatures, &Caps, sizeof(Caps)); 595 if (FAILED(hrc)) 596 return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, 597 "WHvGetCapability/WHvCapabilityCodeFeatures failed: %Rhrc (Last=%#x/%u)", 598 hrc, RTNtLastStatusValue(), RTNtLastErrorValue()); 599 if (Caps.Features.AsUINT64 & ~(uint64_t)0) 600 LogRel(("NEM: Warning! Unknown feature definitions: %#RX64\n", Caps.Features.AsUINT64)); 601 /** @todo RECHECK: WHV_CAPABILITY_FEATURES typedef. */ 602 603 /* 604 * Check that the CPU vendor is supported. 605 */ 606 RT_ZERO(Caps); 607 hrc = WHvGetCapability(WHvCapabilityCodeProcessorVendor, &Caps, sizeof(Caps)); 608 if (FAILED(hrc)) 609 return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, 610 "WHvGetCapability/WHvCapabilityCodeProcessorVendor failed: %Rhrc (Last=%#x/%u)", 611 hrc, RTNtLastStatusValue(), RTNtLastErrorValue()); 612 switch (Caps.ProcessorVendor) 613 { 614 /** @todo RECHECK: WHV_PROCESSOR_VENDOR typedef. */ 615 case WHvProcessorVendorIntel: 616 NEM_LOG_REL_CAP_EX("WHvCapabilityCodeProcessorVendor", "%d - Intel", Caps.ProcessorVendor); 617 pVM->nem.s.enmCpuVendor = CPUMCPUVENDOR_INTEL; 618 break; 619 case WHvProcessorVendorAmd: 620 NEM_LOG_REL_CAP_EX("WHvCapabilityCodeProcessorVendor", "%d - AMD", Caps.ProcessorVendor); 621 pVM->nem.s.enmCpuVendor = CPUMCPUVENDOR_AMD; 622 break; 623 default: 624 NEM_LOG_REL_CAP_EX("WHvCapabilityCodeProcessorVendor", "%d", Caps.ProcessorVendor); 625 return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, "Unknown processor vendor: %d", Caps.ProcessorVendor); 626 } 627 628 /* 629 * CPU features, guessing these are virtual CPU features? 630 */ 631 RT_ZERO(Caps); 632 hrc = WHvGetCapability(WHvCapabilityCodeProcessorFeatures, &Caps, sizeof(Caps)); 633 if (FAILED(hrc)) 634 return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, 635 "WHvGetCapability/WHvCapabilityCodeProcessorFeatures failed: %Rhrc (Last=%#x/%u)", 636 hrc, RTNtLastStatusValue(), RTNtLastErrorValue()); 637 NEM_LOG_REL_CAP_EX("WHvCapabilityCodeProcessorFeatures", "%'#018RX64", Caps.ProcessorFeatures.AsUINT64); 638 #define NEM_LOG_REL_CPU_FEATURE(a_Field) NEM_LOG_REL_CAP_SUB(#a_Field, Caps.ProcessorFeatures.a_Field) 639 NEM_LOG_REL_CPU_FEATURE(Sse3Support); 640 NEM_LOG_REL_CPU_FEATURE(LahfSahfSupport); 641 NEM_LOG_REL_CPU_FEATURE(Ssse3Support); 642 NEM_LOG_REL_CPU_FEATURE(Sse4_1Support); 643 NEM_LOG_REL_CPU_FEATURE(Sse4_2Support); 644 NEM_LOG_REL_CPU_FEATURE(Sse4aSupport); 645 NEM_LOG_REL_CPU_FEATURE(XopSupport); 646 NEM_LOG_REL_CPU_FEATURE(PopCntSupport); 647 NEM_LOG_REL_CPU_FEATURE(Cmpxchg16bSupport); 648 NEM_LOG_REL_CPU_FEATURE(Altmovcr8Support); 649 NEM_LOG_REL_CPU_FEATURE(LzcntSupport); 650 NEM_LOG_REL_CPU_FEATURE(MisAlignSseSupport); 651 NEM_LOG_REL_CPU_FEATURE(MmxExtSupport); 652 NEM_LOG_REL_CPU_FEATURE(Amd3DNowSupport); 653 NEM_LOG_REL_CPU_FEATURE(ExtendedAmd3DNowSupport); 654 NEM_LOG_REL_CPU_FEATURE(Page1GbSupport); 655 NEM_LOG_REL_CPU_FEATURE(AesSupport); 656 NEM_LOG_REL_CPU_FEATURE(PclmulqdqSupport); 657 NEM_LOG_REL_CPU_FEATURE(PcidSupport); 658 NEM_LOG_REL_CPU_FEATURE(Fma4Support); 659 NEM_LOG_REL_CPU_FEATURE(F16CSupport); 660 NEM_LOG_REL_CPU_FEATURE(RdRandSupport); 661 NEM_LOG_REL_CPU_FEATURE(RdWrFsGsSupport); 662 NEM_LOG_REL_CPU_FEATURE(SmepSupport); 663 NEM_LOG_REL_CPU_FEATURE(EnhancedFastStringSupport); 664 NEM_LOG_REL_CPU_FEATURE(Bmi1Support); 665 NEM_LOG_REL_CPU_FEATURE(Bmi2Support); 666 /* two reserved bits here, see below */ 667 NEM_LOG_REL_CPU_FEATURE(MovbeSupport); 668 NEM_LOG_REL_CPU_FEATURE(Npiep1Support); 669 NEM_LOG_REL_CPU_FEATURE(DepX87FPUSaveSupport); 670 NEM_LOG_REL_CPU_FEATURE(RdSeedSupport); 671 NEM_LOG_REL_CPU_FEATURE(AdxSupport); 672 NEM_LOG_REL_CPU_FEATURE(IntelPrefetchSupport); 673 NEM_LOG_REL_CPU_FEATURE(SmapSupport); 674 NEM_LOG_REL_CPU_FEATURE(HleSupport); 675 NEM_LOG_REL_CPU_FEATURE(RtmSupport); 676 NEM_LOG_REL_CPU_FEATURE(RdtscpSupport); 677 NEM_LOG_REL_CPU_FEATURE(ClflushoptSupport); 678 NEM_LOG_REL_CPU_FEATURE(ClwbSupport); 679 NEM_LOG_REL_CPU_FEATURE(ShaSupport); 680 NEM_LOG_REL_CPU_FEATURE(X87PointersSavedSupport); 681 #undef NEM_LOG_REL_CPU_FEATURE 682 if (Caps.ProcessorFeatures.AsUINT64 & (~(RT_BIT_64(43) - 1) | RT_BIT_64(27) | RT_BIT_64(28))) 683 LogRel(("NEM: Warning! Unknown CPU features: %#RX64\n", Caps.ProcessorFeatures.AsUINT64)); 684 pVM->nem.s.uCpuFeatures.u64 = Caps.ProcessorFeatures.AsUINT64; 685 /** @todo RECHECK: WHV_PROCESSOR_FEATURES typedef. */ 686 687 /* 688 * The cache line flush size. 689 */ 690 RT_ZERO(Caps); 691 hrc = WHvGetCapability(WHvCapabilityCodeProcessorClFlushSize, &Caps, sizeof(Caps)); 692 if (FAILED(hrc)) 693 return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, 694 "WHvGetCapability/WHvCapabilityCodeProcessorClFlushSize failed: %Rhrc (Last=%#x/%u)", 695 hrc, RTNtLastStatusValue(), RTNtLastErrorValue()); 696 NEM_LOG_REL_CAP_EX("WHvCapabilityCodeProcessorClFlushSize", "2^%u", Caps.ProcessorClFlushSize); 697 if (Caps.ProcessorClFlushSize < 8 && Caps.ProcessorClFlushSize > 9) 698 return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, "Unsupported cache line flush size: %u", Caps.ProcessorClFlushSize); 699 pVM->nem.s.cCacheLineFlushShift = Caps.ProcessorClFlushSize; 700 701 /* 702 * See if they've added more properties that we're not aware of. 703 */ 704 /** @todo RECHECK: WHV_CAPABILITY_CODE typedef. */ 705 if (!IsDebuggerPresent()) /* Too noisy when in debugger, so skip. */ 706 { 707 static const struct 708 { 709 uint32_t iMin, iMax; } s_aUnknowns[] = 710 { 711 { 0x0003, 0x000f }, 712 { 0x1003, 0x100f }, 713 { 0x2000, 0x200f }, 714 { 0x3000, 0x300f }, 715 { 0x4000, 0x400f }, 716 }; 717 for (uint32_t j = 0; j < RT_ELEMENTS(s_aUnknowns); j++) 718 for (uint32_t i = s_aUnknowns[j].iMin; i <= s_aUnknowns[j].iMax; i++) 719 { 720 RT_ZERO(Caps); 721 hrc = WHvGetCapability((WHV_CAPABILITY_CODE)i, &Caps, sizeof(Caps)); 722 if (SUCCEEDED(hrc)) 723 LogRel(("NEM: Warning! Unknown capability %#x returning: %.*Rhxs\n", i, sizeof(Caps), &Caps)); 724 } 725 } 726 727 #undef NEM_LOG_REL_CAP_EX 728 #undef NEM_LOG_REL_CAP_SUB_EX 729 #undef NEM_LOG_REL_CAP_SUB 730 return VINF_SUCCESS; 731 } 732 733 734 /** 735 * Used to fill in g_IoCtlGetHvPartitionId. 736 */ 737 static NTSTATUS WINAPI 738 nemR3WinIoctlDetector_GetHvPartitionId(HANDLE hFile, HANDLE hEvt, PIO_APC_ROUTINE pfnApcCallback, PVOID pvApcCtx, 739 PIO_STATUS_BLOCK pIos, ULONG uFunction, PVOID pvInput, ULONG cbInput, 740 PVOID pvOutput, ULONG cbOutput) 741 { 742 AssertLogRelMsgReturn(hFile == NEM_WIN_IOCTL_DETECTOR_FAKE_HANDLE, ("hFile=%p\n", hFile), STATUS_INVALID_PARAMETER_1); 743 RT_NOREF(hEvt); RT_NOREF(pfnApcCallback); RT_NOREF(pvApcCtx); 744 AssertLogRelMsgReturn(RT_VALID_PTR(pIos), ("pIos=%p\n", pIos), STATUS_INVALID_PARAMETER_5); 745 AssertLogRelMsgReturn(cbInput == 0, ("cbInput=%#x\n", cbInput), STATUS_INVALID_PARAMETER_8); 746 RT_NOREF(pvInput); 747 748 AssertLogRelMsgReturn(RT_VALID_PTR(pvOutput), ("pvOutput=%p\n", pvOutput), STATUS_INVALID_PARAMETER_9); 749 AssertLogRelMsgReturn(cbOutput == sizeof(HV_PARTITION_ID), ("cbInput=%#x\n", cbInput), STATUS_INVALID_PARAMETER_10); 750 *(HV_PARTITION_ID *)pvOutput = NEM_WIN_IOCTL_DETECTOR_FAKE_PARTITION_ID; 751 752 g_IoCtlGetHvPartitionId.cbInput = cbInput; 753 g_IoCtlGetHvPartitionId.cbOutput = cbOutput; 754 g_IoCtlGetHvPartitionId.uFunction = uFunction; 755 756 return STATUS_SUCCESS; 757 } 758 759 760 /** 761 * Used to fill in g_IoCtlStartVirtualProcessor. 762 */ 763 static NTSTATUS WINAPI 764 nemR3WinIoctlDetector_StartVirtualProcessor(HANDLE hFile, HANDLE hEvt, PIO_APC_ROUTINE pfnApcCallback, PVOID pvApcCtx, 765 PIO_STATUS_BLOCK pIos, ULONG uFunction, PVOID pvInput, ULONG cbInput, 766 PVOID pvOutput, ULONG cbOutput) 767 { 768 AssertLogRelMsgReturn(hFile == NEM_WIN_IOCTL_DETECTOR_FAKE_HANDLE, ("hFile=%p\n", hFile), STATUS_INVALID_PARAMETER_1); 769 RT_NOREF(hEvt); RT_NOREF(pfnApcCallback); RT_NOREF(pvApcCtx); 770 AssertLogRelMsgReturn(RT_VALID_PTR(pIos), ("pIos=%p\n", pIos), STATUS_INVALID_PARAMETER_5); 771 AssertLogRelMsgReturn(cbInput == sizeof(HV_VP_INDEX), ("cbInput=%#x\n", cbInput), STATUS_INVALID_PARAMETER_8); 772 AssertLogRelMsgReturn(RT_VALID_PTR(pvInput), ("pvInput=%p\n", pvInput), STATUS_INVALID_PARAMETER_9); 773 AssertLogRelMsgReturn(*(HV_VP_INDEX *)pvInput == NEM_WIN_IOCTL_DETECTOR_FAKE_VP_INDEX, 774 ("*piCpu=%u\n", *(HV_VP_INDEX *)pvInput), STATUS_INVALID_PARAMETER_9); 775 AssertLogRelMsgReturn(cbOutput == 0, ("cbInput=%#x\n", cbInput), STATUS_INVALID_PARAMETER_10); 776 RT_NOREF(pvOutput); 777 778 g_IoCtlStartVirtualProcessor.cbInput = cbInput; 779 g_IoCtlStartVirtualProcessor.cbOutput = cbOutput; 780 g_IoCtlStartVirtualProcessor.uFunction = uFunction; 781 782 return STATUS_SUCCESS; 783 } 784 785 786 /** 787 * Used to fill in g_IoCtlStartVirtualProcessor. 788 */ 789 static NTSTATUS WINAPI 790 nemR3WinIoctlDetector_StopVirtualProcessor(HANDLE hFile, HANDLE hEvt, PIO_APC_ROUTINE pfnApcCallback, PVOID pvApcCtx, 791 PIO_STATUS_BLOCK pIos, ULONG uFunction, PVOID pvInput, ULONG cbInput, 792 PVOID pvOutput, ULONG cbOutput) 793 { 794 AssertLogRelMsgReturn(hFile == NEM_WIN_IOCTL_DETECTOR_FAKE_HANDLE, ("hFile=%p\n", hFile), STATUS_INVALID_PARAMETER_1); 795 RT_NOREF(hEvt); RT_NOREF(pfnApcCallback); RT_NOREF(pvApcCtx); 796 AssertLogRelMsgReturn(RT_VALID_PTR(pIos), ("pIos=%p\n", pIos), STATUS_INVALID_PARAMETER_5); 797 AssertLogRelMsgReturn(cbInput == sizeof(HV_VP_INDEX), ("cbInput=%#x\n", cbInput), STATUS_INVALID_PARAMETER_8); 798 AssertLogRelMsgReturn(RT_VALID_PTR(pvInput), ("pvInput=%p\n", pvInput), STATUS_INVALID_PARAMETER_9); 799 AssertLogRelMsgReturn(*(HV_VP_INDEX *)pvInput == NEM_WIN_IOCTL_DETECTOR_FAKE_VP_INDEX, 800 ("*piCpu=%u\n", *(HV_VP_INDEX *)pvInput), STATUS_INVALID_PARAMETER_9); 801 AssertLogRelMsgReturn(cbOutput == 0, ("cbInput=%#x\n", cbInput), STATUS_INVALID_PARAMETER_10); 802 RT_NOREF(pvOutput); 803 804 g_IoCtlStopVirtualProcessor.cbInput = cbInput; 805 g_IoCtlStopVirtualProcessor.cbOutput = cbOutput; 806 g_IoCtlStopVirtualProcessor.uFunction = uFunction; 807 808 return STATUS_SUCCESS; 809 } 810 811 812 /** 813 * Used to fill in g_IoCtlMessageSlotHandleAndGetNext 814 */ 815 static NTSTATUS WINAPI 816 nemR3WinIoctlDetector_MessageSlotHandleAndGetNext(HANDLE hFile, HANDLE hEvt, PIO_APC_ROUTINE pfnApcCallback, PVOID pvApcCtx, 817 PIO_STATUS_BLOCK pIos, ULONG uFunction, PVOID pvInput, ULONG cbInput, 818 PVOID pvOutput, ULONG cbOutput) 819 { 820 AssertLogRelMsgReturn(hFile == NEM_WIN_IOCTL_DETECTOR_FAKE_HANDLE, ("hFile=%p\n", hFile), STATUS_INVALID_PARAMETER_1); 821 RT_NOREF(hEvt); RT_NOREF(pfnApcCallback); RT_NOREF(pvApcCtx); 822 AssertLogRelMsgReturn(RT_VALID_PTR(pIos), ("pIos=%p\n", pIos), STATUS_INVALID_PARAMETER_5); 823 824 AssertLogRelMsgReturn(cbInput == sizeof(VID_IOCTL_INPUT_MESSAGE_SLOT_HANDLE_AND_GET_NEXT), ("cbInput=%#x\n", cbInput), 825 STATUS_INVALID_PARAMETER_8); 826 AssertLogRelMsgReturn(RT_VALID_PTR(pvInput), ("pvInput=%p\n", pvInput), STATUS_INVALID_PARAMETER_9); 827 PCVID_IOCTL_INPUT_MESSAGE_SLOT_HANDLE_AND_GET_NEXT pVidIn = (PCVID_IOCTL_INPUT_MESSAGE_SLOT_HANDLE_AND_GET_NEXT)pvInput; 828 AssertLogRelMsgReturn( pVidIn->iCpu == NEM_WIN_IOCTL_DETECTOR_FAKE_VP_INDEX 829 && pVidIn->fFlags == VID_MSHAGN_F_HANDLE_MESSAGE 830 && pVidIn->cMillies == NEM_WIN_IOCTL_DETECTOR_FAKE_TIMEOUT, 831 ("iCpu=%u fFlags=%#x cMillies=%#x\n", pVidIn->iCpu, pVidIn->fFlags, pVidIn->cMillies), 832 STATUS_INVALID_PARAMETER_9); 833 AssertLogRelMsgReturn(cbOutput == 0, ("cbInput=%#x\n", cbInput), STATUS_INVALID_PARAMETER_10); 834 RT_NOREF(pvOutput); 835 836 g_IoCtlMessageSlotHandleAndGetNext.cbInput = cbInput; 837 g_IoCtlMessageSlotHandleAndGetNext.cbOutput = cbOutput; 838 g_IoCtlMessageSlotHandleAndGetNext.uFunction = uFunction; 839 840 return STATUS_SUCCESS; 841 } 842 843 844 #ifdef LOG_ENABLED 845 /** 846 * Used to fill in what g_pIoCtlDetectForLogging points to. 847 */ 848 static NTSTATUS WINAPI nemR3WinIoctlDetector_ForLogging(HANDLE hFile, HANDLE hEvt, PIO_APC_ROUTINE pfnApcCallback, PVOID pvApcCtx, 849 PIO_STATUS_BLOCK pIos, ULONG uFunction, PVOID pvInput, ULONG cbInput, 850 PVOID pvOutput, ULONG cbOutput) 851 { 852 RT_NOREF(hFile, hEvt, pfnApcCallback, pvApcCtx, pIos, pvInput, pvOutput); 853 854 g_pIoCtlDetectForLogging->cbInput = cbInput; 855 g_pIoCtlDetectForLogging->cbOutput = cbOutput; 856 g_pIoCtlDetectForLogging->uFunction = uFunction; 857 858 return STATUS_SUCCESS; 859 } 860 #endif 861 862 863 /** 864 * Worker for nemR3NativeInit that detect I/O control function numbers for VID. 865 * 866 * We use the function numbers directly in ring-0 and to name functions when 867 * logging NtDeviceIoControlFile calls. 868 * 869 * @note We could alternatively do this by disassembling the respective 870 * functions, but hooking NtDeviceIoControlFile and making fake calls 871 * more easily provides the desired information. 872 * 873 * @returns VBox status code. 874 * @param pVM The cross context VM structure. Will set I/O 875 * control info members. 876 * @param pErrInfo Where to always return error info. 877 */ 878 static int nemR3WinInitDiscoverIoControlProperties(PVM pVM, PRTERRINFO pErrInfo) 879 { 880 /* 881 * Probe the I/O control information for select VID APIs so we can use 882 * them directly from ring-0 and better log them. 883 * 884 */ 885 decltype(NtDeviceIoControlFile) * const pfnOrg = *g_ppfnVidNtDeviceIoControlFile; 886 887 /* VidGetHvPartitionId */ 888 *g_ppfnVidNtDeviceIoControlFile = nemR3WinIoctlDetector_GetHvPartitionId; 889 HV_PARTITION_ID idHvPartition = HV_PARTITION_ID_INVALID; 890 BOOL fRet = g_pfnVidGetHvPartitionId(NEM_WIN_IOCTL_DETECTOR_FAKE_HANDLE, &idHvPartition); 891 *g_ppfnVidNtDeviceIoControlFile = pfnOrg; 892 AssertReturn(fRet && idHvPartition == NEM_WIN_IOCTL_DETECTOR_FAKE_PARTITION_ID && g_IoCtlGetHvPartitionId.uFunction != 0, 893 RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, 894 "Problem figuring out VidGetHvPartitionId: fRet=%u idHvPartition=%#x dwErr=%u", 895 fRet, idHvPartition, GetLastError()) ); 896 LogRel(("NEM: VidGetHvPartitionId -> fun:%#x in:%#x out:%#x\n", 897 g_IoCtlGetHvPartitionId.uFunction, g_IoCtlGetHvPartitionId.cbInput, g_IoCtlGetHvPartitionId.cbOutput)); 898 899 /* VidStartVirtualProcessor */ 900 *g_ppfnVidNtDeviceIoControlFile = nemR3WinIoctlDetector_StartVirtualProcessor; 901 fRet = g_pfnVidStartVirtualProcessor(NEM_WIN_IOCTL_DETECTOR_FAKE_HANDLE, NEM_WIN_IOCTL_DETECTOR_FAKE_VP_INDEX); 902 *g_ppfnVidNtDeviceIoControlFile = pfnOrg; 903 AssertReturn(fRet && g_IoCtlStartVirtualProcessor.uFunction != 0, 904 RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, 905 "Problem figuring out VidStartVirtualProcessor: fRet=%u dwErr=%u", 906 fRet, GetLastError()) ); 907 LogRel(("NEM: VidStartVirtualProcessor -> fun:%#x in:%#x out:%#x\n", g_IoCtlStartVirtualProcessor.uFunction, 908 g_IoCtlStartVirtualProcessor.cbInput, g_IoCtlStartVirtualProcessor.cbOutput)); 909 910 /* VidStopVirtualProcessor */ 911 *g_ppfnVidNtDeviceIoControlFile = nemR3WinIoctlDetector_StopVirtualProcessor; 912 fRet = g_pfnVidStopVirtualProcessor(NEM_WIN_IOCTL_DETECTOR_FAKE_HANDLE, NEM_WIN_IOCTL_DETECTOR_FAKE_VP_INDEX); 913 *g_ppfnVidNtDeviceIoControlFile = pfnOrg; 914 AssertReturn(fRet && g_IoCtlStopVirtualProcessor.uFunction != 0, 915 RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, 916 "Problem figuring out VidStopVirtualProcessor: fRet=%u dwErr=%u", 917 fRet, GetLastError()) ); 918 LogRel(("NEM: VidStopVirtualProcessor -> fun:%#x in:%#x out:%#x\n", g_IoCtlStopVirtualProcessor.uFunction, 919 g_IoCtlStopVirtualProcessor.cbInput, g_IoCtlStopVirtualProcessor.cbOutput)); 920 921 /* VidMessageSlotHandleAndGetNext */ 922 *g_ppfnVidNtDeviceIoControlFile = nemR3WinIoctlDetector_MessageSlotHandleAndGetNext; 923 fRet = g_pfnVidMessageSlotHandleAndGetNext(NEM_WIN_IOCTL_DETECTOR_FAKE_HANDLE, 924 NEM_WIN_IOCTL_DETECTOR_FAKE_VP_INDEX, VID_MSHAGN_F_HANDLE_MESSAGE, 925 NEM_WIN_IOCTL_DETECTOR_FAKE_TIMEOUT); 926 *g_ppfnVidNtDeviceIoControlFile = pfnOrg; 927 AssertReturn(fRet && g_IoCtlMessageSlotHandleAndGetNext.uFunction != 0, 928 RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, 929 "Problem figuring out VidMessageSlotHandleAndGetNext: fRet=%u dwErr=%u", 930 fRet, GetLastError()) ); 931 LogRel(("NEM: VidMessageSlotHandleAndGetNext -> fun:%#x in:%#x out:%#x\n", 932 g_IoCtlMessageSlotHandleAndGetNext.uFunction, g_IoCtlMessageSlotHandleAndGetNext.cbInput, 933 g_IoCtlMessageSlotHandleAndGetNext.cbOutput)); 934 935 #ifdef LOG_ENABLED 936 /* The following are only for logging: */ 937 union 938 { 939 VID_MAPPED_MESSAGE_SLOT MapSlot; 940 HV_REGISTER_NAME Name; 941 HV_REGISTER_VALUE Value; 942 } uBuf; 943 944 /* VidMessageSlotMap */ 945 g_pIoCtlDetectForLogging = &g_IoCtlMessageSlotMap; 946 *g_ppfnVidNtDeviceIoControlFile = nemR3WinIoctlDetector_ForLogging; 947 fRet = g_pfnVidMessageSlotMap(NEM_WIN_IOCTL_DETECTOR_FAKE_HANDLE, &uBuf.MapSlot, NEM_WIN_IOCTL_DETECTOR_FAKE_VP_INDEX); 948 *g_ppfnVidNtDeviceIoControlFile = pfnOrg; 949 Assert(fRet); 950 LogRel(("NEM: VidMessageSlotMap -> fun:%#x in:%#x out:%#x\n", g_pIoCtlDetectForLogging->uFunction, 951 g_pIoCtlDetectForLogging->cbInput, g_pIoCtlDetectForLogging->cbOutput)); 952 953 /* VidGetVirtualProcessorState */ 954 uBuf.Name = HvRegisterExplicitSuspend; 955 g_pIoCtlDetectForLogging = &g_IoCtlGetVirtualProcessorState; 956 *g_ppfnVidNtDeviceIoControlFile = nemR3WinIoctlDetector_ForLogging; 957 fRet = g_pfnVidGetVirtualProcessorState(NEM_WIN_IOCTL_DETECTOR_FAKE_HANDLE, NEM_WIN_IOCTL_DETECTOR_FAKE_VP_INDEX, 958 &uBuf.Name, 1, &uBuf.Value); 959 *g_ppfnVidNtDeviceIoControlFile = pfnOrg; 960 Assert(fRet); 961 LogRel(("NEM: VidGetVirtualProcessorState -> fun:%#x in:%#x out:%#x\n", g_pIoCtlDetectForLogging->uFunction, 962 g_pIoCtlDetectForLogging->cbInput, g_pIoCtlDetectForLogging->cbOutput)); 963 964 /* VidSetVirtualProcessorState */ 965 uBuf.Name = HvRegisterExplicitSuspend; 966 g_pIoCtlDetectForLogging = &g_IoCtlSetVirtualProcessorState; 967 *g_ppfnVidNtDeviceIoControlFile = nemR3WinIoctlDetector_ForLogging; 968 fRet = g_pfnVidSetVirtualProcessorState(NEM_WIN_IOCTL_DETECTOR_FAKE_HANDLE, NEM_WIN_IOCTL_DETECTOR_FAKE_VP_INDEX, 969 &uBuf.Name, 1, &uBuf.Value); 970 *g_ppfnVidNtDeviceIoControlFile = pfnOrg; 971 Assert(fRet); 972 LogRel(("NEM: VidSetVirtualProcessorState -> fun:%#x in:%#x out:%#x\n", g_pIoCtlDetectForLogging->uFunction, 973 g_pIoCtlDetectForLogging->cbInput, g_pIoCtlDetectForLogging->cbOutput)); 974 975 g_pIoCtlDetectForLogging = NULL; 976 #endif 977 978 /* Done. */ 979 pVM->nem.s.IoCtlGetHvPartitionId = g_IoCtlGetHvPartitionId; 980 pVM->nem.s.IoCtlStartVirtualProcessor = g_IoCtlStartVirtualProcessor; 981 pVM->nem.s.IoCtlStopVirtualProcessor = g_IoCtlStopVirtualProcessor; 982 pVM->nem.s.IoCtlMessageSlotHandleAndGetNext = g_IoCtlMessageSlotHandleAndGetNext; 983 return VINF_SUCCESS; 984 } 985 986 987 /** 988 * Creates and sets up a Hyper-V (exo) partition. 989 * 990 * @returns VBox status code. 991 * @param pVM The cross context VM structure. 992 * @param pErrInfo Where to always return error info. 993 */ 994 static int nemR3WinInitCreatePartition(PVM pVM, PRTERRINFO pErrInfo) 995 { 996 AssertReturn(!pVM->nem.s.hPartition, RTErrInfoSet(pErrInfo, VERR_WRONG_ORDER, "Wrong initalization order")); 997 AssertReturn(!pVM->nem.s.hPartitionDevice, RTErrInfoSet(pErrInfo, VERR_WRONG_ORDER, "Wrong initalization order")); 998 999 /* 1000 * Create the partition. 1001 */ 1002 WHV_PARTITION_HANDLE hPartition; 1003 HRESULT hrc = WHvCreatePartition(&hPartition); 1004 if (FAILED(hrc)) 1005 return RTErrInfoSetF(pErrInfo, VERR_NEM_VM_CREATE_FAILED, "WHvCreatePartition failed with %Rhrc (Last=%#x/%u)", 1006 hrc, RTNtLastStatusValue(), RTNtLastErrorValue()); 1007 1008 int rc; 1009 1010 /* 1011 * Set partition properties, most importantly the CPU count. 1012 */ 1013 /** 1014 * @todo Someone at Microsoft please explain another weird API: 1015 * - Why this API doesn't take the WHV_PARTITION_PROPERTY_CODE value as an 1016 * argument rather than as part of the struct. That is so weird if you've 1017 * used any other NT or windows API, including WHvGetCapability(). 1018 * - Why use PVOID when WHV_PARTITION_PROPERTY is what's expected. We 1019 * technically only need 9 bytes for setting/getting 1020 * WHVPartitionPropertyCodeProcessorClFlushSize, but the API insists on 16. */ 1021 WHV_PARTITION_PROPERTY Property; 1022 RT_ZERO(Property); 1023 Property.PropertyCode = WHvPartitionPropertyCodeProcessorCount; 1024 Property.ProcessorCount = pVM->cCpus; 1025 hrc = WHvSetPartitionProperty(hPartition, &Property, sizeof(Property)); 1026 if (SUCCEEDED(hrc)) 1027 { 1028 RT_ZERO(Property); 1029 Property.PropertyCode = WHvPartitionPropertyCodeExtendedVmExits; 1030 Property.ExtendedVmExits.X64CpuidExit = pVM->nem.s.fExtendedCpuIdExit; 1031 Property.ExtendedVmExits.X64MsrExit = pVM->nem.s.fExtendedMsrExit; 1032 Property.ExtendedVmExits.ExceptionExit = pVM->nem.s.fExtendedXcptExit; 1033 hrc = WHvSetPartitionProperty(hPartition, &Property, sizeof(Property)); 1034 if (SUCCEEDED(hrc)) 1035 { 1036 /* 1037 * We'll continue setup in nemR3NativeInitAfterCPUM. 1038 */ 1039 pVM->nem.s.fCreatedEmts = false; 1040 pVM->nem.s.hPartition = hPartition; 1041 LogRel(("NEM: Created partition %p.\n", hPartition)); 1042 return VINF_SUCCESS; 1043 } 1044 1045 rc = RTErrInfoSetF(pErrInfo, VERR_NEM_VM_CREATE_FAILED, 1046 "Failed setting WHvPartitionPropertyCodeExtendedVmExits to %'#RX64: %Rhrc", 1047 Property.ExtendedVmExits.AsUINT64, hrc); 1048 } 1049 else 1050 rc = RTErrInfoSetF(pErrInfo, VERR_NEM_VM_CREATE_FAILED, 1051 "Failed setting WHvPartitionPropertyCodeProcessorCount to %u: %Rhrc (Last=%#x/%u)", 1052 pVM->cCpus, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()); 1053 WHvDeletePartition(hPartition); 1054 1055 Assert(!pVM->nem.s.hPartitionDevice); 1056 Assert(!pVM->nem.s.hPartition); 1057 return rc; 1058 } 1059 1060 1061 /** 1062 * Try initialize the native API. 1063 * 1064 * This may only do part of the job, more can be done in 1065 * nemR3NativeInitAfterCPUM() and nemR3NativeInitCompleted(). 1066 * 1067 * @returns VBox status code. 1068 * @param pVM The cross context VM structure. 1069 * @param fFallback Whether we're in fallback mode or use-NEM mode. In 1070 * the latter we'll fail if we cannot initialize. 1071 * @param fForced Whether the HMForced flag is set and we should 1072 * fail if we cannot initialize. 1073 */ 1074 int nemR3NativeInit(PVM pVM, bool fFallback, bool fForced) 1075 { 1076 /* 1077 * Error state. 1078 * The error message will be non-empty on failure and 'rc' will be set too. 1079 */ 1080 RTERRINFOSTATIC ErrInfo; 1081 PRTERRINFO pErrInfo = RTErrInfoInitStatic(&ErrInfo); 1082 int rc = nemR3WinInitProbeAndLoad(fForced, pErrInfo); 1083 if (RT_SUCCESS(rc)) 1084 { 1085 /* 1086 * Check the capabilties of the hypervisor, starting with whether it's present. 1087 */ 1088 rc = nemR3WinInitCheckCapabilities(pVM, pErrInfo); 1089 if (RT_SUCCESS(rc)) 1090 { 1091 /* 1092 * Discover the VID I/O control function numbers we need. 1093 */ 1094 rc = nemR3WinInitDiscoverIoControlProperties(pVM, pErrInfo); 1095 if (RT_SUCCESS(rc)) 1096 { 1097 /* 1098 * Check out our ring-0 capabilities. 1099 */ 1100 rc = SUPR3CallVMMR0Ex(pVM->pVMR0, 0 /*idCpu*/, VMMR0_DO_NEM_INIT_VM, 0, NULL); 1101 if (RT_SUCCESS(rc)) 1102 { 1103 /* 1104 * Create and initialize a partition. 1105 */ 1106 rc = nemR3WinInitCreatePartition(pVM, pErrInfo); 1107 if (RT_SUCCESS(rc)) 1108 { 1109 VM_SET_MAIN_EXECUTION_ENGINE(pVM, VM_EXEC_ENGINE_NATIVE_API); 1110 Log(("NEM: Marked active!\n")); 1111 } 1112 } 1113 } 1114 } 1115 } 1116 1117 /* 1118 * We only fail if in forced mode, otherwise just log the complaint and return. 1119 */ 1120 Assert(pVM->bMainExecutionEngine == VM_EXEC_ENGINE_NATIVE_API || RTErrInfoIsSet(pErrInfo)); 1121 if ( (fForced || !fFallback) 1122 && pVM->bMainExecutionEngine != VM_EXEC_ENGINE_NATIVE_API) 1123 return VMSetError(pVM, RT_SUCCESS_NP(rc) ? VERR_NEM_NOT_AVAILABLE : rc, RT_SRC_POS, "%s", pErrInfo->pszMsg); 1124 1125 if (RTErrInfoIsSet(pErrInfo)) 1126 LogRel(("NEM: Not available: %s\n", pErrInfo->pszMsg)); 1127 return VINF_SUCCESS; 1128 } 1129 1130 1131 /** 1132 * This is called after CPUMR3Init is done. 1133 * 1134 * @returns VBox status code. 1135 * @param pVM The VM handle.. 1136 */ 1137 int nemR3NativeInitAfterCPUM(PVM pVM) 1138 { 1139 /* 1140 * Validate sanity. 1141 */ 1142 WHV_PARTITION_HANDLE hPartition = pVM->nem.s.hPartition; 1143 AssertReturn(hPartition != NULL, VERR_WRONG_ORDER); 1144 AssertReturn(!pVM->nem.s.hPartitionDevice, VERR_WRONG_ORDER); 1145 AssertReturn(!pVM->nem.s.fCreatedEmts, VERR_WRONG_ORDER); 1146 AssertReturn(pVM->bMainExecutionEngine == VM_EXEC_ENGINE_NATIVE_API, VERR_WRONG_ORDER); 1147 1148 /* 1149 * Continue setting up the partition now that we've got most of the CPUID feature stuff. 1150 */ 1151 1152 /* Not sure if we really need to set the vendor. */ 1153 WHV_PARTITION_PROPERTY Property; 1154 RT_ZERO(Property); 1155 Property.PropertyCode = WHvPartitionPropertyCodeProcessorVendor; 1156 Property.ProcessorVendor = pVM->nem.s.enmCpuVendor == CPUMCPUVENDOR_AMD ? WHvProcessorVendorAmd 1157 : WHvProcessorVendorIntel; 1158 HRESULT hrc = WHvSetPartitionProperty(hPartition, &Property, sizeof(Property)); 1159 if (FAILED(hrc)) 1160 return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS, 1161 "Failed to set WHvPartitionPropertyCodeProcessorVendor to %u: %Rhrc (Last=%#x/%u)", 1162 Property.ProcessorVendor, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()); 1163 1164 /* Not sure if we really need to set the cache line flush size. */ 1165 RT_ZERO(Property); 1166 Property.PropertyCode = WHvPartitionPropertyCodeProcessorClFlushSize; 1167 Property.ProcessorClFlushSize = pVM->nem.s.cCacheLineFlushShift; 1168 hrc = WHvSetPartitionProperty(hPartition, &Property, sizeof(Property)); 1169 if (FAILED(hrc)) 1170 return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS, 1171 "Failed to set WHvPartitionPropertyCodeProcessorClFlushSize to %u: %Rhrc (Last=%#x/%u)", 1172 pVM->nem.s.cCacheLineFlushShift, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()); 1173 1174 /* 1175 * Sync CPU features with CPUM. 1176 */ 1177 /** @todo sync CPU features with CPUM. */ 1178 1179 /* Set the partition property. */ 1180 RT_ZERO(Property); 1181 Property.PropertyCode = WHvPartitionPropertyCodeProcessorFeatures; 1182 Property.ProcessorFeatures.AsUINT64 = pVM->nem.s.uCpuFeatures.u64; 1183 hrc = WHvSetPartitionProperty(hPartition, &Property, sizeof(Property)); 1184 if (FAILED(hrc)) 1185 return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS, 1186 "Failed to set WHvPartitionPropertyCodeProcessorFeatures to %'#RX64: %Rhrc (Last=%#x/%u)", 1187 pVM->nem.s.uCpuFeatures.u64, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()); 1188 1189 /* 1190 * Set up the partition and create EMTs. 1191 * 1192 * Seems like this is where the partition is actually instantiated and we get 1193 * a handle to it. 1194 */ 1195 hrc = WHvSetupPartition(hPartition); 1196 if (FAILED(hrc)) 1197 return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS, 1198 "Call to WHvSetupPartition failed: %Rhrc (Last=%#x/%u)", 1199 hrc, RTNtLastStatusValue(), RTNtLastErrorValue()); 1200 1201 /* Get the handle. */ 1202 HANDLE hPartitionDevice; 1203 __try 1204 { 1205 hPartitionDevice = ((HANDLE *)hPartition)[1]; 1206 } 1207 __except(EXCEPTION_EXECUTE_HANDLER) 1208 { 1209 hrc = GetExceptionCode(); 1210 hPartitionDevice = NULL; 1211 } 1212 if ( hPartitionDevice == NULL 1213 || hPartitionDevice == (HANDLE)(intptr_t)-1) 1214 return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS, 1215 "Failed to get device handle for partition %p: %Rhrc", hPartition, hrc); 1216 1217 HV_PARTITION_ID idHvPartition = HV_PARTITION_ID_INVALID; 1218 if (!g_pfnVidGetHvPartitionId(hPartitionDevice, &idHvPartition)) 1219 return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS, 1220 "Failed to get device handle and/or partition ID for %p (hPartitionDevice=%p, Last=%#x/%u)", 1221 hPartition, hPartitionDevice, RTNtLastStatusValue(), RTNtLastErrorValue()); 1222 pVM->nem.s.hPartitionDevice = hPartitionDevice; 1223 pVM->nem.s.idHvPartition = idHvPartition; 1224 1225 /* 1226 * Setup the EMTs. 1227 */ 1228 VMCPUID iCpu; 1229 for (iCpu = 0; iCpu < pVM->cCpus; iCpu++) 1230 { 1231 PVMCPU pVCpu = &pVM->aCpus[iCpu]; 1232 1233 pVCpu->nem.s.hNativeThreadHandle = (RTR3PTR)RTThreadGetNativeHandle(VMR3GetThreadHandle(pVCpu->pUVCpu)); 1234 Assert((HANDLE)pVCpu->nem.s.hNativeThreadHandle != INVALID_HANDLE_VALUE); 1235 1236 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API 1237 VID_MAPPED_MESSAGE_SLOT MappedMsgSlot = { NULL, UINT32_MAX, UINT32_MAX }; 1238 if (g_pfnVidMessageSlotMap(hPartitionDevice, &MappedMsgSlot, iCpu)) 1239 { 1240 AssertLogRelMsg(MappedMsgSlot.iCpu == iCpu && MappedMsgSlot.uParentAdvisory == UINT32_MAX, 1241 ("%#x %#x (iCpu=%#x)\n", MappedMsgSlot.iCpu, MappedMsgSlot.uParentAdvisory, iCpu)); 1242 pVCpu->nem.s.pvMsgSlotMapping = MappedMsgSlot.pMsgBlock; 1243 } 1244 else 1245 { 1246 NTSTATUS const rcNtLast = RTNtLastStatusValue(); 1247 DWORD const dwErrLast = RTNtLastErrorValue(); 1248 return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS, 1249 "Call to WHvSetupPartition failed: %Rhrc (Last=%#x/%u)", hrc, rcNtLast, dwErrLast); 1250 } 1251 #else 1252 hrc = WHvCreateVirtualProcessor(hPartition, iCpu, 0 /*fFlags*/); 1253 if (FAILED(hrc)) 1254 { 1255 NTSTATUS const rcNtLast = RTNtLastStatusValue(); 1256 DWORD const dwErrLast = RTNtLastErrorValue(); 1257 while (iCpu-- > 0) 1258 { 1259 HRESULT hrc2 = WHvDeleteVirtualProcessor(hPartition, iCpu); 1260 AssertLogRelMsg(SUCCEEDED(hrc2), ("WHvDeleteVirtualProcessor(%p, %u) -> %Rhrc (Last=%#x/%u)\n", 1261 hPartition, iCpu, hrc2, RTNtLastStatusValue(), 1262 RTNtLastErrorValue())); 1263 } 1264 return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS, 1265 "Call to WHvSetupPartition failed: %Rhrc (Last=%#x/%u)", hrc, rcNtLast, dwErrLast); 1266 } 1267 #endif /* !NEM_WIN_USE_OUR_OWN_RUN_API */ 1268 } 1269 pVM->nem.s.fCreatedEmts = true; 1270 1271 /* 1272 * Do some more ring-0 initialization now that we've got the partition handle. 1273 */ 1274 int rc = VMMR3CallR0Emt(pVM, &pVM->aCpus[0], VMMR0_DO_NEM_INIT_VM_PART_2, 0, NULL); 1275 if (RT_SUCCESS(rc)) 1276 { 1277 LogRel(("NEM: Successfully set up partition (device handle %p, partition ID %#llx)\n", hPartitionDevice, idHvPartition)); 1278 return VINF_SUCCESS; 1279 } 1280 return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS, "Call to NEMR0InitVMPart2 failed: %Rrc", rc); 1281 } 1282 1283 1284 int nemR3NativeInitCompleted(PVM pVM, VMINITCOMPLETED enmWhat) 1285 { 1286 NOREF(pVM); NOREF(enmWhat); 1287 return VINF_SUCCESS; 1288 } 1289 1290 1291 int nemR3NativeTerm(PVM pVM) 1292 { 1293 /* 1294 * Delete the partition. 1295 */ 1296 WHV_PARTITION_HANDLE hPartition = pVM->nem.s.hPartition; 1297 pVM->nem.s.hPartition = NULL; 1298 pVM->nem.s.hPartitionDevice = NULL; 1299 if (hPartition != NULL) 1300 { 1301 VMCPUID iCpu = pVM->nem.s.fCreatedEmts ? pVM->cCpus : 0; 1302 LogRel(("NEM: Destroying partition %p with its %u VCpus...\n", hPartition, iCpu)); 1303 while (iCpu-- > 0) 1304 { 1305 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API 1306 pVM->aCpus[iCpu].nem.s.pvMsgSlotMapping = NULL; 1307 #else 1308 HRESULT hrc = WHvDeleteVirtualProcessor(hPartition, iCpu); 1309 AssertLogRelMsg(SUCCEEDED(hrc), ("WHvDeleteVirtualProcessor(%p, %u) -> %Rhrc (Last=%#x/%u)\n", 1310 hPartition, iCpu, hrc, RTNtLastStatusValue(), 1311 RTNtLastErrorValue())); 1312 #endif 1313 } 1314 WHvDeletePartition(hPartition); 1315 } 1316 pVM->nem.s.fCreatedEmts = false; 1317 return VINF_SUCCESS; 1318 } 1319 1320 1321 /** 1322 * VM reset notification. 1323 * 1324 * @param pVM The cross context VM structure. 1325 */ 1326 void nemR3NativeReset(PVM pVM) 1327 { 1328 /* Unfix the A20 gate. */ 1329 pVM->nem.s.fA20Fixed = false; 1330 } 1331 1332 1333 /** 1334 * Reset CPU due to INIT IPI or hot (un)plugging. 1335 * 1336 * @param pVCpu The cross context virtual CPU structure of the CPU being 1337 * reset. 1338 * @param fInitIpi Whether this is the INIT IPI or hot (un)plugging case. 1339 */ 1340 void nemR3NativeResetCpu(PVMCPU pVCpu, bool fInitIpi) 1341 { 1342 /* Lock the A20 gate if INIT IPI, make sure it's enabled. */ 1343 if (fInitIpi && pVCpu->idCpu > 0) 1344 { 1345 PVM pVM = pVCpu->CTX_SUFF(pVM); 1346 if (!pVM->nem.s.fA20Enabled) 1347 nemR3NativeNotifySetA20(pVCpu, true); 1348 pVM->nem.s.fA20Enabled = true; 1349 pVM->nem.s.fA20Fixed = true; 1350 } 1351 } 29 NEM_TMPL_STATIC int nemHCNativeSetPhysPage(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhysSrc, RTGCPHYS GCPhysDst, 30 uint32_t fPageProt, uint8_t *pu2State, bool fBackingChanged); 31 1352 32 1353 33 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES … … 1364 44 * @param fFlags HV_MAP_GPA_XXX. 1365 45 */ 1366 DECLINLINE(int) nemR3WinHypercallMapPage(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhysSrc, RTGCPHYS GCPhysDst, uint32_t fFlags) 1367 { 46 DECLINLINE(int) nemHCWinHypercallMapPage(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhysSrc, RTGCPHYS GCPhysDst, uint32_t fFlags) 47 { 48 #ifdef IN_RING0 49 /** @todo optimize further, caller generally has the physical address. */ 50 PGVM pGVM = GVMMR0FastGetGVMByVM(pVM); 51 AssertReturn(pGVM, VERR_INVALID_VM_HANDLE); 52 return nemR0WinMapPages(pGVM, pVM, &pGVM->aCpus[pVCpu->idCpu], GCPhysSrc, GCPhysDst, 1, fFlags); 53 #else 1368 54 pVCpu->nem.s.Hypercall.MapPages.GCPhysSrc = GCPhysSrc & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK; 1369 55 pVCpu->nem.s.Hypercall.MapPages.GCPhysDst = GCPhysDst & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK; … … 1371 57 pVCpu->nem.s.Hypercall.MapPages.fFlags = fFlags; 1372 58 return VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_NEM_MAP_PAGES, 0, NULL); 59 #endif 1373 60 } 1374 61 … … 1382 69 * @param GCPhys The page to unmap. Does not need to be page aligned. 1383 70 */ 1384 DECLINLINE(int) nemR3WinHypercallUnmapPage(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys) 1385 { 71 DECLINLINE(int) nemHCWinHypercallUnmapPage(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys) 72 { 73 # ifdef IN_RING0 74 PGVM pGVM = GVMMR0FastGetGVMByVM(pVM); 75 AssertReturn(pGVM, VERR_INVALID_VM_HANDLE); 76 return nemR0WinUnmapPages(pGVM, &pGVM->aCpus[pVCpu->idCpu], GCPhys, 1); 77 # else 1386 78 pVCpu->nem.s.Hypercall.UnmapPages.GCPhys = GCPhys & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK; 1387 79 pVCpu->nem.s.Hypercall.UnmapPages.cPages = 1; 1388 80 return VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_NEM_UNMAP_PAGES, 0, NULL); 81 # endif 1389 82 } 1390 83 1391 84 #endif /* NEM_WIN_USE_HYPERCALLS_FOR_PAGES */ 1392 85 1393 static int nemR3WinCopyStateToHyperV(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx) 86 87 #ifndef IN_RING0 88 89 NEM_TMPL_STATIC int nemHCWinCopyStateToHyperV(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx) 1394 90 { 1395 91 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS … … 1692 388 } 1693 389 1694 static int nemR3WinCopyStateFromHyperV(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx) 390 391 NEM_TMPL_STATIC int nemHCWinCopyStateFromHyperV(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx) 1695 392 { 1696 393 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS … … 2070 767 * Get the virtual processor running status. 2071 768 */ 2072 DECLINLINE(VID_PROCESSOR_STATUS) nemR3WinCpuGetRunningStatus(PVMCPU pVCpu) 2073 { 769 DECLINLINE(VID_PROCESSOR_STATUS) nemHCWinCpuGetRunningStatus(PVMCPU pVCpu) 770 { 771 # ifdef IN_RING0 772 NOREF(pVCpu); 773 return VidProcessorStatusUndefined; 774 # else 2074 775 RTERRVARS Saved; 2075 776 RTErrVarsSave(&Saved); … … 2085 786 RTErrVarsRestore(&Saved); 2086 787 return enmCpuStatus; 788 # endif 2087 789 } 2088 790 #endif … … 2091 793 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API 2092 794 795 # ifdef IN_RING3 /* hopefully not needed in ring-0, as we'd need KTHREADs and KeAlertThread. */ 2093 796 /** 2094 797 * Our own WHvCancelRunVirtualProcessor that can later be moved to ring-0. … … 2101 804 * calling EMT. 2102 805 */ 2103 static int nemR3WinCancelRunVirtualProcessor(PVM pVM, PVMCPU pVCpu)806 NEM_TMPL_STATIC int nemHCWinCancelRunVirtualProcessor(PVM pVM, PVMCPU pVCpu) 2104 807 { 2105 808 /* … … 2118 821 if (VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM_CANCELED, VMCPUSTATE_STARTED_EXEC_NEM)) 2119 822 { 2120 Log8(("nem R3WinCancelRunVirtualProcessor: Switched %u to canceled state\n", pVCpu->idCpu));823 Log8(("nemHCWinCancelRunVirtualProcessor: Switched %u to canceled state\n", pVCpu->idCpu)); 2121 824 return VINF_SUCCESS; 2122 825 } … … 2126 829 if (VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM_CANCELED, VMCPUSTATE_STARTED_EXEC_NEM_WAIT)) 2127 830 { 831 # ifdef IN_RING0 832 NTSTATUS rcNt = KeAlertThread(??); 833 # else 2128 834 NTSTATUS rcNt = NtAlertThread(pVCpu->nem.s.hNativeThreadHandle); 2129 Log8(("nemR3WinCancelRunVirtualProcessor: Alerted %u: %#x\n", pVCpu->idCpu, rcNt)); 835 # endif 836 Log8(("nemHCWinCancelRunVirtualProcessor: Alerted %u: %#x\n", pVCpu->idCpu, rcNt)); 2130 837 Assert(rcNt == STATUS_SUCCESS); 2131 838 if (NT_SUCCESS(rcNt)) … … 2143 850 } 2144 851 } 852 # endif /* IN_RING3 */ 2145 853 2146 854 … … 2148 856 * Fills in WHV_VP_EXIT_CONTEXT from HV_X64_INTERCEPT_MESSAGE_HEADER. 2149 857 */ 2150 DECLINLINE(void) nem R3WinConvertX64MsgHdrToVpExitCtx(HV_X64_INTERCEPT_MESSAGE_HEADER const *pHdr, WHV_VP_EXIT_CONTEXT *pCtx)858 DECLINLINE(void) nemHCWinConvertX64MsgHdrToVpExitCtx(HV_X64_INTERCEPT_MESSAGE_HEADER const *pHdr, WHV_VP_EXIT_CONTEXT *pCtx) 2151 859 { 2152 860 pCtx->ExecutionState.AsUINT16 = pHdr->ExecutionState.AsUINT16; … … 2168 876 * @param pExitCtx The output structure. Assumes zeroed. 2169 877 */ 2170 static int nemR3WinRunVirtualProcessorConvertPending(HV_MESSAGE_HEADER const *pMsgHdr, WHV_RUN_VP_EXIT_CONTEXT *pExitCtx)878 NEM_TMPL_STATIC int nemHCWinRunVirtualProcessorConvertPending(HV_MESSAGE_HEADER const *pMsgHdr, WHV_RUN_VP_EXIT_CONTEXT *pExitCtx) 2171 879 { 2172 880 switch (pMsgHdr->MessageType) … … 2179 887 2180 888 pExitCtx->ExitReason = WHvRunVpExitReasonMemoryAccess; 2181 nem R3WinConvertX64MsgHdrToVpExitCtx(&pMemMsg->Header, &pExitCtx->MemoryAccess.VpContext);889 nemHCWinConvertX64MsgHdrToVpExitCtx(&pMemMsg->Header, &pExitCtx->MemoryAccess.VpContext); 2182 890 pExitCtx->MemoryAccess.InstructionByteCount = pMemMsg->InstructionByteCount; 2183 891 ((uint64_t *)pExitCtx->MemoryAccess.InstructionBytes)[0] = ((uint64_t const *)pMemMsg->InstructionBytes)[0]; … … 2199 907 2200 908 pExitCtx->ExitReason = WHvRunVpExitReasonX64IoPortAccess; 2201 nem R3WinConvertX64MsgHdrToVpExitCtx(&pPioMsg->Header, &pExitCtx->IoPortAccess.VpContext);909 nemHCWinConvertX64MsgHdrToVpExitCtx(&pPioMsg->Header, &pExitCtx->IoPortAccess.VpContext); 2202 910 pExitCtx->IoPortAccess.InstructionByteCount = pPioMsg->InstructionByteCount; 2203 911 ((uint64_t *)pExitCtx->IoPortAccess.InstructionBytes)[0] = ((uint64_t const *)pPioMsg->InstructionBytes)[0]; … … 2272 980 * @param cbExitCtx Size of the exit information area. 2273 981 */ 2274 static int nemR3WinRunVirtualProcessor(PVM pVM, PVMCPU pVCpu, WHV_RUN_VP_EXIT_CONTEXT *pExitCtx, size_t cbExitCtx)982 NEM_TMPL_STATIC int nemHCWinRunVirtualProcessor(PVM pVM, PVMCPU pVCpu, WHV_RUN_VP_EXIT_CONTEXT *pExitCtx, size_t cbExitCtx) 2275 983 { 2276 984 RT_BZERO(pExitCtx, cbExitCtx); … … 2288 996 Assert(pMappingHeader->enmVidMsgType == VidMessageHypervisorMessage); 2289 997 fHandleAndGetFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE | VID_MSHAGN_F_HANDLE_MESSAGE; 2290 Log8(("nem R3WinRunVirtualProcessor: #1: msg pending, no need to start CPU (cpu state %u)\n", nemR3WinCpuGetRunningStatus(pVCpu) ));998 Log8(("nemHCWinRunVirtualProcessor: #1: msg pending, no need to start CPU (cpu state %u)\n", nemHCWinCpuGetRunningStatus(pVCpu) )); 2291 999 } 2292 1000 else if (bMsgState != NEM_WIN_MSG_STATE_STARTED) … … 2294 1002 if (bMsgState == NEM_WIN_MSG_STATE_PENDING_STOP_AND_MSG) 2295 1003 { 2296 Log8(("nem R3WinRunVirtualProcessor: #0: pending stop+message (cpu status %u)\n", nemR3WinCpuGetRunningStatus(pVCpu) ));1004 Log8(("nemHCWinRunVirtualProcessor: #0: pending stop+message (cpu status %u)\n", nemHCWinCpuGetRunningStatus(pVCpu) )); 2297 1005 /* ACK the pending message and get the stop message. */ 2298 1006 BOOL fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu, … … 2308 1016 } 2309 1017 2310 Log8(("nem R3WinRunVirtualProcessor: #1: starting CPU (cpu status %u)\n", nemR3WinCpuGetRunningStatus(pVCpu) ));1018 Log8(("nemHCWinRunVirtualProcessor: #1: starting CPU (cpu status %u)\n", nemHCWinCpuGetRunningStatus(pVCpu) )); 2311 1019 if (g_pfnVidStartVirtualProcessor(pVM->nem.s.hPartitionDevice, pVCpu->idCpu)) 2312 1020 pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_STARTED; … … 2324 1032 /* This shouldn't happen. */ 2325 1033 fHandleAndGetFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE; 2326 Log8(("nem R3WinRunVirtualProcessor: #1: NO MSG PENDING! No need to start CPU (cpu state %u)\n", nemR3WinCpuGetRunningStatus(pVCpu) ));1034 Log8(("nemHCWinRunVirtualProcessor: #1: NO MSG PENDING! No need to start CPU (cpu state %u)\n", nemHCWinCpuGetRunningStatus(pVCpu) )); 2327 1035 } 2328 1036 } 2329 1037 else 2330 1038 { 2331 Log8(("nem R3WinRunVirtualProcessor: #1: state=%u -> canceled (cpu status %u)\n",2332 VMCPU_GET_STATE(pVCpu), nem R3WinCpuGetRunningStatus(pVCpu)));1039 Log8(("nemHCWinRunVirtualProcessor: #1: state=%u -> canceled (cpu status %u)\n", 1040 VMCPU_GET_STATE(pVCpu), nemHCWinCpuGetRunningStatus(pVCpu))); 2333 1041 pExitCtx->ExitReason = WHvRunVpExitReasonCanceled; 2334 1042 return VINF_SUCCESS; … … 2343 1051 if (VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM_WAIT, VMCPUSTATE_STARTED_EXEC_NEM)) 2344 1052 { 2345 Log8(("nem R3WinRunVirtualProcessor: #2: Waiting %#x (cpu status %u)...\n",2346 fHandleAndGetFlags, nem R3WinCpuGetRunningStatus(pVCpu)));1053 Log8(("nemHCWinRunVirtualProcessor: #2: Waiting %#x (cpu status %u)...\n", 1054 fHandleAndGetFlags, nemHCWinCpuGetRunningStatus(pVCpu))); 2347 1055 BOOL fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu, 2348 1056 fHandleAndGetFlags, cMillies); … … 2356 1064 if (!VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM_WAIT)) 2357 1065 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM_CANCELED); 2358 Log8(("nem R3WinRunVirtualProcessor: #3: wait succeeded: %#x / %#x (cpu status %u)\n",1066 Log8(("nemHCWinRunVirtualProcessor: #3: wait succeeded: %#x / %#x (cpu status %u)\n", 2359 1067 enmVidMsgType, ((HV_MESSAGE_HEADER const *)(pMappingHeader + 1))->MessageType, 2360 nem R3WinCpuGetRunningStatus(pVCpu) ));1068 nemHCWinCpuGetRunningStatus(pVCpu) )); 2361 1069 pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_PENDING_MSG; 2362 return nem R3WinRunVirtualProcessorConvertPending((HV_MESSAGE_HEADER const *)(pMappingHeader + 1), pExitCtx);1070 return nemHCWinRunVirtualProcessorConvertPending((HV_MESSAGE_HEADER const *)(pMappingHeader + 1), pExitCtx); 2363 1071 } 2364 1072 … … 2368 1076 __debugbreak(); 2369 1077 #endif 2370 Log8(("nem R3WinRunVirtualProcessor: #3: wait succeeded, but nothing pending: %#x / %#x (cpu status %u)\n",2371 enmVidMsgType, ((HV_MESSAGE_HEADER const *)(pMappingHeader + 1))->MessageType, nem R3WinCpuGetRunningStatus(pVCpu) ));1078 Log8(("nemHCWinRunVirtualProcessor: #3: wait succeeded, but nothing pending: %#x / %#x (cpu status %u)\n", 1079 enmVidMsgType, ((HV_MESSAGE_HEADER const *)(pMappingHeader + 1))->MessageType, nemHCWinCpuGetRunningStatus(pVCpu) )); 2372 1080 pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_STARTED; 2373 1081 AssertLogRelMsgReturnStmt(enmVidMsgType == VidMessageStopRequestComplete, … … 2385 1093 AssertLogRelMsgReturnStmt( dwErr == STATUS_TIMEOUT 2386 1094 || dwErr == STATUS_ALERTED || dwErr == STATUS_USER_APC, /* just in case */ 2387 ("dwErr=%u (%#x) (cpu status %u)\n", dwErr, dwErr, nem R3WinCpuGetRunningStatus(pVCpu)),1095 ("dwErr=%u (%#x) (cpu status %u)\n", dwErr, dwErr, nemHCWinCpuGetRunningStatus(pVCpu)), 2388 1096 g_pfnVidStopVirtualProcessor(pVM->nem.s.hPartitionDevice, pVCpu->idCpu), 2389 1097 VERR_INTERNAL_ERROR_3); 2390 Log8(("nem R3WinRunVirtualProcessor: #3: wait timed out (cpu status %u)\n", nemR3WinCpuGetRunningStatus(pVCpu) ));1098 Log8(("nemHCWinRunVirtualProcessor: #3: wait timed out (cpu status %u)\n", nemHCWinCpuGetRunningStatus(pVCpu) )); 2391 1099 pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_STARTED; 2392 1100 fHandleAndGetFlags &= ~VID_MSHAGN_F_HANDLE_MESSAGE; … … 2401 1109 * return, and that can be a bit complicated. 2402 1110 */ 2403 Log8(("nem R3WinRunVirtualProcessor: #4: state changed to %u (cpu status %u)\n",2404 VMCPU_GET_STATE(pVCpu), nem R3WinCpuGetRunningStatus(pVCpu) ));1111 Log8(("nemHCWinRunVirtualProcessor: #4: state changed to %u (cpu status %u)\n", 1112 VMCPU_GET_STATE(pVCpu), nemHCWinCpuGetRunningStatus(pVCpu) )); 2405 1113 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM_CANCELED); 2406 1114 … … 2409 1117 if (fHandleAndGetFlags & VID_MSHAGN_F_HANDLE_MESSAGE) 2410 1118 { 2411 Log8(("nem R3WinRunVirtualProcessor: #5: Didn't resume previous message.\n"));1119 Log8(("nemHCWinRunVirtualProcessor: #5: Didn't resume previous message.\n")); 2412 1120 pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_PENDING_MSG; 2413 1121 pExitCtx->ExitReason = WHvRunVpExitReasonCanceled; … … 2419 1127 if (fStop) 2420 1128 { 2421 Log8(("nem R3WinRunVirtualProcessor: #5: Stopping CPU succeeded (cpu status %u)\n", nemR3WinCpuGetRunningStatus(pVCpu) ));1129 Log8(("nemHCWinRunVirtualProcessor: #5: Stopping CPU succeeded (cpu status %u)\n", nemHCWinCpuGetRunningStatus(pVCpu) )); 2422 1130 pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_STOPPED; 2423 1131 pExitCtx->ExitReason = WHvRunVpExitReasonCanceled; … … 2427 1135 /* Dang, the CPU stopped by itself with a message pending. */ 2428 1136 DWORD dwErr = RTNtLastErrorValue(); 2429 Log8(("nem R3WinRunVirtualProcessor: #5: Stopping CPU failed (%u/%#x) - cpu status %u\n",2430 dwErr, dwErr, nem R3WinCpuGetRunningStatus(pVCpu) ));1137 Log8(("nemHCWinRunVirtualProcessor: #5: Stopping CPU failed (%u/%#x) - cpu status %u\n", 1138 dwErr, dwErr, nemHCWinCpuGetRunningStatus(pVCpu) )); 2431 1139 pExitCtx->ExitReason = WHvRunVpExitReasonCanceled; 2432 1140 AssertLogRelMsgReturn(dwErr == ERROR_VID_STOP_PENDING, ("dwErr=%#u\n", dwErr), VERR_INTERNAL_ERROR_3); … … 2440 1148 if (enmVidMsgType == VidMessageHypervisorMessage) 2441 1149 { 2442 Log8(("nem R3WinRunVirtualProcessor: #6: wait succeeded: %#x / %#x (cpu status %u)\n", enmVidMsgType,2443 ((HV_MESSAGE_HEADER const *)(pMappingHeader + 1))->MessageType, nem R3WinCpuGetRunningStatus(pVCpu) ));1150 Log8(("nemHCWinRunVirtualProcessor: #6: wait succeeded: %#x / %#x (cpu status %u)\n", enmVidMsgType, 1151 ((HV_MESSAGE_HEADER const *)(pMappingHeader + 1))->MessageType, nemHCWinCpuGetRunningStatus(pVCpu) )); 2444 1152 pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_PENDING_STOP_AND_MSG; 2445 return nem R3WinRunVirtualProcessorConvertPending((HV_MESSAGE_HEADER const *)(pMappingHeader + 1), pExitCtx);1153 return nemHCWinRunVirtualProcessorConvertPending((HV_MESSAGE_HEADER const *)(pMappingHeader + 1), pExitCtx); 2446 1154 } 2447 1155 2448 1156 /* ACK the stop message, if that's what it is. Don't think we'll ever get here. */ 2449 Log8(("nem R3WinRunVirtualProcessor: #6b: wait succeeded: %#x / %#x (cpu status %u)\n", enmVidMsgType,2450 ((HV_MESSAGE_HEADER const *)(pMappingHeader + 1))->MessageType, nem R3WinCpuGetRunningStatus(pVCpu) ));1157 Log8(("nemHCWinRunVirtualProcessor: #6b: wait succeeded: %#x / %#x (cpu status %u)\n", enmVidMsgType, 1158 ((HV_MESSAGE_HEADER const *)(pMappingHeader + 1))->MessageType, nemHCWinCpuGetRunningStatus(pVCpu) )); 2451 1159 AssertLogRelMsgReturn(enmVidMsgType == VidMessageStopRequestComplete, ("enmVidMsgType=%#x\n", enmVidMsgType), 2452 1160 VERR_INTERNAL_ERROR_3); … … 2467 1175 2468 1176 #ifdef LOG_ENABLED 2469 2470 /**2471 * Log the full details of an exit reason.2472 *2473 * @param pExitReason The exit reason to log.2474 */2475 static void nemR3WinLogExitReason(WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)2476 {2477 bool fExitCtx = false;2478 bool fExitInstr = false;2479 switch (pExitReason->ExitReason)2480 {2481 case WHvRunVpExitReasonMemoryAccess:2482 Log2(("Exit: Memory access: GCPhys=%RGp GCVirt=%RGv %s %s %s\n",2483 pExitReason->MemoryAccess.Gpa, pExitReason->MemoryAccess.Gva,2484 g_apszWHvMemAccesstypes[pExitReason->MemoryAccess.AccessInfo.AccessType],2485 pExitReason->MemoryAccess.AccessInfo.GpaUnmapped ? "unmapped" : "mapped",2486 pExitReason->MemoryAccess.AccessInfo.GvaValid ? "" : "invalid-gc-virt"));2487 AssertMsg(!(pExitReason->MemoryAccess.AccessInfo.AsUINT32 & ~UINT32_C(0xf)),2488 ("MemoryAccess.AccessInfo=%#x\n", pExitReason->MemoryAccess.AccessInfo.AsUINT32));2489 fExitCtx = fExitInstr = true;2490 break;2491 2492 case WHvRunVpExitReasonX64IoPortAccess:2493 Log2(("Exit: I/O port access: IoPort=%#x LB %u %s%s%s rax=%#RX64 rcx=%#RX64 rsi=%#RX64 rdi=%#RX64\n",2494 pExitReason->IoPortAccess.PortNumber,2495 pExitReason->IoPortAccess.AccessInfo.AccessSize,2496 pExitReason->IoPortAccess.AccessInfo.IsWrite ? "out" : "in",2497 pExitReason->IoPortAccess.AccessInfo.StringOp ? " string" : "",2498 pExitReason->IoPortAccess.AccessInfo.RepPrefix ? " rep" : "",2499 pExitReason->IoPortAccess.Rax,2500 pExitReason->IoPortAccess.Rcx,2501 pExitReason->IoPortAccess.Rsi,2502 pExitReason->IoPortAccess.Rdi));2503 Log2(("Exit: + ds=%#x:{%#RX64 LB %#RX32, %#x} es=%#x:{%#RX64 LB %#RX32, %#x}\n",2504 pExitReason->IoPortAccess.Ds.Selector,2505 pExitReason->IoPortAccess.Ds.Base,2506 pExitReason->IoPortAccess.Ds.Limit,2507 pExitReason->IoPortAccess.Ds.Attributes,2508 pExitReason->IoPortAccess.Es.Selector,2509 pExitReason->IoPortAccess.Es.Base,2510 pExitReason->IoPortAccess.Es.Limit,2511 pExitReason->IoPortAccess.Es.Attributes ));2512 2513 AssertMsg( pExitReason->IoPortAccess.AccessInfo.AccessSize == 12514 || pExitReason->IoPortAccess.AccessInfo.AccessSize == 22515 || pExitReason->IoPortAccess.AccessInfo.AccessSize == 4,2516 ("IoPortAccess.AccessInfo.AccessSize=%d\n", pExitReason->IoPortAccess.AccessInfo.AccessSize));2517 AssertMsg(!(pExitReason->IoPortAccess.AccessInfo.AsUINT32 & ~UINT32_C(0x3f)),2518 ("IoPortAccess.AccessInfo=%#x\n", pExitReason->IoPortAccess.AccessInfo.AsUINT32));2519 fExitCtx = fExitInstr = true;2520 break;2521 2522 # if 02523 case WHvRunVpExitReasonUnrecoverableException:2524 case WHvRunVpExitReasonInvalidVpRegisterValue:2525 case WHvRunVpExitReasonUnsupportedFeature:2526 case WHvRunVpExitReasonX64InterruptWindow:2527 case WHvRunVpExitReasonX64Halt:2528 case WHvRunVpExitReasonX64MsrAccess:2529 case WHvRunVpExitReasonX64Cpuid:2530 case WHvRunVpExitReasonException:2531 case WHvRunVpExitReasonCanceled:2532 case WHvRunVpExitReasonAlerted:2533 WHV_X64_MSR_ACCESS_CONTEXT MsrAccess;2534 WHV_X64_CPUID_ACCESS_CONTEXT CpuidAccess;2535 WHV_VP_EXCEPTION_CONTEXT VpException;2536 WHV_X64_INTERRUPTION_DELIVERABLE_CONTEXT InterruptWindow;2537 WHV_UNRECOVERABLE_EXCEPTION_CONTEXT UnrecoverableException;2538 WHV_X64_UNSUPPORTED_FEATURE_CONTEXT UnsupportedFeature;2539 WHV_RUN_VP_CANCELED_CONTEXT CancelReason;2540 #endif2541 2542 case WHvRunVpExitReasonNone:2543 Log2(("Exit: No reason\n"));2544 AssertFailed();2545 break;2546 2547 default:2548 Log(("Exit: %#x\n", pExitReason->ExitReason));2549 break;2550 }2551 2552 /*2553 * Context and maybe instruction details.2554 */2555 if (fExitCtx)2556 {2557 const WHV_VP_EXIT_CONTEXT *pVpCtx = &pExitReason->IoPortAccess.VpContext;2558 Log2(("Exit: + CS:RIP=%04x:%08RX64 RFLAGS=%06RX64 cbInstr=%u CS={%RX64 L %#RX32, %#x}\n",2559 pVpCtx->Cs.Selector,2560 pVpCtx->Rip,2561 pVpCtx->Rflags,2562 pVpCtx->InstructionLength,2563 pVpCtx->Cs.Base, pVpCtx->Cs.Limit, pVpCtx->Cs.Attributes));2564 Log2(("Exit: + cpl=%d CR0.PE=%d CR0.AM=%d EFER.LMA=%d DebugActive=%d InterruptionPending=%d InterruptShadow=%d\n",2565 pVpCtx->ExecutionState.Cpl,2566 pVpCtx->ExecutionState.Cr0Pe,2567 pVpCtx->ExecutionState.Cr0Am,2568 pVpCtx->ExecutionState.EferLma,2569 pVpCtx->ExecutionState.DebugActive,2570 pVpCtx->ExecutionState.InterruptionPending,2571 pVpCtx->ExecutionState.InterruptShadow));2572 AssertMsg(!(pVpCtx->ExecutionState.AsUINT16 & ~UINT16_C(0x107f)),2573 ("ExecutionState.AsUINT16=%#x\n", pVpCtx->ExecutionState.AsUINT16));2574 2575 /** @todo Someone at Microsoft please explain why the InstructionBytes fields2576 * are 16 bytes long, when 15 would've been sufficent and saved 3-7 bytes of2577 * alignment padding? Intel max length is 15, so is this sSome ARM stuff?2578 * Aren't ARM2579 * instructions max 32-bit wide? Confused. */2580 if (fExitInstr && pExitReason->IoPortAccess.InstructionByteCount > 0)2581 Log2(("Exit: + Instruction %.*Rhxs\n",2582 pExitReason->IoPortAccess.InstructionByteCount, pExitReason->IoPortAccess.InstructionBytes));2583 }2584 }2585 2586 2587 1177 /** 2588 1178 * Logs the current CPU state. 2589 1179 */ 2590 static void nemR3WinLogState(PVM pVM, PVMCPU pVCpu)1180 NEM_TMPL_STATIC void nemHCWinLogState(PVM pVM, PVMCPU pVCpu) 2591 1181 { 2592 1182 if (LogIs3Enabled()) 2593 1183 { 1184 # ifdef IN_RING3 2594 1185 char szRegs[4096]; 2595 1186 DBGFR3RegPrintf(pVM->pUVM, pVCpu->idCpu, &szRegs[0], sizeof(szRegs), … … 2625 1216 szInstr, sizeof(szInstr), NULL); 2626 1217 Log3(("%s%s\n", szRegs, szInstr)); 2627 } 2628 } 2629 1218 # else 1219 /** @todo stat logging in ring-0 */ 1220 RT_NOREF(pVM, pVCpu); 1221 # endif 1222 } 1223 } 2630 1224 #endif /* LOG_ENABLED */ 2631 1225 … … 2640 1234 * @param pExitCtx The exit context. 2641 1235 */ 2642 DECLINLINE(void) nem R3WinAdvanceGuestRipAndClearRF(PVMCPU pVCpu, PCPUMCTX pCtx, WHV_VP_EXIT_CONTEXT const *pExitCtx)1236 DECLINLINE(void) nemHCWinAdvanceGuestRipAndClearRF(PVMCPU pVCpu, PCPUMCTX pCtx, WHV_VP_EXIT_CONTEXT const *pExitCtx) 2643 1237 { 2644 1238 /* Advance the RIP. */ … … 2655 1249 2656 1250 2657 static VBOXSTRICTRC nemR3WinHandleHalt(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx) 1251 NEM_TMPL_STATIC VBOXSTRICTRC 1252 nemHCWinHandleHalt(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx) 2658 1253 { 2659 1254 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); 2660 LogFlow(("nem R3WinHandleHalt\n"));1255 LogFlow(("nemHCWinHandleHalt\n")); 2661 1256 return VINF_EM_HALT; 2662 1257 } 2663 1258 2664 1259 2665 static DECLCALLBACK(int) nemR3WinUnmapOnePageCallback(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, uint8_t *pu2NemState, void *pvUser) 1260 NEM_TMPL_STATIC DECLCALLBACK(int) 1261 nemHCWinUnmapOnePageCallback(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, uint8_t *pu2NemState, void *pvUser) 2666 1262 { 2667 1263 RT_NOREF_PV(pvUser); 2668 1264 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES 2669 int rc = nem R3WinHypercallUnmapPage(pVM, pVCpu, GCPhys);1265 int rc = nemHCWinHypercallUnmapPage(pVM, pVCpu, GCPhys); 2670 1266 AssertRC(rc); 2671 1267 if (RT_SUCCESS(rc)) … … 2697 1293 2698 1294 /** 2699 * State to pass between nemR3WinHandleMemoryAccess and2700 * nemR3WinHandleMemoryAccessPageCheckerCallback.1295 * State to pass between nemHCWinHandleMemoryAccess / nemR3WinWHvHandleMemoryAccess 1296 * and nemHCWinHandleMemoryAccessPageCheckerCallback. 2701 1297 */ 2702 typedef struct NEM R3WINHMACPCCSTATE1298 typedef struct NEMHCWINHMACPCCSTATE 2703 1299 { 2704 1300 /** Input: Write access. */ … … 2708 1304 /** Output: Set it we should resume. */ 2709 1305 bool fCanResume; 2710 } NEM R3WINHMACPCCSTATE;1306 } NEMHCWINHMACPCCSTATE; 2711 1307 2712 1308 /** 2713 1309 * @callback_method_impl{FNPGMPHYSNEMCHECKPAGE, 2714 1310 * Worker for nemR3WinHandleMemoryAccess; pvUser points to a 2715 * NEM R3WINHMACPCCSTATE structure. }1311 * NEMHCWINHMACPCCSTATE structure. } 2716 1312 */ 2717 static DECLCALLBACK(int) nemR3WinHandleMemoryAccessPageCheckerCallback(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, 2718 2719 { 2720 NEM R3WINHMACPCCSTATE *pState = (NEMR3WINHMACPCCSTATE *)pvUser;1313 NEM_TMPL_STATIC DECLCALLBACK(int) 1314 nemHCWinHandleMemoryAccessPageCheckerCallback(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, PPGMPHYSNEMPAGEINFO pInfo, void *pvUser) 1315 { 1316 NEMHCWINHMACPCCSTATE *pState = (NEMHCWINHMACPCCSTATE *)pvUser; 2721 1317 pState->fDidSomething = false; 2722 1318 pState->fCanResume = false; … … 2761 1357 if (pInfo->fNemProt == NEM_PAGE_PROT_NONE) 2762 1358 { 2763 Log4(("nem R3WinHandleMemoryAccessPageCheckerCallback: %RGp - #1\n", GCPhys));1359 Log4(("nemHCWinHandleMemoryAccessPageCheckerCallback: %RGp - #1\n", GCPhys)); 2764 1360 return VINF_SUCCESS; 2765 1361 } … … 2769 1365 && !(pInfo->fNemProt & NEM_PAGE_PROT_WRITE)) 2770 1366 { 2771 Log4(("nem R3WinHandleMemoryAccessPageCheckerCallback: %RGp - #1w\n", GCPhys));1367 Log4(("nemHCWinHandleMemoryAccessPageCheckerCallback: %RGp - #1w\n", GCPhys)); 2772 1368 return VINF_SUCCESS; 2773 1369 } 2774 1370 2775 1371 /* Map the page. */ 2776 rc = nem R3NativeSetPhysPage(pVM,1372 rc = nemHCNativeSetPhysPage(pVM, 2777 1373 pVCpu, 2778 1374 GCPhysSrc & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK, … … 2782 1378 true /*fBackingState*/); 2783 1379 pInfo->u2NemState = u2State; 2784 Log4(("nem R3WinHandleMemoryAccessPageCheckerCallback: %RGp - synced => %s + %Rrc\n",1380 Log4(("nemHCWinHandleMemoryAccessPageCheckerCallback: %RGp - synced => %s + %Rrc\n", 2785 1381 GCPhys, g_apszPageStates[u2State], rc)); 2786 1382 pState->fDidSomething = true; … … 2792 1388 && (pInfo->fNemProt & (NEM_PAGE_PROT_READ | NEM_PAGE_PROT_EXECUTE))) 2793 1389 { 2794 Log4(("nem R3WinHandleMemoryAccessPageCheckerCallback: %RGp - #2\n", GCPhys));1390 Log4(("nemHCWinHandleMemoryAccessPageCheckerCallback: %RGp - #2\n", GCPhys)); 2795 1391 return VINF_SUCCESS; 2796 1392 } … … 2802 1398 && pState->fWriteAccess) 2803 1399 { 2804 rc = nem R3WinHypercallMapPage(pVM, pVCpu, GCPhysSrc, GCPhys,1400 rc = nemHCWinHypercallMapPage(pVM, pVCpu, GCPhysSrc, GCPhys, 2805 1401 HV_MAP_GPA_READABLE | HV_MAP_GPA_WRITABLE 2806 1402 | HV_MAP_GPA_EXECUTABLE | HV_MAP_GPA_EXECUTABLE_AGAIN); … … 2829 1425 if (pInfo->fNemProt & NEM_PAGE_PROT_WRITE) 2830 1426 { 2831 Log4(("nem R3WinHandleMemoryAccessPageCheckerCallback: %RGp - #3\n", GCPhys));1427 Log4(("nemHCWinHandleMemoryAccessPageCheckerCallback: %RGp - #3\n", GCPhys)); 2832 1428 return VINF_SUCCESS; 2833 1429 } … … 2846 1442 */ 2847 1443 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES 2848 rc = nem R3WinHypercallUnmapPage(pVM, pVCpu, GCPhys);1444 rc = nemHCWinHypercallUnmapPage(pVM, pVCpu, GCPhys); 2849 1445 AssertRC(rc); 2850 1446 if (RT_SUCCESS(rc)) … … 2863 1459 } 2864 1460 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES 2865 LogRel(("nem R3WinHandleMemoryAccessPageCheckerCallback/unmap: GCPhysDst=%RGp rc=%Rrc\n", GCPhys, rc));1461 LogRel(("nemHCWinHandleMemoryAccessPageCheckerCallback/unmap: GCPhysDst=%RGp rc=%Rrc\n", GCPhys, rc)); 2866 1462 return rc; 2867 1463 #else 2868 LogRel(("nem R3WinHandleMemoryAccessPageCheckerCallback/unmap: GCPhysDst=%RGp %s hrc=%Rhrc (%#x) Last=%#x/%u (cMappedPages=%u)\n",1464 LogRel(("nemHCWinHandleMemoryAccessPageCheckerCallback/unmap: GCPhysDst=%RGp %s hrc=%Rhrc (%#x) Last=%#x/%u (cMappedPages=%u)\n", 2869 1465 GCPhys, g_apszPageStates[u2State], hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue(), 2870 1466 pVM->nem.s.cMappedPages)); 2871 1467 2872 1468 PGMPhysNemEnumPagesByState(pVM, pVCpu, NEM_WIN_PAGE_STATE_READABLE, nemR3WinUnmapOnePageCallback, NULL); 2873 Log(("nem R3WinHandleMemoryAccessPageCheckerCallback: Unmapped all (cMappedPages=%u)\n", pVM->nem.s.cMappedPages));1469 Log(("nemHCWinHandleMemoryAccessPageCheckerCallback: Unmapped all (cMappedPages=%u)\n", pVM->nem.s.cMappedPages)); 2874 1470 2875 1471 pState->fDidSomething = true; … … 2881 1477 2882 1478 2883 /** 2884 * Handles an memory access VMEXIT. 2885 * 2886 * This can be triggered by a number of things. 2887 * 2888 * @returns Strict VBox status code. 2889 * @param pVM The cross context VM structure. 2890 * @param pVCpu The cross context virtual CPU structure. 2891 * @param pCtx The CPU context to update. 2892 * @param pMemCtx The exit reason information. 2893 */ 2894 static VBOXSTRICTRC nemR3WinHandleMemoryAccess(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_MEMORY_ACCESS_CONTEXT const *pMemCtx) 2895 { 2896 /* 2897 * Ask PGM for information about the given GCPhys. We need to check if we're 2898 * out of sync first. 2899 */ 2900 NEMR3WINHMACPCCSTATE State = { pMemCtx->AccessInfo.AccessType == WHvMemoryAccessWrite, false, false }; 2901 PGMPHYSNEMPAGEINFO Info; 2902 int rc = PGMPhysNemPageInfoChecker(pVM, pVCpu, pMemCtx->Gpa, State.fWriteAccess, &Info, 2903 nemR3WinHandleMemoryAccessPageCheckerCallback, &State); 2904 if (RT_SUCCESS(rc)) 2905 { 2906 if (Info.fNemProt & (pMemCtx->AccessInfo.AccessType == WHvMemoryAccessWrite ? NEM_PAGE_PROT_WRITE : NEM_PAGE_PROT_READ)) 2907 { 2908 if (State.fCanResume) 2909 { 2910 Log4(("MemExit: %RGp (=>%RHp) %s fProt=%u%s%s%s; restarting (%s)\n", 2911 pMemCtx->Gpa, Info.HCPhys, g_apszPageStates[Info.u2NemState], Info.fNemProt, 2912 Info.fHasHandlers ? " handlers" : "", Info.fZeroPage ? " zero-pg" : "", 2913 State.fDidSomething ? "" : " no-change", g_apszWHvMemAccesstypes[pMemCtx->AccessInfo.AccessType])); 2914 return VINF_SUCCESS; 2915 } 2916 } 2917 Log4(("MemExit: %RGp (=>%RHp) %s fProt=%u%s%s%s; emulating (%s)\n", 2918 pMemCtx->Gpa, Info.HCPhys, g_apszPageStates[Info.u2NemState], Info.fNemProt, 2919 Info.fHasHandlers ? " handlers" : "", Info.fZeroPage ? " zero-pg" : "", 2920 State.fDidSomething ? "" : " no-change", g_apszWHvMemAccesstypes[pMemCtx->AccessInfo.AccessType])); 2921 } 2922 else 2923 Log4(("MemExit: %RGp rc=%Rrc%s; emulating (%s)\n", pMemCtx->Gpa, rc, 2924 State.fDidSomething ? " modified-backing" : "", g_apszWHvMemAccesstypes[pMemCtx->AccessInfo.AccessType])); 2925 2926 /* 2927 * Emulate the memory access, either access handler or special memory. 2928 */ 2929 VBOXSTRICTRC rcStrict; 2930 if (pMemCtx->InstructionByteCount > 0) 2931 rcStrict = IEMExecOneWithPrefetchedByPC(pVCpu, CPUMCTX2CORE(pCtx), pMemCtx->VpContext.Rip, 2932 pMemCtx->InstructionBytes, pMemCtx->InstructionByteCount); 2933 else 2934 rcStrict = IEMExecOne(pVCpu); 2935 /** @todo do we need to do anything wrt debugging here? */ 2936 return rcStrict; 2937 } 2938 2939 2940 /** 2941 * Handles an I/O port access VMEXIT. 2942 * 2943 * We ASSUME that the hypervisor has don't I/O port access control. 2944 * 2945 * @returns Strict VBox status code. 2946 * @param pVM The cross context VM structure. 2947 * @param pVCpu The cross context virtual CPU structure. 2948 * @param pCtx The CPU context to update. 2949 * @param pIoPortCtx The exit reason information. 2950 */ 2951 static VBOXSTRICTRC nemR3WinHandleIoPortAccess(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, 2952 WHV_X64_IO_PORT_ACCESS_CONTEXT const *pIoPortCtx) 2953 { 2954 Assert( pIoPortCtx->AccessInfo.AccessSize == 1 2955 || pIoPortCtx->AccessInfo.AccessSize == 2 2956 || pIoPortCtx->AccessInfo.AccessSize == 4); 2957 2958 VBOXSTRICTRC rcStrict; 2959 if (!pIoPortCtx->AccessInfo.StringOp) 2960 { 2961 /* 2962 * Simple port I/O. 2963 */ 2964 Assert(pCtx->rax == pIoPortCtx->Rax); 2965 2966 static uint32_t const s_fAndMask[8] = 2967 { UINT32_MAX, UINT32_C(0xff), UINT32_C(0xffff), UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX }; 2968 uint32_t const fAndMask = s_fAndMask[pIoPortCtx->AccessInfo.AccessSize]; 2969 if (pIoPortCtx->AccessInfo.IsWrite) 2970 { 2971 rcStrict = IOMIOPortWrite(pVM, pVCpu, pIoPortCtx->PortNumber, (uint32_t)pIoPortCtx->Rax & fAndMask, 2972 pIoPortCtx->AccessInfo.AccessSize); 2973 if (IOM_SUCCESS(rcStrict)) 2974 nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pIoPortCtx->VpContext); 2975 } 2976 else 2977 { 2978 uint32_t uValue = 0; 2979 rcStrict = IOMIOPortRead(pVM, pVCpu, pIoPortCtx->PortNumber, &uValue, 2980 pIoPortCtx->AccessInfo.AccessSize); 2981 if (IOM_SUCCESS(rcStrict)) 2982 { 2983 pCtx->eax = (pCtx->eax & ~fAndMask) | (uValue & fAndMask); 2984 nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pIoPortCtx->VpContext); 2985 } 2986 } 2987 } 2988 else 2989 { 2990 /* 2991 * String port I/O. 2992 */ 2993 /** @todo Someone at Microsoft please explain how we can get the address mode 2994 * from the IoPortAccess.VpContext. CS.Attributes is only sufficient for 2995 * getting the default mode, it can always be overridden by a prefix. This 2996 * forces us to interpret the instruction from opcodes, which is suboptimal. 2997 * Both AMD-V and VT-x includes the address size in the exit info, at least on 2998 * CPUs that are reasonably new. */ 2999 Assert( pIoPortCtx->Ds.Base == pCtx->ds.u64Base 3000 && pIoPortCtx->Ds.Limit == pCtx->ds.u32Limit 3001 && pIoPortCtx->Ds.Selector == pCtx->ds.Sel); 3002 Assert( pIoPortCtx->Es.Base == pCtx->es.u64Base 3003 && pIoPortCtx->Es.Limit == pCtx->es.u32Limit 3004 && pIoPortCtx->Es.Selector == pCtx->es.Sel); 3005 Assert(pIoPortCtx->Rdi == pCtx->rdi); 3006 Assert(pIoPortCtx->Rsi == pCtx->rsi); 3007 Assert(pIoPortCtx->Rcx == pCtx->rcx); 3008 Assert(pIoPortCtx->Rcx == pCtx->rcx); 3009 3010 rcStrict = IEMExecOne(pVCpu); 3011 } 3012 if (IOM_SUCCESS(rcStrict)) 3013 { 3014 /* 3015 * Do debug checks. 3016 */ 3017 if ( pIoPortCtx->VpContext.ExecutionState.DebugActive /** @todo Microsoft: Does DebugActive this only reflext DR7? */ 3018 || (pIoPortCtx->VpContext.Rflags & X86_EFL_TF) 3019 || DBGFBpIsHwIoArmed(pVM) ) 3020 { 3021 /** @todo Debugging. */ 3022 } 3023 } 3024 return rcStrict; 3025 } 3026 3027 3028 static VBOXSTRICTRC nemR3WinHandleInterruptWindow(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason) 3029 { 3030 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason); 3031 AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED); 3032 } 3033 3034 3035 static VBOXSTRICTRC nemR3WinHandleMsrAccess(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason) 3036 { 3037 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason); 3038 AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED); 3039 } 3040 3041 3042 static VBOXSTRICTRC nemR3WinHandleCpuId(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason) 3043 { 3044 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason); 3045 AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED); 3046 } 3047 3048 3049 static VBOXSTRICTRC nemR3WinHandleException(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason) 3050 { 3051 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason); 3052 AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED); 3053 } 3054 3055 3056 static VBOXSTRICTRC nemR3WinHandleUD(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason) 3057 { 3058 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason); 3059 AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED); 3060 } 3061 3062 3063 static VBOXSTRICTRC nemR3WinHandleTripleFault(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason) 3064 { 3065 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason); 3066 AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED); 3067 } 3068 3069 3070 static VBOXSTRICTRC nemR3WinHandleInvalidState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason) 3071 { 3072 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason); 3073 AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED); 3074 } 3075 3076 3077 VBOXSTRICTRC nemR3NativeRunGC(PVM pVM, PVMCPU pVCpu) 1479 #if 0 /* later */ 1480 NEM_TMPL_STATIC nemHCWinRunGC(PVM pVM, PVMCPU pVCpu) 3078 1481 { 3079 1482 #ifdef LOG_ENABLED … … 3099 1502 */ 3100 1503 PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu); 3101 int rc2 = nem R3WinCopyStateToHyperV(pVM, pVCpu, pCtx);1504 int rc2 = nemHCWinCopyStateToHyperV(pVM, pVCpu, pCtx); 3102 1505 AssertRCBreakStmt(rc2, rcStrict = rc2); 3103 1506 … … 3268 1671 return rcStrict; 3269 1672 } 3270 3271 3272 bool nemR3NativeCanExecuteGuest(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx) 3273 { 3274 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); 3275 return true; 3276 } 3277 3278 3279 bool nemR3NativeSetSingleInstruction(PVM pVM, PVMCPU pVCpu, bool fEnable) 3280 { 3281 NOREF(pVM); NOREF(pVCpu); NOREF(fEnable); 3282 return false; 3283 } 3284 3285 3286 /** 3287 * Forced flag notification call from VMEmt.h. 3288 * 3289 * This is only called when pVCpu is in the VMCPUSTATE_STARTED_EXEC_NEM state. 3290 * 3291 * @param pVM The cross context VM structure. 3292 * @param pVCpu The cross context virtual CPU structure of the CPU 3293 * to be notified. 3294 * @param fFlags Notification flags, VMNOTIFYFF_FLAGS_XXX. 3295 */ 3296 void nemR3NativeNotifyFF(PVM pVM, PVMCPU pVCpu, uint32_t fFlags) 3297 { 3298 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API 3299 nemR3WinCancelRunVirtualProcessor(pVM, pVCpu); 3300 #else 3301 Log8(("nemR3NativeNotifyFF: canceling %u\n", pVCpu->idCpu)); 3302 HRESULT hrc = WHvCancelRunVirtualProcessor(pVM->nem.s.hPartition, pVCpu->idCpu, 0); 3303 AssertMsg(SUCCEEDED(hrc), ("WHvCancelRunVirtualProcessor -> hrc=%Rhrc\n", hrc)); 3304 RT_NOREF_PV(hrc); 3305 #endif 3306 RT_NOREF_PV(fFlags); 3307 } 3308 3309 3310 DECLINLINE(int) nemR3NativeGCPhys2R3PtrReadOnly(PVM pVM, RTGCPHYS GCPhys, const void **ppv) 3311 { 3312 PGMPAGEMAPLOCK Lock; 3313 int rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, GCPhys, ppv, &Lock); 3314 if (RT_SUCCESS(rc)) 3315 PGMPhysReleasePageMappingLock(pVM, &Lock); 3316 return rc; 3317 } 3318 3319 3320 DECLINLINE(int) nemR3NativeGCPhys2R3PtrWriteable(PVM pVM, RTGCPHYS GCPhys, void **ppv) 3321 { 3322 PGMPAGEMAPLOCK Lock; 3323 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhys, ppv, &Lock); 3324 if (RT_SUCCESS(rc)) 3325 PGMPhysReleasePageMappingLock(pVM, &Lock); 3326 return rc; 3327 } 3328 3329 3330 int nemR3NativeNotifyPhysRamRegister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb) 3331 { 3332 Log5(("nemR3NativeNotifyPhysRamRegister: %RGp LB %RGp\n", GCPhys, cb)); 3333 NOREF(pVM); NOREF(GCPhys); NOREF(cb); 3334 return VINF_SUCCESS; 3335 } 3336 3337 3338 int nemR3NativeNotifyPhysMmioExMap(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags, void *pvMmio2) 3339 { 3340 Log5(("nemR3NativeNotifyPhysMmioExMap: %RGp LB %RGp fFlags=%#x pvMmio2=%p\n", GCPhys, cb, fFlags, pvMmio2)); 3341 NOREF(pVM); NOREF(GCPhys); NOREF(cb); NOREF(fFlags); NOREF(pvMmio2); 3342 return VINF_SUCCESS; 3343 } 3344 3345 3346 int nemR3NativeNotifyPhysMmioExUnmap(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags) 3347 { 3348 Log5(("nemR3NativeNotifyPhysMmioExUnmap: %RGp LB %RGp fFlags=%#x\n", GCPhys, cb, fFlags)); 3349 NOREF(pVM); NOREF(GCPhys); NOREF(cb); NOREF(fFlags); 3350 return VINF_SUCCESS; 3351 } 3352 3353 3354 /** 3355 * Called early during ROM registration, right after the pages have been 3356 * allocated and the RAM range updated. 3357 * 3358 * This will be succeeded by a number of NEMHCNotifyPhysPageProtChanged() calls 3359 * and finally a NEMR3NotifyPhysRomRegisterEarly(). 3360 * 3361 * @returns VBox status code 3362 * @param pVM The cross context VM structure. 3363 * @param GCPhys The ROM address (page aligned). 3364 * @param cb The size (page aligned). 3365 * @param fFlags NEM_NOTIFY_PHYS_ROM_F_XXX. 3366 */ 3367 int nemR3NativeNotifyPhysRomRegisterEarly(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags) 3368 { 3369 Log5(("nemR3NativeNotifyPhysRomRegisterEarly: %RGp LB %RGp fFlags=%#x\n", GCPhys, cb, fFlags)); 3370 #if 0 /* Let's not do this after all. We'll protection change notifications for each page and if not we'll map them lazily. */ 3371 RTGCPHYS const cPages = cb >> X86_PAGE_SHIFT; 3372 for (RTGCPHYS iPage = 0; iPage < cPages; iPage++, GCPhys += X86_PAGE_SIZE) 3373 { 3374 const void *pvPage; 3375 int rc = nemR3NativeGCPhys2R3PtrReadOnly(pVM, GCPhys, &pvPage); 3376 if (RT_SUCCESS(rc)) 3377 { 3378 HRESULT hrc = WHvMapGpaRange(pVM->nem.s.hPartition, (void *)pvPage, GCPhys, X86_PAGE_SIZE, 3379 WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagExecute); 3380 if (SUCCEEDED(hrc)) 3381 { /* likely */ } 3382 else 3383 { 3384 LogRel(("nemR3NativeNotifyPhysRomRegisterEarly: GCPhys=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n", 3385 GCPhys, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue())); 3386 return VERR_NEM_INIT_FAILED; 3387 } 3388 } 3389 else 3390 { 3391 LogRel(("nemR3NativeNotifyPhysRomRegisterEarly: GCPhys=%RGp rc=%Rrc\n", GCPhys, rc)); 3392 return rc; 3393 } 3394 } 3395 #else 3396 NOREF(pVM); NOREF(GCPhys); NOREF(cb); 3397 #endif 3398 RT_NOREF_PV(fFlags); 3399 return VINF_SUCCESS; 3400 } 3401 3402 3403 /** 3404 * Called after the ROM range has been fully completed. 3405 * 3406 * This will be preceeded by a NEMR3NotifyPhysRomRegisterEarly() call as well a 3407 * number of NEMHCNotifyPhysPageProtChanged calls. 3408 * 3409 * @returns VBox status code 3410 * @param pVM The cross context VM structure. 3411 * @param GCPhys The ROM address (page aligned). 3412 * @param cb The size (page aligned). 3413 * @param fFlags NEM_NOTIFY_PHYS_ROM_F_XXX. 3414 */ 3415 int nemR3NativeNotifyPhysRomRegisterLate(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags) 3416 { 3417 Log5(("nemR3NativeNotifyPhysRomRegisterLate: %RGp LB %RGp fFlags=%#x\n", GCPhys, cb, fFlags)); 3418 NOREF(pVM); NOREF(GCPhys); NOREF(cb); NOREF(fFlags); 3419 return VINF_SUCCESS; 3420 } 1673 #endif /* later */ 1674 1675 1676 #endif /* IN_RING0 */ 3421 1677 3422 1678 … … 3424 1680 * @callback_method_impl{FNPGMPHYSNEMCHECKPAGE} 3425 1681 */ 3426 static DECLCALLBACK(int) nemR3WinUnsetForA20CheckerCallback(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys,3427 PPGMPHYSNEMPAGEINFO pInfo, void *pvUser)1682 NEM_TMPL_STATIC DECLCALLBACK(int) nemHCWinUnsetForA20CheckerCallback(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, 1683 PPGMPHYSNEMPAGEINFO pInfo, void *pvUser) 3428 1684 { 3429 1685 /* We'll just unmap the memory. */ … … 3431 1687 { 3432 1688 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES 3433 int rc = nem R3WinHypercallUnmapPage(pVM, pVCpu, GCPhys);1689 int rc = nemHCWinHypercallUnmapPage(pVM, pVCpu, GCPhys); 3434 1690 AssertRC(rc); 3435 1691 if (RT_SUCCESS(rc)) … … 3446 1702 { 3447 1703 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES 3448 LogRel(("nem R3WinUnsetForA20CheckerCallback/unmap: GCPhys=%RGp rc=%Rrc\n", GCPhys, rc));1704 LogRel(("nemHCWinUnsetForA20CheckerCallback/unmap: GCPhys=%RGp rc=%Rrc\n", GCPhys, rc)); 3449 1705 return rc; 3450 1706 #else 3451 LogRel(("nem R3WinUnsetForA20CheckerCallback/unmap: GCPhys=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",1707 LogRel(("nemHCWinUnsetForA20CheckerCallback/unmap: GCPhys=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n", 3452 1708 GCPhys, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue())); 3453 1709 return VERR_INTERNAL_ERROR_2; … … 3468 1724 * @param GCPhys The page to unmap. 3469 1725 */ 3470 static int nemR3WinUnmapPageForA20Gate(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys)1726 NEM_TMPL_STATIC int nemHCWinUnmapPageForA20Gate(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys) 3471 1727 { 3472 1728 PGMPHYSNEMPAGEINFO Info; 3473 1729 return PGMPhysNemPageInfoChecker(pVM, pVCpu, GCPhys, false /*fMakeWritable*/, &Info, 3474 nemR3WinUnsetForA20CheckerCallback, NULL); 3475 } 3476 3477 3478 /** 3479 * Called when the A20 state changes. 3480 * 3481 * Hyper-V doesn't seem to offer a simple way of implementing the A20 line 3482 * features of PCs. So, we do a very minimal emulation of the HMA to make DOS 3483 * happy. 3484 * 3485 * @param pVCpu The CPU the A20 state changed on. 3486 * @param fEnabled Whether it was enabled (true) or disabled. 3487 */ 3488 void nemR3NativeNotifySetA20(PVMCPU pVCpu, bool fEnabled) 3489 { 3490 Log(("nemR3NativeNotifySetA20: fEnabled=%RTbool\n", fEnabled)); 3491 PVM pVM = pVCpu->CTX_SUFF(pVM); 3492 if (!pVM->nem.s.fA20Fixed) 3493 { 3494 pVM->nem.s.fA20Enabled = fEnabled; 3495 for (RTGCPHYS GCPhys = _1M; GCPhys < _1M + _64K; GCPhys += X86_PAGE_SIZE) 3496 nemR3WinUnmapPageForA20Gate(pVM, pVCpu, GCPhys); 3497 } 3498 } 3499 3500 3501 void nemR3NativeNotifyHandlerPhysicalRegister(PVM pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhys, RTGCPHYS cb) 3502 { 3503 Log5(("nemR3NativeNotifyHandlerPhysicalRegister: %RGp LB %RGp enmKind=%d\n", GCPhys, cb, enmKind)); 1730 nemHCWinUnsetForA20CheckerCallback, NULL); 1731 } 1732 1733 1734 void nemHCNativeNotifyHandlerPhysicalRegister(PVM pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhys, RTGCPHYS cb) 1735 { 1736 Log5(("nemHCNativeNotifyHandlerPhysicalRegister: %RGp LB %RGp enmKind=%d\n", GCPhys, cb, enmKind)); 3504 1737 NOREF(pVM); NOREF(enmKind); NOREF(GCPhys); NOREF(cb); 3505 1738 } 3506 1739 3507 1740 3508 void nem R3NativeNotifyHandlerPhysicalDeregister(PVM pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhys, RTGCPHYS cb,1741 void nemHCNativeNotifyHandlerPhysicalDeregister(PVM pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhys, RTGCPHYS cb, 3509 1742 int fRestoreAsRAM, bool fRestoreAsRAM2) 3510 1743 { 3511 Log5(("nem R3NativeNotifyHandlerPhysicalDeregister: %RGp LB %RGp enmKind=%d fRestoreAsRAM=%d fRestoreAsRAM2=%d\n",1744 Log5(("nemHCNativeNotifyHandlerPhysicalDeregister: %RGp LB %RGp enmKind=%d fRestoreAsRAM=%d fRestoreAsRAM2=%d\n", 3512 1745 GCPhys, cb, enmKind, fRestoreAsRAM, fRestoreAsRAM2)); 3513 1746 NOREF(pVM); NOREF(enmKind); NOREF(GCPhys); NOREF(cb); NOREF(fRestoreAsRAM); NOREF(fRestoreAsRAM2); … … 3515 1748 3516 1749 3517 void nem R3NativeNotifyHandlerPhysicalModify(PVM pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhysOld,1750 void nemHCNativeNotifyHandlerPhysicalModify(PVM pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhysOld, 3518 1751 RTGCPHYS GCPhysNew, RTGCPHYS cb, bool fRestoreAsRAM) 3519 1752 { 3520 Log5(("nem R3NativeNotifyHandlerPhysicalModify: %RGp LB %RGp -> %RGp enmKind=%d fRestoreAsRAM=%d\n",1753 Log5(("nemHCNativeNotifyHandlerPhysicalModify: %RGp LB %RGp -> %RGp enmKind=%d fRestoreAsRAM=%d\n", 3521 1754 GCPhysOld, cb, GCPhysNew, enmKind, fRestoreAsRAM)); 3522 1755 NOREF(pVM); NOREF(enmKind); NOREF(GCPhysOld); NOREF(GCPhysNew); NOREF(cb); NOREF(fRestoreAsRAM); … … 3542 1775 * @thread EMT(pVCpu) 3543 1776 */ 3544 static int nemR3NativeSetPhysPage(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhysSrc, RTGCPHYS GCPhysDst, uint32_t fPageProt,3545 uint8_t *pu2State, bool fBackingChanged)1777 NEM_TMPL_STATIC int nemHCNativeSetPhysPage(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhysSrc, RTGCPHYS GCPhysDst, 1778 uint32_t fPageProt, uint8_t *pu2State, bool fBackingChanged) 3546 1779 { 3547 1780 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES … … 3558 1791 if (u2OldState > NEM_WIN_PAGE_STATE_UNMAPPED) 3559 1792 { 3560 rc = nem R3WinHypercallUnmapPage(pVM, pVCpu, GCPhysDst);1793 rc = nemHCWinHypercallUnmapPage(pVM, pVCpu, GCPhysDst); 3561 1794 if (RT_SUCCESS(rc)) 3562 1795 { … … 3566 1799 } 3567 1800 else 3568 AssertLogRelMsgFailed(("nem R3NativeSetPhysPage/unmap: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));1801 AssertLogRelMsgFailed(("nemHCNativeSetPhysPage/unmap: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc)); 3569 1802 } 3570 1803 else … … 3575 1808 if (u2OldState != NEM_WIN_PAGE_STATE_WRITABLE || fBackingChanged) 3576 1809 { 3577 rc = nem R3WinHypercallMapPage(pVM, pVCpu, GCPhysSrc, GCPhysDst,1810 rc = nemHCWinHypercallMapPage(pVM, pVCpu, GCPhysSrc, GCPhysDst, 3578 1811 HV_MAP_GPA_READABLE | HV_MAP_GPA_WRITABLE 3579 1812 | HV_MAP_GPA_EXECUTABLE | HV_MAP_GPA_EXECUTABLE_AGAIN); … … 3587 1820 } 3588 1821 else 3589 AssertLogRelMsgFailed(("nem R3NativeSetPhysPage/writable: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));1822 AssertLogRelMsgFailed(("nemHCNativeSetPhysPage/writable: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc)); 3590 1823 } 3591 1824 else … … 3596 1829 if (u2OldState != NEM_WIN_PAGE_STATE_READABLE || fBackingChanged) 3597 1830 { 3598 rc = nem R3WinHypercallMapPage(pVM, pVCpu, GCPhysSrc, GCPhysDst,1831 rc = nemHCWinHypercallMapPage(pVM, pVCpu, GCPhysSrc, GCPhysDst, 3599 1832 HV_MAP_GPA_READABLE | HV_MAP_GPA_EXECUTABLE | HV_MAP_GPA_EXECUTABLE_AGAIN); 3600 1833 if (RT_SUCCESS(rc)) … … 3607 1840 } 3608 1841 else 3609 AssertLogRelMsgFailed(("nem R3NativeSetPhysPage/writable: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));1842 AssertLogRelMsgFailed(("nemHCNativeSetPhysPage/writable: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc)); 3610 1843 } 3611 1844 else … … 3630 1863 { 3631 1864 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES 3632 int rc = nem R3WinHypercallUnmapPage(pVM, pVCpu, GCPhysDst);1865 int rc = nemHCWinHypercallUnmapPage(pVM, pVCpu, GCPhysDst); 3633 1866 AssertRC(rc); 3634 1867 if (RT_SUCCESS(rc)) … … 3645 1878 else 3646 1879 { 3647 LogRel(("nem R3NativeSetPhysPage/unmap: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));1880 LogRel(("nemHCNativeSetPhysPage/unmap: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc)); 3648 1881 return rc; 3649 1882 } … … 3663 1896 else 3664 1897 { 3665 LogRel(("nem R3NativeSetPhysPage/unmap: GCPhysDst=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",1898 LogRel(("nemHCNativeSetPhysPage/unmap: GCPhysDst=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n", 3666 1899 GCPhysDst, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue())); 3667 1900 return VERR_NEM_INIT_FAILED; … … 3677 1910 { 3678 1911 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES 3679 int rc = nem R3WinHypercallMapPage(pVM, pVCpu, GCPhysSrc, GCPhysDst,1912 int rc = nemHCWinHypercallMapPage(pVM, pVCpu, GCPhysSrc, GCPhysDst, 3680 1913 HV_MAP_GPA_READABLE | HV_MAP_GPA_WRITABLE 3681 1914 | HV_MAP_GPA_EXECUTABLE | HV_MAP_GPA_EXECUTABLE_AGAIN); … … 3689 1922 return VINF_SUCCESS; 3690 1923 } 3691 LogRel(("nem R3NativeSetPhysPage/writable: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));1924 LogRel(("nemHCNativeSetPhysPage/writable: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc)); 3692 1925 return rc; 3693 1926 # else … … 3706 1939 return VINF_SUCCESS; 3707 1940 } 3708 LogRel(("nem R3NativeSetPhysPage/writable: GCPhysDst=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",1941 LogRel(("nemHCNativeSetPhysPage/writable: GCPhysDst=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n", 3709 1942 GCPhysDst, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue())); 3710 1943 return VERR_NEM_INIT_FAILED; 3711 1944 } 3712 LogRel(("nem R3NativeSetPhysPage/writable: GCPhysSrc=%RGp rc=%Rrc\n", GCPhysSrc, rc));1945 LogRel(("nemHCNativeSetPhysPage/writable: GCPhysSrc=%RGp rc=%Rrc\n", GCPhysSrc, rc)); 3713 1946 return rc; 3714 1947 # endif … … 3718 1951 { 3719 1952 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES 3720 int rc = nem R3WinHypercallMapPage(pVM, pVCpu, GCPhysSrc, GCPhysDst,1953 int rc = nemHCWinHypercallMapPage(pVM, pVCpu, GCPhysSrc, GCPhysDst, 3721 1954 HV_MAP_GPA_READABLE | HV_MAP_GPA_EXECUTABLE | HV_MAP_GPA_EXECUTABLE_AGAIN); 3722 1955 AssertRC(rc); … … 3729 1962 return VINF_SUCCESS; 3730 1963 } 3731 LogRel(("nem R3NativeSetPhysPage/readonly: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));1964 LogRel(("nemHCNativeSetPhysPage/readonly: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc)); 3732 1965 return rc; 3733 1966 # else … … 3746 1979 return VINF_SUCCESS; 3747 1980 } 3748 LogRel(("nem R3NativeSetPhysPage/readonly: GCPhysDst=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",1981 LogRel(("nemHCNativeSetPhysPage/readonly: GCPhysDst=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n", 3749 1982 GCPhysDst, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue())); 3750 1983 return VERR_NEM_INIT_FAILED; 3751 1984 } 3752 LogRel(("nem R3NativeSetPhysPage/readonly: GCPhysSrc=%RGp rc=%Rrc\n", GCPhysSrc, rc));1985 LogRel(("nemHCNativeSetPhysPage/readonly: GCPhysSrc=%RGp rc=%Rrc\n", GCPhysSrc, rc)); 3753 1986 return rc; 3754 1987 # endif … … 3762 1995 3763 1996 3764 static int nemR3JustUnmapPageFromHyperV(PVM pVM, RTGCPHYS GCPhysDst, uint8_t *pu2State)1997 NEM_TMPL_STATIC int nemHCJustUnmapPageFromHyperV(PVM pVM, RTGCPHYS GCPhysDst, uint8_t *pu2State) 3765 1998 { 3766 1999 if (*pu2State <= NEM_WIN_PAGE_STATE_UNMAPPED) 3767 2000 { 3768 Log5(("nem R3JustUnmapPageFromHyperV: %RGp == unmapped\n", GCPhysDst));2001 Log5(("nemHCJustUnmapPageFromHyperV: %RGp == unmapped\n", GCPhysDst)); 3769 2002 *pu2State = NEM_WIN_PAGE_STATE_UNMAPPED; 3770 2003 return VINF_SUCCESS; 3771 2004 } 3772 2005 3773 #if def NEM_WIN_USE_HYPERCALLS_FOR_PAGES2006 #if defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES) || defined(IN_RING0) 3774 2007 PVMCPU pVCpu = VMMGetCpu(pVM); 3775 int rc = nem R3WinHypercallUnmapPage(pVM, pVCpu, GCPhysDst);2008 int rc = nemHCWinHypercallUnmapPage(pVM, pVCpu, GCPhysDst); 3776 2009 AssertRC(rc); 3777 2010 if (RT_SUCCESS(rc)) … … 3782 2015 return VINF_SUCCESS; 3783 2016 } 3784 LogRel(("nem R3JustUnmapPageFromHyperV/unmap: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));2017 LogRel(("nemHCJustUnmapPageFromHyperV/unmap: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc)); 3785 2018 return rc; 3786 2019 #else … … 3790 2023 uint32_t cMappedPages = ASMAtomicDecU32(&pVM->nem.s.cMappedPages); NOREF(cMappedPages); 3791 2024 *pu2State = NEM_WIN_PAGE_STATE_UNMAPPED; 3792 Log5(("nem R3JustUnmapPageFromHyperV: %RGp => unmapped (total %u)\n", GCPhysDst, cMappedPages));2025 Log5(("nemHCJustUnmapPageFromHyperV: %RGp => unmapped (total %u)\n", GCPhysDst, cMappedPages)); 3793 2026 return VINF_SUCCESS; 3794 2027 } 3795 LogRel(("nem R3JustUnmapPageFromHyperV(%RGp): failed! hrc=%Rhrc (%#x) Last=%#x/%u\n",2028 LogRel(("nemHCJustUnmapPageFromHyperV(%RGp): failed! hrc=%Rhrc (%#x) Last=%#x/%u\n", 3796 2029 GCPhysDst, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue())); 3797 2030 return VERR_INTERNAL_ERROR_3; … … 3800 2033 3801 2034 3802 int nem R3NativeNotifyPhysPageAllocated(PVM pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint32_t fPageProt,2035 int nemHCNativeNotifyPhysPageAllocated(PVM pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint32_t fPageProt, 3803 2036 PGMPAGETYPE enmType, uint8_t *pu2State) 3804 2037 { 3805 Log5(("nem R3NativeNotifyPhysPageAllocated: %RGp HCPhys=%RHp fPageProt=%#x enmType=%d *pu2State=%d\n",2038 Log5(("nemHCNativeNotifyPhysPageAllocated: %RGp HCPhys=%RHp fPageProt=%#x enmType=%d *pu2State=%d\n", 3806 2039 GCPhys, HCPhys, fPageProt, enmType, *pu2State)); 3807 2040 RT_NOREF_PV(HCPhys); RT_NOREF_PV(enmType); 3808 2041 3809 2042 int rc; 3810 #if def NEM_WIN_USE_HYPERCALLS_FOR_PAGES2043 #if defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES) || defined(IN_RING0) 3811 2044 PVMCPU pVCpu = VMMGetCpu(pVM); 3812 2045 if ( pVM->nem.s.fA20Enabled 3813 2046 || !NEM_WIN_IS_RELEVANT_TO_A20(GCPhys)) 3814 rc = nem R3NativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/);2047 rc = nemHCNativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/); 3815 2048 else 3816 2049 { 3817 2050 /* To keep effort at a minimum, we unmap the HMA page alias and resync it lazily when needed. */ 3818 rc = nem R3WinUnmapPageForA20Gate(pVM, pVCpu, GCPhys | RT_BIT_32(20));2051 rc = nemHCWinUnmapPageForA20Gate(pVM, pVCpu, GCPhys | RT_BIT_32(20)); 3819 2052 if (!NEM_WIN_IS_SUBJECT_TO_A20(GCPhys) && RT_SUCCESS(rc)) 3820 rc = nem R3NativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/);2053 rc = nemHCNativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/); 3821 2054 3822 2055 } … … 3835 2068 3836 2069 3837 void nem R3NativeNotifyPhysPageProtChanged(PVM pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint32_t fPageProt,2070 void nemHCNativeNotifyPhysPageProtChanged(PVM pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint32_t fPageProt, 3838 2071 PGMPAGETYPE enmType, uint8_t *pu2State) 3839 2072 { 3840 Log5(("nem R3NativeNotifyPhysPageProtChanged: %RGp HCPhys=%RHp fPageProt=%#x enmType=%d *pu2State=%d\n",2073 Log5(("nemHCNativeNotifyPhysPageProtChanged: %RGp HCPhys=%RHp fPageProt=%#x enmType=%d *pu2State=%d\n", 3841 2074 GCPhys, HCPhys, fPageProt, enmType, *pu2State)); 3842 2075 RT_NOREF_PV(HCPhys); RT_NOREF_PV(enmType); 3843 2076 3844 #if def NEM_WIN_USE_HYPERCALLS_FOR_PAGES2077 #if defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES) || defined(IN_RING0) 3845 2078 PVMCPU pVCpu = VMMGetCpu(pVM); 3846 2079 if ( pVM->nem.s.fA20Enabled 3847 2080 || !NEM_WIN_IS_RELEVANT_TO_A20(GCPhys)) 3848 nem R3NativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, false /*fBackingChanged*/);2081 nemHCNativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, false /*fBackingChanged*/); 3849 2082 else 3850 2083 { 3851 2084 /* To keep effort at a minimum, we unmap the HMA page alias and resync it lazily when needed. */ 3852 nem R3WinUnmapPageForA20Gate(pVM, pVCpu, GCPhys | RT_BIT_32(20));2085 nemHCWinUnmapPageForA20Gate(pVM, pVCpu, GCPhys | RT_BIT_32(20)); 3853 2086 if (!NEM_WIN_IS_SUBJECT_TO_A20(GCPhys)) 3854 nem R3NativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, false /*fBackingChanged*/);2087 nemHCNativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, false /*fBackingChanged*/); 3855 2088 } 3856 2089 #else … … 3866 2099 3867 2100 3868 void nem R3NativeNotifyPhysPageChanged(PVM pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhysPrev, RTHCPHYS HCPhysNew,3869 3870 { 3871 Log5(("nem R3NativeNotifyPhysPageProtChanged: %RGp HCPhys=%RHp->%RHp fPageProt=%#x enmType=%d *pu2State=%d\n",2101 void nemHCNativeNotifyPhysPageChanged(PVM pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhysPrev, RTHCPHYS HCPhysNew, 2102 uint32_t fPageProt, PGMPAGETYPE enmType, uint8_t *pu2State) 2103 { 2104 Log5(("nemHCNativeNotifyPhysPageChanged: %RGp HCPhys=%RHp->%RHp fPageProt=%#x enmType=%d *pu2State=%d\n", 3872 2105 GCPhys, HCPhysPrev, HCPhysNew, fPageProt, enmType, *pu2State)); 3873 2106 RT_NOREF_PV(HCPhysPrev); RT_NOREF_PV(HCPhysNew); RT_NOREF_PV(enmType); 3874 2107 3875 #if def NEM_WIN_USE_HYPERCALLS_FOR_PAGES2108 #if defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES) || defined(IN_RING0) 3876 2109 PVMCPU pVCpu = VMMGetCpu(pVM); 3877 2110 if ( pVM->nem.s.fA20Enabled 3878 2111 || !NEM_WIN_IS_RELEVANT_TO_A20(GCPhys)) 3879 nem R3NativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/);2112 nemHCNativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/); 3880 2113 else 3881 2114 { 3882 2115 /* To keep effort at a minimum, we unmap the HMA page alias and resync it lazily when needed. */ 3883 nem R3WinUnmapPageForA20Gate(pVM, pVCpu, GCPhys | RT_BIT_32(20));2116 nemHCWinUnmapPageForA20Gate(pVM, pVCpu, GCPhys | RT_BIT_32(20)); 3884 2117 if (!NEM_WIN_IS_SUBJECT_TO_A20(GCPhys)) 3885 nem R3NativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/);2118 nemHCNativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/); 3886 2119 } 3887 2120 #else
Note:
See TracChangeset
for help on using the changeset viewer.