VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR0/NEMR0Native-win.cpp@ 71963

Last change on this file since 71963 was 71296, checked in by vboxsync, 7 years ago

NEM: Updates for build 17115 and fixes for AMD-V. bugref:9044

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 74.9 KB
Line 
1/* $Id: NEMR0Native-win.cpp 71296 2018-03-10 00:53:26Z vboxsync $ */
2/** @file
3 * NEM - Native execution manager, native ring-0 Windows backend.
4 */
5
6/*
7 * Copyright (C) 2018 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_NEM
23#include <iprt/nt/nt.h>
24#include <iprt/nt/hyperv.h>
25#include <iprt/nt/vid.h>
26#include <winerror.h>
27
28#include <VBox/vmm/nem.h>
29#include <VBox/vmm/iem.h>
30#include <VBox/vmm/em.h>
31#include <VBox/vmm/apic.h>
32#include "NEMInternal.h"
33#include <VBox/vmm/gvm.h>
34#include <VBox/vmm/vm.h>
35#include <VBox/vmm/gvmm.h>
36#include <VBox/param.h>
37
38#include <iprt/dbg.h>
39#include <iprt/memobj.h>
40#include <iprt/string.h>
41
42
43/* Assert compile context sanity. */
44#ifndef RT_OS_WINDOWS
45# error "Windows only file!"
46#endif
47#ifndef RT_ARCH_AMD64
48# error "AMD64 only file!"
49#endif
50
51
52/*********************************************************************************************************************************
53* Internal Functions *
54*********************************************************************************************************************************/
55typedef uint32_t DWORD; /* for winerror.h constants */
56
57
58/*********************************************************************************************************************************
59* Global Variables *
60*********************************************************************************************************************************/
61static uint64_t (*g_pfnHvlInvokeHypercall)(uint64_t uCallInfo, uint64_t HCPhysInput, uint64_t HCPhysOutput);
62
63
64/*********************************************************************************************************************************
65* Internal Functions *
66*********************************************************************************************************************************/
67NEM_TMPL_STATIC int nemR0WinMapPages(PGVM pGVM, PVM pVM, PGVMCPU pGVCpu, RTGCPHYS GCPhysSrc, RTGCPHYS GCPhysDst,
68 uint32_t cPages, uint32_t fFlags);
69NEM_TMPL_STATIC int nemR0WinUnmapPages(PGVM pGVM, PGVMCPU pGVCpu, RTGCPHYS GCPhys, uint32_t cPages);
70NEM_TMPL_STATIC int nemR0WinExportState(PGVM pGVM, PGVMCPU pGVCpu, PCPUMCTX pCtx);
71NEM_TMPL_STATIC int nemR0WinImportState(PGVM pGVM, PGVMCPU pGVCpu, PCPUMCTX pCtx, uint64_t fWhat);
72DECLINLINE(NTSTATUS) nemR0NtPerformIoControl(PGVM pGVM, uint32_t uFunction, void *pvInput, uint32_t cbInput,
73 void *pvOutput, uint32_t cbOutput);
74
75
76/*
77 * Instantate the code we share with ring-0.
78 */
79#include "../VMMAll/NEMAllNativeTemplate-win.cpp.h"
80
81
82/**
83 * Called by NEMR3Init to make sure we've got what we need.
84 *
85 * @returns VBox status code.
86 * @param pGVM The ring-0 VM handle.
87 * @param pVM The cross context VM handle.
88 * @thread EMT(0)
89 */
90VMMR0_INT_DECL(int) NEMR0InitVM(PGVM pGVM, PVM pVM)
91{
92 AssertCompile(sizeof(pGVM->nem.s) <= sizeof(pGVM->nem.padding));
93 AssertCompile(sizeof(pGVM->aCpus[0].nem.s) <= sizeof(pGVM->aCpus[0].nem.padding));
94
95 int rc = GVMMR0ValidateGVMandVMandEMT(pGVM, pVM, 0);
96 AssertRCReturn(rc, rc);
97
98 /*
99 * We want to perform hypercalls here. The NT kernel started to expose a very low
100 * level interface to do this thru somewhere between build 14271 and 16299. Since
101 * we need build 17083 to get anywhere at all, the exact build is not relevant here.
102 */
103 RTDBGKRNLINFO hKrnlInfo;
104 rc = RTR0DbgKrnlInfoOpen(&hKrnlInfo, 0);
105 if (RT_SUCCESS(rc))
106 {
107 rc = RTR0DbgKrnlInfoQuerySymbol(hKrnlInfo, NULL, "HvlInvokeHypercall", (void **)&g_pfnHvlInvokeHypercall);
108 RTR0DbgKrnlInfoRelease(hKrnlInfo);
109 if (RT_SUCCESS(rc))
110 {
111 /*
112 * Allocate a page for each VCPU to place hypercall data on.
113 */
114 for (VMCPUID i = 0; i < pGVM->cCpus; i++)
115 {
116 PGVMCPU pGVCpu = &pGVM->aCpus[i];
117 rc = RTR0MemObjAllocPage(&pGVCpu->nem.s.hHypercallDataMemObj, PAGE_SIZE, false /*fExecutable*/);
118 if (RT_SUCCESS(rc))
119 {
120 pGVCpu->nem.s.HCPhysHypercallData = RTR0MemObjGetPagePhysAddr(pGVCpu->nem.s.hHypercallDataMemObj, 0 /*iPage*/);
121 pGVCpu->nem.s.pbHypercallData = (uint8_t *)RTR0MemObjAddress(pGVCpu->nem.s.hHypercallDataMemObj);
122 AssertStmt(pGVCpu->nem.s.HCPhysHypercallData != NIL_RTHCPHYS, rc = VERR_INTERNAL_ERROR_3);
123 AssertStmt(pGVCpu->nem.s.pbHypercallData, rc = VERR_INTERNAL_ERROR_3);
124 }
125 else
126 pGVCpu->nem.s.hHypercallDataMemObj = NIL_RTR0MEMOBJ;
127 if (RT_FAILURE(rc))
128 {
129 /* bail. */
130 do
131 {
132 RTR0MemObjFree(pGVCpu->nem.s.hHypercallDataMemObj, true /*fFreeMappings*/);
133 pGVCpu->nem.s.hHypercallDataMemObj = NIL_RTR0MEMOBJ;
134 pGVCpu->nem.s.HCPhysHypercallData = NIL_RTHCPHYS;
135 pGVCpu->nem.s.pbHypercallData = NULL;
136 } while (i-- > 0);
137 return rc;
138 }
139 }
140 /*
141 * So far, so good.
142 */
143 return rc;
144 }
145
146 rc = VERR_NEM_MISSING_KERNEL_API;
147 }
148
149 RT_NOREF(pGVM, pVM);
150 return rc;
151}
152
153
154/**
155 * Perform an I/O control operation on the partition handle (VID.SYS).
156 *
157 * @returns NT status code.
158 * @param pGVM The ring-0 VM structure.
159 * @param uFunction The function to perform.
160 * @param pvInput The input buffer. This must point within the VM
161 * structure so we can easily convert to a ring-3
162 * pointer if necessary.
163 * @param cbInput The size of the input. @a pvInput must be NULL when
164 * zero.
165 * @param pvOutput The output buffer. This must also point within the
166 * VM structure for ring-3 pointer magic.
167 * @param cbOutput The size of the output. @a pvOutput must be NULL
168 * when zero.
169 */
170DECLINLINE(NTSTATUS) nemR0NtPerformIoControl(PGVM pGVM, uint32_t uFunction, void *pvInput, uint32_t cbInput,
171 void *pvOutput, uint32_t cbOutput)
172{
173#ifdef RT_STRICT
174 /*
175 * Input and output parameters are part of the VM CPU structure.
176 */
177 PVM pVM = pGVM->pVM;
178 size_t const cbVM = RT_UOFFSETOF(VM, aCpus[pGVM->cCpus]);
179 if (pvInput)
180 AssertReturn(((uintptr_t)pvInput + cbInput) - (uintptr_t)pVM <= cbVM, VERR_INVALID_PARAMETER);
181 if (pvOutput)
182 AssertReturn(((uintptr_t)pvOutput + cbOutput) - (uintptr_t)pVM <= cbVM, VERR_INVALID_PARAMETER);
183#endif
184
185 int32_t rcNt = STATUS_UNSUCCESSFUL;
186 int rc = SUPR0IoCtlPerform(pGVM->nem.s.pIoCtlCtx, uFunction,
187 pvInput,
188 pvInput ? (uintptr_t)pvInput + pGVM->nem.s.offRing3ConversionDelta : NIL_RTR3PTR,
189 cbInput,
190 pvOutput,
191 pvOutput ? (uintptr_t)pvOutput + pGVM->nem.s.offRing3ConversionDelta : NIL_RTR3PTR,
192 cbOutput,
193 &rcNt);
194 if (RT_SUCCESS(rc) || !NT_SUCCESS((NTSTATUS)rcNt))
195 return (NTSTATUS)rcNt;
196 return STATUS_UNSUCCESSFUL;
197}
198
199
200/**
201 * 2nd part of the initialization, after we've got a partition handle.
202 *
203 * @returns VBox status code.
204 * @param pGVM The ring-0 VM handle.
205 * @param pVM The cross context VM handle.
206 * @thread EMT(0)
207 */
208VMMR0_INT_DECL(int) NEMR0InitVMPart2(PGVM pGVM, PVM pVM)
209{
210 int rc = GVMMR0ValidateGVMandVMandEMT(pGVM, pVM, 0);
211 AssertRCReturn(rc, rc);
212 SUPR0Printf("NEMR0InitVMPart2\n"); LogRel(("2: NEMR0InitVMPart2\n"));
213
214 /*
215 * Copy and validate the I/O control information from ring-3.
216 */
217 NEMWINIOCTL Copy = pVM->nem.s.IoCtlGetHvPartitionId;
218 AssertLogRelReturn(Copy.uFunction != 0, VERR_NEM_INIT_FAILED);
219 AssertLogRelReturn(Copy.cbInput == 0, VERR_NEM_INIT_FAILED);
220 AssertLogRelReturn(Copy.cbOutput == sizeof(HV_PARTITION_ID), VERR_NEM_INIT_FAILED);
221 pGVM->nem.s.IoCtlGetHvPartitionId = Copy;
222
223 Copy = pVM->nem.s.IoCtlStartVirtualProcessor;
224 AssertLogRelReturn(Copy.uFunction != 0, VERR_NEM_INIT_FAILED);
225 AssertLogRelReturn(Copy.cbInput == sizeof(HV_VP_INDEX), VERR_NEM_INIT_FAILED);
226 AssertLogRelReturn(Copy.cbOutput == 0, VERR_NEM_INIT_FAILED);
227 AssertLogRelReturn(Copy.uFunction != pGVM->nem.s.IoCtlGetHvPartitionId.uFunction, VERR_NEM_INIT_FAILED);
228 pGVM->nem.s.IoCtlStartVirtualProcessor = Copy;
229
230 Copy = pVM->nem.s.IoCtlStopVirtualProcessor;
231 AssertLogRelReturn(Copy.uFunction != 0, VERR_NEM_INIT_FAILED);
232 AssertLogRelReturn(Copy.cbInput == sizeof(HV_VP_INDEX), VERR_NEM_INIT_FAILED);
233 AssertLogRelReturn(Copy.cbOutput == 0, VERR_NEM_INIT_FAILED);
234 AssertLogRelReturn(Copy.uFunction != pGVM->nem.s.IoCtlGetHvPartitionId.uFunction, VERR_NEM_INIT_FAILED);
235 AssertLogRelReturn(Copy.uFunction != pGVM->nem.s.IoCtlStartVirtualProcessor.uFunction, VERR_NEM_INIT_FAILED);
236 pGVM->nem.s.IoCtlStopVirtualProcessor = Copy;
237
238 Copy = pVM->nem.s.IoCtlMessageSlotHandleAndGetNext;
239 AssertLogRelReturn(Copy.uFunction != 0, VERR_NEM_INIT_FAILED);
240 AssertLogRelReturn(Copy.cbInput == sizeof(VID_IOCTL_INPUT_MESSAGE_SLOT_HANDLE_AND_GET_NEXT), VERR_NEM_INIT_FAILED);
241 AssertLogRelReturn(Copy.cbOutput == 0, VERR_NEM_INIT_FAILED);
242 AssertLogRelReturn(Copy.uFunction != pGVM->nem.s.IoCtlGetHvPartitionId.uFunction, VERR_NEM_INIT_FAILED);
243 AssertLogRelReturn(Copy.uFunction != pGVM->nem.s.IoCtlStartVirtualProcessor.uFunction, VERR_NEM_INIT_FAILED);
244 AssertLogRelReturn(Copy.uFunction != pGVM->nem.s.IoCtlStopVirtualProcessor.uFunction, VERR_NEM_INIT_FAILED);
245 pGVM->nem.s.IoCtlMessageSlotHandleAndGetNext = Copy;
246
247 /*
248 * Setup of an I/O control context for the partition handle for later use.
249 */
250 rc = SUPR0IoCtlSetupForHandle(pGVM->pSession, pVM->nem.s.hPartitionDevice, 0, &pGVM->nem.s.pIoCtlCtx);
251 AssertLogRelRCReturn(rc, rc);
252 pGVM->nem.s.offRing3ConversionDelta = (uintptr_t)pVM->pVMR3 - (uintptr_t)pGVM->pVM;
253
254 /*
255 * Get the partition ID.
256 */
257 PVMCPU pVCpu = &pGVM->pVM->aCpus[0];
258 NTSTATUS rcNt = nemR0NtPerformIoControl(pGVM, pGVM->nem.s.IoCtlGetHvPartitionId.uFunction, NULL, 0,
259 &pVCpu->nem.s.uIoCtlBuf.idPartition, sizeof(pVCpu->nem.s.uIoCtlBuf.idPartition));
260 AssertLogRelMsgReturn(NT_SUCCESS(rcNt), ("IoCtlGetHvPartitionId failed: %#x\n", rcNt), VERR_NEM_INIT_FAILED);
261 pGVM->nem.s.idHvPartition = pVCpu->nem.s.uIoCtlBuf.idPartition;
262 AssertLogRelMsgReturn(pGVM->nem.s.idHvPartition == pVM->nem.s.idHvPartition,
263 ("idHvPartition mismatch: r0=%#RX64, r3=%#RX64\n", pGVM->nem.s.idHvPartition, pVM->nem.s.idHvPartition),
264 VERR_NEM_INIT_FAILED);
265
266
267 return rc;
268}
269
270
271/**
272 * Cleanup the NEM parts of the VM in ring-0.
273 *
274 * This is always called and must deal the state regardless of whether
275 * NEMR0InitVM() was called or not. So, take care here.
276 *
277 * @param pGVM The ring-0 VM handle.
278 */
279VMMR0_INT_DECL(void) NEMR0CleanupVM(PGVM pGVM)
280{
281 pGVM->nem.s.idHvPartition = HV_PARTITION_ID_INVALID;
282
283 /* Clean up I/O control context. */
284 if (pGVM->nem.s.pIoCtlCtx)
285 {
286 int rc = SUPR0IoCtlCleanup(pGVM->nem.s.pIoCtlCtx);
287 AssertRC(rc);
288 pGVM->nem.s.pIoCtlCtx = NULL;
289 }
290
291 /* Free the hypercall pages. */
292 VMCPUID i = pGVM->cCpus;
293 while (i-- > 0)
294 {
295 PGVMCPU pGVCpu = &pGVM->aCpus[i];
296 if (pGVCpu->nem.s.pbHypercallData)
297 {
298 pGVCpu->nem.s.pbHypercallData = NULL;
299 int rc = RTR0MemObjFree(pGVCpu->nem.s.hHypercallDataMemObj, true /*fFreeMappings*/);
300 AssertRC(rc);
301 }
302 pGVCpu->nem.s.hHypercallDataMemObj = NIL_RTR0MEMOBJ;
303 pGVCpu->nem.s.HCPhysHypercallData = NIL_RTHCPHYS;
304 }
305}
306
307
308#if 0 /* for debugging GPA unmapping. */
309static int nemR3WinDummyReadGpa(PGVM pGVM, PGVMCPU pGVCpu, RTGCPHYS GCPhys)
310{
311 PHV_INPUT_READ_GPA pIn = (PHV_INPUT_READ_GPA)pGVCpu->nem.s.pbHypercallData;
312 PHV_OUTPUT_READ_GPA pOut = (PHV_OUTPUT_READ_GPA)(pIn + 1);
313 pIn->PartitionId = pGVM->nem.s.idHvPartition;
314 pIn->VpIndex = pGVCpu->idCpu;
315 pIn->ByteCount = 0x10;
316 pIn->BaseGpa = GCPhys;
317 pIn->ControlFlags.AsUINT64 = 0;
318 pIn->ControlFlags.CacheType = HvCacheTypeX64WriteCombining;
319 memset(pOut, 0xfe, sizeof(*pOut));
320 uint64_t volatile uResult = g_pfnHvlInvokeHypercall(HvCallReadGpa, pGVCpu->nem.s.HCPhysHypercallData,
321 pGVCpu->nem.s.HCPhysHypercallData + sizeof(*pIn));
322 LogRel(("nemR3WinDummyReadGpa: %RGp -> %#RX64; code=%u rsvd=%u abData=%.16Rhxs\n",
323 GCPhys, uResult, pOut->AccessResult.ResultCode, pOut->AccessResult.Reserved, pOut->Data));
324 __debugbreak();
325
326 return uResult != 0 ? VERR_READ_ERROR : VINF_SUCCESS;
327}
328#endif
329
330
331/**
332 * Worker for NEMR0MapPages and others.
333 */
334NEM_TMPL_STATIC int nemR0WinMapPages(PGVM pGVM, PVM pVM, PGVMCPU pGVCpu, RTGCPHYS GCPhysSrc, RTGCPHYS GCPhysDst,
335 uint32_t cPages, uint32_t fFlags)
336{
337 /*
338 * Validate.
339 */
340 AssertReturn(g_pfnHvlInvokeHypercall, VERR_NEM_MISSING_KERNEL_API);
341
342 AssertReturn(cPages > 0, VERR_OUT_OF_RANGE);
343 AssertReturn(cPages <= NEM_MAX_MAP_PAGES, VERR_OUT_OF_RANGE);
344 AssertReturn(!(fFlags & ~(HV_MAP_GPA_MAYBE_ACCESS_MASK & ~HV_MAP_GPA_DUNNO_ACCESS)), VERR_INVALID_FLAGS);
345 AssertMsgReturn(!(GCPhysDst & X86_PAGE_OFFSET_MASK), ("GCPhysDst=%RGp\n", GCPhysDst), VERR_OUT_OF_RANGE);
346 AssertReturn(GCPhysDst < _1E, VERR_OUT_OF_RANGE);
347 if (GCPhysSrc != GCPhysDst)
348 {
349 AssertMsgReturn(!(GCPhysSrc & X86_PAGE_OFFSET_MASK), ("GCPhysSrc=%RGp\n", GCPhysSrc), VERR_OUT_OF_RANGE);
350 AssertReturn(GCPhysSrc < _1E, VERR_OUT_OF_RANGE);
351 }
352
353 /*
354 * Compose and make the hypercall.
355 * Ring-3 is not allowed to fill in the host physical addresses of the call.
356 */
357 HV_INPUT_MAP_GPA_PAGES *pMapPages = (HV_INPUT_MAP_GPA_PAGES *)pGVCpu->nem.s.pbHypercallData;
358 AssertPtrReturn(pMapPages, VERR_INTERNAL_ERROR_3);
359 pMapPages->TargetPartitionId = pGVM->nem.s.idHvPartition;
360 pMapPages->TargetGpaBase = GCPhysDst >> X86_PAGE_SHIFT;
361 pMapPages->MapFlags = fFlags;
362 pMapPages->u32ExplicitPadding = 0;
363 for (uint32_t iPage = 0; iPage < cPages; iPage++, GCPhysSrc += X86_PAGE_SIZE)
364 {
365 RTHCPHYS HCPhys = NIL_RTGCPHYS;
366 int rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysSrc, &HCPhys);
367 AssertRCReturn(rc, rc);
368 pMapPages->PageList[iPage] = HCPhys >> X86_PAGE_SHIFT;
369 }
370
371 uint64_t uResult = g_pfnHvlInvokeHypercall(HvCallMapGpaPages | ((uint64_t)cPages << 32),
372 pGVCpu->nem.s.HCPhysHypercallData, 0);
373 Log6(("NEMR0MapPages: %RGp/%RGp L %u prot %#x -> %#RX64\n",
374 GCPhysDst, GCPhysSrc - cPages * X86_PAGE_SIZE, cPages, fFlags, uResult));
375 if (uResult == ((uint64_t)cPages << 32))
376 return VINF_SUCCESS;
377
378 LogRel(("g_pfnHvlInvokeHypercall/MapGpaPages -> %#RX64\n", uResult));
379 return VERR_NEM_MAP_PAGES_FAILED;
380}
381
382
383/**
384 * Maps pages into the guest physical address space.
385 *
386 * Generally the caller will be under the PGM lock already, so no extra effort
387 * is needed to make sure all changes happens under it.
388 *
389 * @returns VBox status code.
390 * @param pGVM The ring-0 VM handle.
391 * @param pVM The cross context VM handle.
392 * @param idCpu The calling EMT. Necessary for getting the
393 * hypercall page and arguments.
394 * @thread EMT(idCpu)
395 */
396VMMR0_INT_DECL(int) NEMR0MapPages(PGVM pGVM, PVM pVM, VMCPUID idCpu)
397{
398 /*
399 * Unpack the call.
400 */
401 int rc = GVMMR0ValidateGVMandVMandEMT(pGVM, pVM, idCpu);
402 if (RT_SUCCESS(rc))
403 {
404 PVMCPU pVCpu = &pVM->aCpus[idCpu];
405 PGVMCPU pGVCpu = &pGVM->aCpus[idCpu];
406
407 RTGCPHYS const GCPhysSrc = pVCpu->nem.s.Hypercall.MapPages.GCPhysSrc;
408 RTGCPHYS const GCPhysDst = pVCpu->nem.s.Hypercall.MapPages.GCPhysDst;
409 uint32_t const cPages = pVCpu->nem.s.Hypercall.MapPages.cPages;
410 HV_MAP_GPA_FLAGS const fFlags = pVCpu->nem.s.Hypercall.MapPages.fFlags;
411
412 /*
413 * Do the work.
414 */
415 rc = nemR0WinMapPages(pGVM, pVM, pGVCpu, GCPhysSrc, GCPhysDst, cPages, fFlags);
416 }
417 return rc;
418}
419
420
421/**
422 * Worker for NEMR0UnmapPages and others.
423 */
424NEM_TMPL_STATIC int nemR0WinUnmapPages(PGVM pGVM, PGVMCPU pGVCpu, RTGCPHYS GCPhys, uint32_t cPages)
425{
426 /*
427 * Validate input.
428 */
429 AssertReturn(g_pfnHvlInvokeHypercall, VERR_NEM_MISSING_KERNEL_API);
430
431 AssertReturn(cPages > 0, VERR_OUT_OF_RANGE);
432 AssertReturn(cPages <= NEM_MAX_UNMAP_PAGES, VERR_OUT_OF_RANGE);
433 AssertMsgReturn(!(GCPhys & X86_PAGE_OFFSET_MASK), ("%RGp\n", GCPhys), VERR_OUT_OF_RANGE);
434 AssertReturn(GCPhys < _1E, VERR_OUT_OF_RANGE);
435
436 /*
437 * Compose and make the hypercall.
438 */
439 HV_INPUT_UNMAP_GPA_PAGES *pUnmapPages = (HV_INPUT_UNMAP_GPA_PAGES *)pGVCpu->nem.s.pbHypercallData;
440 AssertPtrReturn(pUnmapPages, VERR_INTERNAL_ERROR_3);
441 pUnmapPages->TargetPartitionId = pGVM->nem.s.idHvPartition;
442 pUnmapPages->TargetGpaBase = GCPhys >> X86_PAGE_SHIFT;
443 pUnmapPages->fFlags = 0;
444
445 uint64_t uResult = g_pfnHvlInvokeHypercall(HvCallUnmapGpaPages | ((uint64_t)cPages << 32),
446 pGVCpu->nem.s.HCPhysHypercallData, 0);
447 Log6(("NEMR0UnmapPages: %RGp L %u -> %#RX64\n", GCPhys, cPages, uResult));
448 if (uResult == ((uint64_t)cPages << 32))
449 {
450#if 1 /* Do we need to do this? Hopefully not... */
451 uint64_t volatile uR = g_pfnHvlInvokeHypercall(HvCallUncommitGpaPages | ((uint64_t)cPages << 32),
452 pGVCpu->nem.s.HCPhysHypercallData, 0);
453 AssertMsg(uR == ((uint64_t)cPages << 32), ("uR=%#RX64\n", uR)); NOREF(uR);
454#endif
455 return VINF_SUCCESS;
456 }
457
458 LogRel(("g_pfnHvlInvokeHypercall/UnmapGpaPages -> %#RX64\n", uResult));
459 return VERR_NEM_UNMAP_PAGES_FAILED;
460}
461
462
463/**
464 * Unmaps pages from the guest physical address space.
465 *
466 * Generally the caller will be under the PGM lock already, so no extra effort
467 * is needed to make sure all changes happens under it.
468 *
469 * @returns VBox status code.
470 * @param pGVM The ring-0 VM handle.
471 * @param pVM The cross context VM handle.
472 * @param idCpu The calling EMT. Necessary for getting the
473 * hypercall page and arguments.
474 * @thread EMT(idCpu)
475 */
476VMMR0_INT_DECL(int) NEMR0UnmapPages(PGVM pGVM, PVM pVM, VMCPUID idCpu)
477{
478 /*
479 * Unpack the call.
480 */
481 int rc = GVMMR0ValidateGVMandVMandEMT(pGVM, pVM, idCpu);
482 if (RT_SUCCESS(rc))
483 {
484 PVMCPU pVCpu = &pVM->aCpus[idCpu];
485 PGVMCPU pGVCpu = &pGVM->aCpus[idCpu];
486
487 RTGCPHYS const GCPhys = pVCpu->nem.s.Hypercall.UnmapPages.GCPhys;
488 uint32_t const cPages = pVCpu->nem.s.Hypercall.UnmapPages.cPages;
489
490 /*
491 * Do the work.
492 */
493 rc = nemR0WinUnmapPages(pGVM, pGVCpu, GCPhys, cPages);
494 }
495 return rc;
496}
497
498
499/**
500 * Worker for NEMR0ExportState.
501 *
502 * Intention is to use it internally later.
503 *
504 * @returns VBox status code.
505 * @param pGVM The ring-0 VM handle.
506 * @param pGVCpu The irng-0 VCPU handle.
507 * @param pCtx The CPU context structure to import into.
508 */
509NEM_TMPL_STATIC int nemR0WinExportState(PGVM pGVM, PGVMCPU pGVCpu, PCPUMCTX pCtx)
510{
511 PVMCPU pVCpu = &pGVM->pVM->aCpus[pGVCpu->idCpu];
512 HV_INPUT_SET_VP_REGISTERS *pInput = (HV_INPUT_SET_VP_REGISTERS *)pGVCpu->nem.s.pbHypercallData;
513 AssertPtrReturn(pInput, VERR_INTERNAL_ERROR_3);
514
515 pInput->PartitionId = pGVM->nem.s.idHvPartition;
516 pInput->VpIndex = pGVCpu->idCpu;
517 pInput->RsvdZ = 0;
518
519 uint64_t const fWhat = ~pCtx->fExtrn & (CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_NEM_WIN_MASK);
520 if (!fWhat)
521 return VINF_SUCCESS;
522 uintptr_t iReg = 0;
523
524 /* GPRs */
525 if (fWhat & CPUMCTX_EXTRN_GPRS_MASK)
526 {
527 if (fWhat & CPUMCTX_EXTRN_RAX)
528 {
529 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
530 pInput->Elements[iReg].Name = HvX64RegisterRax;
531 pInput->Elements[iReg].Value.Reg64 = pCtx->rax;
532 iReg++;
533 }
534 if (fWhat & CPUMCTX_EXTRN_RCX)
535 {
536 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
537 pInput->Elements[iReg].Name = HvX64RegisterRcx;
538 pInput->Elements[iReg].Value.Reg64 = pCtx->rcx;
539 iReg++;
540 }
541 if (fWhat & CPUMCTX_EXTRN_RDX)
542 {
543 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
544 pInput->Elements[iReg].Name = HvX64RegisterRdx;
545 pInput->Elements[iReg].Value.Reg64 = pCtx->rdx;
546 iReg++;
547 }
548 if (fWhat & CPUMCTX_EXTRN_RBX)
549 {
550 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
551 pInput->Elements[iReg].Name = HvX64RegisterRbx;
552 pInput->Elements[iReg].Value.Reg64 = pCtx->rbx;
553 iReg++;
554 }
555 if (fWhat & CPUMCTX_EXTRN_RSP)
556 {
557 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
558 pInput->Elements[iReg].Name = HvX64RegisterRsp;
559 pInput->Elements[iReg].Value.Reg64 = pCtx->rsp;
560 iReg++;
561 }
562 if (fWhat & CPUMCTX_EXTRN_RBP)
563 {
564 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
565 pInput->Elements[iReg].Name = HvX64RegisterRbp;
566 pInput->Elements[iReg].Value.Reg64 = pCtx->rbp;
567 iReg++;
568 }
569 if (fWhat & CPUMCTX_EXTRN_RSI)
570 {
571 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
572 pInput->Elements[iReg].Name = HvX64RegisterRsi;
573 pInput->Elements[iReg].Value.Reg64 = pCtx->rsi;
574 iReg++;
575 }
576 if (fWhat & CPUMCTX_EXTRN_RDI)
577 {
578 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
579 pInput->Elements[iReg].Name = HvX64RegisterRdi;
580 pInput->Elements[iReg].Value.Reg64 = pCtx->rdi;
581 iReg++;
582 }
583 if (fWhat & CPUMCTX_EXTRN_R8_R15)
584 {
585 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
586 pInput->Elements[iReg].Name = HvX64RegisterR8;
587 pInput->Elements[iReg].Value.Reg64 = pCtx->r8;
588 iReg++;
589 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
590 pInput->Elements[iReg].Name = HvX64RegisterR9;
591 pInput->Elements[iReg].Value.Reg64 = pCtx->r9;
592 iReg++;
593 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
594 pInput->Elements[iReg].Name = HvX64RegisterR10;
595 pInput->Elements[iReg].Value.Reg64 = pCtx->r10;
596 iReg++;
597 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
598 pInput->Elements[iReg].Name = HvX64RegisterR11;
599 pInput->Elements[iReg].Value.Reg64 = pCtx->r11;
600 iReg++;
601 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
602 pInput->Elements[iReg].Name = HvX64RegisterR12;
603 pInput->Elements[iReg].Value.Reg64 = pCtx->r12;
604 iReg++;
605 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
606 pInput->Elements[iReg].Name = HvX64RegisterR13;
607 pInput->Elements[iReg].Value.Reg64 = pCtx->r13;
608 iReg++;
609 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
610 pInput->Elements[iReg].Name = HvX64RegisterR14;
611 pInput->Elements[iReg].Value.Reg64 = pCtx->r14;
612 iReg++;
613 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
614 pInput->Elements[iReg].Name = HvX64RegisterR15;
615 pInput->Elements[iReg].Value.Reg64 = pCtx->r15;
616 iReg++;
617 }
618 }
619
620 /* RIP & Flags */
621 if (fWhat & CPUMCTX_EXTRN_RIP)
622 {
623 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
624 pInput->Elements[iReg].Name = HvX64RegisterRip;
625 pInput->Elements[iReg].Value.Reg64 = pCtx->rip;
626 iReg++;
627 }
628 if (fWhat & CPUMCTX_EXTRN_RFLAGS)
629 {
630 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
631 pInput->Elements[iReg].Name = HvX64RegisterRflags;
632 pInput->Elements[iReg].Value.Reg64 = pCtx->rflags.u;
633 iReg++;
634 }
635
636 /* Segments */
637#define COPY_OUT_SEG(a_idx, a_enmName, a_SReg) \
638 do { \
639 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[a_idx]); \
640 pInput->Elements[a_idx].Name = a_enmName; \
641 pInput->Elements[a_idx].Value.Segment.Base = (a_SReg).u64Base; \
642 pInput->Elements[a_idx].Value.Segment.Limit = (a_SReg).u32Limit; \
643 pInput->Elements[a_idx].Value.Segment.Selector = (a_SReg).Sel; \
644 pInput->Elements[a_idx].Value.Segment.Attributes = (a_SReg).Attr.u; \
645 } while (0)
646 if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
647 {
648 if (fWhat & CPUMCTX_EXTRN_CS)
649 {
650 COPY_OUT_SEG(iReg, HvX64RegisterCs, pCtx->cs);
651 iReg++;
652 }
653 if (fWhat & CPUMCTX_EXTRN_ES)
654 {
655 COPY_OUT_SEG(iReg, HvX64RegisterEs, pCtx->es);
656 iReg++;
657 }
658 if (fWhat & CPUMCTX_EXTRN_SS)
659 {
660 COPY_OUT_SEG(iReg, HvX64RegisterSs, pCtx->ss);
661 iReg++;
662 }
663 if (fWhat & CPUMCTX_EXTRN_DS)
664 {
665 COPY_OUT_SEG(iReg, HvX64RegisterDs, pCtx->ds);
666 iReg++;
667 }
668 if (fWhat & CPUMCTX_EXTRN_FS)
669 {
670 COPY_OUT_SEG(iReg, HvX64RegisterFs, pCtx->fs);
671 iReg++;
672 }
673 if (fWhat & CPUMCTX_EXTRN_GS)
674 {
675 COPY_OUT_SEG(iReg, HvX64RegisterGs, pCtx->gs);
676 iReg++;
677 }
678 }
679
680 /* Descriptor tables & task segment. */
681 if (fWhat & CPUMCTX_EXTRN_TABLE_MASK)
682 {
683 if (fWhat & CPUMCTX_EXTRN_LDTR)
684 {
685 COPY_OUT_SEG(iReg, HvX64RegisterLdtr, pCtx->ldtr);
686 iReg++;
687 }
688 if (fWhat & CPUMCTX_EXTRN_TR)
689 {
690 COPY_OUT_SEG(iReg, HvX64RegisterTr, pCtx->tr);
691 iReg++;
692 }
693
694 if (fWhat & CPUMCTX_EXTRN_IDTR)
695 {
696 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
697 pInput->Elements[iReg].Value.Table.Pad[0] = 0;
698 pInput->Elements[iReg].Value.Table.Pad[1] = 0;
699 pInput->Elements[iReg].Value.Table.Pad[2] = 0;
700 pInput->Elements[iReg].Name = HvX64RegisterIdtr;
701 pInput->Elements[iReg].Value.Table.Limit = pCtx->idtr.cbIdt;
702 pInput->Elements[iReg].Value.Table.Base = pCtx->idtr.pIdt;
703 iReg++;
704 }
705 if (fWhat & CPUMCTX_EXTRN_GDTR)
706 {
707 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
708 pInput->Elements[iReg].Value.Table.Pad[0] = 0;
709 pInput->Elements[iReg].Value.Table.Pad[1] = 0;
710 pInput->Elements[iReg].Value.Table.Pad[2] = 0;
711 pInput->Elements[iReg].Name = HvX64RegisterGdtr;
712 pInput->Elements[iReg].Value.Table.Limit = pCtx->gdtr.cbGdt;
713 pInput->Elements[iReg].Value.Table.Base = pCtx->gdtr.pGdt;
714 iReg++;
715 }
716 }
717
718 /* Control registers. */
719 if (fWhat & CPUMCTX_EXTRN_CR_MASK)
720 {
721 if (fWhat & CPUMCTX_EXTRN_CR0)
722 {
723 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
724 pInput->Elements[iReg].Name = HvX64RegisterCr0;
725 pInput->Elements[iReg].Value.Reg64 = pCtx->cr0;
726 iReg++;
727 }
728 if (fWhat & CPUMCTX_EXTRN_CR2)
729 {
730 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
731 pInput->Elements[iReg].Name = HvX64RegisterCr2;
732 pInput->Elements[iReg].Value.Reg64 = pCtx->cr2;
733 iReg++;
734 }
735 if (fWhat & CPUMCTX_EXTRN_CR3)
736 {
737 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
738 pInput->Elements[iReg].Name = HvX64RegisterCr3;
739 pInput->Elements[iReg].Value.Reg64 = pCtx->cr3;
740 iReg++;
741 }
742 if (fWhat & CPUMCTX_EXTRN_CR4)
743 {
744 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
745 pInput->Elements[iReg].Name = HvX64RegisterCr4;
746 pInput->Elements[iReg].Value.Reg64 = pCtx->cr4;
747 iReg++;
748 }
749 }
750 /** @todo CR8/TPR */
751 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
752 pInput->Elements[iReg].Name = HvX64RegisterCr8;
753 pInput->Elements[iReg].Value.Reg64 = CPUMGetGuestCR8(pVCpu);
754 iReg++;
755
756 /** @todo does HvX64RegisterXfem mean XCR0? What about the related MSR. */
757
758 /* Debug registers. */
759/** @todo fixme. Figure out what the hyper-v version of KVM_SET_GUEST_DEBUG would be. */
760 if (fWhat & CPUMCTX_EXTRN_DR0_DR3)
761 {
762 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
763 pInput->Elements[iReg].Name = HvX64RegisterDr0;
764 //pInput->Elements[iReg].Value.Reg64 = CPUMGetHyperDR0(pVCpu);
765 pInput->Elements[iReg].Value.Reg64 = pCtx->dr[0];
766 iReg++;
767 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
768 pInput->Elements[iReg].Name = HvX64RegisterDr1;
769 //pInput->Elements[iReg].Value.Reg64 = CPUMGetHyperDR1(pVCpu);
770 pInput->Elements[iReg].Value.Reg64 = pCtx->dr[1];
771 iReg++;
772 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
773 pInput->Elements[iReg].Name = HvX64RegisterDr2;
774 //pInput->Elements[iReg].Value.Reg64 = CPUMGetHyperDR2(pVCpu);
775 pInput->Elements[iReg].Value.Reg64 = pCtx->dr[2];
776 iReg++;
777 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
778 pInput->Elements[iReg].Name = HvX64RegisterDr3;
779 //pInput->Elements[iReg].Value.Reg64 = CPUMGetHyperDR3(pVCpu);
780 pInput->Elements[iReg].Value.Reg64 = pCtx->dr[3];
781 iReg++;
782 }
783 if (fWhat & CPUMCTX_EXTRN_DR6)
784 {
785 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
786 pInput->Elements[iReg].Name = HvX64RegisterDr6;
787 //pInput->Elements[iReg].Value.Reg64 = CPUMGetHyperDR6(pVCpu);
788 pInput->Elements[iReg].Value.Reg64 = pCtx->dr[6];
789 iReg++;
790 }
791 if (fWhat & CPUMCTX_EXTRN_DR7)
792 {
793 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
794 pInput->Elements[iReg].Name = HvX64RegisterDr7;
795 //pInput->Elements[iReg].Value.Reg64 = CPUMGetHyperDR7(pVCpu);
796 pInput->Elements[iReg].Value.Reg64 = pCtx->dr[7];
797 iReg++;
798 }
799
800 /* Floating point state. */
801 if (fWhat & CPUMCTX_EXTRN_X87)
802 {
803 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
804 pInput->Elements[iReg].Name = HvX64RegisterFpMmx0;
805 pInput->Elements[iReg].Value.Fp.AsUINT128.Low64 = pCtx->pXStateR0->x87.aRegs[0].au64[0];
806 pInput->Elements[iReg].Value.Fp.AsUINT128.High64 = pCtx->pXStateR0->x87.aRegs[0].au64[1];
807 iReg++;
808 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
809 pInput->Elements[iReg].Name = HvX64RegisterFpMmx1;
810 pInput->Elements[iReg].Value.Fp.AsUINT128.Low64 = pCtx->pXStateR0->x87.aRegs[1].au64[0];
811 pInput->Elements[iReg].Value.Fp.AsUINT128.High64 = pCtx->pXStateR0->x87.aRegs[1].au64[1];
812 iReg++;
813 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
814 pInput->Elements[iReg].Name = HvX64RegisterFpMmx2;
815 pInput->Elements[iReg].Value.Fp.AsUINT128.Low64 = pCtx->pXStateR0->x87.aRegs[2].au64[0];
816 pInput->Elements[iReg].Value.Fp.AsUINT128.High64 = pCtx->pXStateR0->x87.aRegs[2].au64[1];
817 iReg++;
818 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
819 pInput->Elements[iReg].Name = HvX64RegisterFpMmx3;
820 pInput->Elements[iReg].Value.Fp.AsUINT128.Low64 = pCtx->pXStateR0->x87.aRegs[3].au64[0];
821 pInput->Elements[iReg].Value.Fp.AsUINT128.High64 = pCtx->pXStateR0->x87.aRegs[3].au64[1];
822 iReg++;
823 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
824 pInput->Elements[iReg].Name = HvX64RegisterFpMmx4;
825 pInput->Elements[iReg].Value.Fp.AsUINT128.Low64 = pCtx->pXStateR0->x87.aRegs[4].au64[0];
826 pInput->Elements[iReg].Value.Fp.AsUINT128.High64 = pCtx->pXStateR0->x87.aRegs[4].au64[1];
827 iReg++;
828 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
829 pInput->Elements[iReg].Name = HvX64RegisterFpMmx5;
830 pInput->Elements[iReg].Value.Fp.AsUINT128.Low64 = pCtx->pXStateR0->x87.aRegs[5].au64[0];
831 pInput->Elements[iReg].Value.Fp.AsUINT128.High64 = pCtx->pXStateR0->x87.aRegs[5].au64[1];
832 iReg++;
833 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
834 pInput->Elements[iReg].Name = HvX64RegisterFpMmx6;
835 pInput->Elements[iReg].Value.Fp.AsUINT128.Low64 = pCtx->pXStateR0->x87.aRegs[6].au64[0];
836 pInput->Elements[iReg].Value.Fp.AsUINT128.High64 = pCtx->pXStateR0->x87.aRegs[6].au64[1];
837 iReg++;
838 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
839 pInput->Elements[iReg].Name = HvX64RegisterFpMmx7;
840 pInput->Elements[iReg].Value.Fp.AsUINT128.Low64 = pCtx->pXStateR0->x87.aRegs[7].au64[0];
841 pInput->Elements[iReg].Value.Fp.AsUINT128.High64 = pCtx->pXStateR0->x87.aRegs[7].au64[1];
842 iReg++;
843
844 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
845 pInput->Elements[iReg].Name = HvX64RegisterFpControlStatus;
846 pInput->Elements[iReg].Value.FpControlStatus.FpControl = pCtx->pXStateR0->x87.FCW;
847 pInput->Elements[iReg].Value.FpControlStatus.FpStatus = pCtx->pXStateR0->x87.FSW;
848 pInput->Elements[iReg].Value.FpControlStatus.FpTag = pCtx->pXStateR0->x87.FTW;
849 pInput->Elements[iReg].Value.FpControlStatus.Reserved = pCtx->pXStateR0->x87.FTW >> 8;
850 pInput->Elements[iReg].Value.FpControlStatus.LastFpOp = pCtx->pXStateR0->x87.FOP;
851 pInput->Elements[iReg].Value.FpControlStatus.LastFpRip = (pCtx->pXStateR0->x87.FPUIP)
852 | ((uint64_t)pCtx->pXStateR0->x87.CS << 32)
853 | ((uint64_t)pCtx->pXStateR0->x87.Rsrvd1 << 48);
854 iReg++;
855/** @todo we've got trouble if if we try write just SSE w/o X87. */
856 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
857 pInput->Elements[iReg].Name = HvX64RegisterXmmControlStatus;
858 pInput->Elements[iReg].Value.XmmControlStatus.LastFpRdp = (pCtx->pXStateR0->x87.FPUDP)
859 | ((uint64_t)pCtx->pXStateR0->x87.DS << 32)
860 | ((uint64_t)pCtx->pXStateR0->x87.Rsrvd2 << 48);
861 pInput->Elements[iReg].Value.XmmControlStatus.XmmStatusControl = pCtx->pXStateR0->x87.MXCSR;
862 pInput->Elements[iReg].Value.XmmControlStatus.XmmStatusControlMask = pCtx->pXStateR0->x87.MXCSR_MASK; /** @todo ??? (Isn't this an output field?) */
863 iReg++;
864 }
865
866 /* Vector state. */
867 if (fWhat & CPUMCTX_EXTRN_SSE_AVX)
868 {
869 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
870 pInput->Elements[iReg].Name = HvX64RegisterXmm0;
871 pInput->Elements[iReg].Value.Reg128.Low64 = pCtx->pXStateR0->x87.aXMM[0].uXmm.s.Lo;
872 pInput->Elements[iReg].Value.Reg128.High64 = pCtx->pXStateR0->x87.aXMM[0].uXmm.s.Hi;
873 iReg++;
874 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
875 pInput->Elements[iReg].Name = HvX64RegisterXmm1;
876 pInput->Elements[iReg].Value.Reg128.Low64 = pCtx->pXStateR0->x87.aXMM[1].uXmm.s.Lo;
877 pInput->Elements[iReg].Value.Reg128.High64 = pCtx->pXStateR0->x87.aXMM[1].uXmm.s.Hi;
878 iReg++;
879 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
880 pInput->Elements[iReg].Name = HvX64RegisterXmm2;
881 pInput->Elements[iReg].Value.Reg128.Low64 = pCtx->pXStateR0->x87.aXMM[2].uXmm.s.Lo;
882 pInput->Elements[iReg].Value.Reg128.High64 = pCtx->pXStateR0->x87.aXMM[2].uXmm.s.Hi;
883 iReg++;
884 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
885 pInput->Elements[iReg].Name = HvX64RegisterXmm3;
886 pInput->Elements[iReg].Value.Reg128.Low64 = pCtx->pXStateR0->x87.aXMM[3].uXmm.s.Lo;
887 pInput->Elements[iReg].Value.Reg128.High64 = pCtx->pXStateR0->x87.aXMM[3].uXmm.s.Hi;
888 iReg++;
889 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
890 pInput->Elements[iReg].Name = HvX64RegisterXmm4;
891 pInput->Elements[iReg].Value.Reg128.Low64 = pCtx->pXStateR0->x87.aXMM[4].uXmm.s.Lo;
892 pInput->Elements[iReg].Value.Reg128.High64 = pCtx->pXStateR0->x87.aXMM[4].uXmm.s.Hi;
893 iReg++;
894 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
895 pInput->Elements[iReg].Name = HvX64RegisterXmm5;
896 pInput->Elements[iReg].Value.Reg128.Low64 = pCtx->pXStateR0->x87.aXMM[5].uXmm.s.Lo;
897 pInput->Elements[iReg].Value.Reg128.High64 = pCtx->pXStateR0->x87.aXMM[5].uXmm.s.Hi;
898 iReg++;
899 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
900 pInput->Elements[iReg].Name = HvX64RegisterXmm6;
901 pInput->Elements[iReg].Value.Reg128.Low64 = pCtx->pXStateR0->x87.aXMM[6].uXmm.s.Lo;
902 pInput->Elements[iReg].Value.Reg128.High64 = pCtx->pXStateR0->x87.aXMM[6].uXmm.s.Hi;
903 iReg++;
904 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
905 pInput->Elements[iReg].Name = HvX64RegisterXmm7;
906 pInput->Elements[iReg].Value.Reg128.Low64 = pCtx->pXStateR0->x87.aXMM[7].uXmm.s.Lo;
907 pInput->Elements[iReg].Value.Reg128.High64 = pCtx->pXStateR0->x87.aXMM[7].uXmm.s.Hi;
908 iReg++;
909 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
910 pInput->Elements[iReg].Name = HvX64RegisterXmm8;
911 pInput->Elements[iReg].Value.Reg128.Low64 = pCtx->pXStateR0->x87.aXMM[8].uXmm.s.Lo;
912 pInput->Elements[iReg].Value.Reg128.High64 = pCtx->pXStateR0->x87.aXMM[8].uXmm.s.Hi;
913 iReg++;
914 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
915 pInput->Elements[iReg].Name = HvX64RegisterXmm9;
916 pInput->Elements[iReg].Value.Reg128.Low64 = pCtx->pXStateR0->x87.aXMM[9].uXmm.s.Lo;
917 pInput->Elements[iReg].Value.Reg128.High64 = pCtx->pXStateR0->x87.aXMM[9].uXmm.s.Hi;
918 iReg++;
919 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
920 pInput->Elements[iReg].Name = HvX64RegisterXmm10;
921 pInput->Elements[iReg].Value.Reg128.Low64 = pCtx->pXStateR0->x87.aXMM[10].uXmm.s.Lo;
922 pInput->Elements[iReg].Value.Reg128.High64 = pCtx->pXStateR0->x87.aXMM[10].uXmm.s.Hi;
923 iReg++;
924 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
925 pInput->Elements[iReg].Name = HvX64RegisterXmm11;
926 pInput->Elements[iReg].Value.Reg128.Low64 = pCtx->pXStateR0->x87.aXMM[11].uXmm.s.Lo;
927 pInput->Elements[iReg].Value.Reg128.High64 = pCtx->pXStateR0->x87.aXMM[11].uXmm.s.Hi;
928 iReg++;
929 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
930 pInput->Elements[iReg].Name = HvX64RegisterXmm12;
931 pInput->Elements[iReg].Value.Reg128.Low64 = pCtx->pXStateR0->x87.aXMM[12].uXmm.s.Lo;
932 pInput->Elements[iReg].Value.Reg128.High64 = pCtx->pXStateR0->x87.aXMM[12].uXmm.s.Hi;
933 iReg++;
934 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
935 pInput->Elements[iReg].Name = HvX64RegisterXmm13;
936 pInput->Elements[iReg].Value.Reg128.Low64 = pCtx->pXStateR0->x87.aXMM[13].uXmm.s.Lo;
937 pInput->Elements[iReg].Value.Reg128.High64 = pCtx->pXStateR0->x87.aXMM[13].uXmm.s.Hi;
938 iReg++;
939 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
940 pInput->Elements[iReg].Name = HvX64RegisterXmm14;
941 pInput->Elements[iReg].Value.Reg128.Low64 = pCtx->pXStateR0->x87.aXMM[14].uXmm.s.Lo;
942 pInput->Elements[iReg].Value.Reg128.High64 = pCtx->pXStateR0->x87.aXMM[14].uXmm.s.Hi;
943 iReg++;
944 HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[iReg]);
945 pInput->Elements[iReg].Name = HvX64RegisterXmm15;
946 pInput->Elements[iReg].Value.Reg128.Low64 = pCtx->pXStateR0->x87.aXMM[15].uXmm.s.Lo;
947 pInput->Elements[iReg].Value.Reg128.High64 = pCtx->pXStateR0->x87.aXMM[15].uXmm.s.Hi;
948 iReg++;
949 }
950
951 /* MSRs */
952 // HvX64RegisterTsc - don't touch
953 /** @todo does HvX64RegisterTsc include TSC_AUX? Is it TSC_AUX? */
954 if (fWhat & CPUMCTX_EXTRN_EFER)
955 {
956 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
957 pInput->Elements[iReg].Name = HvX64RegisterEfer;
958 pInput->Elements[iReg].Value.Reg64 = pCtx->msrEFER;
959 iReg++;
960 }
961 if (fWhat & CPUMCTX_EXTRN_KERNEL_GS_BASE)
962 {
963 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
964 pInput->Elements[iReg].Name = HvX64RegisterKernelGsBase;
965 pInput->Elements[iReg].Value.Reg64 = pCtx->msrKERNELGSBASE;
966 iReg++;
967 }
968 if (fWhat & CPUMCTX_EXTRN_SYSENTER_MSRS)
969 {
970 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
971 pInput->Elements[iReg].Name = HvX64RegisterSysenterCs;
972 pInput->Elements[iReg].Value.Reg64 = pCtx->SysEnter.cs;
973 iReg++;
974 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
975 pInput->Elements[iReg].Name = HvX64RegisterSysenterEip;
976 pInput->Elements[iReg].Value.Reg64 = pCtx->SysEnter.eip;
977 iReg++;
978 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
979 pInput->Elements[iReg].Name = HvX64RegisterSysenterEsp;
980 pInput->Elements[iReg].Value.Reg64 = pCtx->SysEnter.esp;
981 iReg++;
982 }
983 if (fWhat & CPUMCTX_EXTRN_SYSCALL_MSRS)
984 {
985 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
986 pInput->Elements[iReg].Name = HvX64RegisterStar;
987 pInput->Elements[iReg].Value.Reg64 = pCtx->msrSTAR;
988 iReg++;
989 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
990 pInput->Elements[iReg].Name = HvX64RegisterLstar;
991 pInput->Elements[iReg].Value.Reg64 = pCtx->msrLSTAR;
992 iReg++;
993 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
994 pInput->Elements[iReg].Name = HvX64RegisterCstar;
995 pInput->Elements[iReg].Value.Reg64 = pCtx->msrCSTAR;
996 iReg++;
997 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
998 pInput->Elements[iReg].Name = HvX64RegisterSfmask;
999 pInput->Elements[iReg].Value.Reg64 = pCtx->msrSFMASK;
1000 iReg++;
1001 }
1002 if (fWhat & CPUMCTX_EXTRN_OTHER_MSRS)
1003 {
1004 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
1005 pInput->Elements[iReg].Name = HvX64RegisterApicBase;
1006 pInput->Elements[iReg].Value.Reg64 = APICGetBaseMsrNoCheck(pVCpu);
1007 iReg++;
1008 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
1009 pInput->Elements[iReg].Name = HvX64RegisterPat;
1010 pInput->Elements[iReg].Value.Reg64 = pCtx->msrPAT;
1011 iReg++;
1012 }
1013
1014 /* event injection (always clear it). */
1015 if (fWhat & CPUMCTX_EXTRN_NEM_WIN_EVENT_INJECT)
1016 {
1017 HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
1018 pInput->Elements[iReg].Name = HvRegisterPendingInterruption;
1019 pInput->Elements[iReg].Value.Reg64 = 0;
1020 iReg++;
1021 }
1022 /// @todo HvRegisterInterruptState
1023 /// @todo HvRegisterPendingEvent0
1024 /// @todo HvRegisterPendingEvent1
1025
1026 /*
1027 * Set the registers.
1028 */
1029 Assert((uintptr_t)&pInput->Elements[iReg] - (uintptr_t)pGVCpu->nem.s.pbHypercallData < PAGE_SIZE); /* max is 127 */
1030
1031 /*
1032 * Make the hypercall.
1033 */
1034 uint64_t uResult = g_pfnHvlInvokeHypercall(HV_MAKE_CALL_INFO(HvCallSetVpRegisters, iReg),
1035 pGVCpu->nem.s.HCPhysHypercallData, 0 /*GCPhysOutput*/);
1036 AssertLogRelMsgReturn(uResult == HV_MAKE_CALL_REP_RET(iReg),
1037 ("uResult=%RX64 iRegs=%#x\n", uResult, iReg),
1038 VERR_NEM_SET_REGISTERS_FAILED);
1039 //LogFlow(("nemR0WinExportState: uResult=%#RX64 iReg=%zu fWhat=%#018RX64 fExtrn=%#018RX64 -> %#018RX64\n", uResult, iReg, fWhat, pCtx->fExtrn,
1040 // pCtx->fExtrn | CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_NEM_WIN_MASK | CPUMCTX_EXTRN_KEEPER_NEM ));
1041 pCtx->fExtrn |= CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_NEM_WIN_MASK | CPUMCTX_EXTRN_KEEPER_NEM;
1042 return VINF_SUCCESS;
1043}
1044
1045
1046/**
1047 * Export the state to the native API (out of CPUMCTX).
1048 *
1049 * @returns VBox status code
1050 * @param pGVM The ring-0 VM handle.
1051 * @param pVM The cross context VM handle.
1052 * @param idCpu The calling EMT. Necessary for getting the
1053 * hypercall page and arguments.
1054 */
1055VMMR0_INT_DECL(int) NEMR0ExportState(PGVM pGVM, PVM pVM, VMCPUID idCpu)
1056{
1057 /*
1058 * Validate the call.
1059 */
1060 int rc = GVMMR0ValidateGVMandVMandEMT(pGVM, pVM, idCpu);
1061 if (RT_SUCCESS(rc))
1062 {
1063 PVMCPU pVCpu = &pVM->aCpus[idCpu];
1064 PGVMCPU pGVCpu = &pGVM->aCpus[idCpu];
1065 AssertReturn(g_pfnHvlInvokeHypercall, VERR_NEM_MISSING_KERNEL_API);
1066
1067 /*
1068 * Call worker.
1069 */
1070 rc = nemR0WinExportState(pGVM, pGVCpu, CPUMQueryGuestCtxPtr(pVCpu));
1071 }
1072 return rc;
1073}
1074
1075
1076/**
1077 * Worker for NEMR0ImportState.
1078 *
1079 * Intention is to use it internally later.
1080 *
1081 * @returns VBox status code.
1082 * @param pGVM The ring-0 VM handle.
1083 * @param pGVCpu The irng-0 VCPU handle.
1084 * @param pCtx The CPU context structure to import into.
1085 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
1086 */
1087NEM_TMPL_STATIC int nemR0WinImportState(PGVM pGVM, PGVMCPU pGVCpu, PCPUMCTX pCtx, uint64_t fWhat)
1088{
1089 HV_INPUT_GET_VP_REGISTERS *pInput = (HV_INPUT_GET_VP_REGISTERS *)pGVCpu->nem.s.pbHypercallData;
1090 AssertPtrReturn(pInput, VERR_INTERNAL_ERROR_3);
1091
1092 fWhat &= pCtx->fExtrn;
1093
1094 pInput->PartitionId = pGVM->nem.s.idHvPartition;
1095 pInput->VpIndex = pGVCpu->idCpu;
1096 pInput->fFlags = 0;
1097
1098 /* GPRs */
1099 uintptr_t iReg = 0;
1100 if (fWhat & CPUMCTX_EXTRN_GPRS_MASK)
1101 {
1102 if (fWhat & CPUMCTX_EXTRN_RAX)
1103 pInput->Names[iReg++] = HvX64RegisterRax;
1104 if (fWhat & CPUMCTX_EXTRN_RCX)
1105 pInput->Names[iReg++] = HvX64RegisterRcx;
1106 if (fWhat & CPUMCTX_EXTRN_RDX)
1107 pInput->Names[iReg++] = HvX64RegisterRdx;
1108 if (fWhat & CPUMCTX_EXTRN_RBX)
1109 pInput->Names[iReg++] = HvX64RegisterRbx;
1110 if (fWhat & CPUMCTX_EXTRN_RSP)
1111 pInput->Names[iReg++] = HvX64RegisterRsp;
1112 if (fWhat & CPUMCTX_EXTRN_RBP)
1113 pInput->Names[iReg++] = HvX64RegisterRbp;
1114 if (fWhat & CPUMCTX_EXTRN_RSI)
1115 pInput->Names[iReg++] = HvX64RegisterRsi;
1116 if (fWhat & CPUMCTX_EXTRN_RDI)
1117 pInput->Names[iReg++] = HvX64RegisterRdi;
1118 if (fWhat & CPUMCTX_EXTRN_R8_R15)
1119 {
1120 pInput->Names[iReg++] = HvX64RegisterR8;
1121 pInput->Names[iReg++] = HvX64RegisterR9;
1122 pInput->Names[iReg++] = HvX64RegisterR10;
1123 pInput->Names[iReg++] = HvX64RegisterR11;
1124 pInput->Names[iReg++] = HvX64RegisterR12;
1125 pInput->Names[iReg++] = HvX64RegisterR13;
1126 pInput->Names[iReg++] = HvX64RegisterR14;
1127 pInput->Names[iReg++] = HvX64RegisterR15;
1128 }
1129 }
1130
1131 /* RIP & Flags */
1132 if (fWhat & CPUMCTX_EXTRN_RIP)
1133 pInput->Names[iReg++] = HvX64RegisterRip;
1134 if (fWhat & CPUMCTX_EXTRN_RFLAGS)
1135 pInput->Names[iReg++] = HvX64RegisterRflags;
1136
1137 /* Segments */
1138 if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
1139 {
1140 if (fWhat & CPUMCTX_EXTRN_CS)
1141 pInput->Names[iReg++] = HvX64RegisterCs;
1142 if (fWhat & CPUMCTX_EXTRN_ES)
1143 pInput->Names[iReg++] = HvX64RegisterEs;
1144 if (fWhat & CPUMCTX_EXTRN_SS)
1145 pInput->Names[iReg++] = HvX64RegisterSs;
1146 if (fWhat & CPUMCTX_EXTRN_DS)
1147 pInput->Names[iReg++] = HvX64RegisterDs;
1148 if (fWhat & CPUMCTX_EXTRN_FS)
1149 pInput->Names[iReg++] = HvX64RegisterFs;
1150 if (fWhat & CPUMCTX_EXTRN_GS)
1151 pInput->Names[iReg++] = HvX64RegisterGs;
1152 }
1153
1154 /* Descriptor tables and the task segment. */
1155 if (fWhat & CPUMCTX_EXTRN_TABLE_MASK)
1156 {
1157 if (fWhat & CPUMCTX_EXTRN_LDTR)
1158 pInput->Names[iReg++] = HvX64RegisterLdtr;
1159 if (fWhat & CPUMCTX_EXTRN_TR)
1160 pInput->Names[iReg++] = HvX64RegisterTr;
1161 if (fWhat & CPUMCTX_EXTRN_IDTR)
1162 pInput->Names[iReg++] = HvX64RegisterIdtr;
1163 if (fWhat & CPUMCTX_EXTRN_GDTR)
1164 pInput->Names[iReg++] = HvX64RegisterGdtr;
1165 }
1166
1167 /* Control registers. */
1168 if (fWhat & CPUMCTX_EXTRN_CR_MASK)
1169 {
1170 if (fWhat & CPUMCTX_EXTRN_CR0)
1171 pInput->Names[iReg++] = HvX64RegisterCr0;
1172 if (fWhat & CPUMCTX_EXTRN_CR2)
1173 pInput->Names[iReg++] = HvX64RegisterCr2;
1174 if (fWhat & CPUMCTX_EXTRN_CR3)
1175 pInput->Names[iReg++] = HvX64RegisterCr3;
1176 if (fWhat & CPUMCTX_EXTRN_CR4)
1177 pInput->Names[iReg++] = HvX64RegisterCr4;
1178 }
1179 pInput->Names[iReg++] = HvX64RegisterCr8; /// @todo CR8/TPR
1180
1181 /* Debug registers. */
1182 if (fWhat & CPUMCTX_EXTRN_DR0_DR3)
1183 {
1184 pInput->Names[iReg++] = HvX64RegisterDr0;
1185 pInput->Names[iReg++] = HvX64RegisterDr1;
1186 pInput->Names[iReg++] = HvX64RegisterDr2;
1187 pInput->Names[iReg++] = HvX64RegisterDr3;
1188 }
1189 if (fWhat & CPUMCTX_EXTRN_DR6)
1190 pInput->Names[iReg++] = HvX64RegisterDr6;
1191 if (fWhat & CPUMCTX_EXTRN_DR7)
1192 pInput->Names[iReg++] = HvX64RegisterDr7;
1193
1194 /* Floating point state. */
1195 if (fWhat & CPUMCTX_EXTRN_X87)
1196 {
1197 pInput->Names[iReg++] = HvX64RegisterFpMmx0;
1198 pInput->Names[iReg++] = HvX64RegisterFpMmx1;
1199 pInput->Names[iReg++] = HvX64RegisterFpMmx2;
1200 pInput->Names[iReg++] = HvX64RegisterFpMmx3;
1201 pInput->Names[iReg++] = HvX64RegisterFpMmx4;
1202 pInput->Names[iReg++] = HvX64RegisterFpMmx5;
1203 pInput->Names[iReg++] = HvX64RegisterFpMmx6;
1204 pInput->Names[iReg++] = HvX64RegisterFpMmx7;
1205 pInput->Names[iReg++] = HvX64RegisterFpControlStatus;
1206 }
1207 if (fWhat & (CPUMCTX_EXTRN_X87 | CPUMCTX_EXTRN_SSE_AVX))
1208 pInput->Names[iReg++] = HvX64RegisterXmmControlStatus;
1209
1210 /* Vector state. */
1211 if (fWhat & CPUMCTX_EXTRN_SSE_AVX)
1212 {
1213 pInput->Names[iReg++] = HvX64RegisterXmm0;
1214 pInput->Names[iReg++] = HvX64RegisterXmm1;
1215 pInput->Names[iReg++] = HvX64RegisterXmm2;
1216 pInput->Names[iReg++] = HvX64RegisterXmm3;
1217 pInput->Names[iReg++] = HvX64RegisterXmm4;
1218 pInput->Names[iReg++] = HvX64RegisterXmm5;
1219 pInput->Names[iReg++] = HvX64RegisterXmm6;
1220 pInput->Names[iReg++] = HvX64RegisterXmm7;
1221 pInput->Names[iReg++] = HvX64RegisterXmm8;
1222 pInput->Names[iReg++] = HvX64RegisterXmm9;
1223 pInput->Names[iReg++] = HvX64RegisterXmm10;
1224 pInput->Names[iReg++] = HvX64RegisterXmm11;
1225 pInput->Names[iReg++] = HvX64RegisterXmm12;
1226 pInput->Names[iReg++] = HvX64RegisterXmm13;
1227 pInput->Names[iReg++] = HvX64RegisterXmm14;
1228 pInput->Names[iReg++] = HvX64RegisterXmm15;
1229 }
1230
1231 /* MSRs */
1232 // HvX64RegisterTsc - don't touch
1233 if (fWhat & CPUMCTX_EXTRN_EFER)
1234 pInput->Names[iReg++] = HvX64RegisterEfer;
1235 if (fWhat & CPUMCTX_EXTRN_KERNEL_GS_BASE)
1236 pInput->Names[iReg++] = HvX64RegisterKernelGsBase;
1237 if (fWhat & CPUMCTX_EXTRN_SYSENTER_MSRS)
1238 {
1239 pInput->Names[iReg++] = HvX64RegisterSysenterCs;
1240 pInput->Names[iReg++] = HvX64RegisterSysenterEip;
1241 pInput->Names[iReg++] = HvX64RegisterSysenterEsp;
1242 }
1243 if (fWhat & CPUMCTX_EXTRN_SYSCALL_MSRS)
1244 {
1245 pInput->Names[iReg++] = HvX64RegisterStar;
1246 pInput->Names[iReg++] = HvX64RegisterLstar;
1247 pInput->Names[iReg++] = HvX64RegisterCstar;
1248 pInput->Names[iReg++] = HvX64RegisterSfmask;
1249 }
1250
1251 if (fWhat & CPUMCTX_EXTRN_OTHER_MSRS)
1252 {
1253 pInput->Names[iReg++] = HvX64RegisterApicBase; /// @todo APIC BASE
1254 pInput->Names[iReg++] = HvX64RegisterPat;
1255 }
1256
1257 /* event injection */
1258 pInput->Names[iReg++] = HvRegisterPendingInterruption;
1259 pInput->Names[iReg++] = HvRegisterInterruptState;
1260 pInput->Names[iReg++] = HvRegisterInterruptState;
1261 pInput->Names[iReg++] = HvRegisterPendingEvent0;
1262 pInput->Names[iReg++] = HvRegisterPendingEvent1;
1263 size_t const cRegs = iReg;
1264 size_t const cbInput = RT_ALIGN_Z(RT_OFFSETOF(HV_INPUT_GET_VP_REGISTERS, Names[cRegs]), 32);
1265
1266 HV_REGISTER_VALUE *paValues = (HV_REGISTER_VALUE *)((uint8_t *)pInput + cbInput);
1267 Assert((uintptr_t)&paValues[cRegs] - (uintptr_t)pGVCpu->nem.s.pbHypercallData < PAGE_SIZE); /* (max is around 168 registers) */
1268 RT_BZERO(paValues, cRegs * sizeof(paValues[0]));
1269
1270 /*
1271 * Make the hypercall.
1272 */
1273 uint64_t uResult = g_pfnHvlInvokeHypercall(HV_MAKE_CALL_INFO(HvCallGetVpRegisters, cRegs),
1274 pGVCpu->nem.s.HCPhysHypercallData,
1275 pGVCpu->nem.s.HCPhysHypercallData + cbInput);
1276 AssertLogRelMsgReturn(uResult == HV_MAKE_CALL_REP_RET(cRegs),
1277 ("uResult=%RX64 cRegs=%#x\n", uResult, cRegs),
1278 VERR_NEM_GET_REGISTERS_FAILED);
1279 //LogFlow(("nemR0WinImportState: uResult=%#RX64 iReg=%zu fWhat=%#018RX64 fExtr=%#018RX64\n", uResult, cRegs, fWhat, pCtx->fExtrn));
1280
1281 /*
1282 * Copy information to the CPUM context.
1283 */
1284 PVMCPU pVCpu = &pGVM->pVM->aCpus[pGVCpu->idCpu];
1285 iReg = 0;
1286
1287 /* GPRs */
1288 if (fWhat & CPUMCTX_EXTRN_GPRS_MASK)
1289 {
1290 if (fWhat & CPUMCTX_EXTRN_RAX)
1291 {
1292 Assert(pInput->Names[iReg] == HvX64RegisterRax);
1293 pCtx->rax = paValues[iReg++].Reg64;
1294 }
1295 if (fWhat & CPUMCTX_EXTRN_RCX)
1296 {
1297 Assert(pInput->Names[iReg] == HvX64RegisterRcx);
1298 pCtx->rcx = paValues[iReg++].Reg64;
1299 }
1300 if (fWhat & CPUMCTX_EXTRN_RDX)
1301 {
1302 Assert(pInput->Names[iReg] == HvX64RegisterRdx);
1303 pCtx->rdx = paValues[iReg++].Reg64;
1304 }
1305 if (fWhat & CPUMCTX_EXTRN_RBX)
1306 {
1307 Assert(pInput->Names[iReg] == HvX64RegisterRbx);
1308 pCtx->rbx = paValues[iReg++].Reg64;
1309 }
1310 if (fWhat & CPUMCTX_EXTRN_RSP)
1311 {
1312 Assert(pInput->Names[iReg] == HvX64RegisterRsp);
1313 pCtx->rsp = paValues[iReg++].Reg64;
1314 }
1315 if (fWhat & CPUMCTX_EXTRN_RBP)
1316 {
1317 Assert(pInput->Names[iReg] == HvX64RegisterRbp);
1318 pCtx->rbp = paValues[iReg++].Reg64;
1319 }
1320 if (fWhat & CPUMCTX_EXTRN_RSI)
1321 {
1322 Assert(pInput->Names[iReg] == HvX64RegisterRsi);
1323 pCtx->rsi = paValues[iReg++].Reg64;
1324 }
1325 if (fWhat & CPUMCTX_EXTRN_RDI)
1326 {
1327 Assert(pInput->Names[iReg] == HvX64RegisterRdi);
1328 pCtx->rdi = paValues[iReg++].Reg64;
1329 }
1330 if (fWhat & CPUMCTX_EXTRN_R8_R15)
1331 {
1332 Assert(pInput->Names[iReg] == HvX64RegisterR8);
1333 Assert(pInput->Names[iReg + 7] == HvX64RegisterR15);
1334 pCtx->r8 = paValues[iReg++].Reg64;
1335 pCtx->r9 = paValues[iReg++].Reg64;
1336 pCtx->r10 = paValues[iReg++].Reg64;
1337 pCtx->r11 = paValues[iReg++].Reg64;
1338 pCtx->r12 = paValues[iReg++].Reg64;
1339 pCtx->r13 = paValues[iReg++].Reg64;
1340 pCtx->r14 = paValues[iReg++].Reg64;
1341 pCtx->r15 = paValues[iReg++].Reg64;
1342 }
1343 }
1344
1345 /* RIP & Flags */
1346 if (fWhat & CPUMCTX_EXTRN_RIP)
1347 {
1348 Assert(pInput->Names[iReg] == HvX64RegisterRip);
1349 pCtx->rip = paValues[iReg++].Reg64;
1350 }
1351 if (fWhat & CPUMCTX_EXTRN_RFLAGS)
1352 {
1353 Assert(pInput->Names[iReg] == HvX64RegisterRflags);
1354 pCtx->rflags.u = paValues[iReg++].Reg64;
1355 }
1356
1357 /* Segments */
1358#define COPY_BACK_SEG(a_idx, a_enmName, a_SReg) \
1359 do { \
1360 Assert(pInput->Names[a_idx] == a_enmName); \
1361 (a_SReg).u64Base = paValues[a_idx].Segment.Base; \
1362 (a_SReg).u32Limit = paValues[a_idx].Segment.Limit; \
1363 (a_SReg).ValidSel = (a_SReg).Sel = paValues[a_idx].Segment.Selector; \
1364 (a_SReg).Attr.u = paValues[a_idx].Segment.Attributes; \
1365 (a_SReg).fFlags = CPUMSELREG_FLAGS_VALID; \
1366 } while (0)
1367 if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
1368 {
1369 if (fWhat & CPUMCTX_EXTRN_CS)
1370 {
1371 COPY_BACK_SEG(iReg, HvX64RegisterCs, pCtx->cs);
1372 iReg++;
1373 }
1374 if (fWhat & CPUMCTX_EXTRN_ES)
1375 {
1376 COPY_BACK_SEG(iReg, HvX64RegisterEs, pCtx->es);
1377 iReg++;
1378 }
1379 if (fWhat & CPUMCTX_EXTRN_SS)
1380 {
1381 COPY_BACK_SEG(iReg, HvX64RegisterSs, pCtx->ss);
1382 iReg++;
1383 }
1384 if (fWhat & CPUMCTX_EXTRN_DS)
1385 {
1386 COPY_BACK_SEG(iReg, HvX64RegisterDs, pCtx->ds);
1387 iReg++;
1388 }
1389 if (fWhat & CPUMCTX_EXTRN_FS)
1390 {
1391 COPY_BACK_SEG(iReg, HvX64RegisterFs, pCtx->fs);
1392 iReg++;
1393 }
1394 if (fWhat & CPUMCTX_EXTRN_GS)
1395 {
1396 COPY_BACK_SEG(iReg, HvX64RegisterGs, pCtx->gs);
1397 iReg++;
1398 }
1399 }
1400 /* Descriptor tables and the task segment. */
1401 if (fWhat & CPUMCTX_EXTRN_TABLE_MASK)
1402 {
1403 if (fWhat & CPUMCTX_EXTRN_LDTR)
1404 {
1405 COPY_BACK_SEG(iReg, HvX64RegisterLdtr, pCtx->ldtr);
1406 iReg++;
1407 }
1408 if (fWhat & CPUMCTX_EXTRN_TR)
1409 {
1410 /* AMD-V likes loading TR with in AVAIL state, whereas intel insists on BUSY. So,
1411 avoid to trigger sanity assertions around the code, always fix this. */
1412 COPY_BACK_SEG(iReg, HvX64RegisterTr, pCtx->tr);
1413 switch (pCtx->tr.Attr.n.u4Type)
1414 {
1415 case X86_SEL_TYPE_SYS_386_TSS_BUSY:
1416 case X86_SEL_TYPE_SYS_286_TSS_BUSY:
1417 break;
1418 case X86_SEL_TYPE_SYS_386_TSS_AVAIL:
1419 pCtx->tr.Attr.n.u4Type = X86_SEL_TYPE_SYS_386_TSS_BUSY;
1420 break;
1421 case X86_SEL_TYPE_SYS_286_TSS_AVAIL:
1422 pCtx->tr.Attr.n.u4Type = X86_SEL_TYPE_SYS_286_TSS_BUSY;
1423 break;
1424 }
1425 iReg++;
1426 }
1427 if (fWhat & CPUMCTX_EXTRN_IDTR)
1428 {
1429 Assert(pInput->Names[iReg] == HvX64RegisterIdtr);
1430 pCtx->idtr.cbIdt = paValues[iReg].Table.Limit;
1431 pCtx->idtr.pIdt = paValues[iReg].Table.Base;
1432 iReg++;
1433 }
1434 if (fWhat & CPUMCTX_EXTRN_GDTR)
1435 {
1436 Assert(pInput->Names[iReg] == HvX64RegisterGdtr);
1437 pCtx->gdtr.cbGdt = paValues[iReg].Table.Limit;
1438 pCtx->gdtr.pGdt = paValues[iReg].Table.Base;
1439 iReg++;
1440 }
1441 }
1442
1443 /* Control registers. */
1444 bool fMaybeChangedMode = false;
1445 bool fFlushTlb = false;
1446 bool fFlushGlobalTlb = false;
1447 if (fWhat & CPUMCTX_EXTRN_CR_MASK)
1448 {
1449 if (fWhat & CPUMCTX_EXTRN_CR0)
1450 {
1451 Assert(pInput->Names[iReg] == HvX64RegisterCr0);
1452 if (pCtx->cr0 != paValues[iReg].Reg64)
1453 {
1454 CPUMSetGuestCR0(pVCpu, paValues[iReg].Reg64);
1455 fMaybeChangedMode = true;
1456 fFlushTlb = fFlushGlobalTlb = true; /// @todo fix this
1457 }
1458 iReg++;
1459 }
1460 if (fWhat & CPUMCTX_EXTRN_CR2)
1461 {
1462 Assert(pInput->Names[iReg] == HvX64RegisterCr2);
1463 pCtx->cr2 = paValues[iReg].Reg64;
1464 iReg++;
1465 }
1466 if (fWhat & CPUMCTX_EXTRN_CR3)
1467 {
1468 Assert(pInput->Names[iReg] == HvX64RegisterCr3);
1469 if (pCtx->cr3 != paValues[iReg].Reg64)
1470 {
1471 CPUMSetGuestCR3(pVCpu, paValues[iReg].Reg64);
1472 fFlushTlb = true;
1473 }
1474 iReg++;
1475 }
1476 if (fWhat & CPUMCTX_EXTRN_CR4)
1477 {
1478 Assert(pInput->Names[iReg] == HvX64RegisterCr4);
1479 if (pCtx->cr4 != paValues[iReg].Reg64)
1480 {
1481 CPUMSetGuestCR4(pVCpu, paValues[iReg].Reg64);
1482 fMaybeChangedMode = true;
1483 fFlushTlb = fFlushGlobalTlb = true; /// @todo fix this
1484 }
1485 iReg++;
1486 }
1487 }
1488
1489 /// @todo CR8/TPR
1490 Assert(pInput->Names[iReg] == HvX64RegisterCr8);
1491 APICSetTpr(pVCpu, (uint8_t)paValues[iReg].Reg64 << 4);
1492 iReg++;
1493
1494 /* Debug registers. */
1495/** @todo fixme */
1496 if (fWhat & CPUMCTX_EXTRN_DR0_DR3)
1497 {
1498 Assert(pInput->Names[iReg] == HvX64RegisterDr0);
1499 Assert(pInput->Names[iReg+3] == HvX64RegisterDr3);
1500 if (pCtx->dr[0] != paValues[iReg].Reg64)
1501 CPUMSetGuestDR0(pVCpu, paValues[iReg].Reg64);
1502 iReg++;
1503 if (pCtx->dr[1] != paValues[iReg].Reg64)
1504 CPUMSetGuestDR1(pVCpu, paValues[iReg].Reg64);
1505 iReg++;
1506 if (pCtx->dr[2] != paValues[iReg].Reg64)
1507 CPUMSetGuestDR2(pVCpu, paValues[iReg].Reg64);
1508 iReg++;
1509 if (pCtx->dr[3] != paValues[iReg].Reg64)
1510 CPUMSetGuestDR3(pVCpu, paValues[iReg].Reg64);
1511 iReg++;
1512 }
1513 if (fWhat & CPUMCTX_EXTRN_DR6)
1514 {
1515 Assert(pInput->Names[iReg] == HvX64RegisterDr6);
1516 if (pCtx->dr[6] != paValues[iReg].Reg64)
1517 CPUMSetGuestDR6(pVCpu, paValues[iReg].Reg64);
1518 iReg++;
1519 }
1520 if (fWhat & CPUMCTX_EXTRN_DR7)
1521 {
1522 Assert(pInput->Names[iReg] == HvX64RegisterDr7);
1523 if (pCtx->dr[7] != paValues[iReg].Reg64)
1524 CPUMSetGuestDR6(pVCpu, paValues[iReg].Reg64);
1525 iReg++;
1526 }
1527
1528 /* Floating point state. */
1529 if (fWhat & CPUMCTX_EXTRN_X87)
1530 {
1531 Assert(pInput->Names[iReg] == HvX64RegisterFpMmx0);
1532 Assert(pInput->Names[iReg + 7] == HvX64RegisterFpMmx7);
1533 pCtx->pXStateR0->x87.aRegs[0].au64[0] = paValues[iReg].Fp.AsUINT128.Low64;
1534 pCtx->pXStateR0->x87.aRegs[0].au64[1] = paValues[iReg].Fp.AsUINT128.High64;
1535 iReg++;
1536 pCtx->pXStateR0->x87.aRegs[1].au64[0] = paValues[iReg].Fp.AsUINT128.Low64;
1537 pCtx->pXStateR0->x87.aRegs[1].au64[1] = paValues[iReg].Fp.AsUINT128.High64;
1538 iReg++;
1539 pCtx->pXStateR0->x87.aRegs[2].au64[0] = paValues[iReg].Fp.AsUINT128.Low64;
1540 pCtx->pXStateR0->x87.aRegs[2].au64[1] = paValues[iReg].Fp.AsUINT128.High64;
1541 iReg++;
1542 pCtx->pXStateR0->x87.aRegs[3].au64[0] = paValues[iReg].Fp.AsUINT128.Low64;
1543 pCtx->pXStateR0->x87.aRegs[3].au64[1] = paValues[iReg].Fp.AsUINT128.High64;
1544 iReg++;
1545 pCtx->pXStateR0->x87.aRegs[4].au64[0] = paValues[iReg].Fp.AsUINT128.Low64;
1546 pCtx->pXStateR0->x87.aRegs[4].au64[1] = paValues[iReg].Fp.AsUINT128.High64;
1547 iReg++;
1548 pCtx->pXStateR0->x87.aRegs[5].au64[0] = paValues[iReg].Fp.AsUINT128.Low64;
1549 pCtx->pXStateR0->x87.aRegs[5].au64[1] = paValues[iReg].Fp.AsUINT128.High64;
1550 iReg++;
1551 pCtx->pXStateR0->x87.aRegs[6].au64[0] = paValues[iReg].Fp.AsUINT128.Low64;
1552 pCtx->pXStateR0->x87.aRegs[6].au64[1] = paValues[iReg].Fp.AsUINT128.High64;
1553 iReg++;
1554 pCtx->pXStateR0->x87.aRegs[7].au64[0] = paValues[iReg].Fp.AsUINT128.Low64;
1555 pCtx->pXStateR0->x87.aRegs[7].au64[1] = paValues[iReg].Fp.AsUINT128.High64;
1556 iReg++;
1557
1558 Assert(pInput->Names[iReg] == HvX64RegisterFpControlStatus);
1559 pCtx->pXStateR0->x87.FCW = paValues[iReg].FpControlStatus.FpControl;
1560 pCtx->pXStateR0->x87.FSW = paValues[iReg].FpControlStatus.FpStatus;
1561 pCtx->pXStateR0->x87.FTW = paValues[iReg].FpControlStatus.FpTag
1562 /*| (paValues[iReg].FpControlStatus.Reserved << 8)*/;
1563 pCtx->pXStateR0->x87.FOP = paValues[iReg].FpControlStatus.LastFpOp;
1564 pCtx->pXStateR0->x87.FPUIP = (uint32_t)paValues[iReg].FpControlStatus.LastFpRip;
1565 pCtx->pXStateR0->x87.CS = (uint16_t)(paValues[iReg].FpControlStatus.LastFpRip >> 32);
1566 pCtx->pXStateR0->x87.Rsrvd1 = (uint16_t)(paValues[iReg].FpControlStatus.LastFpRip >> 48);
1567 iReg++;
1568 }
1569
1570 if (fWhat & (CPUMCTX_EXTRN_X87 | CPUMCTX_EXTRN_SSE_AVX))
1571 {
1572 Assert(pInput->Names[iReg] == HvX64RegisterXmmControlStatus);
1573 if (fWhat & CPUMCTX_EXTRN_X87)
1574 {
1575 pCtx->pXStateR0->x87.FPUDP = (uint32_t)paValues[iReg].XmmControlStatus.LastFpRdp;
1576 pCtx->pXStateR0->x87.DS = (uint16_t)(paValues[iReg].XmmControlStatus.LastFpRdp >> 32);
1577 pCtx->pXStateR0->x87.Rsrvd2 = (uint16_t)(paValues[iReg].XmmControlStatus.LastFpRdp >> 48);
1578 }
1579 pCtx->pXStateR0->x87.MXCSR = paValues[iReg].XmmControlStatus.XmmStatusControl;
1580 pCtx->pXStateR0->x87.MXCSR_MASK = paValues[iReg].XmmControlStatus.XmmStatusControlMask; /** @todo ??? (Isn't this an output field?) */
1581 iReg++;
1582 }
1583
1584 /* Vector state. */
1585 if (fWhat & CPUMCTX_EXTRN_SSE_AVX)
1586 {
1587 Assert(pInput->Names[iReg] == HvX64RegisterXmm0);
1588 Assert(pInput->Names[iReg+15] == HvX64RegisterXmm15);
1589 pCtx->pXStateR0->x87.aXMM[0].uXmm.s.Lo = paValues[iReg].Reg128.Low64;
1590 pCtx->pXStateR0->x87.aXMM[0].uXmm.s.Hi = paValues[iReg].Reg128.High64;
1591 iReg++;
1592 pCtx->pXStateR0->x87.aXMM[1].uXmm.s.Lo = paValues[iReg].Reg128.Low64;
1593 pCtx->pXStateR0->x87.aXMM[1].uXmm.s.Hi = paValues[iReg].Reg128.High64;
1594 iReg++;
1595 pCtx->pXStateR0->x87.aXMM[2].uXmm.s.Lo = paValues[iReg].Reg128.Low64;
1596 pCtx->pXStateR0->x87.aXMM[2].uXmm.s.Hi = paValues[iReg].Reg128.High64;
1597 iReg++;
1598 pCtx->pXStateR0->x87.aXMM[3].uXmm.s.Lo = paValues[iReg].Reg128.Low64;
1599 pCtx->pXStateR0->x87.aXMM[3].uXmm.s.Hi = paValues[iReg].Reg128.High64;
1600 iReg++;
1601 pCtx->pXStateR0->x87.aXMM[4].uXmm.s.Lo = paValues[iReg].Reg128.Low64;
1602 pCtx->pXStateR0->x87.aXMM[4].uXmm.s.Hi = paValues[iReg].Reg128.High64;
1603 iReg++;
1604 pCtx->pXStateR0->x87.aXMM[5].uXmm.s.Lo = paValues[iReg].Reg128.Low64;
1605 pCtx->pXStateR0->x87.aXMM[5].uXmm.s.Hi = paValues[iReg].Reg128.High64;
1606 iReg++;
1607 pCtx->pXStateR0->x87.aXMM[6].uXmm.s.Lo = paValues[iReg].Reg128.Low64;
1608 pCtx->pXStateR0->x87.aXMM[6].uXmm.s.Hi = paValues[iReg].Reg128.High64;
1609 iReg++;
1610 pCtx->pXStateR0->x87.aXMM[7].uXmm.s.Lo = paValues[iReg].Reg128.Low64;
1611 pCtx->pXStateR0->x87.aXMM[7].uXmm.s.Hi = paValues[iReg].Reg128.High64;
1612 iReg++;
1613 pCtx->pXStateR0->x87.aXMM[8].uXmm.s.Lo = paValues[iReg].Reg128.Low64;
1614 pCtx->pXStateR0->x87.aXMM[8].uXmm.s.Hi = paValues[iReg].Reg128.High64;
1615 iReg++;
1616 pCtx->pXStateR0->x87.aXMM[9].uXmm.s.Lo = paValues[iReg].Reg128.Low64;
1617 pCtx->pXStateR0->x87.aXMM[9].uXmm.s.Hi = paValues[iReg].Reg128.High64;
1618 iReg++;
1619 pCtx->pXStateR0->x87.aXMM[10].uXmm.s.Lo = paValues[iReg].Reg128.Low64;
1620 pCtx->pXStateR0->x87.aXMM[10].uXmm.s.Hi = paValues[iReg].Reg128.High64;
1621 iReg++;
1622 pCtx->pXStateR0->x87.aXMM[11].uXmm.s.Lo = paValues[iReg].Reg128.Low64;
1623 pCtx->pXStateR0->x87.aXMM[11].uXmm.s.Hi = paValues[iReg].Reg128.High64;
1624 iReg++;
1625 pCtx->pXStateR0->x87.aXMM[12].uXmm.s.Lo = paValues[iReg].Reg128.Low64;
1626 pCtx->pXStateR0->x87.aXMM[12].uXmm.s.Hi = paValues[iReg].Reg128.High64;
1627 iReg++;
1628 pCtx->pXStateR0->x87.aXMM[13].uXmm.s.Lo = paValues[iReg].Reg128.Low64;
1629 pCtx->pXStateR0->x87.aXMM[13].uXmm.s.Hi = paValues[iReg].Reg128.High64;
1630 iReg++;
1631 pCtx->pXStateR0->x87.aXMM[14].uXmm.s.Lo = paValues[iReg].Reg128.Low64;
1632 pCtx->pXStateR0->x87.aXMM[14].uXmm.s.Hi = paValues[iReg].Reg128.High64;
1633 iReg++;
1634 pCtx->pXStateR0->x87.aXMM[15].uXmm.s.Lo = paValues[iReg].Reg128.Low64;
1635 pCtx->pXStateR0->x87.aXMM[15].uXmm.s.Hi = paValues[iReg].Reg128.High64;
1636 iReg++;
1637 }
1638
1639
1640 /* MSRs */
1641 // HvX64RegisterTsc - don't touch
1642 if (fWhat & CPUMCTX_EXTRN_EFER)
1643 {
1644 Assert(pInput->Names[iReg] == HvX64RegisterEfer);
1645 if (paValues[iReg].Reg64 != pCtx->msrEFER)
1646 {
1647 pCtx->msrEFER = paValues[iReg].Reg64;
1648 fMaybeChangedMode = true;
1649 }
1650 iReg++;
1651 }
1652 if (fWhat & CPUMCTX_EXTRN_KERNEL_GS_BASE)
1653 {
1654 Assert(pInput->Names[iReg] == HvX64RegisterKernelGsBase);
1655 pCtx->msrKERNELGSBASE = paValues[iReg].Reg64;
1656 iReg++;
1657 }
1658 if (fWhat & CPUMCTX_EXTRN_SYSENTER_MSRS)
1659 {
1660 Assert(pInput->Names[iReg] == HvX64RegisterSysenterCs);
1661 pCtx->SysEnter.cs = paValues[iReg].Reg64;
1662 iReg++;
1663 Assert(pInput->Names[iReg] == HvX64RegisterSysenterEip);
1664 pCtx->SysEnter.eip = paValues[iReg].Reg64;
1665 iReg++;
1666 Assert(pInput->Names[iReg] == HvX64RegisterSysenterEsp);
1667 pCtx->SysEnter.esp = paValues[iReg].Reg64;
1668 iReg++;
1669 }
1670 if (fWhat & CPUMCTX_EXTRN_SYSCALL_MSRS)
1671 {
1672 Assert(pInput->Names[iReg] == HvX64RegisterStar);
1673 pCtx->msrSTAR = paValues[iReg].Reg64;
1674 iReg++;
1675 Assert(pInput->Names[iReg] == HvX64RegisterLstar);
1676 pCtx->msrLSTAR = paValues[iReg].Reg64;
1677 iReg++;
1678 Assert(pInput->Names[iReg] == HvX64RegisterCstar);
1679 pCtx->msrCSTAR = paValues[iReg].Reg64;
1680 iReg++;
1681 Assert(pInput->Names[iReg] == HvX64RegisterSfmask);
1682 pCtx->msrSFMASK = paValues[iReg].Reg64;
1683 iReg++;
1684 }
1685 if (fWhat & CPUMCTX_EXTRN_OTHER_MSRS)
1686 {
1687 Assert(pInput->Names[iReg] == HvX64RegisterApicBase);
1688 if (paValues[iReg].Reg64 != APICGetBaseMsrNoCheck(pVCpu))
1689 {
1690 VBOXSTRICTRC rc2 = APICSetBaseMsr(pVCpu, paValues[iReg].Reg64);
1691 Assert(rc2 == VINF_SUCCESS); NOREF(rc2);
1692 }
1693 iReg++;
1694
1695 Assert(pInput->Names[iReg] == HvX64RegisterPat);
1696 pCtx->msrPAT = paValues[iReg].Reg64;
1697 iReg++;
1698 }
1699
1700 /* Event injection. */
1701 /// @todo HvRegisterPendingInterruption
1702 Assert(pInput->Names[iReg] == HvRegisterPendingInterruption);
1703 if (paValues[iReg].PendingInterruption.InterruptionPending)
1704 {
1705 Log7(("PendingInterruption: type=%u vector=%#x errcd=%RTbool/%#x instr-len=%u nested=%u\n",
1706 paValues[iReg].PendingInterruption.InterruptionType, paValues[iReg].PendingInterruption.InterruptionVector,
1707 paValues[iReg].PendingInterruption.DeliverErrorCode, paValues[iReg].PendingInterruption.ErrorCode,
1708 paValues[iReg].PendingInterruption.InstructionLength, paValues[iReg].PendingInterruption.NestedEvent));
1709 AssertMsg((paValues[iReg].PendingInterruption.AsUINT64 & UINT64_C(0xfc00)) == 0,
1710 ("%#RX64\n", paValues[iReg].PendingInterruption.AsUINT64));
1711 }
1712
1713 /// @todo HvRegisterInterruptState
1714 /// @todo HvRegisterPendingEvent0
1715 /// @todo HvRegisterPendingEvent1
1716
1717 /* Almost done, just update extrn flags and maybe change PGM mode. */
1718 pCtx->fExtrn &= ~fWhat;
1719
1720 /* Typical. */
1721 if (!fMaybeChangedMode && !fFlushTlb)
1722 return VINF_SUCCESS;
1723
1724 /*
1725 * Slow.
1726 */
1727 int rc = VINF_SUCCESS;
1728 if (fMaybeChangedMode)
1729 {
1730 rc = PGMChangeMode(pVCpu, pCtx->cr0, pCtx->cr4, pCtx->msrEFER);
1731 if (rc == VINF_PGM_CHANGE_MODE)
1732 {
1733 LogFlow(("nemR0WinImportState: -> VERR_NEM_CHANGE_PGM_MODE!\n"));
1734 return VERR_NEM_CHANGE_PGM_MODE;
1735 }
1736 AssertMsg(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc));
1737 }
1738
1739 if (fFlushTlb)
1740 {
1741 LogFlow(("nemR0WinImportState: -> VERR_NEM_FLUSH_TLB!\n"));
1742 rc = VERR_NEM_FLUSH_TLB; /* Calling PGMFlushTLB w/o long jump setup doesn't work, ring-3 does it. */
1743 }
1744
1745 return rc;
1746}
1747
1748
1749/**
1750 * Import the state from the native API (back to CPUMCTX).
1751 *
1752 * @returns VBox status code
1753 * @param pGVM The ring-0 VM handle.
1754 * @param pVM The cross context VM handle.
1755 * @param idCpu The calling EMT. Necessary for getting the
1756 * hypercall page and arguments.
1757 * @param fWhat What to import, CPUMCTX_EXTRN_XXX. Set
1758 * CPUMCTX_EXTERN_ALL for everything.
1759 */
1760VMMR0_INT_DECL(int) NEMR0ImportState(PGVM pGVM, PVM pVM, VMCPUID idCpu, uint64_t fWhat)
1761{
1762 /*
1763 * Validate the call.
1764 */
1765 int rc = GVMMR0ValidateGVMandVMandEMT(pGVM, pVM, idCpu);
1766 if (RT_SUCCESS(rc))
1767 {
1768 PVMCPU pVCpu = &pVM->aCpus[idCpu];
1769 PGVMCPU pGVCpu = &pGVM->aCpus[idCpu];
1770 AssertReturn(g_pfnHvlInvokeHypercall, VERR_NEM_MISSING_KERNEL_API);
1771
1772 /*
1773 * Call worker.
1774 */
1775 rc = nemR0WinImportState(pGVM, pGVCpu, CPUMQueryGuestCtxPtr(pVCpu), fWhat);
1776 }
1777 return rc;
1778}
1779
1780
1781VMMR0_INT_DECL(VBOXSTRICTRC) NEMR0RunGuestCode(PGVM pGVM, VMCPUID idCpu)
1782{
1783#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
1784 PVM pVM = pGVM->pVM;
1785 return nemHCWinRunGC(pVM, &pVM->aCpus[idCpu], pGVM, &pGVM->aCpus[idCpu]);
1786#else
1787 RT_NOREF(pGVM, idCpu);
1788 return VERR_NOT_IMPLEMENTED;
1789#endif
1790}
1791
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette