VirtualBox

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

最後變更 在這個檔案從71204是 71184,由 vboxsync 提交於 7 年 前

CPUM,NEM: Introduced CPUMCTX field for tracking state that's not in the structure. Made NEM/win only get/set the register it needs. New NEM runloop based on low level messages, skipping translations. bugref:9044

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

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