Changeset 71152 in vbox for trunk/src/VBox/VMM/VMMR3
- Timestamp:
- Feb 28, 2018 12:36:04 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 121046
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp
r71136 r71152 62 62 # define NEM_WIN_INTERCEPT_NT_IO_CTLS 63 63 #endif 64 65 /** @name Our two-bit physical page state for PGMPAGE66 * @{ */67 #define NEM_WIN_PAGE_STATE_NOT_SET 068 #define NEM_WIN_PAGE_STATE_UNMAPPED 169 #define NEM_WIN_PAGE_STATE_READABLE 270 #define NEM_WIN_PAGE_STATE_WRITABLE 371 /** @} */72 73 /** Checks if a_GCPhys is subject to the limited A20 gate emulation. */74 #define NEM_WIN_IS_SUBJECT_TO_A20(a_GCPhys) ((RTGCPHYS)((a_GCPhys) - _1M) < (RTGCPHYS)_64K)75 76 /** Checks if a_GCPhys is relevant to the limited A20 gate emulation. */77 #define NEM_WIN_IS_RELEVANT_TO_A20(a_GCPhys) \78 ( ((RTGCPHYS)((a_GCPhys) - _1M) < (RTGCPHYS)_64K) || ((RTGCPHYS)(a_GCPhys) < (RTGCPHYS)_64K) )79 64 80 65 /** VID I/O control detection: Fake partition handle input. */ … … 227 212 #endif 228 213 229 /** NEM_WIN_PAGE_STATE_XXX names. */230 static const char * const g_apszPageStates[4] = { "not-set", "unmapped", "readable", "writable" };231 214 /** WHV_MEMORY_ACCESS_TYPE names */ 232 215 static const char * const g_apszWHvMemAccesstypes[4] = { "read", "write", "exec", "!undefined!" }; … … 236 219 * Internal Functions * 237 220 *********************************************************************************************************************************/ 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" 240 226 241 227 … … 1351 1337 } 1352 1338 1353 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES1354 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 for1363 * 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_REGISTERS1396 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 #else1402 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 touch1639 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 WHvX64RegisterSysenterCs1652 /// @todo WHvX64RegisterSysenterEip1653 /// @todo WHvX64RegisterSysenterEsp1654 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 WHvRegisterInterruptState1672 /// @todo WHvRegisterPendingEvent01673 /// @todo WHvRegisterPendingEvent11674 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_CTLS1681 Log12(("Calling WHvSetVirtualProcessorRegisters(%p, %u, %p, %u, %p)\n",1682 pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, iReg, aValues));1683 #endif1684 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_REGISTERS1697 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 #else1709 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 touch1794 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_CTLS1822 Log12(("Calling WHvGetVirtualProcessorRegisters(%p, %u, %p, %u, %p)\n",1823 pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, cRegs, aValues));1824 #endif1825 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 this1890 }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 this1903 }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.FpTag1984 /*| (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 touch1999 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 WHvX64RegisterSysenterCs2019 /// @todo WHvX64RegisterSysenterEip2020 /// @todo WHvX64RegisterSysenterEsp2021 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 WHvRegisterPendingInterruption2031 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 WHvRegisterInterruptState2042 /// @todo WHvRegisterPendingEvent02043 /// @todo WHvRegisterPendingEvent12044 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 2067 1339 2068 1340 #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 requires2079 * the following patch to be enabled (windbg): eb vid+12180 0f 84 98 00 00 002080 */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 #endif2089 2090 2091 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API2092 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 the2101 * 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 on2110 * 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 code2167 * @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 the2270 * 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 else2314 {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 else2323 {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 else2330 {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 pending2352 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_bird2368 __debugbreak();2369 #endif2370 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 else2380 {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_TIMEOUT2386 || 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 else2396 {2397 /*2398 * State changed and we need to return.2399 *2400 * We must ensure that the processor is not running while we2401 * 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 return2408 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_ENABLED2469 1341 2470 1342 /** … … 2473 1345 * @param pExitReason The exit reason to log. 2474 1346 */ 2475 static void nemR3WinLog ExitReason(WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)1347 static void nemR3WinLogWHvExitReason(WHV_RUN_VP_EXIT_CONTEXT const *pExitReason) 2476 1348 { 2477 1349 bool fExitCtx = false; … … 2584 1456 } 2585 1457 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 2630 1458 #endif /* LOG_ENABLED */ 2631 1459 2632 1460 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) 1461 static VBOXSTRICTRC nemR3WinWHvHandleHalt(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx) 2658 1462 { 2659 1463 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); 2660 LogFlow(("nemR3Win HandleHalt\n"));1464 LogFlow(("nemR3WinWHvHandleHalt\n")); 2661 1465 return VINF_EM_HALT; 2662 1466 } 2663 1467 2664 1468 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 */ 1474 static DECLCALLBACK(int) nemR3WinWHvUnmapOnePageCallback(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, uint8_t *pu2NemState, void *pvUser) 2666 1475 { 2667 1476 RT_NOREF_PV(pvUser); 2668 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES2669 int rc = nemR3WinHypercallUnmapPage(pVM, pVCpu, GCPhys);2670 AssertRC(rc);2671 if (RT_SUCCESS(rc))2672 #else2673 1477 RT_NOREF_PV(pVCpu); 2674 1478 HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhys, X86_PAGE_SIZE); 2675 1479 if (SUCCEEDED(hrc)) 2676 #endif2677 1480 { 2678 1481 Log5(("NEM GPA unmap all: %RGp (cMappedPages=%u)\n", GCPhys, pVM->nem.s.cMappedPages - 1)); … … 2681 1484 else 2682 1485 { 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", 2687 1487 GCPhys, g_apszPageStates[*pu2NemState], hrc, hrc, RTNtLastStatusValue(), 2688 1488 RTNtLastErrorValue(), pVM->nem.s.cMappedPages)); 2689 #endif2690 1489 *pu2NemState = NEM_WIN_PAGE_STATE_NOT_SET; 2691 1490 } … … 2694 1493 return VINF_SUCCESS; 2695 1494 } 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 */ 2881 1496 2882 1497 … … 2892 1507 * @param pMemCtx The exit reason information. 2893 1508 */ 2894 static VBOXSTRICTRC nemR3Win HandleMemoryAccess(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_MEMORY_ACCESS_CONTEXT const *pMemCtx)1509 static VBOXSTRICTRC nemR3WinWHvHandleMemoryAccess(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_MEMORY_ACCESS_CONTEXT const *pMemCtx) 2895 1510 { 2896 1511 /* … … 2898 1513 * out of sync first. 2899 1514 */ 2900 NEM R3WINHMACPCCSTATE State = { pMemCtx->AccessInfo.AccessType == WHvMemoryAccessWrite, false, false };1515 NEMHCWINHMACPCCSTATE State = { pMemCtx->AccessInfo.AccessType == WHvMemoryAccessWrite, false, false }; 2901 1516 PGMPHYSNEMPAGEINFO Info; 2902 1517 int rc = PGMPhysNemPageInfoChecker(pVM, pVCpu, pMemCtx->Gpa, State.fWriteAccess, &Info, 2903 nem R3WinHandleMemoryAccessPageCheckerCallback, &State);1518 nemHCWinHandleMemoryAccessPageCheckerCallback, &State); 2904 1519 if (RT_SUCCESS(rc)) 2905 1520 { … … 2949 1564 * @param pIoPortCtx The exit reason information. 2950 1565 */ 2951 static VBOXSTRICTRC nemR3Win HandleIoPortAccess(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx,2952 WHV_X64_IO_PORT_ACCESS_CONTEXT const *pIoPortCtx)1566 static VBOXSTRICTRC nemR3WinWHvHandleIoPortAccess(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, 1567 WHV_X64_IO_PORT_ACCESS_CONTEXT const *pIoPortCtx) 2953 1568 { 2954 1569 Assert( pIoPortCtx->AccessInfo.AccessSize == 1 … … 2972 1587 pIoPortCtx->AccessInfo.AccessSize); 2973 1588 if (IOM_SUCCESS(rcStrict)) 2974 nem R3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pIoPortCtx->VpContext);1589 nemHCWinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pIoPortCtx->VpContext); 2975 1590 } 2976 1591 else … … 2982 1597 { 2983 1598 pCtx->eax = (pCtx->eax & ~fAndMask) | (uValue & fAndMask); 2984 nem R3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pIoPortCtx->VpContext);1599 nemHCWinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pIoPortCtx->VpContext); 2985 1600 } 2986 1601 } … … 3026 1641 3027 1642 3028 static VBOXSTRICTRC nemR3Win HandleInterruptWindow(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)1643 static VBOXSTRICTRC nemR3WinWHvHandleInterruptWindow(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason) 3029 1644 { 3030 1645 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason); … … 3033 1648 3034 1649 3035 static VBOXSTRICTRC nemR3Win HandleMsrAccess(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)1650 static VBOXSTRICTRC nemR3WinWHvHandleMsrAccess(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason) 3036 1651 { 3037 1652 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason); … … 3040 1655 3041 1656 3042 static VBOXSTRICTRC nemR3Win HandleCpuId(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)1657 static VBOXSTRICTRC nemR3WinWHvHandleCpuId(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason) 3043 1658 { 3044 1659 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason); … … 3047 1662 3048 1663 3049 static VBOXSTRICTRC nemR3Win HandleException(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)1664 static VBOXSTRICTRC nemR3WinWHvHandleException(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason) 3050 1665 { 3051 1666 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason); … … 3054 1669 3055 1670 3056 static VBOXSTRICTRC nemR3Win HandleUD(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)1671 static VBOXSTRICTRC nemR3WinWHvHandleUD(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason) 3057 1672 { 3058 1673 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason); … … 3061 1676 3062 1677 3063 static VBOXSTRICTRC nemR3Win HandleTripleFault(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)1678 static VBOXSTRICTRC nemR3WinWHvHandleTripleFault(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason) 3064 1679 { 3065 1680 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason); … … 3068 1683 3069 1684 3070 static VBOXSTRICTRC nemR3Win HandleInvalidState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)1685 static VBOXSTRICTRC nemR3WinWHvHandleInvalidState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason) 3071 1686 { 3072 1687 NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason); … … 3075 1690 3076 1691 3077 VBOXSTRICTRC nemR3 NativeRunGC(PVM pVM, PVMCPU pVCpu)1692 VBOXSTRICTRC nemR3WinWHvRunGC(PVM pVM, PVMCPU pVCpu) 3078 1693 { 3079 1694 #ifdef LOG_ENABLED … … 3081 1696 { 3082 1697 Log3(("nemR3NativeRunGC: Entering #%u\n", pVCpu->idCpu)); 3083 nem R3WinLogState(pVM, pVCpu);1698 nemHCWinLogState(pVM, pVCpu); 3084 1699 } 3085 1700 #endif … … 3099 1714 */ 3100 1715 PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu); 3101 int rc2 = nem R3WinCopyStateToHyperV(pVM, pVCpu, pCtx);1716 int rc2 = nemHCWinCopyStateToHyperV(pVM, pVCpu, pCtx); 3102 1717 AssertRCBreakStmt(rc2, rcStrict = rc2); 3103 1718 … … 3111 1726 { 3112 1727 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API 3113 int rc2 = nem R3WinRunVirtualProcessor(pVM, pVCpu, &ExitReason, sizeof(ExitReason));1728 int rc2 = nemHCWinRunVirtualProcessor(pVM, pVCpu, &ExitReason, sizeof(ExitReason)); 3114 1729 AssertRCBreakStmt(rc2, rcStrict = rc2); 3115 1730 #else … … 3135 1750 * Copy back the state. 3136 1751 */ 3137 rc2 = nem R3WinCopyStateFromHyperV(pVM, pVCpu, pCtx);1752 rc2 = nemHCWinCopyStateFromHyperV(pVM, pVCpu, pCtx); 3138 1753 AssertRCBreakStmt(rc2, rcStrict = rc2); 3139 1754 … … 3143 1758 */ 3144 1759 if (LogIs2Enabled()) 3145 nemR3WinLog ExitReason(&ExitReason);1760 nemR3WinLogWHvExitReason(&ExitReason); 3146 1761 if (LogIs3Enabled()) 3147 nem R3WinLogState(pVM, pVCpu);1762 nemHCWinLogState(pVM, pVCpu); 3148 1763 #endif 3149 1764 … … 3191 1806 3192 1807 case WHvRunVpExitReasonX64Halt: 3193 rcStrict = nemR3Win HandleHalt(pVM, pVCpu, pCtx);1808 rcStrict = nemR3WinWHvHandleHalt(pVM, pVCpu, pCtx); 3194 1809 break; 3195 1810 3196 1811 case WHvRunVpExitReasonMemoryAccess: 3197 rcStrict = nemR3Win HandleMemoryAccess(pVM, pVCpu, pCtx, &ExitReason.MemoryAccess);1812 rcStrict = nemR3WinWHvHandleMemoryAccess(pVM, pVCpu, pCtx, &ExitReason.MemoryAccess); 3198 1813 break; 3199 1814 3200 1815 case WHvRunVpExitReasonX64IoPortAccess: 3201 rcStrict = nemR3Win HandleIoPortAccess(pVM, pVCpu, pCtx, &ExitReason.IoPortAccess);1816 rcStrict = nemR3WinWHvHandleIoPortAccess(pVM, pVCpu, pCtx, &ExitReason.IoPortAccess); 3202 1817 break; 3203 1818 3204 1819 case WHvRunVpExitReasonX64InterruptWindow: 3205 rcStrict = nemR3Win HandleInterruptWindow(pVM, pVCpu, pCtx, &ExitReason);1820 rcStrict = nemR3WinWHvHandleInterruptWindow(pVM, pVCpu, pCtx, &ExitReason); 3206 1821 break; 3207 1822 3208 1823 case WHvRunVpExitReasonX64MsrAccess: /* needs configuring */ 3209 rcStrict = nemR3Win HandleMsrAccess(pVM, pVCpu, pCtx, &ExitReason);1824 rcStrict = nemR3WinWHvHandleMsrAccess(pVM, pVCpu, pCtx, &ExitReason); 3210 1825 break; 3211 1826 3212 1827 case WHvRunVpExitReasonX64Cpuid: /* needs configuring */ 3213 rcStrict = nemR3Win HandleCpuId(pVM, pVCpu, pCtx, &ExitReason);1828 rcStrict = nemR3WinWHvHandleCpuId(pVM, pVCpu, pCtx, &ExitReason); 3214 1829 break; 3215 1830 3216 1831 case WHvRunVpExitReasonException: /* needs configuring */ 3217 rcStrict = nemR3Win HandleException(pVM, pVCpu, pCtx, &ExitReason);1832 rcStrict = nemR3WinWHvHandleException(pVM, pVCpu, pCtx, &ExitReason); 3218 1833 break; 3219 1834 3220 1835 /* Unlikely exits: */ 3221 1836 case WHvRunVpExitReasonUnsupportedFeature: 3222 rcStrict = nemR3Win HandleUD(pVM, pVCpu, pCtx, &ExitReason);1837 rcStrict = nemR3WinWHvHandleUD(pVM, pVCpu, pCtx, &ExitReason); 3223 1838 break; 3224 1839 3225 1840 case WHvRunVpExitReasonUnrecoverableException: 3226 rcStrict = nemR3Win HandleTripleFault(pVM, pVCpu, pCtx, &ExitReason);1841 rcStrict = nemR3WinWHvHandleTripleFault(pVM, pVCpu, pCtx, &ExitReason); 3227 1842 break; 3228 1843 3229 1844 case WHvRunVpExitReasonInvalidVpRegisterValue: 3230 rcStrict = nemR3Win HandleInvalidState(pVM, pVCpu, pCtx, &ExitReason);1845 rcStrict = nemR3WinWHvHandleInvalidState(pVM, pVCpu, pCtx, &ExitReason); 3231 1846 break; 3232 1847 … … 3251 1866 else 3252 1867 { 3253 PGMPhysNemEnumPagesByState(pVM, pVCpu, NEM_WIN_PAGE_STATE_READABLE, nemR3Win UnmapOnePageCallback, NULL);1868 PGMPhysNemEnumPagesByState(pVM, pVCpu, NEM_WIN_PAGE_STATE_READABLE, nemR3WinWHvUnmapOnePageCallback, NULL); 3254 1869 Log(("nemR3NativeRunGC: Unmapped all; cMappedPages=%u -> %u\n", cMappedPages, pVM->nem.s.cMappedPages)); 3255 1870 } … … 3270 1885 3271 1886 1887 VBOXSTRICTRC 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 3272 1902 bool nemR3NativeCanExecuteGuest(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx) 3273 1903 { … … 3297 1927 { 3298 1928 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API 3299 nem R3WinCancelRunVirtualProcessor(pVM, pVCpu);1929 nemHCWinCancelRunVirtualProcessor(pVM, pVCpu); 3300 1930 #else 3301 1931 Log8(("nemR3NativeNotifyFF: canceling %u\n", pVCpu->idCpu)); … … 3431 2061 { 3432 2062 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES 3433 int rc = nem R3WinHypercallUnmapPage(pVM, pVCpu, GCPhys);2063 int rc = nemHCWinHypercallUnmapPage(pVM, pVCpu, GCPhys); 3434 2064 AssertRC(rc); 3435 2065 if (RT_SUCCESS(rc)) … … 3498 2128 } 3499 2129 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 memory3530 * 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 the3535 * calling EMT.3536 * @param GCPhysSrc The source page address.3537 * @param GCPhysDst The hyper-V destination page. This may differ from3538 * 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_PAGES3548 /*3549 * When using the hypercalls instead of the ring-3 APIs, we don't need to3550 * 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 redo3552 * 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 else3568 AssertLogRelMsgFailed(("nemR3NativeSetPhysPage/unmap: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));3569 }3570 else3571 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_WRITABLE3579 | 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_UNMAPPED3584 ? 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 else3589 AssertLogRelMsgFailed(("nemR3NativeSetPhysPage/writable: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));3590 }3591 else3592 rc = VINF_SUCCESS;3593 }3594 else3595 {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_UNMAPPED3604 ? 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 else3609 AssertLogRelMsgFailed(("nemR3NativeSetPhysPage/writable: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));3610 }3611 else3612 rc = VINF_SUCCESS;3613 }3614 3615 return VINF_SUCCESS;3616 3617 #else3618 /*3619 * Looks like we need to unmap a page before we can change the backing3620 * 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_WRITABLE3625 : fPageProt & NEM_PAGE_PROT_READ ? NEM_WIN_PAGE_STATE_READABLE : NEM_WIN_PAGE_STATE_UNMAPPED;3626 if ( fBackingChanged3627 || u2NewState != u2OldState)3628 {3629 if (u2OldState > NEM_WIN_PAGE_STATE_UNMAPPED)3630 {3631 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES3632 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 else3646 {3647 LogRel(("nemR3NativeSetPhysPage/unmap: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));3648 return rc;3649 }3650 # else3651 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 else3664 {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 # endif3670 }3671 }3672 3673 /*3674 * Writeable mapping?3675 */3676 if (fPageProt & NEM_PAGE_PROT_WRITE)3677 {3678 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES3679 int rc = nemR3WinHypercallMapPage(pVM, pVCpu, GCPhysSrc, GCPhysDst,3680 HV_MAP_GPA_READABLE | HV_MAP_GPA_WRITABLE3681 | 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 # else3694 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 # endif3715 }3716 3717 if (fPageProt & NEM_PAGE_PROT_READ)3718 {3719 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_PAGES3720 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 # else3734 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 # endif3755 }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_PAGES3774 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 #else3787 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 #endif3799 }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_PAGES3811 PVMCPU pVCpu = VMMGetCpu(pVM);3812 if ( pVM->nem.s.fA20Enabled3813 || !NEM_WIN_IS_RELEVANT_TO_A20(GCPhys))3814 rc = nemR3NativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/);3815 else3816 {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 #else3824 RT_NOREF_PV(fPageProt);3825 if ( pVM->nem.s.fA20Enabled3826 || !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 else3831 rc = VINF_SUCCESS; /* ignore since we've got the alias page at this address. */3832 #endif3833 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_PAGES3845 PVMCPU pVCpu = VMMGetCpu(pVM);3846 if ( pVM->nem.s.fA20Enabled3847 || !NEM_WIN_IS_RELEVANT_TO_A20(GCPhys))3848 nemR3NativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, false /*fBackingChanged*/);3849 else3850 {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 #else3857 RT_NOREF_PV(fPageProt);3858 if ( pVM->nem.s.fA20Enabled3859 || !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 #endif3865 }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_PAGES3876 PVMCPU pVCpu = VMMGetCpu(pVM);3877 if ( pVM->nem.s.fA20Enabled3878 || !NEM_WIN_IS_RELEVANT_TO_A20(GCPhys))3879 nemR3NativeSetPhysPage(pVM, pVCpu, GCPhys, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/);3880 else3881 {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 #else3888 RT_NOREF_PV(fPageProt);3889 if ( pVM->nem.s.fA20Enabled3890 || !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 #endif3896 }3897
Note:
See TracChangeset
for help on using the changeset viewer.