VirtualBox

Changeset 72918 in vbox


Ignore:
Timestamp:
Jul 5, 2018 1:53:14 PM (7 years ago)
Author:
vboxsync
Message:

NEM/win: Cleanups. bugref:9044

Location:
trunk/src/VBox/VMM
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR0/NEMR0Native-win.cpp

    r72917 r72918  
    12861286         * Call worker.
    12871287         */
    1288         rc = nemR0WinExportState(pGVM, pGVCpu, CPUMQueryGuestCtxPtr(pVCpu));
     1288        rc = nemR0WinExportState(pGVM, pGVCpu, &pVCpu->cpum.GstCtx);
    12891289    }
    12901290    return rc;
     
    22072207         * Call worker.
    22082208         */
    2209         rc = nemR0WinImportState(pGVM, pGVCpu, CPUMQueryGuestCtxPtr(pVCpu), fWhat);
     2209        rc = nemR0WinImportState(pGVM, pGVCpu, &pVCpu->cpum.GstCtx, fWhat);
    22102210    }
    22112211    return rc;
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp

    r72695 r72918  
    16301630    }
    16311631}
    1632 
    1633 #if 0 //ndef NEM_WIN_USE_OUR_OWN_RUN_API - migrating to NEMAllNativeTemplate-win.cpp.h  */
    1634 
    1635 # ifdef LOG_ENABLED
    1636 /**
    1637  * Log the full details of an exit reason.
    1638  *
    1639  * @param   pExitReason     The exit reason to log.
    1640  */
    1641 static void nemR3WinLogWHvExitReason(WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
    1642 {
    1643     bool fExitCtx = false;
    1644     bool fExitInstr = false;
    1645     switch (pExitReason->ExitReason)
    1646     {
    1647         case WHvRunVpExitReasonMemoryAccess:
    1648             Log2(("Exit: Memory access: GCPhys=%RGp GCVirt=%RGv %s %s %s\n",
    1649                   pExitReason->MemoryAccess.Gpa, pExitReason->MemoryAccess.Gva,
    1650                   g_apszWHvMemAccesstypes[pExitReason->MemoryAccess.AccessInfo.AccessType],
    1651                   pExitReason->MemoryAccess.AccessInfo.GpaUnmapped ? "unmapped" : "mapped",
    1652                   pExitReason->MemoryAccess.AccessInfo.GvaValid    ? "" : "invalid-gc-virt"));
    1653             AssertMsg(!(pExitReason->MemoryAccess.AccessInfo.AsUINT32 & ~UINT32_C(0xf)),
    1654                       ("MemoryAccess.AccessInfo=%#x\n", pExitReason->MemoryAccess.AccessInfo.AsUINT32));
    1655             fExitCtx = fExitInstr = true;
    1656             break;
    1657 
    1658         case WHvRunVpExitReasonX64IoPortAccess:
    1659             Log2(("Exit: I/O port access: IoPort=%#x LB %u %s%s%s rax=%#RX64 rcx=%#RX64 rsi=%#RX64 rdi=%#RX64\n",
    1660                   pExitReason->IoPortAccess.PortNumber,
    1661                   pExitReason->IoPortAccess.AccessInfo.AccessSize,
    1662                   pExitReason->IoPortAccess.AccessInfo.IsWrite ? "out" : "in",
    1663                   pExitReason->IoPortAccess.AccessInfo.StringOp ? " string" : "",
    1664                   pExitReason->IoPortAccess.AccessInfo.RepPrefix ? " rep" : "",
    1665                   pExitReason->IoPortAccess.Rax,
    1666                   pExitReason->IoPortAccess.Rcx,
    1667                   pExitReason->IoPortAccess.Rsi,
    1668                   pExitReason->IoPortAccess.Rdi));
    1669             Log2(("Exit: + ds=%#x:{%#RX64 LB %#RX32, %#x}  es=%#x:{%#RX64 LB %#RX32, %#x}\n",
    1670                   pExitReason->IoPortAccess.Ds.Selector,
    1671                   pExitReason->IoPortAccess.Ds.Base,
    1672                   pExitReason->IoPortAccess.Ds.Limit,
    1673                   pExitReason->IoPortAccess.Ds.Attributes,
    1674                   pExitReason->IoPortAccess.Es.Selector,
    1675                   pExitReason->IoPortAccess.Es.Base,
    1676                   pExitReason->IoPortAccess.Es.Limit,
    1677                   pExitReason->IoPortAccess.Es.Attributes ));
    1678 
    1679             AssertMsg(   pExitReason->IoPortAccess.AccessInfo.AccessSize == 1
    1680                       || pExitReason->IoPortAccess.AccessInfo.AccessSize == 2
    1681                       || pExitReason->IoPortAccess.AccessInfo.AccessSize == 4,
    1682                       ("IoPortAccess.AccessInfo.AccessSize=%d\n", pExitReason->IoPortAccess.AccessInfo.AccessSize));
    1683             AssertMsg(!(pExitReason->IoPortAccess.AccessInfo.AsUINT32 & ~UINT32_C(0x3f)),
    1684                       ("IoPortAccess.AccessInfo=%#x\n", pExitReason->IoPortAccess.AccessInfo.AsUINT32));
    1685             fExitCtx = fExitInstr = true;
    1686             break;
    1687 
    1688 #  if 0
    1689         case WHvRunVpExitReasonUnrecoverableException:
    1690         case WHvRunVpExitReasonInvalidVpRegisterValue:
    1691         case WHvRunVpExitReasonUnsupportedFeature:
    1692         case WHvRunVpExitReasonX64InterruptWindow:
    1693         case WHvRunVpExitReasonX64Halt:
    1694         case WHvRunVpExitReasonX64MsrAccess:
    1695         case WHvRunVpExitReasonX64Cpuid:
    1696         case WHvRunVpExitReasonException:
    1697         case WHvRunVpExitReasonCanceled:
    1698         case WHvRunVpExitReasonAlerted:
    1699             WHV_X64_MSR_ACCESS_CONTEXT MsrAccess;
    1700             WHV_X64_CPUID_ACCESS_CONTEXT CpuidAccess;
    1701             WHV_VP_EXCEPTION_CONTEXT VpException;
    1702             WHV_X64_INTERRUPTION_DELIVERABLE_CONTEXT InterruptWindow;
    1703             WHV_UNRECOVERABLE_EXCEPTION_CONTEXT UnrecoverableException;
    1704             WHV_X64_UNSUPPORTED_FEATURE_CONTEXT UnsupportedFeature;
    1705             WHV_RUN_VP_CANCELED_CONTEXT CancelReason;
    1706 #  endif
    1707 
    1708         case WHvRunVpExitReasonNone:
    1709             Log2(("Exit: No reason\n"));
    1710             AssertFailed();
    1711             break;
    1712 
    1713         default:
    1714             Log(("Exit: %#x\n", pExitReason->ExitReason));
    1715             break;
    1716     }
    1717 
    1718     /*
    1719      * Context and maybe instruction details.
    1720      */
    1721     if (fExitCtx)
    1722     {
    1723         const WHV_VP_EXIT_CONTEXT *pVpCtx = &pExitReason->VpContext;
    1724         Log2(("Exit: + CS:RIP=%04x:%08RX64 RFLAGS=%06RX64 cbInstr=%u CS={%RX64 L %#RX32, %#x}\n",
    1725               pVpCtx->Cs.Selector,
    1726               pVpCtx->Rip,
    1727               pVpCtx->Rflags,
    1728               pVpCtx->InstructionLength,
    1729               pVpCtx->Cs.Base, pVpCtx->Cs.Limit, pVpCtx->Cs.Attributes));
    1730         Log2(("Exit: + cpl=%d CR0.PE=%d CR0.AM=%d EFER.LMA=%d DebugActive=%d InterruptionPending=%d InterruptShadow=%d\n",
    1731               pVpCtx->ExecutionState.Cpl,
    1732               pVpCtx->ExecutionState.Cr0Pe,
    1733               pVpCtx->ExecutionState.Cr0Am,
    1734               pVpCtx->ExecutionState.EferLma,
    1735               pVpCtx->ExecutionState.DebugActive,
    1736               pVpCtx->ExecutionState.InterruptionPending,
    1737               pVpCtx->ExecutionState.InterruptShadow));
    1738         AssertMsg(!(pVpCtx->ExecutionState.AsUINT16 & ~UINT16_C(0x107f)),
    1739                   ("ExecutionState.AsUINT16=%#x\n", pVpCtx->ExecutionState.AsUINT16));
    1740 
    1741         /** @todo Someone at Microsoft please explain why the InstructionBytes fields
    1742          * are 16 bytes long, when 15 would've been sufficent and saved 3-7 bytes of
    1743          * alignment padding?  Intel max length is 15, so is this sSome ARM stuff?
    1744          * Aren't ARM
    1745          * instructions max 32-bit wide?  Confused. */
    1746         if (fExitInstr && pExitReason->IoPortAccess.InstructionByteCount > 0)
    1747             Log2(("Exit: + Instruction %.*Rhxs\n",
    1748                   pExitReason->IoPortAccess.InstructionByteCount, &pExitReason->IoPortAccess.InstructionBytes[0]));
    1749     }
    1750 }
    1751 # endif /* LOG_ENABLED */
    1752 
    1753 
    1754 static VBOXSTRICTRC nemR3WinWHvHandleHalt(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
    1755 {
    1756     NOREF(pVM); NOREF(pVCpu); NOREF(pCtx);
    1757     LogFlow(("nemR3WinWHvHandleHalt\n"));
    1758     return VINF_EM_HALT;
    1759 }
    1760 
    1761 
    1762 # ifndef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
    1763 /**
    1764  * @callback_method_impl{FNPGMPHYSNEMENUMCALLBACK,
    1765  *      Hack to unmap all pages when/before we run into quota (WHv only).}
    1766  */
    1767 static DECLCALLBACK(int) nemR3WinWHvUnmapOnePageCallback(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, uint8_t *pu2NemState, void *pvUser)
    1768 {
    1769     RT_NOREF_PV(pvUser);
    1770     RT_NOREF_PV(pVCpu);
    1771     HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhys, X86_PAGE_SIZE);
    1772     if (SUCCEEDED(hrc))
    1773     {
    1774         Log5(("NEM GPA unmap all: %RGp (cMappedPages=%u)\n", GCPhys, pVM->nem.s.cMappedPages - 1));
    1775         *pu2NemState = NEM_WIN_PAGE_STATE_UNMAPPED;
    1776     }
    1777     else
    1778     {
    1779         LogRel(("nemR3WinWHvUnmapOnePageCallback: GCPhys=%RGp %s hrc=%Rhrc (%#x) Last=%#x/%u (cMappedPages=%u)\n",
    1780                 GCPhys, g_apszPageStates[*pu2NemState], hrc, hrc, RTNtLastStatusValue(),
    1781                 RTNtLastErrorValue(), pVM->nem.s.cMappedPages));
    1782         *pu2NemState = NEM_WIN_PAGE_STATE_NOT_SET;
    1783     }
    1784     if (pVM->nem.s.cMappedPages > 0)
    1785         ASMAtomicDecU32(&pVM->nem.s.cMappedPages);
    1786     return VINF_SUCCESS;
    1787 }
    1788 # endif /* !NEM_WIN_USE_HYPERCALLS_FOR_PAGES */
    1789 
    1790 
    1791 /**
    1792  * Handles an memory access VMEXIT.
    1793  *
    1794  * This can be triggered by a number of things.
    1795  *
    1796  * @returns Strict VBox status code.
    1797  * @param   pVM             The cross context VM structure.
    1798  * @param   pVCpu           The cross context virtual CPU structure.
    1799  * @param   pCtx            The CPU context to update.
    1800  * @param   pMemCtx         The exit reason information.
    1801  * @param   pVpContext      The processor context info associated with the exit.
    1802  */
    1803 static VBOXSTRICTRC nemR3WinWHvHandleMemoryAccess(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_MEMORY_ACCESS_CONTEXT const *pMemCtx,
    1804                                                   WHV_VP_EXIT_CONTEXT const *pVpContext)
    1805 {
    1806     /*
    1807      * Ask PGM for information about the given GCPhys.  We need to check if we're
    1808      * out of sync first.
    1809      */
    1810     NEMHCWINHMACPCCSTATE State = { pMemCtx->AccessInfo.AccessType == WHvMemoryAccessWrite, false, false };
    1811     PGMPHYSNEMPAGEINFO   Info;
    1812     int rc = PGMPhysNemPageInfoChecker(pVM, pVCpu, pMemCtx->Gpa, State.fWriteAccess, &Info,
    1813                                        nemHCWinHandleMemoryAccessPageCheckerCallback, &State);
    1814     if (RT_SUCCESS(rc))
    1815     {
    1816         if (Info.fNemProt & (pMemCtx->AccessInfo.AccessType == WHvMemoryAccessWrite ? NEM_PAGE_PROT_WRITE : NEM_PAGE_PROT_READ))
    1817         {
    1818             if (State.fCanResume)
    1819             {
    1820                 Log4(("MemExit: %RGp (=>%RHp) %s fProt=%u%s%s%s; restarting (%s)\n",
    1821                       pMemCtx->Gpa, Info.HCPhys, g_apszPageStates[Info.u2NemState], Info.fNemProt,
    1822                       Info.fHasHandlers ? " handlers" : "", Info.fZeroPage    ? " zero-pg" : "",
    1823                       State.fDidSomething ? "" : " no-change", g_apszWHvMemAccesstypes[pMemCtx->AccessInfo.AccessType]));
    1824                 return VINF_SUCCESS;
    1825             }
    1826         }
    1827         Log4(("MemExit: %RGp (=>%RHp) %s fProt=%u%s%s%s; emulating (%s)\n",
    1828               pMemCtx->Gpa, Info.HCPhys, g_apszPageStates[Info.u2NemState], Info.fNemProt,
    1829               Info.fHasHandlers ? " handlers" : "", Info.fZeroPage    ? " zero-pg" : "",
    1830               State.fDidSomething ? "" : " no-change", g_apszWHvMemAccesstypes[pMemCtx->AccessInfo.AccessType]));
    1831     }
    1832     else
    1833         Log4(("MemExit: %RGp rc=%Rrc%s; emulating (%s)\n", pMemCtx->Gpa, rc,
    1834               State.fDidSomething ? " modified-backing" : "", g_apszWHvMemAccesstypes[pMemCtx->AccessInfo.AccessType]));
    1835 
    1836     /*
    1837      * Emulate the memory access, either access handler or special memory.
    1838      */
    1839     rc = nemHCWinCopyStateFromHyperV(pVM, pVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM);
    1840     AssertRCReturn(rc, rc);
    1841 
    1842     VBOXSTRICTRC rcStrict;
    1843     if (pMemCtx->InstructionByteCount > 0)
    1844         rcStrict = IEMExecOneWithPrefetchedByPC(pVCpu, CPUMCTX2CORE(pCtx), pVpContext->Rip,
    1845                                                 &pMemCtx->InstructionBytes[0], pMemCtx->InstructionByteCount);
    1846     else
    1847         rcStrict = IEMExecOne(pVCpu);
    1848     /** @todo do we need to do anything wrt debugging here?   */
    1849     return rcStrict;
    1850 }
    1851 
    1852 
    1853 /**
    1854  * Handles an I/O port access VMEXIT.
    1855  *
    1856  * We ASSUME that the hypervisor has don't I/O port access control.
    1857  *
    1858  * @returns Strict VBox status code.
    1859  * @param   pVM             The cross context VM structure.
    1860  * @param   pVCpu           The cross context virtual CPU structure.
    1861  * @param   pCtx            The CPU context to update.
    1862  * @param   pIoPortCtx      The exit reason information.
    1863  * @param   pVpContext      The processor context info associated with the exit.
    1864  */
    1865 static VBOXSTRICTRC
    1866 nemR3WinWHvHandleIoPortAccess(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_X64_IO_PORT_ACCESS_CONTEXT const *pIoPortCtx,
    1867                               WHV_VP_EXIT_CONTEXT const *pVpContext)
    1868 {
    1869     Assert(   pIoPortCtx->AccessInfo.AccessSize == 1
    1870            || pIoPortCtx->AccessInfo.AccessSize == 2
    1871            || pIoPortCtx->AccessInfo.AccessSize == 4);
    1872 
    1873     VBOXSTRICTRC rcStrict;
    1874     if (!pIoPortCtx->AccessInfo.StringOp)
    1875     {
    1876         /*
    1877          * Simple port I/O.
    1878          */
    1879         //Assert(pCtx->rax == pIoPortCtx->Rax); - sledgehammer
    1880 
    1881         static uint32_t const s_fAndMask[8] =
    1882         { UINT32_MAX, UINT32_C(0xff), UINT32_C(0xffff), UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX };
    1883         uint32_t const fAndMask = s_fAndMask[pIoPortCtx->AccessInfo.AccessSize];
    1884         if (pIoPortCtx->AccessInfo.IsWrite)
    1885         {
    1886             rcStrict = IOMIOPortWrite(pVM, pVCpu, pIoPortCtx->PortNumber, (uint32_t)pIoPortCtx->Rax & fAndMask,
    1887                                       pIoPortCtx->AccessInfo.AccessSize);
    1888             if (IOM_SUCCESS(rcStrict))
    1889                 nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, pVpContext);
    1890         }
    1891         else
    1892         {
    1893             uint32_t uValue = 0;
    1894             rcStrict = IOMIOPortRead(pVM, pVCpu, pIoPortCtx->PortNumber, &uValue,
    1895                                      pIoPortCtx->AccessInfo.AccessSize);
    1896             if (IOM_SUCCESS(rcStrict))
    1897             {
    1898                 pCtx->eax = (pCtx->eax & ~fAndMask) | (uValue & fAndMask);
    1899                 nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, pVpContext);
    1900             }
    1901         }
    1902     }
    1903     else
    1904     {
    1905         /*
    1906          * String port I/O.
    1907          */
    1908         /** @todo Someone at Microsoft please explain how we can get the address mode
    1909          * from the IoPortAccess.VpContext.  CS.Attributes is only sufficient for
    1910          * getting the default mode, it can always be overridden by a prefix.   This
    1911          * forces us to interpret the instruction from opcodes, which is suboptimal.
    1912          * Both AMD-V and VT-x includes the address size in the exit info, at least on
    1913          * CPUs that are reasonably new. */
    1914 # if 0 // requires sledgehammer
    1915         Assert(   pIoPortCtx->Ds.Base     == pCtx->ds.u64Base
    1916                && pIoPortCtx->Ds.Limit    == pCtx->ds.u32Limit
    1917                && pIoPortCtx->Ds.Selector == pCtx->ds.Sel);
    1918         Assert(   pIoPortCtx->Es.Base     == pCtx->es.u64Base
    1919                && pIoPortCtx->Es.Limit    == pCtx->es.u32Limit
    1920                && pIoPortCtx->Es.Selector == pCtx->es.Sel);
    1921         Assert(pIoPortCtx->Rdi == pCtx->rdi);
    1922         Assert(pIoPortCtx->Rsi == pCtx->rsi);
    1923         Assert(pIoPortCtx->Rcx == pCtx->rcx);
    1924         Assert(pIoPortCtx->Rcx == pCtx->rcx);
    1925 # endif
    1926 
    1927         int rc = nemHCWinCopyStateFromHyperV(pVM, pVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM);
    1928         AssertRCReturn(rc, rc);
    1929 
    1930         rcStrict = IEMExecOne(pVCpu);
    1931     }
    1932     if (IOM_SUCCESS(rcStrict))
    1933     {
    1934         /*
    1935          * Do debug checks.
    1936          */
    1937         if (   pVpContext->ExecutionState.DebugActive /** @todo Microsoft: Does DebugActive this only reflext DR7? */
    1938             || (pVpContext->Rflags & X86_EFL_TF)
    1939             || DBGFBpIsHwIoArmed(pVM) )
    1940         {
    1941             /** @todo Debugging. */
    1942         }
    1943     }
    1944     return rcStrict;
    1945 }
    1946 
    1947 
    1948 static VBOXSTRICTRC nemR3WinWHvHandleInterruptWindow(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
    1949 {
    1950     NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason);
    1951     AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED);
    1952 }
    1953 
    1954 
    1955 static VBOXSTRICTRC nemR3WinWHvHandleMsrAccess(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
    1956 {
    1957     NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason);
    1958     AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED);
    1959 }
    1960 
    1961 
    1962 static VBOXSTRICTRC nemR3WinWHvHandleCpuId(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
    1963 {
    1964     NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason);
    1965     AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED);
    1966 }
    1967 
    1968 
    1969 static VBOXSTRICTRC nemR3WinWHvHandleException(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
    1970 {
    1971     NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason);
    1972     AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED);
    1973 }
    1974 
    1975 
    1976 static VBOXSTRICTRC nemR3WinWHvHandleUD(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
    1977 {
    1978     NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason);
    1979     AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED);
    1980 }
    1981 
    1982 
    1983 static VBOXSTRICTRC nemR3WinWHvHandleTripleFault(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
    1984 {
    1985     NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason);
    1986     AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED);
    1987 }
    1988 
    1989 
    1990 static VBOXSTRICTRC nemR3WinWHvHandleInvalidState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, WHV_RUN_VP_EXIT_CONTEXT const *pExitReason)
    1991 {
    1992     NOREF(pVM); NOREF(pVCpu); NOREF(pCtx); NOREF(pExitReason);
    1993     AssertLogRelFailedReturn(VERR_NOT_IMPLEMENTED);
    1994 }
    1995 
    1996 
    1997 VBOXSTRICTRC nemR3WinWHvRunGC(PVM pVM, PVMCPU pVCpu)
    1998 {
    1999 # ifdef LOG_ENABLED
    2000     if (LogIs3Enabled())
    2001     {
    2002         Log3(("nemR3NativeRunGC: Entering #%u\n", pVCpu->idCpu));
    2003         nemHCWinLogState(pVM, pVCpu);
    2004     }
    2005 # endif
    2006 
    2007     /*
    2008      * The run loop.
    2009      */
    2010     PCPUMCTX     pCtx            = CPUMQueryGuestCtxPtr(pVCpu);
    2011     const bool   fSingleStepping = false; /** @todo get this from somewhere. */
    2012     VBOXSTRICTRC rcStrict        = VINF_SUCCESS;
    2013     for (unsigned iLoop = 0;;iLoop++)
    2014     {
    2015         /*
    2016          * Copy the state.
    2017          */
    2018         int rc2 = nemHCWinCopyStateToHyperV(pVM, pVCpu, pCtx);
    2019         AssertRCBreakStmt(rc2, rcStrict = rc2);
    2020 
    2021         /*
    2022          * Run a bit.
    2023          */
    2024         WHV_RUN_VP_EXIT_CONTEXT ExitReason;
    2025         RT_ZERO(ExitReason);
    2026         if (   !VM_FF_IS_PENDING(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC)
    2027             && !VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
    2028         {
    2029             Log8(("Calling WHvRunVirtualProcessor\n"));
    2030             VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM, VMCPUSTATE_STARTED);
    2031             HRESULT hrc = WHvRunVirtualProcessor(pVM->nem.s.hPartition, pVCpu->idCpu, &ExitReason, sizeof(ExitReason));
    2032             VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM);
    2033             AssertLogRelMsgBreakStmt(SUCCEEDED(hrc),
    2034                                      ("WHvRunVirtualProcessor(%p, %u,,) -> %Rhrc (Last=%#x/%u)\n", pVM->nem.s.hPartition, pVCpu->idCpu,
    2035                                       hrc, RTNtLastStatusValue(), RTNtLastErrorValue()),
    2036                                      rcStrict = VERR_INTERNAL_ERROR);
    2037             Log2(("WHvRunVirtualProcessor -> %#x; exit code %#x (%d) (cpu status %u)\n",
    2038                   hrc, ExitReason.ExitReason, ExitReason.ExitReason, nemHCWinCpuGetRunningStatus(pVCpu) ));
    2039         }
    2040         else
    2041         {
    2042             LogFlow(("nemR3NativeRunGC: returning: pending FF (pre exec)\n"));
    2043             break;
    2044         }
    2045 
    2046 # if 0 /* sledgehammer approach */
    2047         /*
    2048          * Copy back the state.
    2049          */
    2050         rc2 = nemHCWinCopyStateFromHyperV(pVM, pVCpu, pCtx, UINT64_MAX);
    2051         AssertRCBreakStmt(rc2, rcStrict = rc2);
    2052 # endif
    2053 
    2054 # ifdef LOG_ENABLED
    2055         /*
    2056          * Do some logging.
    2057          */
    2058         if (LogIs2Enabled())
    2059             nemR3WinLogWHvExitReason(&ExitReason);
    2060         if (LogIs3Enabled())
    2061             nemHCWinLogState(pVM, pVCpu);
    2062 # endif
    2063 
    2064 # if 0 //def VBOX_STRICT - requires sledgehammer
    2065         /* Assert that the VpContext field makes sense. */
    2066         switch (ExitReason.ExitReason)
    2067         {
    2068             case WHvRunVpExitReasonMemoryAccess:
    2069             case WHvRunVpExitReasonX64IoPortAccess:
    2070             case WHvRunVpExitReasonX64MsrAccess:
    2071             case WHvRunVpExitReasonX64Cpuid:
    2072             case WHvRunVpExitReasonException:
    2073             case WHvRunVpExitReasonUnrecoverableException:
    2074                 Assert(   ExitReason.IoPortAccess.VpContext.InstructionLength > 0
    2075                        || (   ExitReason.ExitReason == WHvRunVpExitReasonMemoryAccess
    2076                            && ExitReason.MemoryAccess.AccessInfo.AccessType == WHvMemoryAccessExecute));
    2077                 Assert(ExitReason.IoPortAccess.VpContext.InstructionLength < 16);
    2078                 Assert(ExitReason.IoPortAccess.VpContext.ExecutionState.Cpl == CPUMGetGuestCPL(pVCpu));
    2079                 Assert(ExitReason.IoPortAccess.VpContext.ExecutionState.Cr0Pe == RT_BOOL(pCtx->cr0 & X86_CR0_PE));
    2080                 Assert(ExitReason.IoPortAccess.VpContext.ExecutionState.Cr0Am == RT_BOOL(pCtx->cr0 & X86_CR0_AM));
    2081                 Assert(ExitReason.IoPortAccess.VpContext.ExecutionState.EferLma == RT_BOOL(pCtx->msrEFER & MSR_K6_EFER_LMA));
    2082                 Assert(ExitReason.IoPortAccess.VpContext.ExecutionState.DebugActive == RT_BOOL(pCtx->dr[7] & X86_DR7_ENABLED_MASK));
    2083                 Assert(ExitReason.IoPortAccess.VpContext.ExecutionState.Reserved0 == 0);
    2084                 Assert(ExitReason.IoPortAccess.VpContext.ExecutionState.Reserved1 == 0);
    2085                 Assert(ExitReason.IoPortAccess.VpContext.Rip == pCtx->rip);
    2086                 Assert(ExitReason.IoPortAccess.VpContext.Rflags == pCtx->rflags.u);
    2087                 Assert(   ExitReason.IoPortAccess.VpContext.Cs.Base     == pCtx->cs.u64Base
    2088                        && ExitReason.IoPortAccess.VpContext.Cs.Limit    == pCtx->cs.u32Limit
    2089                        && ExitReason.IoPortAccess.VpContext.Cs.Selector == pCtx->cs.Sel);
    2090                 break;
    2091             default: break; /* shut up compiler. */
    2092         }
    2093 # endif
    2094 
    2095         /*
    2096          * Deal with the exit.
    2097          */
    2098         switch (ExitReason.ExitReason)
    2099         {
    2100             /* Frequent exits: */
    2101             case WHvRunVpExitReasonCanceled:
    2102             //case WHvRunVpExitReasonAlerted:
    2103                 rcStrict = VINF_SUCCESS;
    2104                 break;
    2105 
    2106             case WHvRunVpExitReasonX64Halt:
    2107                 rcStrict = nemR3WinWHvHandleHalt(pVM, pVCpu, pCtx);
    2108                 break;
    2109 
    2110             case WHvRunVpExitReasonMemoryAccess:
    2111                 rcStrict = nemR3WinWHvHandleMemoryAccess(pVM, pVCpu, pCtx, &ExitReason.MemoryAccess, &ExitReason.VpContext);
    2112                 break;
    2113 
    2114             case WHvRunVpExitReasonX64IoPortAccess:
    2115                 rcStrict = nemR3WinWHvHandleIoPortAccess(pVM, pVCpu, pCtx, &ExitReason.IoPortAccess, &ExitReason.VpContext);
    2116                 break;
    2117 
    2118             case WHvRunVpExitReasonX64InterruptWindow:
    2119                 rcStrict = nemR3WinWHvHandleInterruptWindow(pVM, pVCpu, pCtx, &ExitReason);
    2120                 break;
    2121 
    2122             case WHvRunVpExitReasonX64MsrAccess: /* needs configuring */
    2123                 rcStrict = nemR3WinWHvHandleMsrAccess(pVM, pVCpu, pCtx, &ExitReason);
    2124                 break;
    2125 
    2126             case WHvRunVpExitReasonX64Cpuid: /* needs configuring */
    2127                 rcStrict = nemR3WinWHvHandleCpuId(pVM, pVCpu, pCtx, &ExitReason);
    2128                 break;
    2129 
    2130             case WHvRunVpExitReasonException: /* needs configuring */
    2131                 rcStrict = nemR3WinWHvHandleException(pVM, pVCpu, pCtx, &ExitReason);
    2132                 break;
    2133 
    2134             /* Unlikely exits: */
    2135             case WHvRunVpExitReasonUnsupportedFeature:
    2136                 rcStrict = nemR3WinWHvHandleUD(pVM, pVCpu, pCtx, &ExitReason);
    2137                 break;
    2138 
    2139             case WHvRunVpExitReasonUnrecoverableException:
    2140                 rcStrict = nemR3WinWHvHandleTripleFault(pVM, pVCpu, pCtx, &ExitReason);
    2141                 break;
    2142 
    2143             case WHvRunVpExitReasonInvalidVpRegisterValue:
    2144                 rcStrict = nemR3WinWHvHandleInvalidState(pVM, pVCpu, pCtx, &ExitReason);
    2145                 break;
    2146 
    2147             /* Undesired exits: */
    2148             case WHvRunVpExitReasonNone:
    2149             default:
    2150                 AssertLogRelMsgFailed(("Unknown ExitReason: %#x\n", ExitReason.ExitReason));
    2151                 rcStrict = VERR_INTERNAL_ERROR_3;
    2152                 break;
    2153         }
    2154         if (rcStrict != VINF_SUCCESS)
    2155         {
    2156             LogFlow(("nemR3NativeRunGC: returning: %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
    2157             break;
    2158         }
    2159 
    2160 # ifndef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
    2161         /* Hack alert! */
    2162         uint32_t const cMappedPages = pVM->nem.s.cMappedPages;
    2163         if (cMappedPages < 4000)
    2164         { /* likely */ }
    2165         else
    2166         {
    2167             PGMPhysNemEnumPagesByState(pVM, pVCpu, NEM_WIN_PAGE_STATE_READABLE, nemR3WinWHvUnmapOnePageCallback, NULL);
    2168             Log(("nemR3NativeRunGC: Unmapped all; cMappedPages=%u -> %u\n", cMappedPages, pVM->nem.s.cMappedPages));
    2169         }
    2170 # endif
    2171 
    2172         /* If any FF is pending, return to the EM loops.  That's okay for the
    2173            current sledgehammer approach. */
    2174         if (   VM_FF_IS_PENDING(   pVM,   !fSingleStepping ? VM_FF_HP_R0_PRE_HM_MASK    : VM_FF_HP_R0_PRE_HM_STEP_MASK)
    2175             || VMCPU_FF_IS_PENDING(pVCpu, !fSingleStepping ? VMCPU_FF_HP_R0_PRE_HM_MASK : VMCPU_FF_HP_R0_PRE_HM_STEP_MASK) )
    2176         {
    2177             LogFlow(("nemR3NativeRunGC: returning: pending FF (%#x / %#x)\n", pVM->fGlobalForcedActions, pVCpu->fLocalForcedActions));
    2178             break;
    2179         }
    2180     }
    2181 
    2182 
    2183     /*
    2184      * Copy back the state before returning.
    2185      */
    2186     if (pCtx->fExtrn & (CPUMCTX_EXTRN_ALL | (CPUMCTX_EXTRN_NEM_WIN_MASK & ~CPUMCTX_EXTRN_NEM_WIN_EVENT_INJECT)))
    2187     {
    2188         int rc2 = nemHCWinCopyStateFromHyperV(pVM, pVCpu, pCtx, CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_NEM_WIN_MASK);
    2189         if (RT_SUCCESS(rc2))
    2190             pCtx->fExtrn = 0;
    2191         else if (RT_SUCCESS(rcStrict))
    2192             rcStrict = rc2;
    2193     }
    2194     else
    2195         pCtx->fExtrn = 0;
    2196 
    2197     return rcStrict;
    2198 }
    2199 
    2200 #endif /* !NEM_WIN_USE_OUR_OWN_RUN_API - migrating to NEMAllNativeTemplate-win.cpp.h*/
    22011632
    22021633
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