VirtualBox

Changeset 71152 in vbox for trunk/src/VBox/VMM/VMMR3


Ignore:
Timestamp:
Feb 28, 2018 12:36:04 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
121046
Message:

VMM/NEM/win: Refactoring... bugref:9044

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp

    r71136 r71152  
    6262# define NEM_WIN_INTERCEPT_NT_IO_CTLS
    6363#endif
    64 
    65 /** @name Our two-bit physical page state for PGMPAGE
    66  * @{ */
    67 #define NEM_WIN_PAGE_STATE_NOT_SET      0
    68 #define NEM_WIN_PAGE_STATE_UNMAPPED     1
    69 #define NEM_WIN_PAGE_STATE_READABLE     2
    70 #define NEM_WIN_PAGE_STATE_WRITABLE     3
    71 /** @} */
    72 
    73 /** Checks if a_GCPhys is subject to the limited A20 gate emulation.  */
    74 #define NEM_WIN_IS_SUBJECT_TO_A20(a_GCPhys)     ((RTGCPHYS)((a_GCPhys) - _1M) < (RTGCPHYS)_64K)
    75 
    76 /** Checks if a_GCPhys is relevant to the limited A20 gate emulation.  */
    77 #define NEM_WIN_IS_RELEVANT_TO_A20(a_GCPhys)    \
    78     ( ((RTGCPHYS)((a_GCPhys) - _1M) < (RTGCPHYS)_64K) || ((RTGCPHYS)(a_GCPhys) < (RTGCPHYS)_64K) )
    7964
    8065/** VID I/O control detection: Fake partition handle input. */
     
    227212#endif
    228213
    229 /** NEM_WIN_PAGE_STATE_XXX names. */
    230 static const char * const g_apszPageStates[4] = { "not-set", "unmapped", "readable", "writable" };
    231214/** WHV_MEMORY_ACCESS_TYPE names */
    232215static const char * const g_apszWHvMemAccesstypes[4] = { "read", "write", "exec", "!undefined!" };
     
    236219*   Internal Functions                                                                                                           *
    237220*********************************************************************************************************************************/
    238 static int nemR3NativeSetPhysPage(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhysSrc, RTGCPHYS GCPhysDst, uint32_t fPageProt,
    239                                   uint8_t *pu2State, bool fBackingChanged);
     221
     222/*
     223 * Instantate the code we share with ring-0.
     224 */
     225#include "../VMMAll/NEMAllNativeTemplate-win.cpp.h"
    240226
    241227
     
    13511337}
    13521338
    1353 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
    1354 
    1355 /**
    1356  * Wrapper around VMMR0_DO_NEM_MAP_PAGES for a single page.
    1357  *
    1358  * @returns VBox status code.
    1359  * @param   pVM         The cross context VM structure.
    1360  * @param   pVCpu       The cross context virtual CPU structure of the caller.
    1361  * @param   GCPhysSrc   The source page.  Does not need to be page aligned.
    1362  * @param   GCPhysDst   The destination page.  Same as @a GCPhysSrc except for
    1363  *                      when A20 is disabled.
    1364  * @param   fFlags      HV_MAP_GPA_XXX.
    1365  */
    1366 DECLINLINE(int) nemR3WinHypercallMapPage(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhysSrc, RTGCPHYS GCPhysDst, uint32_t fFlags)
    1367 {
    1368     pVCpu->nem.s.Hypercall.MapPages.GCPhysSrc   = GCPhysSrc & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK;
    1369     pVCpu->nem.s.Hypercall.MapPages.GCPhysDst   = GCPhysDst & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK;
    1370     pVCpu->nem.s.Hypercall.MapPages.cPages      = 1;
    1371     pVCpu->nem.s.Hypercall.MapPages.fFlags      = fFlags;
    1372     return VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_NEM_MAP_PAGES, 0, NULL);
    1373 }
    1374 
    1375 
    1376 /**
    1377  * Wrapper around VMMR0_DO_NEM_UNMAP_PAGES for a single page.
    1378  *
    1379  * @returns VBox status code.
    1380  * @param   pVM         The cross context VM structure.
    1381  * @param   pVCpu       The cross context virtual CPU structure of the caller.
    1382  * @param   GCPhys      The page to unmap.  Does not need to be page aligned.
    1383  */
    1384 DECLINLINE(int) nemR3WinHypercallUnmapPage(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys)
    1385 {
    1386     pVCpu->nem.s.Hypercall.UnmapPages.GCPhys    = GCPhys & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK;
    1387     pVCpu->nem.s.Hypercall.UnmapPages.cPages    = 1;
    1388     return VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_NEM_UNMAP_PAGES, 0, NULL);
    1389 }
    1390 
    1391 #endif /* NEM_WIN_USE_HYPERCALLS_FOR_PAGES */
    1392 
    1393 static int nemR3WinCopyStateToHyperV(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
    1394 {
    1395 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS
    1396     NOREF(pCtx);
    1397     int rc = VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_NEM_EXPORT_STATE, UINT64_MAX, NULL);
    1398     AssertLogRelRCReturn(rc, rc);
    1399     return rc;
    1400 
    1401 #else
    1402     WHV_REGISTER_NAME  aenmNames[128];
    1403     WHV_REGISTER_VALUE aValues[128];
    1404 
    1405     /* GPRs */
    1406     aenmNames[0]      = WHvX64RegisterRax;
    1407     aValues[0].Reg64  = pCtx->rax;
    1408     aenmNames[1]      = WHvX64RegisterRcx;
    1409     aValues[1].Reg64  = pCtx->rcx;
    1410     aenmNames[2]      = WHvX64RegisterRdx;
    1411     aValues[2].Reg64  = pCtx->rdx;
    1412     aenmNames[3]      = WHvX64RegisterRbx;
    1413     aValues[3].Reg64  = pCtx->rbx;
    1414     aenmNames[4]      = WHvX64RegisterRsp;
    1415     aValues[4].Reg64  = pCtx->rsp;
    1416     aenmNames[5]      = WHvX64RegisterRbp;
    1417     aValues[5].Reg64  = pCtx->rbp;
    1418     aenmNames[6]      = WHvX64RegisterRsi;
    1419     aValues[6].Reg64  = pCtx->rsi;
    1420     aenmNames[7]      = WHvX64RegisterRdi;
    1421     aValues[7].Reg64  = pCtx->rdi;
    1422     aenmNames[8]      = WHvX64RegisterR8;
    1423     aValues[8].Reg64  = pCtx->r8;
    1424     aenmNames[9]      = WHvX64RegisterR9;
    1425     aValues[9].Reg64  = pCtx->r9;
    1426     aenmNames[10]     = WHvX64RegisterR10;
    1427     aValues[10].Reg64 = pCtx->r10;
    1428     aenmNames[11]     = WHvX64RegisterR11;
    1429     aValues[11].Reg64 = pCtx->r11;
    1430     aenmNames[12]     = WHvX64RegisterR12;
    1431     aValues[12].Reg64 = pCtx->r12;
    1432     aenmNames[13]     = WHvX64RegisterR13;
    1433     aValues[13].Reg64 = pCtx->r13;
    1434     aenmNames[14]     = WHvX64RegisterR14;
    1435     aValues[14].Reg64 = pCtx->r14;
    1436     aenmNames[15]     = WHvX64RegisterR15;
    1437     aValues[15].Reg64 = pCtx->r15;
    1438 
    1439     /* RIP & Flags */
    1440     aenmNames[16]     = WHvX64RegisterRip;
    1441     aValues[16].Reg64 = pCtx->rip;
    1442     aenmNames[17]     = WHvX64RegisterRflags;
    1443     aValues[17].Reg64 = pCtx->rflags.u;
    1444 
    1445     /* Segments */
    1446 #define COPY_OUT_SEG(a_idx, a_enmName, a_SReg) \
    1447         do { \
    1448             aenmNames[a_idx]                  = a_enmName; \
    1449             aValues[a_idx].Segment.Base       = (a_SReg).u64Base; \
    1450             aValues[a_idx].Segment.Limit      = (a_SReg).u32Limit; \
    1451             aValues[a_idx].Segment.Selector   = (a_SReg).Sel; \
    1452             aValues[a_idx].Segment.Attributes = (a_SReg).Attr.u; \
    1453         } while (0)
    1454     COPY_OUT_SEG(18, WHvX64RegisterEs,   pCtx->es);
    1455     COPY_OUT_SEG(19, WHvX64RegisterCs,   pCtx->cs);
    1456     COPY_OUT_SEG(20, WHvX64RegisterSs,   pCtx->ss);
    1457     COPY_OUT_SEG(21, WHvX64RegisterDs,   pCtx->ds);
    1458     COPY_OUT_SEG(22, WHvX64RegisterFs,   pCtx->fs);
    1459     COPY_OUT_SEG(23, WHvX64RegisterGs,   pCtx->gs);
    1460     COPY_OUT_SEG(24, WHvX64RegisterLdtr, pCtx->ldtr);
    1461     COPY_OUT_SEG(25, WHvX64RegisterTr,   pCtx->tr);
    1462 
    1463     uintptr_t iReg = 26;
    1464     /* Descriptor tables. */
    1465     aenmNames[iReg] = WHvX64RegisterIdtr;
    1466     aValues[iReg].Table.Limit = pCtx->idtr.cbIdt;
    1467     aValues[iReg].Table.Base  = pCtx->idtr.pIdt;
    1468     iReg++;
    1469     aenmNames[iReg] = WHvX64RegisterGdtr;
    1470     aValues[iReg].Table.Limit = pCtx->gdtr.cbGdt;
    1471     aValues[iReg].Table.Base  = pCtx->gdtr.pGdt;
    1472     iReg++;
    1473 
    1474     /* Control registers. */
    1475     aenmNames[iReg]     = WHvX64RegisterCr0;
    1476     aValues[iReg].Reg64 = pCtx->cr0;
    1477     iReg++;
    1478     aenmNames[iReg]     = WHvX64RegisterCr2;
    1479     aValues[iReg].Reg64 = pCtx->cr2;
    1480     iReg++;
    1481     aenmNames[iReg]     = WHvX64RegisterCr3;
    1482     aValues[iReg].Reg64 = pCtx->cr3;
    1483     iReg++;
    1484     aenmNames[iReg]     = WHvX64RegisterCr4;
    1485     aValues[iReg].Reg64 = pCtx->cr4;
    1486     iReg++;
    1487     aenmNames[iReg]     = WHvX64RegisterCr8;
    1488     aValues[iReg].Reg64 = CPUMGetGuestCR8(pVCpu);
    1489     iReg++;
    1490 
    1491     /* Debug registers. */
    1492 /** @todo fixme. Figure out what the hyper-v version of KVM_SET_GUEST_DEBUG would be. */
    1493     aenmNames[iReg]     = WHvX64RegisterDr0;
    1494     //aValues[iReg].Reg64 = CPUMGetHyperDR0(pVCpu);
    1495     aValues[iReg].Reg64 = pCtx->dr[0];
    1496     iReg++;
    1497     aenmNames[iReg]     = WHvX64RegisterDr1;
    1498     //aValues[iReg].Reg64 = CPUMGetHyperDR1(pVCpu);
    1499     aValues[iReg].Reg64 = pCtx->dr[1];
    1500     iReg++;
    1501     aenmNames[iReg]     = WHvX64RegisterDr2;
    1502     //aValues[iReg].Reg64 = CPUMGetHyperDR2(pVCpu);
    1503     aValues[iReg].Reg64 = pCtx->dr[2];
    1504     iReg++;
    1505     aenmNames[iReg]     = WHvX64RegisterDr3;
    1506     //aValues[iReg].Reg64 = CPUMGetHyperDR3(pVCpu);
    1507     aValues[iReg].Reg64 = pCtx->dr[3];
    1508     iReg++;
    1509     aenmNames[iReg]     = WHvX64RegisterDr6;
    1510     //aValues[iReg].Reg64 = CPUMGetHyperDR6(pVCpu);
    1511     aValues[iReg].Reg64 = pCtx->dr[6];
    1512     iReg++;
    1513     aenmNames[iReg]     = WHvX64RegisterDr7;
    1514     //aValues[iReg].Reg64 = CPUMGetHyperDR7(pVCpu);
    1515     aValues[iReg].Reg64 = pCtx->dr[7];
    1516     iReg++;
    1517 
    1518     /* Vector state. */
    1519     aenmNames[iReg]     = WHvX64RegisterXmm0;
    1520     aValues[iReg].Reg128.Low64  = pCtx->pXStateR3->x87.aXMM[0].uXmm.s.Lo;
    1521     aValues[iReg].Reg128.High64 = pCtx->pXStateR3->x87.aXMM[0].uXmm.s.Hi;
    1522     iReg++;
    1523     aenmNames[iReg]     = WHvX64RegisterXmm1;
    1524     aValues[iReg].Reg128.Low64  = pCtx->pXStateR3->x87.aXMM[1].uXmm.s.Lo;
    1525     aValues[iReg].Reg128.High64 = pCtx->pXStateR3->x87.aXMM[1].uXmm.s.Hi;
    1526     iReg++;
    1527     aenmNames[iReg]     = WHvX64RegisterXmm2;
    1528     aValues[iReg].Reg128.Low64  = pCtx->pXStateR3->x87.aXMM[2].uXmm.s.Lo;
    1529     aValues[iReg].Reg128.High64 = pCtx->pXStateR3->x87.aXMM[2].uXmm.s.Hi;
    1530     iReg++;
    1531     aenmNames[iReg]     = WHvX64RegisterXmm3;
    1532     aValues[iReg].Reg128.Low64  = pCtx->pXStateR3->x87.aXMM[3].uXmm.s.Lo;
    1533     aValues[iReg].Reg128.High64 = pCtx->pXStateR3->x87.aXMM[3].uXmm.s.Hi;
    1534     iReg++;
    1535     aenmNames[iReg]     = WHvX64RegisterXmm4;
    1536     aValues[iReg].Reg128.Low64  = pCtx->pXStateR3->x87.aXMM[4].uXmm.s.Lo;
    1537     aValues[iReg].Reg128.High64 = pCtx->pXStateR3->x87.aXMM[4].uXmm.s.Hi;
    1538     iReg++;
    1539     aenmNames[iReg]     = WHvX64RegisterXmm5;
    1540     aValues[iReg].Reg128.Low64  = pCtx->pXStateR3->x87.aXMM[5].uXmm.s.Lo;
    1541     aValues[iReg].Reg128.High64 = pCtx->pXStateR3->x87.aXMM[5].uXmm.s.Hi;
    1542     iReg++;
    1543     aenmNames[iReg]     = WHvX64RegisterXmm6;
    1544     aValues[iReg].Reg128.Low64  = pCtx->pXStateR3->x87.aXMM[6].uXmm.s.Lo;
    1545     aValues[iReg].Reg128.High64 = pCtx->pXStateR3->x87.aXMM[6].uXmm.s.Hi;
    1546     iReg++;
    1547     aenmNames[iReg]     = WHvX64RegisterXmm7;
    1548     aValues[iReg].Reg128.Low64  = pCtx->pXStateR3->x87.aXMM[7].uXmm.s.Lo;
    1549     aValues[iReg].Reg128.High64 = pCtx->pXStateR3->x87.aXMM[7].uXmm.s.Hi;
    1550     iReg++;
    1551     aenmNames[iReg]     = WHvX64RegisterXmm8;
    1552     aValues[iReg].Reg128.Low64  = pCtx->pXStateR3->x87.aXMM[8].uXmm.s.Lo;
    1553     aValues[iReg].Reg128.High64 = pCtx->pXStateR3->x87.aXMM[8].uXmm.s.Hi;
    1554     iReg++;
    1555     aenmNames[iReg]     = WHvX64RegisterXmm9;
    1556     aValues[iReg].Reg128.Low64  = pCtx->pXStateR3->x87.aXMM[9].uXmm.s.Lo;
    1557     aValues[iReg].Reg128.High64 = pCtx->pXStateR3->x87.aXMM[9].uXmm.s.Hi;
    1558     iReg++;
    1559     aenmNames[iReg]     = WHvX64RegisterXmm10;
    1560     aValues[iReg].Reg128.Low64  = pCtx->pXStateR3->x87.aXMM[10].uXmm.s.Lo;
    1561     aValues[iReg].Reg128.High64 = pCtx->pXStateR3->x87.aXMM[10].uXmm.s.Hi;
    1562     iReg++;
    1563     aenmNames[iReg]     = WHvX64RegisterXmm11;
    1564     aValues[iReg].Reg128.Low64  = pCtx->pXStateR3->x87.aXMM[11].uXmm.s.Lo;
    1565     aValues[iReg].Reg128.High64 = pCtx->pXStateR3->x87.aXMM[11].uXmm.s.Hi;
    1566     iReg++;
    1567     aenmNames[iReg]     = WHvX64RegisterXmm12;
    1568     aValues[iReg].Reg128.Low64  = pCtx->pXStateR3->x87.aXMM[12].uXmm.s.Lo;
    1569     aValues[iReg].Reg128.High64 = pCtx->pXStateR3->x87.aXMM[12].uXmm.s.Hi;
    1570     iReg++;
    1571     aenmNames[iReg]     = WHvX64RegisterXmm13;
    1572     aValues[iReg].Reg128.Low64  = pCtx->pXStateR3->x87.aXMM[13].uXmm.s.Lo;
    1573     aValues[iReg].Reg128.High64 = pCtx->pXStateR3->x87.aXMM[13].uXmm.s.Hi;
    1574     iReg++;
    1575     aenmNames[iReg]     = WHvX64RegisterXmm14;
    1576     aValues[iReg].Reg128.Low64  = pCtx->pXStateR3->x87.aXMM[14].uXmm.s.Lo;
    1577     aValues[iReg].Reg128.High64 = pCtx->pXStateR3->x87.aXMM[14].uXmm.s.Hi;
    1578     iReg++;
    1579     aenmNames[iReg]     = WHvX64RegisterXmm15;
    1580     aValues[iReg].Reg128.Low64  = pCtx->pXStateR3->x87.aXMM[15].uXmm.s.Lo;
    1581     aValues[iReg].Reg128.High64 = pCtx->pXStateR3->x87.aXMM[15].uXmm.s.Hi;
    1582     iReg++;
    1583 
    1584     /* Floating point state. */
    1585     aenmNames[iReg]     = WHvX64RegisterFpMmx0;
    1586     aValues[iReg].Fp.AsUINT128.Low64  = pCtx->pXStateR3->x87.aRegs[0].au64[0];
    1587     aValues[iReg].Fp.AsUINT128.High64 = pCtx->pXStateR3->x87.aRegs[0].au64[1];
    1588     iReg++;
    1589     aenmNames[iReg]     = WHvX64RegisterFpMmx1;
    1590     aValues[iReg].Fp.AsUINT128.Low64  = pCtx->pXStateR3->x87.aRegs[1].au64[0];
    1591     aValues[iReg].Fp.AsUINT128.High64 = pCtx->pXStateR3->x87.aRegs[1].au64[1];
    1592     iReg++;
    1593     aenmNames[iReg]     = WHvX64RegisterFpMmx2;
    1594     aValues[iReg].Fp.AsUINT128.Low64  = pCtx->pXStateR3->x87.aRegs[2].au64[0];
    1595     aValues[iReg].Fp.AsUINT128.High64 = pCtx->pXStateR3->x87.aRegs[2].au64[1];
    1596     iReg++;
    1597     aenmNames[iReg]     = WHvX64RegisterFpMmx3;
    1598     aValues[iReg].Fp.AsUINT128.Low64  = pCtx->pXStateR3->x87.aRegs[3].au64[0];
    1599     aValues[iReg].Fp.AsUINT128.High64 = pCtx->pXStateR3->x87.aRegs[3].au64[1];
    1600     iReg++;
    1601     aenmNames[iReg]     = WHvX64RegisterFpMmx4;
    1602     aValues[iReg].Fp.AsUINT128.Low64  = pCtx->pXStateR3->x87.aRegs[4].au64[0];
    1603     aValues[iReg].Fp.AsUINT128.High64 = pCtx->pXStateR3->x87.aRegs[4].au64[1];
    1604     iReg++;
    1605     aenmNames[iReg]     = WHvX64RegisterFpMmx5;
    1606     aValues[iReg].Fp.AsUINT128.Low64  = pCtx->pXStateR3->x87.aRegs[5].au64[0];
    1607     aValues[iReg].Fp.AsUINT128.High64 = pCtx->pXStateR3->x87.aRegs[5].au64[1];
    1608     iReg++;
    1609     aenmNames[iReg]     = WHvX64RegisterFpMmx6;
    1610     aValues[iReg].Fp.AsUINT128.Low64  = pCtx->pXStateR3->x87.aRegs[6].au64[0];
    1611     aValues[iReg].Fp.AsUINT128.High64 = pCtx->pXStateR3->x87.aRegs[6].au64[1];
    1612     iReg++;
    1613     aenmNames[iReg]     = WHvX64RegisterFpMmx7;
    1614     aValues[iReg].Fp.AsUINT128.Low64  = pCtx->pXStateR3->x87.aRegs[7].au64[0];
    1615     aValues[iReg].Fp.AsUINT128.High64 = pCtx->pXStateR3->x87.aRegs[7].au64[1];
    1616     iReg++;
    1617 
    1618     aenmNames[iReg]     = WHvX64RegisterFpControlStatus;
    1619     aValues[iReg].FpControlStatus.FpControl = pCtx->pXStateR3->x87.FCW;
    1620     aValues[iReg].FpControlStatus.FpStatus  = pCtx->pXStateR3->x87.FSW;
    1621     aValues[iReg].FpControlStatus.FpTag     = pCtx->pXStateR3->x87.FTW;
    1622     aValues[iReg].FpControlStatus.Reserved  = pCtx->pXStateR3->x87.FTW >> 8;
    1623     aValues[iReg].FpControlStatus.LastFpOp  = pCtx->pXStateR3->x87.FOP;
    1624     aValues[iReg].FpControlStatus.LastFpRip = (pCtx->pXStateR3->x87.FPUIP)
    1625                                             | ((uint64_t)pCtx->pXStateR3->x87.CS << 32)
    1626                                             | ((uint64_t)pCtx->pXStateR3->x87.Rsrvd1 << 48);
    1627     iReg++;
    1628 
    1629     aenmNames[iReg]     = WHvX64RegisterXmmControlStatus;
    1630     aValues[iReg].XmmControlStatus.LastFpRdp            = (pCtx->pXStateR3->x87.FPUDP)
    1631                                                         | ((uint64_t)pCtx->pXStateR3->x87.DS << 32)
    1632                                                         | ((uint64_t)pCtx->pXStateR3->x87.Rsrvd2 << 48);
    1633     aValues[iReg].XmmControlStatus.XmmStatusControl     = pCtx->pXStateR3->x87.MXCSR;
    1634     aValues[iReg].XmmControlStatus.XmmStatusControlMask = pCtx->pXStateR3->x87.MXCSR_MASK; /** @todo ??? (Isn't this an output field?) */
    1635     iReg++;
    1636 
    1637     /* MSRs */
    1638     // WHvX64RegisterTsc - don't touch
    1639     aenmNames[iReg]     = WHvX64RegisterEfer;
    1640     aValues[iReg].Reg64 = pCtx->msrEFER;
    1641     iReg++;
    1642     aenmNames[iReg]     = WHvX64RegisterKernelGsBase;
    1643     aValues[iReg].Reg64 = pCtx->msrKERNELGSBASE;
    1644     iReg++;
    1645     aenmNames[iReg]     = WHvX64RegisterApicBase;
    1646     aValues[iReg].Reg64 = APICGetBaseMsrNoCheck(pVCpu);
    1647     iReg++;
    1648     aenmNames[iReg]     = WHvX64RegisterPat;
    1649     aValues[iReg].Reg64 = pCtx->msrPAT;
    1650     iReg++;
    1651     /// @todo WHvX64RegisterSysenterCs
    1652     /// @todo WHvX64RegisterSysenterEip
    1653     /// @todo WHvX64RegisterSysenterEsp
    1654     aenmNames[iReg]     = WHvX64RegisterStar;
    1655     aValues[iReg].Reg64 = pCtx->msrSTAR;
    1656     iReg++;
    1657     aenmNames[iReg]     = WHvX64RegisterLstar;
    1658     aValues[iReg].Reg64 = pCtx->msrLSTAR;
    1659     iReg++;
    1660     aenmNames[iReg]     = WHvX64RegisterCstar;
    1661     aValues[iReg].Reg64 = pCtx->msrCSTAR;
    1662     iReg++;
    1663     aenmNames[iReg]     = WHvX64RegisterSfmask;
    1664     aValues[iReg].Reg64 = pCtx->msrSFMASK;
    1665     iReg++;
    1666 
    1667     /* event injection (always clear it). */
    1668     aenmNames[iReg]     = WHvRegisterPendingInterruption;
    1669     aValues[iReg].Reg64 = 0;
    1670     iReg++;
    1671     /// @todo WHvRegisterInterruptState
    1672     /// @todo WHvRegisterPendingEvent0
    1673     /// @todo WHvRegisterPendingEvent1
    1674 
    1675     /*
    1676      * Set the registers.
    1677      */
    1678     Assert(iReg < RT_ELEMENTS(aValues));
    1679     Assert(iReg < RT_ELEMENTS(aenmNames));
    1680 #ifdef NEM_WIN_INTERCEPT_NT_IO_CTLS
    1681     Log12(("Calling WHvSetVirtualProcessorRegisters(%p, %u, %p, %u, %p)\n",
    1682            pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, iReg, aValues));
    1683 #endif
    1684     HRESULT hrc = WHvSetVirtualProcessorRegisters(pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, iReg, aValues);
    1685     if (SUCCEEDED(hrc))
    1686         return VINF_SUCCESS;
    1687     AssertLogRelMsgFailed(("WHvSetVirtualProcessorRegisters(%p, %u,,%u,) -> %Rhrc (Last=%#x/%u)\n",
    1688                            pVM->nem.s.hPartition, pVCpu->idCpu, iReg,
    1689                            hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    1690     return VERR_INTERNAL_ERROR;
    1691 #endif /* !NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS */
    1692 }
    1693 
    1694 static int nemR3WinCopyStateFromHyperV(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
    1695 {
    1696 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS
    1697     NOREF(pCtx);
    1698     int rc = VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_NEM_IMPORT_STATE, UINT64_MAX, NULL);
    1699     if (RT_SUCCESS(rc))
    1700         return rc;
    1701     if (rc == VERR_NEM_FLUSH_TLB)
    1702         return PGMFlushTLB(pVCpu, pCtx->cr3, true /*fGlobal*/);
    1703     if (rc == VERR_NEM_CHANGE_PGM_MODE)
    1704         return PGMChangeMode(pVCpu, pCtx->cr0, pCtx->cr4, pCtx->msrEFER);
    1705     AssertLogRelRCReturn(rc, rc);
    1706     return rc;
    1707 
    1708 #else
    1709     WHV_REGISTER_NAME  aenmNames[128];
    1710 
    1711     /* GPRs */
    1712     aenmNames[0]  = WHvX64RegisterRax;
    1713     aenmNames[1]  = WHvX64RegisterRcx;
    1714     aenmNames[2]  = WHvX64RegisterRdx;
    1715     aenmNames[3]  = WHvX64RegisterRbx;
    1716     aenmNames[4]  = WHvX64RegisterRsp;
    1717     aenmNames[5]  = WHvX64RegisterRbp;
    1718     aenmNames[6]  = WHvX64RegisterRsi;
    1719     aenmNames[7]  = WHvX64RegisterRdi;
    1720     aenmNames[8]  = WHvX64RegisterR8;
    1721     aenmNames[9]  = WHvX64RegisterR9;
    1722     aenmNames[10] = WHvX64RegisterR10;
    1723     aenmNames[11] = WHvX64RegisterR11;
    1724     aenmNames[12] = WHvX64RegisterR12;
    1725     aenmNames[13] = WHvX64RegisterR13;
    1726     aenmNames[14] = WHvX64RegisterR14;
    1727     aenmNames[15] = WHvX64RegisterR15;
    1728 
    1729     /* RIP & Flags */
    1730     aenmNames[16] = WHvX64RegisterRip;
    1731     aenmNames[17] = WHvX64RegisterRflags;
    1732 
    1733     /* Segments */
    1734     aenmNames[18] = WHvX64RegisterEs;
    1735     aenmNames[19] = WHvX64RegisterCs;
    1736     aenmNames[20] = WHvX64RegisterSs;
    1737     aenmNames[21] = WHvX64RegisterDs;
    1738     aenmNames[22] = WHvX64RegisterFs;
    1739     aenmNames[23] = WHvX64RegisterGs;
    1740     aenmNames[24] = WHvX64RegisterLdtr;
    1741     aenmNames[25] = WHvX64RegisterTr;
    1742 
    1743     /* Descriptor tables. */
    1744     aenmNames[26] = WHvX64RegisterIdtr;
    1745     aenmNames[27] = WHvX64RegisterGdtr;
    1746 
    1747     /* Control registers. */
    1748     aenmNames[28] = WHvX64RegisterCr0;
    1749     aenmNames[29] = WHvX64RegisterCr2;
    1750     aenmNames[30] = WHvX64RegisterCr3;
    1751     aenmNames[31] = WHvX64RegisterCr4;
    1752     aenmNames[32] = WHvX64RegisterCr8;
    1753 
    1754     /* Debug registers. */
    1755     aenmNames[33] = WHvX64RegisterDr0;
    1756     aenmNames[34] = WHvX64RegisterDr1;
    1757     aenmNames[35] = WHvX64RegisterDr2;
    1758     aenmNames[36] = WHvX64RegisterDr3;
    1759     aenmNames[37] = WHvX64RegisterDr6;
    1760     aenmNames[38] = WHvX64RegisterDr7;
    1761 
    1762     /* Vector state. */
    1763     aenmNames[39] = WHvX64RegisterXmm0;
    1764     aenmNames[40] = WHvX64RegisterXmm1;
    1765     aenmNames[41] = WHvX64RegisterXmm2;
    1766     aenmNames[42] = WHvX64RegisterXmm3;
    1767     aenmNames[43] = WHvX64RegisterXmm4;
    1768     aenmNames[44] = WHvX64RegisterXmm5;
    1769     aenmNames[45] = WHvX64RegisterXmm6;
    1770     aenmNames[46] = WHvX64RegisterXmm7;
    1771     aenmNames[47] = WHvX64RegisterXmm8;
    1772     aenmNames[48] = WHvX64RegisterXmm9;
    1773     aenmNames[49] = WHvX64RegisterXmm10;
    1774     aenmNames[50] = WHvX64RegisterXmm11;
    1775     aenmNames[51] = WHvX64RegisterXmm12;
    1776     aenmNames[52] = WHvX64RegisterXmm13;
    1777     aenmNames[53] = WHvX64RegisterXmm14;
    1778     aenmNames[54] = WHvX64RegisterXmm15;
    1779 
    1780     /* Floating point state. */
    1781     aenmNames[55] = WHvX64RegisterFpMmx0;
    1782     aenmNames[56] = WHvX64RegisterFpMmx1;
    1783     aenmNames[57] = WHvX64RegisterFpMmx2;
    1784     aenmNames[58] = WHvX64RegisterFpMmx3;
    1785     aenmNames[59] = WHvX64RegisterFpMmx4;
    1786     aenmNames[60] = WHvX64RegisterFpMmx5;
    1787     aenmNames[61] = WHvX64RegisterFpMmx6;
    1788     aenmNames[62] = WHvX64RegisterFpMmx7;
    1789     aenmNames[63] = WHvX64RegisterFpControlStatus;
    1790     aenmNames[64] = WHvX64RegisterXmmControlStatus;
    1791 
    1792     /* MSRs */
    1793     // WHvX64RegisterTsc - don't touch
    1794     aenmNames[65] = WHvX64RegisterEfer;
    1795     aenmNames[66] = WHvX64RegisterKernelGsBase;
    1796     aenmNames[67] = WHvX64RegisterApicBase;
    1797     aenmNames[68] = WHvX64RegisterPat;
    1798     aenmNames[69] = WHvX64RegisterSysenterCs;
    1799     aenmNames[70] = WHvX64RegisterSysenterEip;
    1800     aenmNames[71] = WHvX64RegisterSysenterEsp;
    1801     aenmNames[72] = WHvX64RegisterStar;
    1802     aenmNames[73] = WHvX64RegisterLstar;
    1803     aenmNames[74] = WHvX64RegisterCstar;
    1804     aenmNames[75] = WHvX64RegisterSfmask;
    1805 
    1806     /* event injection */
    1807     aenmNames[76] = WHvRegisterPendingInterruption;
    1808     aenmNames[77] = WHvRegisterInterruptState;
    1809     aenmNames[78] = WHvRegisterInterruptState;
    1810     aenmNames[79] = WHvRegisterPendingEvent0;
    1811     aenmNames[80] = WHvRegisterPendingEvent1;
    1812     unsigned const cRegs = 81;
    1813 
    1814     /*
    1815      * Get the registers.
    1816      */
    1817     WHV_REGISTER_VALUE aValues[cRegs];
    1818     RT_ZERO(aValues);
    1819     Assert(RT_ELEMENTS(aValues) >= cRegs);
    1820     Assert(RT_ELEMENTS(aenmNames) >= cRegs);
    1821 #ifdef NEM_WIN_INTERCEPT_NT_IO_CTLS
    1822     Log12(("Calling WHvGetVirtualProcessorRegisters(%p, %u, %p, %u, %p)\n",
    1823           pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, cRegs, aValues));
    1824 #endif
    1825     HRESULT hrc = WHvGetVirtualProcessorRegisters(pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, cRegs, aValues);
    1826     if (SUCCEEDED(hrc))
    1827     {
    1828         /* GPRs */
    1829         Assert(aenmNames[0]  == WHvX64RegisterRax);
    1830         Assert(aenmNames[15] == WHvX64RegisterR15);
    1831         pCtx->rax = aValues[0].Reg64;
    1832         pCtx->rcx = aValues[1].Reg64;
    1833         pCtx->rdx = aValues[2].Reg64;
    1834         pCtx->rbx = aValues[3].Reg64;
    1835         pCtx->rsp = aValues[4].Reg64;
    1836         pCtx->rbp = aValues[5].Reg64;
    1837         pCtx->rsi = aValues[6].Reg64;
    1838         pCtx->rdi = aValues[7].Reg64;
    1839         pCtx->r8  = aValues[8].Reg64;
    1840         pCtx->r9  = aValues[9].Reg64;
    1841         pCtx->r10 = aValues[10].Reg64;
    1842         pCtx->r11 = aValues[11].Reg64;
    1843         pCtx->r12 = aValues[12].Reg64;
    1844         pCtx->r13 = aValues[13].Reg64;
    1845         pCtx->r14 = aValues[14].Reg64;
    1846         pCtx->r15 = aValues[15].Reg64;
    1847 
    1848         /* RIP & Flags */
    1849         Assert(aenmNames[16] == WHvX64RegisterRip);
    1850         pCtx->rip      = aValues[16].Reg64;
    1851         pCtx->rflags.u = aValues[17].Reg64;
    1852 
    1853         /* Segments */
    1854 #define COPY_BACK_SEG(a_idx, a_enmName, a_SReg) \
    1855             do { \
    1856                 Assert(aenmNames[a_idx] == a_enmName); \
    1857                 (a_SReg).u64Base  = aValues[a_idx].Segment.Base; \
    1858                 (a_SReg).u32Limit = aValues[a_idx].Segment.Limit; \
    1859                 (a_SReg).ValidSel = (a_SReg).Sel = aValues[a_idx].Segment.Selector; \
    1860                 (a_SReg).Attr.u   = aValues[a_idx].Segment.Attributes; \
    1861                 (a_SReg).fFlags   = CPUMSELREG_FLAGS_VALID; \
    1862             } while (0)
    1863         COPY_BACK_SEG(18, WHvX64RegisterEs,   pCtx->es);
    1864         COPY_BACK_SEG(19, WHvX64RegisterCs,   pCtx->cs);
    1865         COPY_BACK_SEG(20, WHvX64RegisterSs,   pCtx->ss);
    1866         COPY_BACK_SEG(21, WHvX64RegisterDs,   pCtx->ds);
    1867         COPY_BACK_SEG(22, WHvX64RegisterFs,   pCtx->fs);
    1868         COPY_BACK_SEG(23, WHvX64RegisterGs,   pCtx->gs);
    1869         COPY_BACK_SEG(24, WHvX64RegisterLdtr, pCtx->ldtr);
    1870         COPY_BACK_SEG(25, WHvX64RegisterTr,   pCtx->tr);
    1871 
    1872         /* Descriptor tables. */
    1873         Assert(aenmNames[26] == WHvX64RegisterIdtr);
    1874         pCtx->idtr.cbIdt = aValues[26].Table.Limit;
    1875         pCtx->idtr.pIdt  = aValues[26].Table.Base;
    1876         Assert(aenmNames[27] == WHvX64RegisterGdtr);
    1877         pCtx->gdtr.cbGdt = aValues[27].Table.Limit;
    1878         pCtx->gdtr.pGdt  = aValues[27].Table.Base;
    1879 
    1880         /* Control registers. */
    1881         Assert(aenmNames[28] == WHvX64RegisterCr0);
    1882         bool fMaybeChangedMode = false;
    1883         bool fFlushTlb         = false;
    1884         bool fFlushGlobalTlb   = false;
    1885         if (pCtx->cr0 != aValues[28].Reg64)
    1886         {
    1887             CPUMSetGuestCR0(pVCpu, aValues[28].Reg64);
    1888             fMaybeChangedMode = true;
    1889             fFlushTlb = fFlushGlobalTlb = true; /// @todo fix this
    1890         }
    1891         Assert(aenmNames[29] == WHvX64RegisterCr2);
    1892         pCtx->cr2 = aValues[29].Reg64;
    1893         if (pCtx->cr3 != aValues[30].Reg64)
    1894         {
    1895             CPUMSetGuestCR3(pVCpu, aValues[30].Reg64);
    1896             fFlushTlb = true;
    1897         }
    1898         if (pCtx->cr4 != aValues[31].Reg64)
    1899         {
    1900             CPUMSetGuestCR4(pVCpu, aValues[31].Reg64);
    1901             fMaybeChangedMode = true;
    1902             fFlushTlb = fFlushGlobalTlb = true; /// @todo fix this
    1903         }
    1904         APICSetTpr(pVCpu, (uint8_t)aValues[32].Reg64 << 4);
    1905 
    1906         /* Debug registers. */
    1907         Assert(aenmNames[33] == WHvX64RegisterDr0);
    1908     /** @todo fixme */
    1909         if (pCtx->dr[0] != aValues[33].Reg64)
    1910             CPUMSetGuestDR0(pVCpu, aValues[33].Reg64);
    1911         if (pCtx->dr[1] != aValues[34].Reg64)
    1912             CPUMSetGuestDR1(pVCpu, aValues[34].Reg64);
    1913         if (pCtx->dr[2] != aValues[35].Reg64)
    1914             CPUMSetGuestDR2(pVCpu, aValues[35].Reg64);
    1915         if (pCtx->dr[3] != aValues[36].Reg64)
    1916             CPUMSetGuestDR3(pVCpu, aValues[36].Reg64);
    1917         Assert(aenmNames[37] == WHvX64RegisterDr6);
    1918         Assert(aenmNames[38] == WHvX64RegisterDr7);
    1919         if (pCtx->dr[6] != aValues[37].Reg64)
    1920             CPUMSetGuestDR6(pVCpu, aValues[37].Reg64);
    1921         if (pCtx->dr[7] != aValues[38].Reg64)
    1922             CPUMSetGuestDR6(pVCpu, aValues[38].Reg64);
    1923 
    1924         /* Vector state. */
    1925         Assert(aenmNames[39] == WHvX64RegisterXmm0);
    1926         Assert(aenmNames[54] == WHvX64RegisterXmm15);
    1927         pCtx->pXStateR3->x87.aXMM[0].uXmm.s.Lo  = aValues[39].Reg128.Low64;
    1928         pCtx->pXStateR3->x87.aXMM[0].uXmm.s.Hi  = aValues[39].Reg128.High64;
    1929         pCtx->pXStateR3->x87.aXMM[1].uXmm.s.Lo  = aValues[40].Reg128.Low64;
    1930         pCtx->pXStateR3->x87.aXMM[1].uXmm.s.Hi  = aValues[40].Reg128.High64;
    1931         pCtx->pXStateR3->x87.aXMM[2].uXmm.s.Lo  = aValues[41].Reg128.Low64;
    1932         pCtx->pXStateR3->x87.aXMM[2].uXmm.s.Hi  = aValues[41].Reg128.High64;
    1933         pCtx->pXStateR3->x87.aXMM[3].uXmm.s.Lo  = aValues[42].Reg128.Low64;
    1934         pCtx->pXStateR3->x87.aXMM[3].uXmm.s.Hi  = aValues[42].Reg128.High64;
    1935         pCtx->pXStateR3->x87.aXMM[4].uXmm.s.Lo  = aValues[43].Reg128.Low64;
    1936         pCtx->pXStateR3->x87.aXMM[4].uXmm.s.Hi  = aValues[43].Reg128.High64;
    1937         pCtx->pXStateR3->x87.aXMM[5].uXmm.s.Lo  = aValues[44].Reg128.Low64;
    1938         pCtx->pXStateR3->x87.aXMM[5].uXmm.s.Hi  = aValues[44].Reg128.High64;
    1939         pCtx->pXStateR3->x87.aXMM[6].uXmm.s.Lo  = aValues[45].Reg128.Low64;
    1940         pCtx->pXStateR3->x87.aXMM[6].uXmm.s.Hi  = aValues[45].Reg128.High64;
    1941         pCtx->pXStateR3->x87.aXMM[7].uXmm.s.Lo  = aValues[46].Reg128.Low64;
    1942         pCtx->pXStateR3->x87.aXMM[7].uXmm.s.Hi  = aValues[46].Reg128.High64;
    1943         pCtx->pXStateR3->x87.aXMM[8].uXmm.s.Lo  = aValues[47].Reg128.Low64;
    1944         pCtx->pXStateR3->x87.aXMM[8].uXmm.s.Hi  = aValues[47].Reg128.High64;
    1945         pCtx->pXStateR3->x87.aXMM[9].uXmm.s.Lo  = aValues[48].Reg128.Low64;
    1946         pCtx->pXStateR3->x87.aXMM[9].uXmm.s.Hi  = aValues[48].Reg128.High64;
    1947         pCtx->pXStateR3->x87.aXMM[10].uXmm.s.Lo = aValues[49].Reg128.Low64;
    1948         pCtx->pXStateR3->x87.aXMM[10].uXmm.s.Hi = aValues[49].Reg128.High64;
    1949         pCtx->pXStateR3->x87.aXMM[11].uXmm.s.Lo = aValues[50].Reg128.Low64;
    1950         pCtx->pXStateR3->x87.aXMM[11].uXmm.s.Hi = aValues[50].Reg128.High64;
    1951         pCtx->pXStateR3->x87.aXMM[12].uXmm.s.Lo = aValues[51].Reg128.Low64;
    1952         pCtx->pXStateR3->x87.aXMM[12].uXmm.s.Hi = aValues[51].Reg128.High64;
    1953         pCtx->pXStateR3->x87.aXMM[13].uXmm.s.Lo = aValues[52].Reg128.Low64;
    1954         pCtx->pXStateR3->x87.aXMM[13].uXmm.s.Hi = aValues[52].Reg128.High64;
    1955         pCtx->pXStateR3->x87.aXMM[14].uXmm.s.Lo = aValues[53].Reg128.Low64;
    1956         pCtx->pXStateR3->x87.aXMM[14].uXmm.s.Hi = aValues[53].Reg128.High64;
    1957         pCtx->pXStateR3->x87.aXMM[15].uXmm.s.Lo = aValues[54].Reg128.Low64;
    1958         pCtx->pXStateR3->x87.aXMM[15].uXmm.s.Hi = aValues[54].Reg128.High64;
    1959 
    1960         /* Floating point state. */
    1961         Assert(aenmNames[55] == WHvX64RegisterFpMmx0);
    1962         Assert(aenmNames[62] == WHvX64RegisterFpMmx7);
    1963         pCtx->pXStateR3->x87.aRegs[0].au64[0] = aValues[55].Fp.AsUINT128.Low64;
    1964         pCtx->pXStateR3->x87.aRegs[0].au64[1] = aValues[55].Fp.AsUINT128.High64;
    1965         pCtx->pXStateR3->x87.aRegs[1].au64[0] = aValues[56].Fp.AsUINT128.Low64;
    1966         pCtx->pXStateR3->x87.aRegs[1].au64[1] = aValues[56].Fp.AsUINT128.High64;
    1967         pCtx->pXStateR3->x87.aRegs[2].au64[0] = aValues[57].Fp.AsUINT128.Low64;
    1968         pCtx->pXStateR3->x87.aRegs[2].au64[1] = aValues[57].Fp.AsUINT128.High64;
    1969         pCtx->pXStateR3->x87.aRegs[3].au64[0] = aValues[58].Fp.AsUINT128.Low64;
    1970         pCtx->pXStateR3->x87.aRegs[3].au64[1] = aValues[58].Fp.AsUINT128.High64;
    1971         pCtx->pXStateR3->x87.aRegs[4].au64[0] = aValues[59].Fp.AsUINT128.Low64;
    1972         pCtx->pXStateR3->x87.aRegs[4].au64[1] = aValues[59].Fp.AsUINT128.High64;
    1973         pCtx->pXStateR3->x87.aRegs[5].au64[0] = aValues[60].Fp.AsUINT128.Low64;
    1974         pCtx->pXStateR3->x87.aRegs[5].au64[1] = aValues[60].Fp.AsUINT128.High64;
    1975         pCtx->pXStateR3->x87.aRegs[6].au64[0] = aValues[61].Fp.AsUINT128.Low64;
    1976         pCtx->pXStateR3->x87.aRegs[6].au64[1] = aValues[61].Fp.AsUINT128.High64;
    1977         pCtx->pXStateR3->x87.aRegs[7].au64[0] = aValues[62].Fp.AsUINT128.Low64;
    1978         pCtx->pXStateR3->x87.aRegs[7].au64[1] = aValues[62].Fp.AsUINT128.High64;
    1979 
    1980         Assert(aenmNames[63] == WHvX64RegisterFpControlStatus);
    1981         pCtx->pXStateR3->x87.FCW        = aValues[63].FpControlStatus.FpControl;
    1982         pCtx->pXStateR3->x87.FSW        = aValues[63].FpControlStatus.FpStatus;
    1983         pCtx->pXStateR3->x87.FTW        = aValues[63].FpControlStatus.FpTag
    1984                                         /*| (aValues[63].FpControlStatus.Reserved << 8)*/;
    1985         pCtx->pXStateR3->x87.FOP        = aValues[63].FpControlStatus.LastFpOp;
    1986         pCtx->pXStateR3->x87.FPUIP      = (uint32_t)aValues[63].FpControlStatus.LastFpRip;
    1987         pCtx->pXStateR3->x87.CS         = (uint16_t)(aValues[63].FpControlStatus.LastFpRip >> 32);
    1988         pCtx->pXStateR3->x87.Rsrvd1     = (uint16_t)(aValues[63].FpControlStatus.LastFpRip >> 48);
    1989 
    1990         Assert(aenmNames[64] == WHvX64RegisterXmmControlStatus);
    1991         pCtx->pXStateR3->x87.FPUDP      = (uint32_t)aValues[64].XmmControlStatus.LastFpRdp;
    1992         pCtx->pXStateR3->x87.DS         = (uint16_t)(aValues[64].XmmControlStatus.LastFpRdp >> 32);
    1993         pCtx->pXStateR3->x87.Rsrvd2     = (uint16_t)(aValues[64].XmmControlStatus.LastFpRdp >> 48);
    1994         pCtx->pXStateR3->x87.MXCSR      = aValues[64].XmmControlStatus.XmmStatusControl;
    1995         pCtx->pXStateR3->x87.MXCSR_MASK = aValues[64].XmmControlStatus.XmmStatusControlMask; /** @todo ??? (Isn't this an output field?) */
    1996 
    1997         /* MSRs */
    1998         // WHvX64RegisterTsc - don't touch
    1999         Assert(aenmNames[65] == WHvX64RegisterEfer);
    2000         if (aValues[65].Reg64 != pCtx->msrEFER)
    2001         {
    2002             pCtx->msrEFER = aValues[65].Reg64;
    2003             fMaybeChangedMode = true;
    2004         }
    2005 
    2006         Assert(aenmNames[66] == WHvX64RegisterKernelGsBase);
    2007         pCtx->msrKERNELGSBASE = aValues[66].Reg64;
    2008 
    2009         Assert(aenmNames[67] == WHvX64RegisterApicBase);
    2010         if (aValues[67].Reg64 != APICGetBaseMsrNoCheck(pVCpu))
    2011         {
    2012             VBOXSTRICTRC rc2 = APICSetBaseMsr(pVCpu, aValues[67].Reg64);
    2013             Assert(rc2 == VINF_SUCCESS); NOREF(rc2);
    2014         }
    2015 
    2016         Assert(aenmNames[68] == WHvX64RegisterPat);
    2017         pCtx->msrPAT    = aValues[68].Reg64;
    2018         /// @todo WHvX64RegisterSysenterCs
    2019         /// @todo WHvX64RegisterSysenterEip
    2020         /// @todo WHvX64RegisterSysenterEsp
    2021         Assert(aenmNames[72] == WHvX64RegisterStar);
    2022         pCtx->msrSTAR   = aValues[72].Reg64;
    2023         Assert(aenmNames[73] == WHvX64RegisterLstar);
    2024         pCtx->msrLSTAR  = aValues[73].Reg64;
    2025         Assert(aenmNames[74] == WHvX64RegisterCstar);
    2026         pCtx->msrCSTAR  = aValues[74].Reg64;
    2027         Assert(aenmNames[75] == WHvX64RegisterSfmask);
    2028         pCtx->msrSFMASK = aValues[75].Reg64;
    2029 
    2030         /// @todo WHvRegisterPendingInterruption
    2031         Assert(aenmNames[76] == WHvRegisterPendingInterruption);
    2032         WHV_X64_PENDING_INTERRUPTION_REGISTER const * pPendingInt = (WHV_X64_PENDING_INTERRUPTION_REGISTER const *)&aValues[76];
    2033         if (pPendingInt->InterruptionPending)
    2034         {
    2035             Log7(("PendingInterruption: type=%u vector=%#x errcd=%RTbool/%#x instr-len=%u nested=%u\n",
    2036                   pPendingInt->InterruptionType, pPendingInt->InterruptionVector, pPendingInt->DeliverErrorCode,
    2037                   pPendingInt->ErrorCode, pPendingInt->InstructionLength, pPendingInt->NestedEvent));
    2038             AssertMsg((pPendingInt->AsUINT64 & UINT64_C(0xfc00)) == 0, ("%#RX64\n", pPendingInt->AsUINT64));
    2039         }
    2040 
    2041         /// @todo WHvRegisterInterruptState
    2042         /// @todo WHvRegisterPendingEvent0
    2043         /// @todo WHvRegisterPendingEvent1
    2044 
    2045 
    2046         if (fMaybeChangedMode)
    2047         {
    2048             int rc = PGMChangeMode(pVCpu, pCtx->cr0, pCtx->cr4, pCtx->msrEFER);
    2049             AssertRC(rc);
    2050         }
    2051         if (fFlushTlb)
    2052         {
    2053             int rc = PGMFlushTLB(pVCpu, pCtx->cr3, fFlushGlobalTlb);
    2054             AssertRC(rc);
    2055         }
    2056 
    2057         return VINF_SUCCESS;
    2058     }
    2059 
    2060     AssertLogRelMsgFailed(("WHvGetVirtualProcessorRegisters(%p, %u,,%u,) -> %Rhrc (Last=%#x/%u)\n",
    2061                            pVM->nem.s.hPartition, pVCpu->idCpu, cRegs,
    2062                            hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    2063     return VERR_INTERNAL_ERROR;
    2064 #endif /* !NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS */
    2065 }
    2066 
    20671339
    20681340#ifdef LOG_ENABLED
    2069 /**
    2070  * Get the virtual processor running status.
    2071  */
    2072 DECLINLINE(VID_PROCESSOR_STATUS) nemR3WinCpuGetRunningStatus(PVMCPU pVCpu)
    2073 {
    2074     RTERRVARS Saved;
    2075     RTErrVarsSave(&Saved);
    2076 
    2077     /*
    2078      * This API is disabled in release builds, it seems.  On build 17101 it requires
    2079      * the following patch to be enabled (windbg): eb vid+12180 0f 84 98 00 00 00
    2080      */
    2081     VID_PROCESSOR_STATUS enmCpuStatus = VidProcessorStatusUndefined;
    2082     NTSTATUS rcNt = g_pfnVidGetVirtualProcessorRunningStatus(pVCpu->pVMR3->nem.s.hPartitionDevice, pVCpu->idCpu, &enmCpuStatus);
    2083     AssertRC(rcNt);
    2084 
    2085     RTErrVarsRestore(&Saved);
    2086     return enmCpuStatus;
    2087 }
    2088 #endif
    2089 
    2090 
    2091 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API
    2092 
    2093 /**
    2094  * Our own WHvCancelRunVirtualProcessor that can later be moved to ring-0.
    2095  *
    2096  * This is an experiment only.
    2097  *
    2098  * @returns VBox status code.
    2099  * @param   pVM             The cross context VM structure.
    2100  * @param   pVCpu           The cross context virtual CPU structure of the
    2101  *                          calling EMT.
    2102  */
    2103 static int nemR3WinCancelRunVirtualProcessor(PVM pVM, PVMCPU pVCpu)
    2104 {
    2105     /*
    2106      * Work the state.
    2107      *
    2108      * From the looks of things, we should let the EMT call VidStopVirtualProcessor.
    2109      * So, we just need to modify the state and kick the EMT if it's waiting on
    2110      * messages.  For the latter we use QueueUserAPC / KeAlterThread.
    2111      */
    2112     for (;;)
    2113     {
    2114         VMCPUSTATE enmState = VMCPU_GET_STATE(pVCpu);
    2115         switch (enmState)
    2116         {
    2117             case VMCPUSTATE_STARTED_EXEC_NEM:
    2118                 if (VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM_CANCELED, VMCPUSTATE_STARTED_EXEC_NEM))
    2119                 {
    2120                     Log8(("nemR3WinCancelRunVirtualProcessor: Switched %u to canceled state\n", pVCpu->idCpu));
    2121                     return VINF_SUCCESS;
    2122                 }
    2123                 break;
    2124 
    2125             case VMCPUSTATE_STARTED_EXEC_NEM_WAIT:
    2126                 if (VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM_CANCELED, VMCPUSTATE_STARTED_EXEC_NEM_WAIT))
    2127                 {
    2128                     NTSTATUS rcNt = NtAlertThread(pVCpu->nem.s.hNativeThreadHandle);
    2129                     Log8(("nemR3WinCancelRunVirtualProcessor: Alerted %u: %#x\n", pVCpu->idCpu, rcNt));
    2130                     Assert(rcNt == STATUS_SUCCESS);
    2131                     if (NT_SUCCESS(rcNt))
    2132                         return VINF_SUCCESS;
    2133                     AssertLogRelMsgFailedReturn(("NtAlertThread failed: %#x\n", rcNt), RTErrConvertFromNtStatus(rcNt));
    2134                 }
    2135                 break;
    2136 
    2137             default:
    2138                 return VINF_SUCCESS;
    2139         }
    2140 
    2141         ASMNopPause();
    2142         RT_NOREF(pVM);
    2143     }
    2144 }
    2145 
    2146 
    2147 /**
    2148  * Fills in WHV_VP_EXIT_CONTEXT from HV_X64_INTERCEPT_MESSAGE_HEADER.
    2149  */
    2150 DECLINLINE(void) nemR3WinConvertX64MsgHdrToVpExitCtx(HV_X64_INTERCEPT_MESSAGE_HEADER const *pHdr, WHV_VP_EXIT_CONTEXT *pCtx)
    2151 {
    2152     pCtx->ExecutionState.AsUINT16   = pHdr->ExecutionState.AsUINT16;
    2153     pCtx->InstructionLength         = pHdr->InstructionLength;
    2154     pCtx->Cs.Base                   = pHdr->CsSegment.Base;
    2155     pCtx->Cs.Limit                  = pHdr->CsSegment.Limit;
    2156     pCtx->Cs.Selector               = pHdr->CsSegment.Selector;
    2157     pCtx->Cs.Attributes             = pHdr->CsSegment.Attributes;
    2158     pCtx->Rip                       = pHdr->Rip;
    2159     pCtx->Rflags                    = pHdr->Rflags;
    2160 }
    2161 
    2162 
    2163 /**
    2164  * Convert hyper-V exit message to the WinHvPlatform structures.
    2165  *
    2166  * @returns VBox status code
    2167  * @param   pMsgHdr         The message to convert.
    2168  * @param   pExitCtx        The output structure. Assumes zeroed.
    2169  */
    2170 static int nemR3WinRunVirtualProcessorConvertPending(HV_MESSAGE_HEADER const *pMsgHdr, WHV_RUN_VP_EXIT_CONTEXT *pExitCtx)
    2171 {
    2172     switch (pMsgHdr->MessageType)
    2173     {
    2174         case HvMessageTypeUnmappedGpa:
    2175         case HvMessageTypeGpaIntercept:
    2176         {
    2177             PCHV_X64_MEMORY_INTERCEPT_MESSAGE pMemMsg = (PCHV_X64_MEMORY_INTERCEPT_MESSAGE)(pMsgHdr + 1);
    2178             Assert(pMsgHdr->PayloadSize == RT_UOFFSETOF(HV_X64_MEMORY_INTERCEPT_MESSAGE, DsSegment));
    2179 
    2180             pExitCtx->ExitReason                            = WHvRunVpExitReasonMemoryAccess;
    2181             nemR3WinConvertX64MsgHdrToVpExitCtx(&pMemMsg->Header, &pExitCtx->MemoryAccess.VpContext);
    2182             pExitCtx->MemoryAccess.InstructionByteCount     = pMemMsg->InstructionByteCount;
    2183             ((uint64_t *)pExitCtx->MemoryAccess.InstructionBytes)[0] = ((uint64_t const *)pMemMsg->InstructionBytes)[0];
    2184             ((uint64_t *)pExitCtx->MemoryAccess.InstructionBytes)[1] = ((uint64_t const *)pMemMsg->InstructionBytes)[1];
    2185 
    2186             pExitCtx->MemoryAccess.AccessInfo.AccessType    = pMemMsg->Header.InterceptAccessType;
    2187             pExitCtx->MemoryAccess.AccessInfo.GpaUnmapped   = pMsgHdr->MessageType == HvMessageTypeUnmappedGpa;
    2188             pExitCtx->MemoryAccess.AccessInfo.GvaValid      = pMemMsg->MemoryAccessInfo.GvaValid;
    2189             pExitCtx->MemoryAccess.AccessInfo.Reserved      = pMemMsg->MemoryAccessInfo.Reserved;
    2190             pExitCtx->MemoryAccess.Gpa                      = pMemMsg->GuestPhysicalAddress;
    2191             pExitCtx->MemoryAccess.Gva                      = pMemMsg->GuestVirtualAddress;
    2192             return VINF_SUCCESS;
    2193         }
    2194 
    2195         case HvMessageTypeX64IoPortIntercept:
    2196         {
    2197             PCHV_X64_IO_PORT_INTERCEPT_MESSAGE pPioMsg= (PCHV_X64_IO_PORT_INTERCEPT_MESSAGE)(pMsgHdr + 1);
    2198             Assert(pMsgHdr->PayloadSize == sizeof(*pPioMsg));
    2199 
    2200             pExitCtx->ExitReason                            = WHvRunVpExitReasonX64IoPortAccess;
    2201             nemR3WinConvertX64MsgHdrToVpExitCtx(&pPioMsg->Header, &pExitCtx->IoPortAccess.VpContext);
    2202             pExitCtx->IoPortAccess.InstructionByteCount     = pPioMsg->InstructionByteCount;
    2203             ((uint64_t *)pExitCtx->IoPortAccess.InstructionBytes)[0] = ((uint64_t const *)pPioMsg->InstructionBytes)[0];
    2204             ((uint64_t *)pExitCtx->IoPortAccess.InstructionBytes)[1] = ((uint64_t const *)pPioMsg->InstructionBytes)[1];
    2205 
    2206             pExitCtx->IoPortAccess.AccessInfo.IsWrite       = pPioMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE;
    2207             pExitCtx->IoPortAccess.AccessInfo.AccessSize    = pPioMsg->AccessInfo.AccessSize;
    2208             pExitCtx->IoPortAccess.AccessInfo.StringOp      = pPioMsg->AccessInfo.StringOp;
    2209             pExitCtx->IoPortAccess.AccessInfo.RepPrefix     = pPioMsg->AccessInfo.RepPrefix;
    2210             pExitCtx->IoPortAccess.AccessInfo.Reserved      = pPioMsg->AccessInfo.Reserved;
    2211             pExitCtx->IoPortAccess.PortNumber               = pPioMsg->PortNumber;
    2212             pExitCtx->IoPortAccess.Rax                      = pPioMsg->Rax;
    2213             pExitCtx->IoPortAccess.Rcx                      = pPioMsg->Rcx;
    2214             pExitCtx->IoPortAccess.Rsi                      = pPioMsg->Rsi;
    2215             pExitCtx->IoPortAccess.Rdi                      = pPioMsg->Rdi;
    2216             pExitCtx->IoPortAccess.Ds.Base                  = pPioMsg->DsSegment.Base;
    2217             pExitCtx->IoPortAccess.Ds.Limit                 = pPioMsg->DsSegment.Limit;
    2218             pExitCtx->IoPortAccess.Ds.Selector              = pPioMsg->DsSegment.Selector;
    2219             pExitCtx->IoPortAccess.Ds.Attributes            = pPioMsg->DsSegment.Attributes;
    2220             pExitCtx->IoPortAccess.Es.Base                  = pPioMsg->EsSegment.Base;
    2221             pExitCtx->IoPortAccess.Es.Limit                 = pPioMsg->EsSegment.Limit;
    2222             pExitCtx->IoPortAccess.Es.Selector              = pPioMsg->EsSegment.Selector;
    2223             pExitCtx->IoPortAccess.Es.Attributes            = pPioMsg->EsSegment.Attributes;
    2224             return VINF_SUCCESS;
    2225         }
    2226 
    2227         case HvMessageTypeX64Halt:
    2228         {
    2229             PCHV_X64_HALT_MESSAGE pHaltMsg = (PCHV_X64_HALT_MESSAGE)(pMsgHdr + 1);
    2230             AssertMsg(pHaltMsg->u64Reserved == 0, ("HALT reserved: %#RX64\n", pHaltMsg->u64Reserved));
    2231             pExitCtx->ExitReason = WHvRunVpExitReasonX64Halt;
    2232             return VINF_SUCCESS;
    2233         }
    2234 
    2235         case HvMessageTypeX64InterruptWindow:
    2236             AssertLogRelMsgFailedReturn(("Message type %#x not implemented!\n", pMsgHdr->MessageType), VERR_INTERNAL_ERROR_2);
    2237 
    2238         case HvMessageTypeInvalidVpRegisterValue:
    2239         case HvMessageTypeUnrecoverableException:
    2240         case HvMessageTypeUnsupportedFeature:
    2241         case HvMessageTypeTlbPageSizeMismatch:
    2242             AssertLogRelMsgFailedReturn(("Message type %#x not implemented!\n", pMsgHdr->MessageType), VERR_INTERNAL_ERROR_2);
    2243 
    2244         case HvMessageTypeX64MsrIntercept:
    2245         case HvMessageTypeX64CpuidIntercept:
    2246         case HvMessageTypeX64ExceptionIntercept:
    2247         case HvMessageTypeX64ApicEoi:
    2248         case HvMessageTypeX64LegacyFpError:
    2249         case HvMessageTypeX64RegisterIntercept:
    2250         case HvMessageTypeApicEoi:
    2251         case HvMessageTypeFerrAsserted:
    2252         case HvMessageTypeEventLogBufferComplete:
    2253         case HvMessageTimerExpired:
    2254             AssertLogRelMsgFailedReturn(("Unexpected message type #x!\n", pMsgHdr->MessageType), VERR_INTERNAL_ERROR_2);
    2255 
    2256         default:
    2257             AssertLogRelMsgFailedReturn(("Unknown message type #x!\n", pMsgHdr->MessageType), VERR_INTERNAL_ERROR_2);
    2258     }
    2259 }
    2260 
    2261 
    2262 /**
    2263  * Our own WHvRunVirtualProcessor that can later be moved to ring-0.
    2264  *
    2265  * This is an experiment only.
    2266  *
    2267  * @returns VBox status code.
    2268  * @param   pVM             The cross context VM structure.
    2269  * @param   pVCpu           The cross context virtual CPU structure of the
    2270  *                          calling EMT.
    2271  * @param   pExitCtx        Where to return exit information.
    2272  * @param   cbExitCtx       Size of the exit information area.
    2273  */
    2274 static int nemR3WinRunVirtualProcessor(PVM pVM, PVMCPU pVCpu, WHV_RUN_VP_EXIT_CONTEXT *pExitCtx, size_t cbExitCtx)
    2275 {
    2276     RT_BZERO(pExitCtx, cbExitCtx);
    2277 
    2278     /*
    2279      * Tell the CPU to execute stuff if we haven't got a pending message.
    2280      */
    2281     VID_MESSAGE_MAPPING_HEADER volatile *pMappingHeader = (VID_MESSAGE_MAPPING_HEADER volatile *)pVCpu->nem.s.pvMsgSlotMapping;
    2282     uint32_t                             fHandleAndGetFlags;
    2283     if (VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM, VMCPUSTATE_STARTED))
    2284     {
    2285         uint8_t const bMsgState = pVCpu->nem.s.bMsgState;
    2286         if (bMsgState == NEM_WIN_MSG_STATE_PENDING_MSG)
    2287         {
    2288             Assert(pMappingHeader->enmVidMsgType == VidMessageHypervisorMessage);
    2289             fHandleAndGetFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE | VID_MSHAGN_F_HANDLE_MESSAGE;
    2290             Log8(("nemR3WinRunVirtualProcessor: #1: msg pending, no need to start CPU (cpu state %u)\n", nemR3WinCpuGetRunningStatus(pVCpu) ));
    2291         }
    2292         else if (bMsgState != NEM_WIN_MSG_STATE_STARTED)
    2293         {
    2294             if (bMsgState == NEM_WIN_MSG_STATE_PENDING_STOP_AND_MSG)
    2295             {
    2296                 Log8(("nemR3WinRunVirtualProcessor: #0: pending stop+message (cpu status %u)\n", nemR3WinCpuGetRunningStatus(pVCpu) ));
    2297                 /* ACK the pending message and get the stop message. */
    2298                 BOOL fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu,
    2299                                                                  VID_MSHAGN_F_HANDLE_MESSAGE | VID_MSHAGN_F_GET_NEXT_MESSAGE, 5000);
    2300                 AssertLogRelMsg(fWait, ("dwErr=%u (%#x) rcNt=%#x\n", RTNtLastErrorValue(), RTNtLastErrorValue(), RTNtLastStatusValue()));
    2301 
    2302                 /* ACK the stop message. */
    2303                 fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu,
    2304                                                             VID_MSHAGN_F_HANDLE_MESSAGE, 5000);
    2305                 AssertLogRelMsg(fWait, ("dwErr=%u (%#x) rcNt=%#x\n", RTNtLastErrorValue(), RTNtLastErrorValue(), RTNtLastStatusValue()));
    2306 
    2307                 pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_STOPPED;
    2308             }
    2309 
    2310             Log8(("nemR3WinRunVirtualProcessor: #1: starting CPU (cpu status %u)\n", nemR3WinCpuGetRunningStatus(pVCpu) ));
    2311             if (g_pfnVidStartVirtualProcessor(pVM->nem.s.hPartitionDevice, pVCpu->idCpu))
    2312                 pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_STARTED;
    2313             else
    2314             {
    2315                 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM);
    2316                 AssertLogRelMsgFailedReturn(("VidStartVirtualProcessor failed for CPU #%u: rcNt=%#x dwErr=%u\n",
    2317                                              pVCpu->idCpu, RTNtLastStatusValue(), RTNtLastErrorValue()),
    2318                                             VERR_INTERNAL_ERROR_3);
    2319             }
    2320             fHandleAndGetFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE;
    2321         }
    2322         else
    2323         {
    2324             /* This shouldn't happen. */
    2325             fHandleAndGetFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE;
    2326             Log8(("nemR3WinRunVirtualProcessor: #1: NO MSG PENDING! No need to start CPU (cpu state %u)\n", nemR3WinCpuGetRunningStatus(pVCpu) ));
    2327         }
    2328     }
    2329     else
    2330     {
    2331         Log8(("nemR3WinRunVirtualProcessor: #1: state=%u -> canceled (cpu status %u)\n",
    2332               VMCPU_GET_STATE(pVCpu), nemR3WinCpuGetRunningStatus(pVCpu)));
    2333         pExitCtx->ExitReason = WHvRunVpExitReasonCanceled;
    2334         return VINF_SUCCESS;
    2335     }
    2336 
    2337     /*
    2338      * Wait for it to stop and give us a reason to work with.
    2339      */
    2340     uint32_t cMillies = 5000; // Starting low so we can experiment without getting stuck.
    2341     for (;;)
    2342     {
    2343         if (VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM_WAIT, VMCPUSTATE_STARTED_EXEC_NEM))
    2344         {
    2345             Log8(("nemR3WinRunVirtualProcessor: #2: Waiting %#x (cpu status %u)...\n",
    2346                   fHandleAndGetFlags, nemR3WinCpuGetRunningStatus(pVCpu)));
    2347             BOOL fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu,
    2348                                                              fHandleAndGetFlags, cMillies);
    2349             if (fWait)
    2350             {
    2351                 /* Not sure yet, but we have to check whether there is anything pending
    2352                    and retry if there isn't. */
    2353                 VID_MESSAGE_TYPE const enmVidMsgType = pMappingHeader->enmVidMsgType;
    2354                 if (enmVidMsgType == VidMessageHypervisorMessage)
    2355                 {
    2356                     if (!VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM_WAIT))
    2357                         VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM_CANCELED);
    2358                     Log8(("nemR3WinRunVirtualProcessor: #3: wait succeeded: %#x / %#x (cpu status %u)\n",
    2359                           enmVidMsgType, ((HV_MESSAGE_HEADER const *)(pMappingHeader + 1))->MessageType,
    2360                           nemR3WinCpuGetRunningStatus(pVCpu) ));
    2361                     pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_PENDING_MSG;
    2362                     return nemR3WinRunVirtualProcessorConvertPending((HV_MESSAGE_HEADER const *)(pMappingHeader + 1), pExitCtx);
    2363                 }
    2364 
    2365                 /* This shouldn't happen, and I think its wrong. */
    2366                 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM, VMCPUSTATE_STARTED_EXEC_NEM_WAIT);
    2367 #ifdef DEBUG_bird
    2368                 __debugbreak();
    2369 #endif
    2370                 Log8(("nemR3WinRunVirtualProcessor: #3: wait succeeded, but nothing pending: %#x / %#x (cpu status %u)\n",
    2371                       enmVidMsgType, ((HV_MESSAGE_HEADER const *)(pMappingHeader + 1))->MessageType, nemR3WinCpuGetRunningStatus(pVCpu) ));
    2372                 pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_STARTED;
    2373                 AssertLogRelMsgReturnStmt(enmVidMsgType == VidMessageStopRequestComplete,
    2374                                           ("enmVidMsgType=%#x\n", enmVidMsgType),
    2375                                           g_pfnVidStopVirtualProcessor(pVM->nem.s.hPartitionDevice, pVCpu->idCpu),
    2376                                           VERR_INTERNAL_ERROR_3);
    2377                 fHandleAndGetFlags &= ~VID_MSHAGN_F_HANDLE_MESSAGE;
    2378             }
    2379             else
    2380             {
    2381                 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM, VMCPUSTATE_STARTED_EXEC_NEM_WAIT);
    2382 
    2383                 /* Note! VID.SYS merges STATUS_ALERTED and STATUS_USER_APC into STATUS_TIMEOUT. */
    2384                 DWORD const dwErr = RTNtLastErrorValue();
    2385                 AssertLogRelMsgReturnStmt(   dwErr == STATUS_TIMEOUT
    2386                                           || dwErr == STATUS_ALERTED || dwErr == STATUS_USER_APC, /* just in case */
    2387                                           ("dwErr=%u (%#x) (cpu status %u)\n", dwErr, dwErr, nemR3WinCpuGetRunningStatus(pVCpu)),
    2388                                           g_pfnVidStopVirtualProcessor(pVM->nem.s.hPartitionDevice, pVCpu->idCpu),
    2389                                           VERR_INTERNAL_ERROR_3);
    2390                 Log8(("nemR3WinRunVirtualProcessor: #3: wait timed out (cpu status %u)\n", nemR3WinCpuGetRunningStatus(pVCpu) ));
    2391                 pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_STARTED;
    2392                 fHandleAndGetFlags &= ~VID_MSHAGN_F_HANDLE_MESSAGE;
    2393             }
    2394         }
    2395         else
    2396         {
    2397             /*
    2398              * State changed and we need to return.
    2399              *
    2400              * We must ensure that the processor is not running while we
    2401              * return, and that can be a bit complicated.
    2402              */
    2403             Log8(("nemR3WinRunVirtualProcessor: #4: state changed to %u (cpu status %u)\n",
    2404                   VMCPU_GET_STATE(pVCpu), nemR3WinCpuGetRunningStatus(pVCpu) ));
    2405             VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM_CANCELED);
    2406 
    2407             /* If we haven't marked the pervious message as handled, simply return
    2408                without doing anything special. */
    2409             if (fHandleAndGetFlags & VID_MSHAGN_F_HANDLE_MESSAGE)
    2410             {
    2411                 Log8(("nemR3WinRunVirtualProcessor: #5: Didn't resume previous message.\n"));
    2412                 pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_PENDING_MSG;
    2413                 pExitCtx->ExitReason = WHvRunVpExitReasonCanceled;
    2414                 return VINF_SUCCESS;
    2415             }
    2416 
    2417             /* The processor is running, so try stop it. */
    2418             BOOL fStop = g_pfnVidStopVirtualProcessor(pVM->nem.s.hPartitionDevice, pVCpu->idCpu);
    2419             if (fStop)
    2420             {
    2421                 Log8(("nemR3WinRunVirtualProcessor: #5: Stopping CPU succeeded (cpu status %u)\n", nemR3WinCpuGetRunningStatus(pVCpu) ));
    2422                 pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_STOPPED;
    2423                 pExitCtx->ExitReason = WHvRunVpExitReasonCanceled;
    2424                 return VINF_SUCCESS;
    2425             }
    2426 
    2427             /* Dang, the CPU stopped by itself with a message pending. */
    2428             DWORD dwErr = RTNtLastErrorValue();
    2429             Log8(("nemR3WinRunVirtualProcessor: #5: Stopping CPU failed (%u/%#x) - cpu status %u\n",
    2430                   dwErr, dwErr, nemR3WinCpuGetRunningStatus(pVCpu) ));
    2431             pExitCtx->ExitReason = WHvRunVpExitReasonCanceled;
    2432             AssertLogRelMsgReturn(dwErr == ERROR_VID_STOP_PENDING, ("dwErr=%#u\n", dwErr), VERR_INTERNAL_ERROR_3);
    2433 
    2434             /* Get the pending message. */
    2435             BOOL fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu,
    2436                                                              VID_MSHAGN_F_GET_NEXT_MESSAGE, 5000);
    2437             AssertLogRelMsgReturn(fWait, ("error=%#u\n", RTNtLastErrorValue()), VERR_INTERNAL_ERROR_3);
    2438 
    2439             VID_MESSAGE_TYPE const enmVidMsgType = pMappingHeader->enmVidMsgType;
    2440             if (enmVidMsgType == VidMessageHypervisorMessage)
    2441             {
    2442                 Log8(("nemR3WinRunVirtualProcessor: #6: wait succeeded: %#x / %#x (cpu status %u)\n", enmVidMsgType,
    2443                       ((HV_MESSAGE_HEADER const *)(pMappingHeader + 1))->MessageType, nemR3WinCpuGetRunningStatus(pVCpu) ));
    2444                 pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_PENDING_STOP_AND_MSG;
    2445                 return nemR3WinRunVirtualProcessorConvertPending((HV_MESSAGE_HEADER const *)(pMappingHeader + 1), pExitCtx);
    2446             }
    2447 
    2448             /* ACK the stop message, if that's what it is.  Don't think we'll ever get here. */
    2449             Log8(("nemR3WinRunVirtualProcessor: #6b: wait succeeded: %#x / %#x (cpu status %u)\n", enmVidMsgType,
    2450                   ((HV_MESSAGE_HEADER const *)(pMappingHeader + 1))->MessageType, nemR3WinCpuGetRunningStatus(pVCpu) ));
    2451             AssertLogRelMsgReturn(enmVidMsgType == VidMessageStopRequestComplete, ("enmVidMsgType=%#x\n", enmVidMsgType),
    2452                                   VERR_INTERNAL_ERROR_3);
    2453             fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu,
    2454                                                         VID_MSHAGN_F_HANDLE_MESSAGE, 5000);
    2455             AssertLogRelMsgReturn(fWait, ("dwErr=%#u\n", RTNtLastErrorValue()), VERR_INTERNAL_ERROR_3);
    2456 
    2457             pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_STOPPED;
    2458             pExitCtx->ExitReason = WHvRunVpExitReasonCanceled;
    2459             return VINF_SUCCESS;
    2460         }
    2461 
    2462         /** @todo check flags and stuff? */
    2463     }
    2464 }
    2465 
    2466 #endif /* NEM_WIN_USE_OUR_OWN_RUN_API */
    2467 
    2468 #ifdef LOG_ENABLED
    24691341
    24701342/**
     
    24731345 * @param   pExitReason     The exit reason to log.
    24741346 */
    2475 static void nemR3WinLogExitReason(WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
     1347static void nemR3WinLogWHvExitReason(WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
    24761348{
    24771349    bool fExitCtx = false;
     
    25841456}
    25851457
    2586 
    2587 /**
    2588  * Logs the current CPU state.
    2589  */
    2590 static void nemR3WinLogState(PVM pVM, PVMCPU pVCpu)
    2591 {
    2592     if (LogIs3Enabled())
    2593     {
    2594         char szRegs[4096];
    2595         DBGFR3RegPrintf(pVM->pUVM, pVCpu->idCpu, &szRegs[0], sizeof(szRegs),
    2596                         "rax=%016VR{rax} rbx=%016VR{rbx} rcx=%016VR{rcx} rdx=%016VR{rdx}\n"
    2597                         "rsi=%016VR{rsi} rdi=%016VR{rdi} r8 =%016VR{r8} r9 =%016VR{r9}\n"
    2598                         "r10=%016VR{r10} r11=%016VR{r11} r12=%016VR{r12} r13=%016VR{r13}\n"
    2599                         "r14=%016VR{r14} r15=%016VR{r15} %VRF{rflags}\n"
    2600                         "rip=%016VR{rip} rsp=%016VR{rsp} rbp=%016VR{rbp}\n"
    2601                         "cs={%04VR{cs} base=%016VR{cs_base} limit=%08VR{cs_lim} flags=%04VR{cs_attr}} cr0=%016VR{cr0}\n"
    2602                         "ds={%04VR{ds} base=%016VR{ds_base} limit=%08VR{ds_lim} flags=%04VR{ds_attr}} cr2=%016VR{cr2}\n"
    2603                         "es={%04VR{es} base=%016VR{es_base} limit=%08VR{es_lim} flags=%04VR{es_attr}} cr3=%016VR{cr3}\n"
    2604                         "fs={%04VR{fs} base=%016VR{fs_base} limit=%08VR{fs_lim} flags=%04VR{fs_attr}} cr4=%016VR{cr4}\n"
    2605                         "gs={%04VR{gs} base=%016VR{gs_base} limit=%08VR{gs_lim} flags=%04VR{gs_attr}} cr8=%016VR{cr8}\n"
    2606                         "ss={%04VR{ss} base=%016VR{ss_base} limit=%08VR{ss_lim} flags=%04VR{ss_attr}}\n"
    2607                         "dr0=%016VR{dr0} dr1=%016VR{dr1} dr2=%016VR{dr2} dr3=%016VR{dr3}\n"
    2608                         "dr6=%016VR{dr6} dr7=%016VR{dr7}\n"
    2609                         "gdtr=%016VR{gdtr_base}:%04VR{gdtr_lim}  idtr=%016VR{idtr_base}:%04VR{idtr_lim}  rflags=%08VR{rflags}\n"
    2610                         "ldtr={%04VR{ldtr} base=%016VR{ldtr_base} limit=%08VR{ldtr_lim} flags=%08VR{ldtr_attr}}\n"
    2611                         "tr  ={%04VR{tr} base=%016VR{tr_base} limit=%08VR{tr_lim} flags=%08VR{tr_attr}}\n"
    2612                         "    sysenter={cs=%04VR{sysenter_cs} eip=%08VR{sysenter_eip} esp=%08VR{sysenter_esp}}\n"
    2613                         "        efer=%016VR{efer}\n"
    2614                         "         pat=%016VR{pat}\n"
    2615                         "     sf_mask=%016VR{sf_mask}\n"
    2616                         "krnl_gs_base=%016VR{krnl_gs_base}\n"
    2617                         "       lstar=%016VR{lstar}\n"
    2618                         "        star=%016VR{star} cstar=%016VR{cstar}\n"
    2619                         "fcw=%04VR{fcw} fsw=%04VR{fsw} ftw=%04VR{ftw} mxcsr=%04VR{mxcsr} mxcsr_mask=%04VR{mxcsr_mask}\n"
    2620                         );
    2621 
    2622         char szInstr[256];
    2623         DBGFR3DisasInstrEx(pVM->pUVM, pVCpu->idCpu, 0, 0,
    2624                            DBGF_DISAS_FLAGS_CURRENT_GUEST | DBGF_DISAS_FLAGS_DEFAULT_MODE,
    2625                            szInstr, sizeof(szInstr), NULL);
    2626         Log3(("%s%s\n", szRegs, szInstr));
    2627     }
    2628 }
    2629 
    26301458#endif /* LOG_ENABLED */
    26311459
    26321460
    2633 /**
    2634  * Advances the guest RIP and clear EFLAGS.RF.
    2635  *
    2636  * This may clear VMCPU_FF_INHIBIT_INTERRUPTS.
    2637  *
    2638  * @param   pVCpu           The cross context virtual CPU structure.
    2639  * @param   pCtx            The CPU context to update.
    2640  * @param   pExitCtx        The exit context.
    2641  */
    2642 DECLINLINE(void) nemR3WinAdvanceGuestRipAndClearRF(PVMCPU pVCpu, PCPUMCTX pCtx, WHV_VP_EXIT_CONTEXT const *pExitCtx)
    2643 {
    2644     /* Advance the RIP. */
    2645     Assert(pExitCtx->InstructionLength > 0 && pExitCtx->InstructionLength < 16);
    2646     pCtx->rip += pExitCtx->InstructionLength;
    2647     pCtx->rflags.Bits.u1RF = 0;
    2648 
    2649     /* Update interrupt inhibition. */
    2650     if (!VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
    2651     { /* likely */ }
    2652     else if (pCtx->rip != EMGetInhibitInterruptsPC(pVCpu))
    2653         VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
    2654 }
    2655 
    2656 
    2657 static VBOXSTRICTRC nemR3WinHandleHalt(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
     1461static VBOXSTRICTRC nemR3WinWHvHandleHalt(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
    26581462{
    26591463    NOREF(pVM); NOREF(pVCpu); NOREF(pCtx);
    2660     LogFlow(("nemR3WinHandleHalt\n"));
     1464    LogFlow(("nemR3WinWHvHandleHalt\n"));
    26611465    return VINF_EM_HALT;
    26621466}
    26631467
    26641468
    2665 static DECLCALLBACK(int) nemR3WinUnmapOnePageCallback(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, uint8_t *pu2NemState, void *pvUser)
     1469#ifndef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
     1470/**
     1471 * @callback_method_impl{FNPGMPHYSNEMENUMCALLBACK,
     1472 *      Hack to unmap all pages when/before we run into quota (WHv only).}
     1473 */
     1474static DECLCALLBACK(int) nemR3WinWHvUnmapOnePageCallback(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, uint8_t *pu2NemState, void *pvUser)
    26661475{
    26671476    RT_NOREF_PV(pvUser);
    2668 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
    2669     int rc = nemR3WinHypercallUnmapPage(pVM, pVCpu, GCPhys);
    2670     AssertRC(rc);
    2671     if (RT_SUCCESS(rc))
    2672 #else
    26731477    RT_NOREF_PV(pVCpu);
    26741478    HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhys, X86_PAGE_SIZE);
    26751479    if (SUCCEEDED(hrc))
    2676 #endif
    26771480    {
    26781481        Log5(("NEM GPA unmap all: %RGp (cMappedPages=%u)\n", GCPhys, pVM->nem.s.cMappedPages - 1));
     
    26811484    else
    26821485    {
    2683 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
    2684         LogRel(("nemR3WinUnmapOnePageCallback: GCPhys=%RGp rc=%Rrc\n", GCPhys, rc));
    2685 #else
    2686         LogRel(("nemR3WinUnmapOnePageCallback: GCPhys=%RGp %s hrc=%Rhrc (%#x) Last=%#x/%u (cMappedPages=%u)\n",
     1486        LogRel(("nemR3WinWHvUnmapOnePageCallback: GCPhys=%RGp %s hrc=%Rhrc (%#x) Last=%#x/%u (cMappedPages=%u)\n",
    26871487                GCPhys, g_apszPageStates[*pu2NemState], hrc, hrc, RTNtLastStatusValue(),
    26881488                RTNtLastErrorValue(), pVM->nem.s.cMappedPages));
    2689 #endif
    26901489        *pu2NemState = NEM_WIN_PAGE_STATE_NOT_SET;
    26911490    }
     
    26941493    return VINF_SUCCESS;
    26951494}
    2696 
    2697 
    2698 /**
    2699  * State to pass between  nemR3WinHandleMemoryAccess and
    2700  * nemR3WinHandleMemoryAccessPageCheckerCallback.
    2701  */
    2702 typedef struct NEMR3WINHMACPCCSTATE
    2703 {
    2704     /** Input: Write access. */
    2705     bool    fWriteAccess;
    2706     /** Output: Set if we did something. */
    2707     bool    fDidSomething;
    2708     /** Output: Set it we should resume. */
    2709     bool    fCanResume;
    2710 } NEMR3WINHMACPCCSTATE;
    2711 
    2712 /**
    2713  * @callback_method_impl{FNPGMPHYSNEMCHECKPAGE,
    2714  *      Worker for nemR3WinHandleMemoryAccess; pvUser points to a
    2715  *      NEMR3WINHMACPCCSTATE structure. }
    2716  */
    2717 static DECLCALLBACK(int) nemR3WinHandleMemoryAccessPageCheckerCallback(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys,
    2718                                                                        PPGMPHYSNEMPAGEINFO pInfo, void *pvUser)
    2719 {
    2720     NEMR3WINHMACPCCSTATE *pState = (NEMR3WINHMACPCCSTATE *)pvUser;
    2721     pState->fDidSomething = false;
    2722     pState->fCanResume    = false;
    2723 
    2724     /* If A20 is disabled, we may need to make another query on the masked
    2725        page to get the correct protection information. */
    2726     uint8_t  u2State = pInfo->u2NemState;
    2727     RTGCPHYS GCPhysSrc;
    2728     if (   pVM->nem.s.fA20Enabled
    2729         || !NEM_WIN_IS_SUBJECT_TO_A20(GCPhys))
    2730         GCPhysSrc = GCPhys;
    2731     else
    2732     {
    2733         GCPhysSrc = GCPhys & ~(RTGCPHYS)RT_BIT_32(20);
    2734         PGMPHYSNEMPAGEINFO Info2;
    2735         int rc = PGMPhysNemPageInfoChecker(pVM, pVCpu, GCPhysSrc, pState->fWriteAccess, &Info2, NULL, NULL);
    2736         AssertRCReturn(rc, rc);
    2737 
    2738         *pInfo = Info2;
    2739         pInfo->u2NemState = u2State;
    2740     }
    2741 
    2742     /*
    2743      * Consolidate current page state with actual page protection and access type.
    2744      * We don't really consider downgrades here, as they shouldn't happen.
    2745      */
    2746 #ifndef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
    2747     /** @todo Someone at microsoft please explain:
    2748      * I'm not sure WTF was going on, but I ended up in a loop if I remapped a
    2749      * readonly page as writable (unmap, then map again).  Specifically, this was an
    2750      * issue with the big VRAM mapping at 0xe0000000 when booing DSL 4.4.1.  So, in
    2751      * a hope to work around that we no longer pre-map anything, just unmap stuff
    2752      * and do it lazily here.  And here we will first unmap, restart, and then remap
    2753      * with new protection or backing.
    2754      */
    2755 #endif
    2756     int rc;
    2757     switch (u2State)
    2758     {
    2759         case NEM_WIN_PAGE_STATE_UNMAPPED:
    2760         case NEM_WIN_PAGE_STATE_NOT_SET:
    2761             if (pInfo->fNemProt == NEM_PAGE_PROT_NONE)
    2762             {
    2763                 Log4(("nemR3WinHandleMemoryAccessPageCheckerCallback: %RGp - #1\n", GCPhys));
    2764                 return VINF_SUCCESS;
    2765             }
    2766 
    2767             /* Don't bother remapping it if it's a write request to a non-writable page. */
    2768             if (   pState->fWriteAccess
    2769                 && !(pInfo->fNemProt & NEM_PAGE_PROT_WRITE))
    2770             {
    2771                 Log4(("nemR3WinHandleMemoryAccessPageCheckerCallback: %RGp - #1w\n", GCPhys));
    2772                 return VINF_SUCCESS;
    2773             }
    2774 
    2775             /* Map the page. */
    2776             rc = nemR3NativeSetPhysPage(pVM,
    2777                                         pVCpu,
    2778                                         GCPhysSrc & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK,
    2779                                         GCPhys & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK,
    2780                                         pInfo->fNemProt,
    2781                                         &u2State,
    2782                                         true /*fBackingState*/);
    2783             pInfo->u2NemState = u2State;
    2784             Log4(("nemR3WinHandleMemoryAccessPageCheckerCallback: %RGp - synced => %s + %Rrc\n",
    2785                   GCPhys, g_apszPageStates[u2State], rc));
    2786             pState->fDidSomething = true;
    2787             pState->fCanResume    = true;
    2788             return rc;
    2789 
    2790         case NEM_WIN_PAGE_STATE_READABLE:
    2791             if (   !(pInfo->fNemProt & NEM_PAGE_PROT_WRITE)
    2792                 && (pInfo->fNemProt & (NEM_PAGE_PROT_READ | NEM_PAGE_PROT_EXECUTE)))
    2793             {
    2794                 Log4(("nemR3WinHandleMemoryAccessPageCheckerCallback: %RGp - #2\n", GCPhys));
    2795                 return VINF_SUCCESS;
    2796             }
    2797 
    2798 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
    2799             /* Upgrade page to writable. */
    2800 /** @todo test this*/
    2801             if (   (pInfo->fNemProt & NEM_PAGE_PROT_WRITE)
    2802                 && pState->fWriteAccess)
    2803             {
    2804                 rc = nemR3WinHypercallMapPage(pVM, pVCpu, GCPhysSrc, GCPhys,
    2805                                               HV_MAP_GPA_READABLE   | HV_MAP_GPA_WRITABLE
    2806                                               | HV_MAP_GPA_EXECUTABLE | HV_MAP_GPA_EXECUTABLE_AGAIN);
    2807                 AssertRC(rc);
    2808                 if (RT_SUCCESS(rc))
    2809                 {
    2810                     pInfo->u2NemState = NEM_WIN_PAGE_STATE_WRITABLE;
    2811                     pState->fDidSomething = true;
    2812                     pState->fCanResume    = true;
    2813                     Log5(("NEM GPA write-upgrade/exit: %RGp (was %s, cMappedPages=%u)\n",
    2814                           GCPhys, g_apszPageStates[u2State], pVM->nem.s.cMappedPages));
    2815                 }
    2816             }
    2817             else
    2818             {
    2819                 /* Need to emulate the acces. */
    2820                 AssertBreak(pInfo->fNemProt != NEM_PAGE_PROT_NONE); /* There should be no downgrades. */
    2821                 rc = VINF_SUCCESS;
    2822             }
    2823             return rc;
    2824 #else
    2825             break;
    2826 #endif
    2827 
    2828         case NEM_WIN_PAGE_STATE_WRITABLE:
    2829             if (pInfo->fNemProt & NEM_PAGE_PROT_WRITE)
    2830             {
    2831                 Log4(("nemR3WinHandleMemoryAccessPageCheckerCallback: %RGp - #3\n", GCPhys));
    2832                 return VINF_SUCCESS;
    2833             }
    2834 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
    2835             AssertFailed(); /* There should be no downgrades. */
    2836 #endif
    2837             break;
    2838 
    2839         default:
    2840             AssertLogRelMsgFailedReturn(("u2State=%#x\n", u2State), VERR_INTERNAL_ERROR_3);
    2841     }
    2842 
    2843     /*
    2844      * Unmap and restart the instruction.
    2845      * If this fails, which it does every so often, just unmap everything for now.
    2846      */
    2847 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
    2848     rc = nemR3WinHypercallUnmapPage(pVM, pVCpu, GCPhys);
    2849     AssertRC(rc);
    2850     if (RT_SUCCESS(rc))
    2851 #else
    2852     /** @todo figure out whether we mess up the state or if it's WHv.   */
    2853     HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhys, X86_PAGE_SIZE);
    2854     if (SUCCEEDED(hrc))
    2855 #endif
    2856     {
    2857         pState->fDidSomething = true;
    2858         pState->fCanResume    = true;
    2859         pInfo->u2NemState = NEM_WIN_PAGE_STATE_UNMAPPED;
    2860         uint32_t cMappedPages = ASMAtomicDecU32(&pVM->nem.s.cMappedPages); NOREF(cMappedPages);
    2861         Log5(("NEM GPA unmapped/exit: %RGp (was %s, cMappedPages=%u)\n", GCPhys, g_apszPageStates[u2State], cMappedPages));
    2862         return VINF_SUCCESS;
    2863     }
    2864 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
    2865     LogRel(("nemR3WinHandleMemoryAccessPageCheckerCallback/unmap: GCPhysDst=%RGp rc=%Rrc\n", GCPhys, rc));
    2866     return rc;
    2867 #else
    2868     LogRel(("nemR3WinHandleMemoryAccessPageCheckerCallback/unmap: GCPhysDst=%RGp %s hrc=%Rhrc (%#x) Last=%#x/%u (cMappedPages=%u)\n",
    2869             GCPhys, g_apszPageStates[u2State], hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue(),
    2870             pVM->nem.s.cMappedPages));
    2871 
    2872     PGMPhysNemEnumPagesByState(pVM, pVCpu, NEM_WIN_PAGE_STATE_READABLE, nemR3WinUnmapOnePageCallback, NULL);
    2873     Log(("nemR3WinHandleMemoryAccessPageCheckerCallback: Unmapped all (cMappedPages=%u)\n", pVM->nem.s.cMappedPages));
    2874 
    2875     pState->fDidSomething = true;
    2876     pState->fCanResume    = true;
    2877     pInfo->u2NemState = NEM_WIN_PAGE_STATE_UNMAPPED;
    2878     return VINF_SUCCESS;
    2879 #endif
    2880 }
     1495#endif /* !NEM_WIN_USE_HYPERCALLS_FOR_PAGES */
    28811496
    28821497
     
    28921507 * @param   pMemCtx         The exit reason information.
    28931508 */
    2894 static VBOXSTRICTRC nemR3WinHandleMemoryAccess(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_MEMORY_ACCESS_CONTEXT const *pMemCtx)
     1509static VBOXSTRICTRC nemR3WinWHvHandleMemoryAccess(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_MEMORY_ACCESS_CONTEXT const *pMemCtx)
    28951510{
    28961511    /*
     
    28981513     * out of sync first.
    28991514     */
    2900     NEMR3WINHMACPCCSTATE State = { pMemCtx->AccessInfo.AccessType == WHvMemoryAccessWrite, false, false };
     1515    NEMHCWINHMACPCCSTATE State = { pMemCtx->AccessInfo.AccessType == WHvMemoryAccessWrite, false, false };
    29011516    PGMPHYSNEMPAGEINFO   Info;
    29021517    int rc = PGMPhysNemPageInfoChecker(pVM, pVCpu, pMemCtx->Gpa, State.fWriteAccess, &Info,
    2903                                        nemR3WinHandleMemoryAccessPageCheckerCallback, &State);
     1518                                       nemHCWinHandleMemoryAccessPageCheckerCallback, &State);
    29041519    if (RT_SUCCESS(rc))
    29051520    {
     
    29491564 * @param   pIoPortCtx      The exit reason information.
    29501565 */
    2951 static VBOXSTRICTRC nemR3WinHandleIoPortAccess(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx,
    2952                                                WHV_X64_IO_PORT_ACCESS_CONTEXT const *pIoPortCtx)
     1566static VBOXSTRICTRC nemR3WinWHvHandleIoPortAccess(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx,
     1567                                                  WHV_X64_IO_PORT_ACCESS_CONTEXT const *pIoPortCtx)
    29531568{
    29541569    Assert(   pIoPortCtx->AccessInfo.AccessSize == 1
     
    29721587                                      pIoPortCtx->AccessInfo.AccessSize);
    29731588            if (IOM_SUCCESS(rcStrict))
    2974                 nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pIoPortCtx->VpContext);
     1589                nemHCWinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pIoPortCtx->VpContext);
    29751590        }
    29761591        else
     
    29821597            {
    29831598                pCtx->eax = (pCtx->eax & ~fAndMask) | (uValue & fAndMask);
    2984                 nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pIoPortCtx->VpContext);
     1599                nemHCWinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pIoPortCtx->VpContext);
    29851600            }
    29861601        }
     
    30261641
    30271642
    3028 static VBOXSTRICTRC nemR3WinHandleInterruptWindow(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
     1643static VBOXSTRICTRC nemR3WinWHvHandleInterruptWindow(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
    30291644{
    30301645    NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason);
     
    30331648
    30341649
    3035 static VBOXSTRICTRC nemR3WinHandleMsrAccess(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
     1650static VBOXSTRICTRC nemR3WinWHvHandleMsrAccess(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
    30361651{
    30371652    NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason);
     
    30401655
    30411656
    3042 static VBOXSTRICTRC nemR3WinHandleCpuId(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
     1657static VBOXSTRICTRC nemR3WinWHvHandleCpuId(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
    30431658{
    30441659    NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason);
     
    30471662
    30481663
    3049 static VBOXSTRICTRC nemR3WinHandleException(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
     1664static VBOXSTRICTRC nemR3WinWHvHandleException(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
    30501665{
    30511666    NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason);
     
    30541669
    30551670
    3056 static VBOXSTRICTRC nemR3WinHandleUD(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
     1671static VBOXSTRICTRC nemR3WinWHvHandleUD(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
    30571672{
    30581673    NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason);
     
    30611676
    30621677
    3063 static VBOXSTRICTRC nemR3WinHandleTripleFault(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
     1678static VBOXSTRICTRC nemR3WinWHvHandleTripleFault(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
    30641679{
    30651680    NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason);
     
    30681683
    30691684
    3070 static VBOXSTRICTRC nemR3WinHandleInvalidState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
     1685static VBOXSTRICTRC nemR3WinWHvHandleInvalidState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
    30711686{
    30721687    NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason);
     
    30751690
    30761691
    3077 VBOXSTRICTRC nemR3NativeRunGC(PVM pVM, PVMCPU pVCpu)
     1692VBOXSTRICTRC nemR3WinWHvRunGC(PVM pVM, PVMCPU pVCpu)
    30781693{
    30791694#ifdef LOG_ENABLED
     
    30811696    {
    30821697        Log3(("nemR3NativeRunGC: Entering #%u\n", pVCpu->idCpu));
    3083         nemR3WinLogState(pVM, pVCpu);
     1698        nemHCWinLogState(pVM, pVCpu);
    30841699    }
    30851700#endif
     
    30991714         */
    31001715        PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
    3101         int rc2 = nemR3WinCopyStateToHyperV(pVM, pVCpu, pCtx);
     1716        int rc2 = nemHCWinCopyStateToHyperV(pVM, pVCpu, pCtx);
    31021717        AssertRCBreakStmt(rc2, rcStrict = rc2);
    31031718
     
    31111726        {
    31121727#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
    3113             int rc2 = nemR3WinRunVirtualProcessor(pVM, pVCpu, &ExitReason, sizeof(ExitReason));
     1728            int rc2 = nemHCWinRunVirtualProcessor(pVM, pVCpu, &ExitReason, sizeof(ExitReason));
    31141729            AssertRCBreakStmt(rc2, rcStrict = rc2);
    31151730#else
     
    31351750         * Copy back the state.
    31361751         */
    3137         rc2 = nemR3WinCopyStateFromHyperV(pVM, pVCpu, pCtx);
     1752        rc2 = nemHCWinCopyStateFromHyperV(pVM, pVCpu, pCtx);
    31381753        AssertRCBreakStmt(rc2, rcStrict = rc2);
    31391754
     
    31431758         */
    31441759        if (LogIs2Enabled())
    3145             nemR3WinLogExitReason(&ExitReason);
     1760            nemR3WinLogWHvExitReason(&ExitReason);
    31461761        if (LogIs3Enabled())
    3147             nemR3WinLogState(pVM, pVCpu);
     1762            nemHCWinLogState(pVM, pVCpu);
    31481763#endif
    31491764
     
    31911806
    31921807            case WHvRunVpExitReasonX64Halt:
    3193                 rcStrict = nemR3WinHandleHalt(pVM, pVCpu, pCtx);
     1808                rcStrict = nemR3WinWHvHandleHalt(pVM, pVCpu, pCtx);
    31941809                break;
    31951810
    31961811            case WHvRunVpExitReasonMemoryAccess:
    3197                 rcStrict = nemR3WinHandleMemoryAccess(pVM, pVCpu, pCtx, &ExitReason.MemoryAccess);
     1812                rcStrict = nemR3WinWHvHandleMemoryAccess(pVM, pVCpu, pCtx, &ExitReason.MemoryAccess);
    31981813                break;
    31991814
    32001815            case WHvRunVpExitReasonX64IoPortAccess:
    3201                 rcStrict = nemR3WinHandleIoPortAccess(pVM, pVCpu, pCtx, &ExitReason.IoPortAccess);
     1816                rcStrict = nemR3WinWHvHandleIoPortAccess(pVM, pVCpu, pCtx, &ExitReason.IoPortAccess);
    32021817                break;
    32031818
    32041819            case WHvRunVpExitReasonX64InterruptWindow:
    3205                 rcStrict = nemR3WinHandleInterruptWindow(pVM, pVCpu, pCtx, &ExitReason);
     1820                rcStrict = nemR3WinWHvHandleInterruptWindow(pVM, pVCpu, pCtx, &ExitReason);
    32061821                break;
    32071822
    32081823            case WHvRunVpExitReasonX64MsrAccess: /* needs configuring */
    3209                 rcStrict = nemR3WinHandleMsrAccess(pVM, pVCpu, pCtx, &ExitReason);
     1824                rcStrict = nemR3WinWHvHandleMsrAccess(pVM, pVCpu, pCtx, &ExitReason);
    32101825                break;
    32111826
    32121827            case WHvRunVpExitReasonX64Cpuid: /* needs configuring */
    3213                 rcStrict = nemR3WinHandleCpuId(pVM, pVCpu, pCtx, &ExitReason);
     1828                rcStrict = nemR3WinWHvHandleCpuId(pVM, pVCpu, pCtx, &ExitReason);
    32141829                break;
    32151830
    32161831            case WHvRunVpExitReasonException: /* needs configuring */
    3217                 rcStrict = nemR3WinHandleException(pVM, pVCpu, pCtx, &ExitReason);
     1832                rcStrict = nemR3WinWHvHandleException(pVM, pVCpu, pCtx, &ExitReason);
    32181833                break;
    32191834
    32201835            /* Unlikely exits: */
    32211836            case WHvRunVpExitReasonUnsupportedFeature:
    3222                 rcStrict = nemR3WinHandleUD(pVM, pVCpu, pCtx, &ExitReason);
     1837                rcStrict = nemR3WinWHvHandleUD(pVM, pVCpu, pCtx, &ExitReason);
    32231838                break;
    32241839
    32251840            case WHvRunVpExitReasonUnrecoverableException:
    3226                 rcStrict = nemR3WinHandleTripleFault(pVM, pVCpu, pCtx, &ExitReason);
     1841                rcStrict = nemR3WinWHvHandleTripleFault(pVM, pVCpu, pCtx, &ExitReason);
    32271842                break;
    32281843
    32291844            case WHvRunVpExitReasonInvalidVpRegisterValue:
    3230                 rcStrict = nemR3WinHandleInvalidState(pVM, pVCpu, pCtx, &ExitReason);
     1845                rcStrict = nemR3WinWHvHandleInvalidState(pVM, pVCpu, pCtx, &ExitReason);
    32311846                break;
    32321847
     
    32511866        else
    32521867        {
    3253             PGMPhysNemEnumPagesByState(pVM, pVCpu, NEM_WIN_PAGE_STATE_READABLE, nemR3WinUnmapOnePageCallback, NULL);
     1868            PGMPhysNemEnumPagesByState(pVM, pVCpu, NEM_WIN_PAGE_STATE_READABLE, nemR3WinWHvUnmapOnePageCallback, NULL);
    32541869            Log(("nemR3NativeRunGC: Unmapped all; cMappedPages=%u -> %u\n", cMappedPages, pVM->nem.s.cMappedPages));
    32551870        }
     
    32701885
    32711886
     1887VBOXSTRICTRC nemR3NativeRunGC(PVM pVM, PVMCPU pVCpu)
     1888{
     1889#if 1
     1890    return nemR3WinWHvRunGC(pVM, pVCpu);
     1891#elif 1
     1892    return nemHCWinRunGC(pVM, pVCpu);
     1893#else
     1894    int rc = VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_NEM_RUN_GC, 0, NULL);
     1895    if (RT_SUCCESS(rc))
     1896        return pVCpu->nem.s.rcRing0;
     1897    return rc;
     1898#endif
     1899}
     1900
     1901
    32721902bool nemR3NativeCanExecuteGuest(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
    32731903{
     
    32971927{
    32981928#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
    3299     nemR3WinCancelRunVirtualProcessor(pVM, pVCpu);
     1929    nemHCWinCancelRunVirtualProcessor(pVM, pVCpu);
    33001930#else
    33011931    Log8(("nemR3NativeNotifyFF: canceling %u\n", pVCpu->idCpu));
     
    34312061    {
    34322062#ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
    3433         int rc = nemR3WinHypercallUnmapPage(pVM, pVCpu, GCPhys);
     2063        int rc = nemHCWinHypercallUnmapPage(pVM, pVCpu, GCPhys);
    34342064        AssertRC(rc);
    34352065        if (RT_SUCCESS(rc))
     
    34982128}
    34992129
    3500 
    3501 void nemR3NativeNotifyHandlerPhysicalRegister(PVM pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhys, RTGCPHYS cb)
    3502 {
    3503     Log5(("nemR3NativeNotifyHandlerPhysicalRegister: %RGp LB %RGp enmKind=%d\n", GCPhys, cb, enmKind));
    3504     NOREF(pVM); NOREF(enmKind); NOREF(GCPhys); NOREF(cb);
    3505 }
    3506 
    3507 
    3508 void nemR3NativeNotifyHandlerPhysicalDeregister(PVM pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhys, RTGCPHYS cb,
    3509                                                 int fRestoreAsRAM, bool fRestoreAsRAM2)
    3510 {
    3511     Log5(("nemR3NativeNotifyHandlerPhysicalDeregister: %RGp LB %RGp enmKind=%d fRestoreAsRAM=%d fRestoreAsRAM2=%d\n",
    3512           GCPhys, cb, enmKind, fRestoreAsRAM, fRestoreAsRAM2));
    3513     NOREF(pVM); NOREF(enmKind); NOREF(GCPhys); NOREF(cb); NOREF(fRestoreAsRAM); NOREF(fRestoreAsRAM2);
    3514 }
    3515 
    3516 
    3517 void nemR3NativeNotifyHandlerPhysicalModify(PVM pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhysOld,
    3518                                             RTGCPHYS GCPhysNew, RTGCPHYS cb, bool fRestoreAsRAM)
    3519 {
    3520     Log5(("nemR3NativeNotifyHandlerPhysicalModify: %RGp LB %RGp -> %RGp enmKind=%d fRestoreAsRAM=%d\n",
    3521           GCPhysOld, cb, GCPhysNew, enmKind, fRestoreAsRAM));
    3522     NOREF(pVM); NOREF(enmKind); NOREF(GCPhysOld); NOREF(GCPhysNew); NOREF(cb); NOREF(fRestoreAsRAM);
    3523 }
    3524 
    3525 
    3526 /**
    3527  * Worker that maps pages into Hyper-V.
    3528  *
    3529  * This is used by the PGM physical page notifications as well as the memory
    3530  * access VMEXIT handlers.
    3531  *
    3532  * @returns VBox status code.
    3533  * @param   pVM             The cross context VM structure.
    3534  * @param   pVCpu           The cross context virtual CPU structure of the
    3535  *                          calling EMT.
    3536  * @param   GCPhysSrc       The source page address.
    3537  * @param   GCPhysDst       The hyper-V destination page.  This may differ from
    3538  *                          GCPhysSrc when A20 is disabled.
    3539  * @param   fPageProt       NEM_PAGE_PROT_XXX.
    3540  * @param   pu2State        Our page state (input/output).
    3541  * @param   fBackingChanged Set if the page backing is being changed.
    3542  * @thread  EMT(pVCpu)
    3543  */
    3544 static int nemR3NativeSetPhysPage(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhysSrc, RTGCPHYS GCPhysDst, uint32_t fPageProt,
    3545                                   uint8_t *pu2State, bool fBackingChanged)
    3546 {
    3547 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
    3548     /*
    3549      * When using the hypercalls instead of the ring-3 APIs, we don't need to
    3550      * unmap memory before modifying it.  We still want to track the state though,
    3551      * since unmap will fail when called an unmapped page and we don't want to redo
    3552      * upgrades/downgrades.
    3553      */
    3554     uint8_t const u2OldState = *pu2State;
    3555     int rc;
    3556     if (fPageProt == NEM_PAGE_PROT_NONE)
    3557     {
    3558         if (u2OldState > NEM_WIN_PAGE_STATE_UNMAPPED)
    3559         {
    3560             rc = nemR3WinHypercallUnmapPage(pVM, pVCpu, GCPhysDst);
    3561             if (RT_SUCCESS(rc))
    3562             {
    3563                 *pu2State = NEM_WIN_PAGE_STATE_UNMAPPED;
    3564                 uint32_t cMappedPages = ASMAtomicDecU32(&pVM->nem.s.cMappedPages); NOREF(cMappedPages);
    3565                 Log5(("NEM GPA unmapped/set: %RGp (was %s, cMappedPages=%u)\n", GCPhysDst, g_apszPageStates[u2OldState], cMappedPages));
    3566             }
    3567             else
    3568                 AssertLogRelMsgFailed(("nemR3NativeSetPhysPage/unmap: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));
    3569         }
    3570         else
    3571             rc = VINF_SUCCESS;
    3572     }
    3573     else if (fPageProt & NEM_PAGE_PROT_WRITE)
    3574     {
    3575         if (u2OldState != NEM_WIN_PAGE_STATE_WRITABLE || fBackingChanged)
    3576         {
    3577             rc = nemR3WinHypercallMapPage(pVM, pVCpu, GCPhysSrc, GCPhysDst,
    3578                                             HV_MAP_GPA_READABLE   | HV_MAP_GPA_WRITABLE
    3579                                           | HV_MAP_GPA_EXECUTABLE | HV_MAP_GPA_EXECUTABLE_AGAIN);
    3580             if (RT_SUCCESS(rc))
    3581             {
    3582                 *pu2State = NEM_WIN_PAGE_STATE_WRITABLE;
    3583                 uint32_t cMappedPages = u2OldState <= NEM_WIN_PAGE_STATE_UNMAPPED
    3584                                       ? ASMAtomicIncU32(&pVM->nem.s.cMappedPages) : pVM->nem.s.cMappedPages;
    3585                 Log5(("NEM GPA writable/set: %RGp (was %s, cMappedPages=%u)\n", GCPhysDst, g_apszPageStates[u2OldState], cMappedPages));
    3586                 NOREF(cMappedPages);
    3587             }
    3588             else
    3589                 AssertLogRelMsgFailed(("nemR3NativeSetPhysPage/writable: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));
    3590         }
    3591         else
    3592             rc = VINF_SUCCESS;
    3593     }
    3594     else
    3595     {
    3596         if (u2OldState != NEM_WIN_PAGE_STATE_READABLE || fBackingChanged)
    3597         {
    3598             rc = nemR3WinHypercallMapPage(pVM, pVCpu, GCPhysSrc, GCPhysDst,
    3599                                           HV_MAP_GPA_READABLE | HV_MAP_GPA_EXECUTABLE | HV_MAP_GPA_EXECUTABLE_AGAIN);
    3600             if (RT_SUCCESS(rc))
    3601             {
    3602                 *pu2State = NEM_WIN_PAGE_STATE_READABLE;
    3603                 uint32_t cMappedPages = u2OldState <= NEM_WIN_PAGE_STATE_UNMAPPED
    3604                                       ? ASMAtomicIncU32(&pVM->nem.s.cMappedPages) : pVM->nem.s.cMappedPages;
    3605                 Log5(("NEM GPA read+exec/set: %RGp (was %s, cMappedPages=%u)\n", GCPhysDst, g_apszPageStates[u2OldState], cMappedPages));
    3606                 NOREF(cMappedPages);
    3607             }
    3608             else
    3609                 AssertLogRelMsgFailed(("nemR3NativeSetPhysPage/writable: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));
    3610         }
    3611         else
    3612             rc = VINF_SUCCESS;
    3613     }
    3614 
    3615     return VINF_SUCCESS;
    3616 
    3617 #else
    3618     /*
    3619      * Looks like we need to unmap a page before we can change the backing
    3620      * or even modify the protection.  This is going to be *REALLY* efficient.
    3621      * PGM lends us two bits to keep track of the state here.
    3622      */
    3623     uint8_t const u2OldState = *pu2State;
    3624     uint8_t const u2NewState = fPageProt & NEM_PAGE_PROT_WRITE ? NEM_WIN_PAGE_STATE_WRITABLE
    3625                              : fPageProt & NEM_PAGE_PROT_READ  ? NEM_WIN_PAGE_STATE_READABLE : NEM_WIN_PAGE_STATE_UNMAPPED;
    3626     if (   fBackingChanged
    3627         || u2NewState != u2OldState)
    3628     {
    3629         if (u2OldState > NEM_WIN_PAGE_STATE_UNMAPPED)
    3630         {
    3631 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
    3632             int rc = nemR3WinHypercallUnmapPage(pVM, pVCpu, GCPhysDst);
    3633             AssertRC(rc);
    3634             if (RT_SUCCESS(rc))
    3635             {
    3636                 *pu2State = NEM_WIN_PAGE_STATE_UNMAPPED;
    3637                 uint32_t cMappedPages = ASMAtomicDecU32(&pVM->nem.s.cMappedPages); NOREF(cMappedPages);
    3638                 if (u2NewState == NEM_WIN_PAGE_STATE_UNMAPPED)
    3639                 {
    3640                     Log5(("NEM GPA unmapped/set: %RGp (was %s, cMappedPages=%u)\n",
    3641                           GCPhysDst, g_apszPageStates[u2OldState], cMappedPages));
    3642                     return VINF_SUCCESS;
    3643                 }
    3644             }
    3645             else
    3646             {
    3647                 LogRel(("nemR3NativeSetPhysPage/unmap: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));
    3648                 return rc;
    3649             }
    3650 # else
    3651             HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhysDst, X86_PAGE_SIZE);
    3652             if (SUCCEEDED(hrc))
    3653             {
    3654                 *pu2State = NEM_WIN_PAGE_STATE_UNMAPPED;
    3655                 uint32_t cMappedPages = ASMAtomicDecU32(&pVM->nem.s.cMappedPages); NOREF(cMappedPages);
    3656                 if (u2NewState == NEM_WIN_PAGE_STATE_UNMAPPED)
    3657                 {
    3658                     Log5(("NEM GPA unmapped/set: %RGp (was %s, cMappedPages=%u)\n",
    3659                           GCPhysDst, g_apszPageStates[u2OldState], cMappedPages));
    3660                     return VINF_SUCCESS;
    3661                 }
    3662             }
    3663             else
    3664             {
    3665                 LogRel(("nemR3NativeSetPhysPage/unmap: GCPhysDst=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",
    3666                         GCPhysDst, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    3667                 return VERR_NEM_INIT_FAILED;
    3668             }
    3669 # endif
    3670         }
    3671     }
    3672 
    3673     /*
    3674      * Writeable mapping?
    3675      */
    3676     if (fPageProt & NEM_PAGE_PROT_WRITE)
    3677     {
    3678 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
    3679         int rc = nemR3WinHypercallMapPage(pVM, pVCpu, GCPhysSrc, GCPhysDst,
    3680                                             HV_MAP_GPA_READABLE   | HV_MAP_GPA_WRITABLE
    3681                                           | HV_MAP_GPA_EXECUTABLE | HV_MAP_GPA_EXECUTABLE_AGAIN);
    3682         AssertRC(rc);
    3683         if (RT_SUCCESS(rc))
    3684         {
    3685             *pu2State = NEM_WIN_PAGE_STATE_WRITABLE;
    3686             uint32_t cMappedPages = ASMAtomicIncU32(&pVM->nem.s.cMappedPages); NOREF(cMappedPages);
    3687             Log5(("NEM GPA mapped/set: %RGp %s (was %s, cMappedPages=%u)\n",
    3688                   GCPhysDst, g_apszPageStates[u2NewState], g_apszPageStates[u2OldState], cMappedPages));
    3689             return VINF_SUCCESS;
    3690         }
    3691         LogRel(("nemR3NativeSetPhysPage/writable: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));
    3692         return rc;
    3693 # else
    3694         void *pvPage;
    3695         int rc = nemR3NativeGCPhys2R3PtrWriteable(pVM, GCPhysSrc, &pvPage);
    3696         if (RT_SUCCESS(rc))
    3697         {
    3698             HRESULT hrc = WHvMapGpaRange(pVM->nem.s.hPartition, pvPage, GCPhysDst, X86_PAGE_SIZE,
    3699                                          WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagExecute | WHvMapGpaRangeFlagWrite);
    3700             if (SUCCEEDED(hrc))
    3701             {
    3702                 *pu2State = NEM_WIN_PAGE_STATE_WRITABLE;
    3703                 uint32_t cMappedPages = ASMAtomicIncU32(&pVM->nem.s.cMappedPages); NOREF(cMappedPages);
    3704                 Log5(("NEM GPA mapped/set: %RGp %s (was %s, cMappedPages=%u)\n",
    3705                       GCPhysDst, g_apszPageStates[u2NewState], g_apszPageStates[u2OldState], cMappedPages));
    3706                 return VINF_SUCCESS;
    3707             }
    3708             LogRel(("nemR3NativeSetPhysPage/writable: GCPhysDst=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",
    3709                     GCPhysDst, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    3710             return VERR_NEM_INIT_FAILED;
    3711         }
    3712         LogRel(("nemR3NativeSetPhysPage/writable: GCPhysSrc=%RGp rc=%Rrc\n", GCPhysSrc, rc));
    3713         return rc;
    3714 # endif
    3715     }
    3716 
    3717     if (fPageProt & NEM_PAGE_PROT_READ)
    3718     {
    3719 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
    3720         int rc = nemR3WinHypercallMapPage(pVM, pVCpu, GCPhysSrc, GCPhysDst,
    3721                                           HV_MAP_GPA_READABLE | HV_MAP_GPA_EXECUTABLE | HV_MAP_GPA_EXECUTABLE_AGAIN);
    3722         AssertRC(rc);
    3723         if (RT_SUCCESS(rc))
    3724         {
    3725             *pu2State = NEM_WIN_PAGE_STATE_READABLE;
    3726             uint32_t cMappedPages = ASMAtomicIncU32(&pVM->nem.s.cMappedPages); NOREF(cMappedPages);
    3727             Log5(("NEM GPA mapped/set: %RGp %s (was %s, cMappedPages=%u)\n",
    3728                   GCPhysDst, g_apszPageStates[u2NewState], g_apszPageStates[u2OldState], cMappedPages));
    3729             return VINF_SUCCESS;
    3730         }
    3731         LogRel(("nemR3NativeSetPhysPage/readonly: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));
    3732         return rc;
    3733 # else
    3734         const void *pvPage;
    3735         int rc = nemR3NativeGCPhys2R3PtrReadOnly(pVM, GCPhysSrc, &pvPage);
    3736         if (RT_SUCCESS(rc))
    3737         {
    3738             HRESULT hrc = WHvMapGpaRange(pVM->nem.s.hPartition, (void *)pvPage, GCPhysDst, X86_PAGE_SIZE,
    3739                                          WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagExecute);
    3740             if (SUCCEEDED(hrc))
    3741             {
    3742                 *pu2State = NEM_WIN_PAGE_STATE_READABLE;
    3743                 uint32_t cMappedPages = ASMAtomicIncU32(&pVM->nem.s.cMappedPages); NOREF(cMappedPages);
    3744                 Log5(("NEM GPA mapped/set: %RGp %s (was %s, cMappedPages=%u)\n",
    3745                       GCPhysDst, g_apszPageStates[u2NewState], g_apszPageStates[u2OldState], cMappedPages));
    3746                 return VINF_SUCCESS;
    3747             }
    3748             LogRel(("nemR3NativeSetPhysPage/readonly: GCPhysDst=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",
    3749                     GCPhysDst, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    3750             return VERR_NEM_INIT_FAILED;
    3751         }
    3752         LogRel(("nemR3NativeSetPhysPage/readonly: GCPhysSrc=%RGp rc=%Rrc\n", GCPhysSrc, rc));
    3753         return rc;
    3754 # endif
    3755     }
    3756 
    3757     /* We already unmapped it above. */
    3758     *pu2State = NEM_WIN_PAGE_STATE_UNMAPPED;
    3759     return VINF_SUCCESS;
    3760 #endif /* !NEM_WIN_USE_HYPERCALLS_FOR_PAGES */
    3761 }
    3762 
    3763 
    3764 static int nemR3JustUnmapPageFromHyperV(PVM pVM, RTGCPHYS GCPhysDst, uint8_t *pu2State)
    3765 {
    3766     if (*pu2State <= NEM_WIN_PAGE_STATE_UNMAPPED)
    3767     {
    3768         Log5(("nemR3JustUnmapPageFromHyperV: %RGp == unmapped\n", GCPhysDst));
    3769         *pu2State = NEM_WIN_PAGE_STATE_UNMAPPED;
    3770         return VINF_SUCCESS;
    3771     }
    3772 
    3773 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
    3774     PVMCPU pVCpu = VMMGetCpu(pVM);
    3775     int rc = nemR3WinHypercallUnmapPage(pVM, pVCpu, GCPhysDst);
    3776     AssertRC(rc);
    3777     if (RT_SUCCESS(rc))
    3778     {
    3779         uint32_t cMappedPages = ASMAtomicDecU32(&pVM->nem.s.cMappedPages); NOREF(cMappedPages);
    3780         Log5(("NEM GPA unmapped/just: %RGp (was %s, cMappedPages=%u)\n", GCPhysDst, g_apszPageStates[*pu2State], cMappedPages));
    3781         *pu2State = NEM_WIN_PAGE_STATE_UNMAPPED;
    3782         return VINF_SUCCESS;
    3783     }
    3784     LogRel(("nemR3JustUnmapPageFromHyperV/unmap: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));
    3785     return rc;
    3786 #else
    3787     HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhysDst & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK, X86_PAGE_SIZE);
    3788     if (SUCCEEDED(hrc))
    3789     {
    3790         uint32_t cMappedPages = ASMAtomicDecU32(&pVM->nem.s.cMappedPages); NOREF(cMappedPages);
    3791         *pu2State = NEM_WIN_PAGE_STATE_UNMAPPED;
    3792         Log5(("nemR3JustUnmapPageFromHyperV: %RGp => unmapped (total %u)\n", GCPhysDst, cMappedPages));
    3793         return VINF_SUCCESS;
    3794     }
    3795     LogRel(("nemR3JustUnmapPageFromHyperV(%RGp): failed! hrc=%Rhrc (%#x) Last=%#x/%u\n",
    3796             GCPhysDst, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    3797     return VERR_INTERNAL_ERROR_3;
    3798 #endif
    3799 }
    3800 
    3801 
    3802 int nemR3NativeNotifyPhysPageAllocated(PVM pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint32_t fPageProt,
    3803                                        PGMPAGETYPE enmType, uint8_t *pu2State)
    3804 {
    3805     Log5(("nemR3NativeNotifyPhysPageAllocated: %RGp HCPhys=%RHp fPageProt=%#x enmType=%d *pu2State=%d\n",
    3806           GCPhys, HCPhys, fPageProt, enmType, *pu2State));
    3807     RT_NOREF_PV(HCPhys); RT_NOREF_PV(enmType);
    3808 
    3809     int rc;
    3810 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
    3811     PVMCPU pVCpu = VMMGetCpu(pVM);
    3812     if (   pVM->nem.s.fA20Enabled
    3813         || !NEM_WIN_IS_RELEVANT_TO_A20(GCPhys))
    3814         rc = nemR3NativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/);
    3815     else
    3816     {
    3817         /* To keep effort at a minimum, we unmap the HMA page alias and resync it lazily when needed. */
    3818         rc = nemR3WinUnmapPageForA20Gate(pVM, pVCpu, GCPhys | RT_BIT_32(20));
    3819         if (!NEM_WIN_IS_SUBJECT_TO_A20(GCPhys) && RT_SUCCESS(rc))
    3820             rc = nemR3NativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/);
    3821 
    3822     }
    3823 #else
    3824     RT_NOREF_PV(fPageProt);
    3825     if (   pVM->nem.s.fA20Enabled
    3826         || !NEM_WIN_IS_RELEVANT_TO_A20(GCPhys))
    3827         rc = nemR3JustUnmapPageFromHyperV(pVM, GCPhys, pu2State);
    3828     else if (!NEM_WIN_IS_SUBJECT_TO_A20(GCPhys))
    3829         rc = nemR3JustUnmapPageFromHyperV(pVM, GCPhys, pu2State);
    3830     else
    3831         rc = VINF_SUCCESS; /* ignore since we've got the alias page at this address. */
    3832 #endif
    3833     return rc;
    3834 }
    3835 
    3836 
    3837 void nemR3NativeNotifyPhysPageProtChanged(PVM pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint32_t fPageProt,
    3838                                           PGMPAGETYPE enmType, uint8_t *pu2State)
    3839 {
    3840     Log5(("nemR3NativeNotifyPhysPageProtChanged: %RGp HCPhys=%RHp fPageProt=%#x enmType=%d *pu2State=%d\n",
    3841           GCPhys, HCPhys, fPageProt, enmType, *pu2State));
    3842     RT_NOREF_PV(HCPhys); RT_NOREF_PV(enmType);
    3843 
    3844 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
    3845     PVMCPU pVCpu = VMMGetCpu(pVM);
    3846     if (   pVM->nem.s.fA20Enabled
    3847         || !NEM_WIN_IS_RELEVANT_TO_A20(GCPhys))
    3848         nemR3NativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, false /*fBackingChanged*/);
    3849     else
    3850     {
    3851         /* To keep effort at a minimum, we unmap the HMA page alias and resync it lazily when needed. */
    3852         nemR3WinUnmapPageForA20Gate(pVM, pVCpu, GCPhys | RT_BIT_32(20));
    3853         if (!NEM_WIN_IS_SUBJECT_TO_A20(GCPhys))
    3854             nemR3NativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, false /*fBackingChanged*/);
    3855     }
    3856 #else
    3857     RT_NOREF_PV(fPageProt);
    3858     if (   pVM->nem.s.fA20Enabled
    3859         || !NEM_WIN_IS_RELEVANT_TO_A20(GCPhys))
    3860         nemR3JustUnmapPageFromHyperV(pVM, GCPhys, pu2State);
    3861     else if (!NEM_WIN_IS_SUBJECT_TO_A20(GCPhys))
    3862         nemR3JustUnmapPageFromHyperV(pVM, GCPhys, pu2State);
    3863     /* else: ignore since we've got the alias page at this address. */
    3864 #endif
    3865 }
    3866 
    3867 
    3868 void nemR3NativeNotifyPhysPageChanged(PVM pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhysPrev, RTHCPHYS HCPhysNew,
    3869                                       uint32_t fPageProt, PGMPAGETYPE enmType, uint8_t *pu2State)
    3870 {
    3871     Log5(("nemR3NativeNotifyPhysPageProtChanged: %RGp HCPhys=%RHp->%RHp fPageProt=%#x enmType=%d *pu2State=%d\n",
    3872           GCPhys, HCPhysPrev, HCPhysNew, fPageProt, enmType, *pu2State));
    3873     RT_NOREF_PV(HCPhysPrev); RT_NOREF_PV(HCPhysNew); RT_NOREF_PV(enmType);
    3874 
    3875 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
    3876     PVMCPU pVCpu = VMMGetCpu(pVM);
    3877     if (   pVM->nem.s.fA20Enabled
    3878         || !NEM_WIN_IS_RELEVANT_TO_A20(GCPhys))
    3879         nemR3NativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/);
    3880     else
    3881     {
    3882         /* To keep effort at a minimum, we unmap the HMA page alias and resync it lazily when needed. */
    3883         nemR3WinUnmapPageForA20Gate(pVM, pVCpu, GCPhys | RT_BIT_32(20));
    3884         if (!NEM_WIN_IS_SUBJECT_TO_A20(GCPhys))
    3885             nemR3NativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/);
    3886     }
    3887 #else
    3888     RT_NOREF_PV(fPageProt);
    3889     if (   pVM->nem.s.fA20Enabled
    3890         || !NEM_WIN_IS_RELEVANT_TO_A20(GCPhys))
    3891         nemR3JustUnmapPageFromHyperV(pVM, GCPhys, pu2State);
    3892     else if (!NEM_WIN_IS_SUBJECT_TO_A20(GCPhys))
    3893         nemR3JustUnmapPageFromHyperV(pVM, GCPhys, pu2State);
    3894     /* else: ignore since we've got the alias page at this address. */
    3895 #endif
    3896 }
    3897 
Note: See TracChangeset for help on using the changeset viewer.

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