Changeset 72575 in vbox
- Timestamp:
- Jun 15, 2018 9:25:32 PM (7 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/NEMAllNativeTemplate-win.cpp.h
r72569 r72575 1842 1842 nemHCWinHandleMessageMemory(PVM pVM, PVMCPU pVCpu, HV_X64_MEMORY_INTERCEPT_MESSAGE const *pMsg, PCPUMCTX pCtx, PGVMCPU pGVCpu) 1843 1843 { 1844 uint64_t const uHostTsc = ASMReadTSC(); 1844 1845 Assert( pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_READ 1845 1846 || pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE … … 1891 1892 Info.fHasHandlers ? " handlers" : "", Info.fZeroPage ? " zero-pg" : "", 1892 1893 State.fDidSomething ? "" : " no-change", g_apszHvInterceptAccessTypes[pMsg->Header.InterceptAccessType])); 1894 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_NEM, NEMEXITTYPE_MEMORY_ACCESS), 1895 pMsg->Header.Rip + pMsg->Header.CsSegment.Base, uHostTsc); 1893 1896 return VINF_SUCCESS; 1894 1897 } … … 1909 1912 * Emulate the memory access, either access handler or special memory. 1910 1913 */ 1911 EMHistoryAddExit(pVCpu,1912 pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE1913 ? EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_MMIO_WRITE)1914 : EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_MMIO_READ),1915 pMsg->Header.Rip + pMsg->Header.CsSegment.Base, ASMReadTSC());1914 PCEMEXITREC pExitRec = EMHistoryAddExit(pVCpu, 1915 pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE 1916 ? EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_MMIO_WRITE) 1917 : EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_MMIO_READ), 1918 pMsg->Header.Rip + pMsg->Header.CsSegment.Base, uHostTsc); 1916 1919 nemHCWinCopyStateFromX64Header(pVCpu, pCtx, &pMsg->Header); 1917 1920 VBOXSTRICTRC rcStrict; … … 1931 1934 if (pMsg->Header.ExecutionState.Reserved0 || pMsg->Header.ExecutionState.Reserved1) 1932 1935 Log(("MemExit/Hdr/State: Reserved0=%#x Reserved1=%#x\n", pMsg->Header.ExecutionState.Reserved0, pMsg->Header.ExecutionState.Reserved1)); 1933 //if (pMsg->InstructionByteCount > 0) 1934 // Log4(("InstructionByteCount=%#x %.16Rhxs\n", pMsg->InstructionByteCount, pMsg->InstructionBytes)); 1935 1936 if (pMsg->InstructionByteCount > 0) 1937 rcStrict = IEMExecOneWithPrefetchedByPC(pVCpu, CPUMCTX2CORE(pCtx), pMsg->Header.Rip, 1938 pMsg->InstructionBytes, pMsg->InstructionByteCount); 1936 1937 if (!pExitRec) 1938 { 1939 //if (pMsg->InstructionByteCount > 0) 1940 // Log4(("InstructionByteCount=%#x %.16Rhxs\n", pMsg->InstructionByteCount, pMsg->InstructionBytes)); 1941 if (pMsg->InstructionByteCount > 0) 1942 rcStrict = IEMExecOneWithPrefetchedByPC(pVCpu, CPUMCTX2CORE(pCtx), pMsg->Header.Rip, 1943 pMsg->InstructionBytes, pMsg->InstructionByteCount); 1944 else 1945 rcStrict = IEMExecOne(pVCpu); 1946 /** @todo do we need to do anything wrt debugging here? */ 1947 } 1939 1948 else 1940 rcStrict = IEMExecOne(pVCpu); 1941 /** @todo do we need to do anything wrt debugging here? */ 1949 { 1950 /* Frequent access or probing. */ 1951 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0); 1952 Log4(("MemExit/%u: %04x:%08RX64/%s: EMHistoryExec -> %Rrc + %04x:%08RX64\n", 1953 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header), 1954 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip)); 1955 } 1942 1956 return rcStrict; 1943 1957 } … … 1956 1970 nemR3WinHandleExitMemory(PVM pVM, PVMCPU pVCpu, WHV_RUN_VP_EXIT_CONTEXT const *pExit, PCPUMCTX pCtx) 1957 1971 { 1972 uint64_t const uHostTsc = ASMReadTSC(); 1958 1973 Assert(pExit->MemoryAccess.AccessInfo.AccessType != 3); 1959 1974 AssertMsg(pExit->VpContext.InstructionLength < 0x10, ("%#x\n", pExit->VpContext.InstructionLength)); … … 1985 2000 Info.fHasHandlers ? " handlers" : "", Info.fZeroPage ? " zero-pg" : "", 1986 2001 State.fDidSomething ? "" : " no-change", g_apszHvInterceptAccessTypes[pExit->MemoryAccess.AccessInfo.AccessType])); 2002 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_NEM, NEMEXITTYPE_MEMORY_ACCESS), 2003 pExit->VpContext.Rip + pExit->VpContext.Cs.Base, uHostTsc); 1987 2004 return VINF_SUCCESS; 1988 2005 } … … 2003 2020 * Emulate the memory access, either access handler or special memory. 2004 2021 */ 2005 EMHistoryAddExit(pVCpu, 2006 pExit->MemoryAccess.AccessInfo.AccessType == WHvMemoryAccessWrite 2007 ? EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_MMIO_WRITE) 2008 : EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_MMIO_READ), 2009 pExit->VpContext.Rip + pExit->VpContext.Cs.Base, ASMReadTSC()); 2010 2022 PCEMEXITREC pExitRec = EMHistoryAddExit(pVCpu, 2023 pExit->MemoryAccess.AccessInfo.AccessType == WHvMemoryAccessWrite 2024 ? EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_MMIO_WRITE) 2025 : EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_MMIO_READ), 2026 pExit->VpContext.Rip + pExit->VpContext.Cs.Base, uHostTsc); 2011 2027 nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext); 2012 2028 rc = nemHCWinCopyStateFromHyperV(pVM, pVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM | CPUMCTX_EXTRN_DS | CPUMCTX_EXTRN_ES); 2013 2029 AssertRCReturn(rc, rc); 2014 2015 2030 if (pExit->VpContext.ExecutionState.Reserved0 || pExit->VpContext.ExecutionState.Reserved1) 2016 2031 Log(("MemExit/Hdr/State: Reserved0=%#x Reserved1=%#x\n", pExit->VpContext.ExecutionState.Reserved0, pExit->VpContext.ExecutionState.Reserved1)); 2017 //if (pMsg->InstructionByteCount > 0)2018 // Log4(("InstructionByteCount=%#x %.16Rhxs\n", pMsg->InstructionByteCount, pMsg->InstructionBytes));2019 2032 2020 2033 VBOXSTRICTRC rcStrict; 2021 if (pExit->MemoryAccess.InstructionByteCount > 0) 2022 rcStrict = IEMExecOneWithPrefetchedByPC(pVCpu, CPUMCTX2CORE(pCtx), pExit->VpContext.Rip, 2023 pExit->MemoryAccess.InstructionBytes, pExit->MemoryAccess.InstructionByteCount); 2034 if (!pExitRec) 2035 { 2036 //if (pMsg->InstructionByteCount > 0) 2037 // Log4(("InstructionByteCount=%#x %.16Rhxs\n", pMsg->InstructionByteCount, pMsg->InstructionBytes)); 2038 if (pExit->MemoryAccess.InstructionByteCount > 0) 2039 rcStrict = IEMExecOneWithPrefetchedByPC(pVCpu, CPUMCTX2CORE(pCtx), pExit->VpContext.Rip, 2040 pExit->MemoryAccess.InstructionBytes, pExit->MemoryAccess.InstructionByteCount); 2041 else 2042 rcStrict = IEMExecOne(pVCpu); 2043 /** @todo do we need to do anything wrt debugging here? */ 2044 } 2024 2045 else 2025 rcStrict = IEMExecOne(pVCpu); 2026 /** @todo do we need to do anything wrt debugging here? */ 2046 { 2047 /* Frequent access or probing. */ 2048 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0); 2049 Log4(("MemExit/%u: %04x:%08RX64/%s: EMHistoryExec -> %Rrc + %04x:%08RX64\n", 2050 pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), 2051 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip)); 2052 } 2027 2053 return rcStrict; 2028 2054 } … … 2057 2083 pCtx->fExtrn &= ~CPUMCTX_EXTRN_NEM_WIN_EVENT_INJECT; 2058 2084 2085 /* 2086 * Add history first to avoid two paths doing EMHistoryExec calls. 2087 */ 2059 2088 VBOXSTRICTRC rcStrict; 2060 if (!pMsg->AccessInfo.StringOp) 2061 { 2062 /* 2063 * Simple port I/O. 2064 */ 2065 EMHistoryAddExit(pVCpu, 2066 pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE 2067 ? EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_IO_PORT_WRITE) 2068 : EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_IO_PORT_READ), 2069 pMsg->Header.Rip + pMsg->Header.CsSegment.Base, ASMReadTSC()); 2070 2071 static uint32_t const s_fAndMask[8] = 2072 { UINT32_MAX, UINT32_C(0xff), UINT32_C(0xffff), UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX }; 2073 uint32_t const fAndMask = s_fAndMask[pMsg->AccessInfo.AccessSize]; 2074 2075 nemHCWinCopyStateFromX64Header(pVCpu, pCtx, &pMsg->Header); 2076 if (pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE) 2077 { 2078 rcStrict = IOMIOPortWrite(pVM, pVCpu, pMsg->PortNumber, (uint32_t)pMsg->Rax & fAndMask, pMsg->AccessInfo.AccessSize); 2079 Log4(("IOExit/%u: %04x:%08RX64/%s: OUT %#x, %#x LB %u rcStrict=%Rrc\n", 2080 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header), 2081 pMsg->PortNumber, (uint32_t)pMsg->Rax & fAndMask, pMsg->AccessInfo.AccessSize, VBOXSTRICTRC_VAL(rcStrict) )); 2082 if (IOM_SUCCESS(rcStrict)) 2083 nemHCWinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pMsg->Header); 2089 PCEMEXITREC pExitRec = EMHistoryAddExit(pVCpu, 2090 !pMsg->AccessInfo.StringOp 2091 ? ( pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE 2092 ? EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_IO_PORT_WRITE) 2093 : EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_IO_PORT_READ)) 2094 : ( pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE 2095 ? EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_IO_PORT_STR_WRITE) 2096 : EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_IO_PORT_STR_READ)), 2097 pMsg->Header.Rip + pMsg->Header.CsSegment.Base, ASMReadTSC()); 2098 if (!pExitRec) 2099 { 2100 if (!pMsg->AccessInfo.StringOp) 2101 { 2102 /* 2103 * Simple port I/O. 2104 */ 2105 static uint32_t const s_fAndMask[8] = 2106 { UINT32_MAX, UINT32_C(0xff), UINT32_C(0xffff), UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX }; 2107 uint32_t const fAndMask = s_fAndMask[pMsg->AccessInfo.AccessSize]; 2108 2109 nemHCWinCopyStateFromX64Header(pVCpu, pCtx, &pMsg->Header); 2110 if (pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE) 2111 { 2112 rcStrict = IOMIOPortWrite(pVM, pVCpu, pMsg->PortNumber, (uint32_t)pMsg->Rax & fAndMask, pMsg->AccessInfo.AccessSize); 2113 Log4(("IOExit/%u: %04x:%08RX64/%s: OUT %#x, %#x LB %u rcStrict=%Rrc\n", 2114 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header), 2115 pMsg->PortNumber, (uint32_t)pMsg->Rax & fAndMask, pMsg->AccessInfo.AccessSize, VBOXSTRICTRC_VAL(rcStrict) )); 2116 if (IOM_SUCCESS(rcStrict)) 2117 nemHCWinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pMsg->Header); 2084 2118 # ifdef IN_RING0 2085 else if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE2086 && !pCtx->rflags.Bits.u1TF2087 /** @todo check for debug breakpoints */ )2088 return EMRZSetPendingIoPortWrite(pVCpu, pMsg->PortNumber, pMsg->Header.InstructionLength,2089 pMsg->AccessInfo.AccessSize, (uint32_t)pMsg->Rax & fAndMask);2119 else if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE 2120 && !pCtx->rflags.Bits.u1TF 2121 /** @todo check for debug breakpoints */ ) 2122 return EMRZSetPendingIoPortWrite(pVCpu, pMsg->PortNumber, pMsg->Header.InstructionLength, 2123 pMsg->AccessInfo.AccessSize, (uint32_t)pMsg->Rax & fAndMask); 2090 2124 # endif 2091 else2092 {2093 pCtx->rax = pMsg->Rax;2094 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RAX;2095 }2096 }2097 else2098 {2099 uint32_t uValue = 0;2100 rcStrict = IOMIOPortRead(pVM, pVCpu, pMsg->PortNumber, &uValue, pMsg->AccessInfo.AccessSize);2101 Log4(("IOExit/%u: %04x:%08RX64/%s: IN %#x LB %u -> %#x, rcStrict=%Rrc\n",2102 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header),2103 pMsg->PortNumber, pMsg->AccessInfo.AccessSize, uValue, VBOXSTRICTRC_VAL(rcStrict) ));2104 if (IOM_SUCCESS(rcStrict))2105 {2106 if (pMsg->AccessInfo.AccessSize != 4)2107 pCtx->rax = (pMsg->Rax & ~(uint64_t)fAndMask) | (uValue & fAndMask);2108 2125 else 2109 pCtx->rax = uValue;2110 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RAX;2111 Log4(("IOExit/%u: RAX %#RX64 -> %#RX64\n", pVCpu->idCpu, pMsg->Rax, pCtx->rax));2112 nemHCWinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pMsg->Header);2126 { 2127 pCtx->rax = pMsg->Rax; 2128 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RAX; 2129 } 2113 2130 } 2114 2131 else 2115 2132 { 2116 pCtx->rax = pMsg->Rax; 2117 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RAX; 2133 uint32_t uValue = 0; 2134 rcStrict = IOMIOPortRead(pVM, pVCpu, pMsg->PortNumber, &uValue, pMsg->AccessInfo.AccessSize); 2135 Log4(("IOExit/%u: %04x:%08RX64/%s: IN %#x LB %u -> %#x, rcStrict=%Rrc\n", 2136 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header), 2137 pMsg->PortNumber, pMsg->AccessInfo.AccessSize, uValue, VBOXSTRICTRC_VAL(rcStrict) )); 2138 if (IOM_SUCCESS(rcStrict)) 2139 { 2140 if (pMsg->AccessInfo.AccessSize != 4) 2141 pCtx->rax = (pMsg->Rax & ~(uint64_t)fAndMask) | (uValue & fAndMask); 2142 else 2143 pCtx->rax = uValue; 2144 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RAX; 2145 Log4(("IOExit/%u: RAX %#RX64 -> %#RX64\n", pVCpu->idCpu, pMsg->Rax, pCtx->rax)); 2146 nemHCWinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pMsg->Header); 2147 } 2148 else 2149 { 2150 pCtx->rax = pMsg->Rax; 2151 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RAX; 2118 2152 # ifdef IN_RING0 2119 if ( rcStrict == VINF_IOM_R3_IOPORT_READ2120 && !pCtx->rflags.Bits.u1TF2121 /** @todo check for debug breakpoints */ )2122 return EMRZSetPendingIoPortRead(pVCpu, pMsg->PortNumber, pMsg->Header.InstructionLength,2123 pMsg->AccessInfo.AccessSize);2153 if ( rcStrict == VINF_IOM_R3_IOPORT_READ 2154 && !pCtx->rflags.Bits.u1TF 2155 /** @todo check for debug breakpoints */ ) 2156 return EMRZSetPendingIoPortRead(pVCpu, pMsg->PortNumber, pMsg->Header.InstructionLength, 2157 pMsg->AccessInfo.AccessSize); 2124 2158 # endif 2159 } 2125 2160 } 2126 2161 } 2127 } 2162 else 2163 { 2164 /* 2165 * String port I/O. 2166 */ 2167 /** @todo Someone at Microsoft please explain how we can get the address mode 2168 * from the IoPortAccess.VpContext. CS.Attributes is only sufficient for 2169 * getting the default mode, it can always be overridden by a prefix. This 2170 * forces us to interpret the instruction from opcodes, which is suboptimal. 2171 * Both AMD-V and VT-x includes the address size in the exit info, at least on 2172 * CPUs that are reasonably new. 2173 * 2174 * Of course, it's possible this is an undocumented and we just need to do some 2175 * experiments to figure out how it's communicated. Alternatively, we can scan 2176 * the opcode bytes for possible evil prefixes. 2177 */ 2178 nemHCWinCopyStateFromX64Header(pVCpu, pCtx, &pMsg->Header); 2179 pCtx->fExtrn &= ~( CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RCX | CPUMCTX_EXTRN_RDI | CPUMCTX_EXTRN_RSI 2180 | CPUMCTX_EXTRN_DS | CPUMCTX_EXTRN_ES); 2181 NEM_WIN_COPY_BACK_SEG(pCtx->ds, pMsg->DsSegment); 2182 NEM_WIN_COPY_BACK_SEG(pCtx->es, pMsg->EsSegment); 2183 pCtx->rax = pMsg->Rax; 2184 pCtx->rcx = pMsg->Rcx; 2185 pCtx->rdi = pMsg->Rdi; 2186 pCtx->rsi = pMsg->Rsi; 2187 # ifdef IN_RING0 2188 rcStrict = nemR0WinImportStateStrict(pGVCpu->pGVM, pGVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM, "IOExit"); 2189 if (rcStrict != VINF_SUCCESS) 2190 return rcStrict; 2191 # else 2192 int rc = nemHCWinCopyStateFromHyperV(pVM, pVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM); 2193 AssertRCReturn(rc, rc); 2194 RT_NOREF(pGVCpu); 2195 # endif 2196 2197 Log4(("IOExit/%u: %04x:%08RX64/%s: %s%s %#x LB %u (emulating)\n", 2198 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header), 2199 pMsg->AccessInfo.RepPrefix ? "REP " : "", 2200 pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE ? "OUTS" : "INS", 2201 pMsg->PortNumber, pMsg->AccessInfo.AccessSize )); 2202 rcStrict = IEMExecOne(pVCpu); 2203 } 2204 if (IOM_SUCCESS(rcStrict)) 2205 { 2206 /* 2207 * Do debug checks. 2208 */ 2209 if ( pMsg->Header.ExecutionState.DebugActive /** @todo Microsoft: Does DebugActive this only reflect DR7? */ 2210 || (pMsg->Header.Rflags & X86_EFL_TF) 2211 || DBGFBpIsHwIoArmed(pVM) ) 2212 { 2213 /** @todo Debugging. */ 2214 } 2215 } 2216 return rcStrict; 2217 } 2218 2219 /* 2220 * Frequent exit or something needing probing. 2221 * Get state and call EMHistoryExec. 2222 */ 2223 nemHCWinCopyStateFromX64Header(pVCpu, pCtx, &pMsg->Header); 2224 if (!pMsg->AccessInfo.StringOp) 2225 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RAX; 2128 2226 else 2129 2227 { 2130 /*2131 * String port I/O.2132 */2133 /** @todo Someone at Microsoft please explain how we can get the address mode2134 * from the IoPortAccess.VpContext. CS.Attributes is only sufficient for2135 * getting the default mode, it can always be overridden by a prefix. This2136 * forces us to interpret the instruction from opcodes, which is suboptimal.2137 * Both AMD-V and VT-x includes the address size in the exit info, at least on2138 * CPUs that are reasonably new.2139 *2140 * Of course, it's possible this is an undocumented and we just need to do some2141 * experiments to figure out how it's communicated. Alternatively, we can scan2142 * the opcode bytes for possible evil prefixes.2143 */2144 EMHistoryAddExit(pVCpu,2145 pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE2146 ? EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_IO_PORT_STR_WRITE)2147 : EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_IO_PORT_STR_READ),2148 pMsg->Header.Rip + pMsg->Header.CsSegment.Base, ASMReadTSC());2149 2150 nemHCWinCopyStateFromX64Header(pVCpu, pCtx, &pMsg->Header);2151 2228 pCtx->fExtrn &= ~( CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RCX | CPUMCTX_EXTRN_RDI | CPUMCTX_EXTRN_RSI 2152 2229 | CPUMCTX_EXTRN_DS | CPUMCTX_EXTRN_ES); 2153 2230 NEM_WIN_COPY_BACK_SEG(pCtx->ds, pMsg->DsSegment); 2154 2231 NEM_WIN_COPY_BACK_SEG(pCtx->es, pMsg->EsSegment); 2155 pCtx->rax = pMsg->Rax;2156 2232 pCtx->rcx = pMsg->Rcx; 2157 2233 pCtx->rdi = pMsg->Rdi; 2158 2234 pCtx->rsi = pMsg->Rsi; 2235 } 2236 pCtx->rax = pMsg->Rax; 2237 2159 2238 # ifdef IN_RING0 2160 2161 2162 2239 rcStrict = nemR0WinImportStateStrict(pGVCpu->pGVM, pGVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM, "IOExit"); 2240 if (rcStrict != VINF_SUCCESS) 2241 return rcStrict; 2163 2242 # else 2164 2165 2166 2243 int rc = nemHCWinCopyStateFromHyperV(pVM, pVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM); 2244 AssertRCReturn(rc, rc); 2245 RT_NOREF(pGVCpu); 2167 2246 # endif 2168 2247 2169 Log4(("IOExit/%u: %04x:%08RX64/%s: %s%s %#x LB %u (emulating)\n", 2170 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header), 2171 pMsg->AccessInfo.RepPrefix ? "REP " : "", 2172 pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE ? "OUTS" : "INS", 2173 pMsg->PortNumber, pMsg->AccessInfo.AccessSize )); 2174 rcStrict = IEMExecOne(pVCpu); 2175 } 2176 if (IOM_SUCCESS(rcStrict)) 2177 { 2178 /* 2179 * Do debug checks. 2180 */ 2181 if ( pMsg->Header.ExecutionState.DebugActive /** @todo Microsoft: Does DebugActive this only reflect DR7? */ 2182 || (pMsg->Header.Rflags & X86_EFL_TF) 2183 || DBGFBpIsHwIoArmed(pVM) ) 2184 { 2185 /** @todo Debugging. */ 2186 } 2187 } 2248 Log4(("IOExit/%u: %04x:%08RX64/%s: %s%s%s %#x LB %u -> EMHistoryExec\n", 2249 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header), 2250 pMsg->AccessInfo.RepPrefix ? "REP " : "", 2251 pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE ? "OUT" : "IN", 2252 pMsg->AccessInfo.StringOp ? "S" : "", 2253 pMsg->PortNumber, pMsg->AccessInfo.AccessSize)); 2254 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0); 2255 Log4(("IOExit/%u: %04x:%08RX64/%s: EMHistoryExec -> %Rrc + %04x:%08RX64\n", 2256 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header), 2257 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip)); 2188 2258 return rcStrict; 2189 2259 } … … 2213 2283 pCtx->fExtrn &= ~CPUMCTX_EXTRN_NEM_WIN_EVENT_INJECT; 2214 2284 2215 VBOXSTRICTRC rcStrict; 2285 /* 2286 * Add history first to avoid two paths doing EMHistoryExec calls. 2287 */ 2288 PCEMEXITREC pExitRec = EMHistoryAddExit(pVCpu, 2289 !pExit->IoPortAccess.AccessInfo.StringOp 2290 ? ( pExit->MemoryAccess.AccessInfo.AccessType == WHvMemoryAccessWrite 2291 ? EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_IO_PORT_WRITE) 2292 : EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_IO_PORT_READ)) 2293 : ( pExit->MemoryAccess.AccessInfo.AccessType == WHvMemoryAccessWrite 2294 ? EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_IO_PORT_STR_WRITE) 2295 : EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_IO_PORT_STR_READ)), 2296 pExit->VpContext.Rip + pExit->VpContext.Cs.Base, ASMReadTSC()); 2297 if (!pExitRec) 2298 { 2299 VBOXSTRICTRC rcStrict; 2300 if (!pExit->IoPortAccess.AccessInfo.StringOp) 2301 { 2302 /* 2303 * Simple port I/O. 2304 */ 2305 static uint32_t const s_fAndMask[8] = 2306 { UINT32_MAX, UINT32_C(0xff), UINT32_C(0xffff), UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX }; 2307 uint32_t const fAndMask = s_fAndMask[pExit->IoPortAccess.AccessInfo.AccessSize]; 2308 if (pExit->IoPortAccess.AccessInfo.IsWrite) 2309 { 2310 rcStrict = IOMIOPortWrite(pVM, pVCpu, pExit->IoPortAccess.PortNumber, 2311 (uint32_t)pExit->IoPortAccess.Rax & fAndMask, 2312 pExit->IoPortAccess.AccessInfo.AccessSize); 2313 Log4(("IOExit/%u: %04x:%08RX64/%s: OUT %#x, %#x LB %u rcStrict=%Rrc\n", 2314 pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), 2315 pExit->IoPortAccess.PortNumber, (uint32_t)pExit->IoPortAccess.Rax & fAndMask, 2316 pExit->IoPortAccess.AccessInfo.AccessSize, VBOXSTRICTRC_VAL(rcStrict) )); 2317 if (IOM_SUCCESS(rcStrict)) 2318 { 2319 nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext); 2320 nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pExit->VpContext); 2321 } 2322 } 2323 else 2324 { 2325 uint32_t uValue = 0; 2326 rcStrict = IOMIOPortRead(pVM, pVCpu, pExit->IoPortAccess.PortNumber, &uValue, 2327 pExit->IoPortAccess.AccessInfo.AccessSize); 2328 Log4(("IOExit/%u: %04x:%08RX64/%s: IN %#x LB %u -> %#x, rcStrict=%Rrc\n", 2329 pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), 2330 pExit->IoPortAccess.PortNumber, pExit->IoPortAccess.AccessInfo.AccessSize, uValue, VBOXSTRICTRC_VAL(rcStrict) )); 2331 if (IOM_SUCCESS(rcStrict)) 2332 { 2333 if (pExit->IoPortAccess.AccessInfo.AccessSize != 4) 2334 pCtx->rax = (pExit->IoPortAccess.Rax & ~(uint64_t)fAndMask) | (uValue & fAndMask); 2335 else 2336 pCtx->rax = uValue; 2337 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RAX; 2338 Log4(("IOExit/%u: RAX %#RX64 -> %#RX64\n", pVCpu->idCpu, pExit->IoPortAccess.Rax, pCtx->rax)); 2339 nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext); 2340 nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pExit->VpContext); 2341 } 2342 } 2343 } 2344 else 2345 { 2346 /* 2347 * String port I/O. 2348 */ 2349 /** @todo Someone at Microsoft please explain how we can get the address mode 2350 * from the IoPortAccess.VpContext. CS.Attributes is only sufficient for 2351 * getting the default mode, it can always be overridden by a prefix. This 2352 * forces us to interpret the instruction from opcodes, which is suboptimal. 2353 * Both AMD-V and VT-x includes the address size in the exit info, at least on 2354 * CPUs that are reasonably new. 2355 * 2356 * Of course, it's possible this is an undocumented and we just need to do some 2357 * experiments to figure out how it's communicated. Alternatively, we can scan 2358 * the opcode bytes for possible evil prefixes. 2359 */ 2360 nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext); 2361 pCtx->fExtrn &= ~( CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RCX | CPUMCTX_EXTRN_RDI | CPUMCTX_EXTRN_RSI 2362 | CPUMCTX_EXTRN_DS | CPUMCTX_EXTRN_ES); 2363 NEM_WIN_COPY_BACK_SEG(pCtx->ds, pExit->IoPortAccess.Ds); 2364 NEM_WIN_COPY_BACK_SEG(pCtx->es, pExit->IoPortAccess.Es); 2365 pCtx->rax = pExit->IoPortAccess.Rax; 2366 pCtx->rcx = pExit->IoPortAccess.Rcx; 2367 pCtx->rdi = pExit->IoPortAccess.Rdi; 2368 pCtx->rsi = pExit->IoPortAccess.Rsi; 2369 int rc = nemHCWinCopyStateFromHyperV(pVM, pVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM); 2370 AssertRCReturn(rc, rc); 2371 2372 Log4(("IOExit/%u: %04x:%08RX64/%s: %s%s %#x LB %u (emulating)\n", 2373 pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), 2374 pExit->IoPortAccess.AccessInfo.RepPrefix ? "REP " : "", 2375 pExit->IoPortAccess.AccessInfo.IsWrite ? "OUTS" : "INS", 2376 pExit->IoPortAccess.PortNumber, pExit->IoPortAccess.AccessInfo.AccessSize )); 2377 rcStrict = IEMExecOne(pVCpu); 2378 } 2379 if (IOM_SUCCESS(rcStrict)) 2380 { 2381 /* 2382 * Do debug checks. 2383 */ 2384 if ( pExit->VpContext.ExecutionState.DebugActive /** @todo Microsoft: Does DebugActive this only reflect DR7? */ 2385 || (pExit->VpContext.Rflags & X86_EFL_TF) 2386 || DBGFBpIsHwIoArmed(pVM) ) 2387 { 2388 /** @todo Debugging. */ 2389 } 2390 } 2391 return rcStrict; 2392 } 2393 2394 /* 2395 * Frequent exit or something needing probing. 2396 * Get state and call EMHistoryExec. 2397 */ 2398 nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext); 2216 2399 if (!pExit->IoPortAccess.AccessInfo.StringOp) 2217 { 2218 /* 2219 * Simple port I/O. 2220 */ 2221 EMHistoryAddExit(pVCpu, 2222 pExit->MemoryAccess.AccessInfo.AccessType == WHvMemoryAccessWrite 2223 ? EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_IO_PORT_WRITE) 2224 : EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_IO_PORT_READ), 2225 pExit->VpContext.Rip + pExit->VpContext.Cs.Base, ASMReadTSC()); 2226 2227 static uint32_t const s_fAndMask[8] = 2228 { UINT32_MAX, UINT32_C(0xff), UINT32_C(0xffff), UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX }; 2229 uint32_t const fAndMask = s_fAndMask[pExit->IoPortAccess.AccessInfo.AccessSize]; 2230 if (pExit->IoPortAccess.AccessInfo.IsWrite) 2231 { 2232 rcStrict = IOMIOPortWrite(pVM, pVCpu, pExit->IoPortAccess.PortNumber, (uint32_t)pExit->IoPortAccess.Rax & fAndMask, 2233 pExit->IoPortAccess.AccessInfo.AccessSize); 2234 Log4(("IOExit/%u: %04x:%08RX64/%s: OUT %#x, %#x LB %u rcStrict=%Rrc\n", 2235 pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), 2236 pExit->IoPortAccess.PortNumber, (uint32_t)pExit->IoPortAccess.Rax & fAndMask, 2237 pExit->IoPortAccess.AccessInfo.AccessSize, VBOXSTRICTRC_VAL(rcStrict) )); 2238 if (IOM_SUCCESS(rcStrict)) 2239 { 2240 nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext); 2241 nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pExit->VpContext); 2242 } 2243 } 2244 else 2245 { 2246 uint32_t uValue = 0; 2247 rcStrict = IOMIOPortRead(pVM, pVCpu, pExit->IoPortAccess.PortNumber, &uValue, pExit->IoPortAccess.AccessInfo.AccessSize); 2248 Log4(("IOExit/%u: %04x:%08RX64/%s: IN %#x LB %u -> %#x, rcStrict=%Rrc\n", 2249 pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), 2250 pExit->IoPortAccess.PortNumber, pExit->IoPortAccess.AccessInfo.AccessSize, uValue, VBOXSTRICTRC_VAL(rcStrict) )); 2251 if (IOM_SUCCESS(rcStrict)) 2252 { 2253 if (pExit->IoPortAccess.AccessInfo.AccessSize != 4) 2254 pCtx->rax = (pExit->IoPortAccess.Rax & ~(uint64_t)fAndMask) | (uValue & fAndMask); 2255 else 2256 pCtx->rax = uValue; 2257 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RAX; 2258 Log4(("IOExit/%u: RAX %#RX64 -> %#RX64\n", pVCpu->idCpu, pExit->IoPortAccess.Rax, pCtx->rax)); 2259 nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext); 2260 nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pExit->VpContext); 2261 } 2262 } 2263 } 2400 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RAX; 2264 2401 else 2265 2402 { 2266 /*2267 * String port I/O.2268 */2269 /** @todo Someone at Microsoft please explain how we can get the address mode2270 * from the IoPortAccess.VpContext. CS.Attributes is only sufficient for2271 * getting the default mode, it can always be overridden by a prefix. This2272 * forces us to interpret the instruction from opcodes, which is suboptimal.2273 * Both AMD-V and VT-x includes the address size in the exit info, at least on2274 * CPUs that are reasonably new.2275 *2276 * Of course, it's possible this is an undocumented and we just need to do some2277 * experiments to figure out how it's communicated. Alternatively, we can scan2278 * the opcode bytes for possible evil prefixes.2279 */2280 EMHistoryAddExit(pVCpu,2281 pExit->MemoryAccess.AccessInfo.AccessType == WHvMemoryAccessWrite2282 ? EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_IO_PORT_STR_WRITE)2283 : EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_IO_PORT_STR_READ),2284 pExit->VpContext.Rip + pExit->VpContext.Cs.Base, ASMReadTSC());2285 2286 nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext);2287 2403 pCtx->fExtrn &= ~( CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RCX | CPUMCTX_EXTRN_RDI | CPUMCTX_EXTRN_RSI 2288 2404 | CPUMCTX_EXTRN_DS | CPUMCTX_EXTRN_ES); 2289 2405 NEM_WIN_COPY_BACK_SEG(pCtx->ds, pExit->IoPortAccess.Ds); 2290 2406 NEM_WIN_COPY_BACK_SEG(pCtx->es, pExit->IoPortAccess.Es); 2291 pCtx->rax = pExit->IoPortAccess.Rax;2292 2407 pCtx->rcx = pExit->IoPortAccess.Rcx; 2293 2408 pCtx->rdi = pExit->IoPortAccess.Rdi; 2294 2409 pCtx->rsi = pExit->IoPortAccess.Rsi; 2295 int rc = nemHCWinCopyStateFromHyperV(pVM, pVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM); 2296 AssertRCReturn(rc, rc); 2297 2298 Log4(("IOExit/%u: %04x:%08RX64/%s: %s%s %#x LB %u (emulating)\n", 2299 pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), 2300 pExit->IoPortAccess.AccessInfo.RepPrefix ? "REP " : "", 2301 pExit->IoPortAccess.AccessInfo.IsWrite ? "OUTS" : "INS", 2302 pExit->IoPortAccess.PortNumber, pExit->IoPortAccess.AccessInfo.AccessSize )); 2303 rcStrict = IEMExecOne(pVCpu); 2304 } 2305 if (IOM_SUCCESS(rcStrict)) 2306 { 2307 /* 2308 * Do debug checks. 2309 */ 2310 if ( pExit->VpContext.ExecutionState.DebugActive /** @todo Microsoft: Does DebugActive this only reflect DR7? */ 2311 || (pExit->VpContext.Rflags & X86_EFL_TF) 2312 || DBGFBpIsHwIoArmed(pVM) ) 2313 { 2314 /** @todo Debugging. */ 2315 } 2316 } 2410 } 2411 pCtx->rax = pExit->IoPortAccess.Rax; 2412 int rc = nemHCWinCopyStateFromHyperV(pVM, pVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM); 2413 AssertRCReturn(rc, rc); 2414 Log4(("IOExit/%u: %04x:%08RX64/%s: %s%s%s %#x LB %u -> EMHistoryExec\n", 2415 pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), 2416 pExit->IoPortAccess.AccessInfo.RepPrefix ? "REP " : "", 2417 pExit->IoPortAccess.AccessInfo.IsWrite ? "OUT" : "IN", 2418 pExit->IoPortAccess.AccessInfo.StringOp ? "S" : "", 2419 pExit->IoPortAccess.PortNumber, pExit->IoPortAccess.AccessInfo.AccessSize)); 2420 VBOXSTRICTRC rcStrict = EMHistoryExec(pVCpu, pExitRec, 0); 2421 Log4(("IOExit/%u: %04x:%08RX64/%s: EMHistoryExec -> %Rrc + %04x:%08RX64\n", 2422 pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), 2423 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip)); 2317 2424 return rcStrict; 2318 2319 2425 } 2320 2426 #endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */ … … 2401 2507 #endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */ 2402 2508 2509 2403 2510 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API 2404 2511 /** … … 2406 2513 * 2407 2514 * @returns Strict VBox status code. 2515 * @param pVM The cross context VM structure. 2408 2516 * @param pVCpu The cross context per CPU structure. 2409 2517 * @param pMsg The message. 2410 * @param p Ctx The register context.2518 * @param pGVCpu The global (ring-0) per CPU structure (NULL in r3). 2411 2519 * @sa nemR3WinHandleExitCpuId 2412 2520 */ 2413 NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinHandleMessageCpuId(PVMCPU pVCpu, HV_X64_CPUID_INTERCEPT_MESSAGE const *pMsg, PCPUMCTX pCtx) 2521 NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinHandleMessageCpuId(PVM pVM, PVMCPU pVCpu, HV_X64_CPUID_INTERCEPT_MESSAGE const *pMsg, 2522 PGVMCPU pGVCpu) 2414 2523 { 2415 2524 AssertMsg(pMsg->Header.InstructionLength < 0x10, ("%#x\n", pMsg->Header.InstructionLength)); 2416 2417 /* 2418 * Soak up state and execute the instruction. 2419 * 2420 * Note! If this grows slightly more complicated, combine into an IEMExecDecodedCpuId 2421 * function and make everyone use it. 2422 */ 2423 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_CPUID), 2424 pMsg->Header.Rip + pMsg->Header.CsSegment.Base, ASMReadTSC()); 2425 2426 /** @todo Combine implementations into IEMExecDecodedCpuId as this will 2427 * only get weirder with nested VT-x and AMD-V support. */ 2428 nemHCWinCopyStateFromX64Header(pVCpu, pCtx, &pMsg->Header); 2429 2430 /* Copy in the low register values (top is always cleared). */ 2431 pCtx->rax = (uint32_t)pMsg->Rax; 2432 pCtx->rcx = (uint32_t)pMsg->Rcx; 2433 pCtx->rdx = (uint32_t)pMsg->Rdx; 2434 pCtx->rbx = (uint32_t)pMsg->Rbx; 2435 pCtx->fExtrn &= ~(CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RCX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RBX); 2436 2437 /* Get the correct values. */ 2438 CPUMGetGuestCpuId(pVCpu, pCtx->eax, pCtx->ecx, &pCtx->eax, &pCtx->ebx, &pCtx->ecx, &pCtx->edx); 2439 2440 Log4(("CpuIdExit/%u: %04x:%08RX64/%s: rax=%08RX64 / rcx=%08RX64 / rdx=%08RX64 / rbx=%08RX64 -> %08RX32 / %08RX32 / %08RX32 / %08RX32 (hv: %08RX64 / %08RX64 / %08RX64 / %08RX64)\n", 2525 PCEMEXITREC pExitRec = EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_CPUID), 2526 pMsg->Header.Rip + pMsg->Header.CsSegment.Base, ASMReadTSC()); 2527 if (!pExitRec) 2528 { 2529 /* 2530 * Soak up state and execute the instruction. 2531 * 2532 * Note! If this grows slightly more complicated, combine into an IEMExecDecodedCpuId 2533 * function and make everyone use it. 2534 */ 2535 /** @todo Combine implementations into IEMExecDecodedCpuId as this will 2536 * only get weirder with nested VT-x and AMD-V support. */ 2537 nemHCWinCopyStateFromX64Header(pVCpu, &pVCpu->cpum.GstCtx, &pMsg->Header); 2538 2539 /* Copy in the low register values (top is always cleared). */ 2540 pVCpu->cpum.GstCtx.rax = (uint32_t)pMsg->Rax; 2541 pVCpu->cpum.GstCtx.rcx = (uint32_t)pMsg->Rcx; 2542 pVCpu->cpum.GstCtx.rdx = (uint32_t)pMsg->Rdx; 2543 pVCpu->cpum.GstCtx.rbx = (uint32_t)pMsg->Rbx; 2544 pVCpu->cpum.GstCtx.fExtrn &= ~(CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RCX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RBX); 2545 2546 /* Get the correct values. */ 2547 CPUMGetGuestCpuId(pVCpu, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx, 2548 &pVCpu->cpum.GstCtx.eax, &pVCpu->cpum.GstCtx.ebx, &pVCpu->cpum.GstCtx.ecx, &pVCpu->cpum.GstCtx.edx); 2549 2550 Log4(("CpuIdExit/%u: %04x:%08RX64/%s: rax=%08RX64 / rcx=%08RX64 / rdx=%08RX64 / rbx=%08RX64 -> %08RX32 / %08RX32 / %08RX32 / %08RX32 (hv: %08RX64 / %08RX64 / %08RX64 / %08RX64)\n", 2551 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header), 2552 pMsg->Rax, pMsg->Rcx, pMsg->Rdx, pMsg->Rbx, 2553 pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.ebx, 2554 pMsg->DefaultResultRax, pMsg->DefaultResultRcx, pMsg->DefaultResultRdx, pMsg->DefaultResultRbx)); 2555 2556 /* Move RIP and we're done. */ 2557 nemHCWinAdvanceGuestRipAndClearRF(pVCpu, &pVCpu->cpum.GstCtx, &pMsg->Header); 2558 2559 return VINF_SUCCESS; 2560 } 2561 2562 /* 2563 * Frequent exit or something needing probing. 2564 * Get state and call EMHistoryExec. 2565 */ 2566 nemHCWinCopyStateFromX64Header(pVCpu, &pVCpu->cpum.GstCtx, &pMsg->Header); 2567 pVCpu->cpum.GstCtx.rax = pMsg->Rax; 2568 pVCpu->cpum.GstCtx.rcx = pMsg->Rcx; 2569 pVCpu->cpum.GstCtx.rdx = pMsg->Rdx; 2570 pVCpu->cpum.GstCtx.rbx = pMsg->Rbx; 2571 pVCpu->cpum.GstCtx.fExtrn &= ~(CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RCX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RBX); 2572 Log4(("CpuIdExit/%u: %04x:%08RX64/%s: rax=%08RX64 / rcx=%08RX64 / rdx=%08RX64 / rbx=%08RX64 (hv: %08RX64 / %08RX64 / %08RX64 / %08RX64) ==> EMHistoryExec\n", 2441 2573 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header), 2442 2574 pMsg->Rax, pMsg->Rcx, pMsg->Rdx, pMsg->Rbx, 2443 pCtx->eax, pCtx->ecx, pCtx->edx, pCtx->ebx,2444 2575 pMsg->DefaultResultRax, pMsg->DefaultResultRcx, pMsg->DefaultResultRdx, pMsg->DefaultResultRbx)); 2445 2446 /* Move RIP and we're done. */ 2447 nemHCWinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pMsg->Header); 2448 2449 return VINF_SUCCESS; 2576 # ifdef IN_RING0 2577 VBOXSTRICTRC rcStrict = nemR0WinImportStateStrict(pGVCpu->pGVM, pGVCpu, &pVCpu->cpum.GstCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM, "CpuIdExit"); 2578 if (rcStrict != VINF_SUCCESS) 2579 return rcStrict; 2580 RT_NOREF(pVM); 2581 # else 2582 int rc = nemHCWinCopyStateFromHyperV(pVM, pVCpu, &pVCpu->cpum.GstCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM); 2583 AssertRCReturn(rc, rc); 2584 RT_NOREF(pGVCpu); 2585 # endif 2586 VBOXSTRICTRC rcStrictExec = EMHistoryExec(pVCpu, pExitRec, 0); 2587 Log4(("CpuIdExit/%u: %04x:%08RX64/%s: EMHistoryExec -> %Rrc + %04x:%08RX64\n", 2588 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header), 2589 VBOXSTRICTRC_VAL(rcStrictExec), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip)); 2590 return rcStrictExec; 2450 2591 } 2451 2592 #elif defined(IN_RING3) … … 2457 2598 * @param pVCpu The cross context per CPU structure. 2458 2599 * @param pExit The VM exit information to handle. 2459 * @param pCtx The register context.2460 2600 * @sa nemHCWinHandleMessageCpuId 2461 2601 */ 2462 2602 NEM_TMPL_STATIC VBOXSTRICTRC 2463 nemR3WinHandleExitCpuId(PVM pVM, PVMCPU pVCpu, WHV_RUN_VP_EXIT_CONTEXT const *pExit , PCPUMCTX pCtx)2603 nemR3WinHandleExitCpuId(PVM pVM, PVMCPU pVCpu, WHV_RUN_VP_EXIT_CONTEXT const *pExit) 2464 2604 { 2465 2605 AssertMsg(pExit->VpContext.InstructionLength < 0x10, ("%#x\n", pExit->VpContext.InstructionLength)); 2466 2467 /*2468 * Soak up state and execute the instruction.2469 *2470 * Note! If this grows slightly more complicated, combine into an IEMExecDecodedCpuId2471 * function and make everyone use it.2472 */2473 2606 PCEMEXITREC pExitRec = EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_CPUID), 2474 2607 pExit->VpContext.Rip + pExit->VpContext.Cs.Base, ASMReadTSC()); 2475 nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext);2476 2608 if (!pExitRec) 2477 2609 { 2610 /* 2611 * Soak up state and execute the instruction. 2612 * 2613 * Note! If this grows slightly more complicated, combine into an IEMExecDecodedCpuId 2614 * function and make everyone use it. 2615 */ 2478 2616 /** @todo Combine implementations into IEMExecDecodedCpuId as this will 2479 2617 * only get weirder with nested VT-x and AMD-V support. */ 2618 nemR3WinCopyStateFromX64Header(pVCpu, &pVCpu->cpum.GstCtx, &pExit->VpContext); 2480 2619 2481 2620 /* Copy in the low register values (top is always cleared). */ 2482 p Ctx->rax = (uint32_t)pExit->CpuidAccess.Rax;2483 p Ctx->rcx = (uint32_t)pExit->CpuidAccess.Rcx;2484 p Ctx->rdx = (uint32_t)pExit->CpuidAccess.Rdx;2485 p Ctx->rbx = (uint32_t)pExit->CpuidAccess.Rbx;2486 p Ctx->fExtrn &= ~(CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RCX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RBX);2621 pVCpu->cpum.GstCtx.rax = (uint32_t)pExit->CpuidAccess.Rax; 2622 pVCpu->cpum.GstCtx.rcx = (uint32_t)pExit->CpuidAccess.Rcx; 2623 pVCpu->cpum.GstCtx.rdx = (uint32_t)pExit->CpuidAccess.Rdx; 2624 pVCpu->cpum.GstCtx.rbx = (uint32_t)pExit->CpuidAccess.Rbx; 2625 pVCpu->cpum.GstCtx.fExtrn &= ~(CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RCX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RBX); 2487 2626 2488 2627 /* Get the correct values. */ 2489 CPUMGetGuestCpuId(pVCpu, pCtx->eax, pCtx->ecx, &pCtx->eax, &pCtx->ebx, &pCtx->ecx, &pCtx->edx); 2628 CPUMGetGuestCpuId(pVCpu, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx, 2629 &pVCpu->cpum.GstCtx.eax, &pVCpu->cpum.GstCtx.ebx, &pVCpu->cpum.GstCtx.ecx, &pVCpu->cpum.GstCtx.edx); 2490 2630 2491 2631 Log4(("CpuIdExit/%u: %04x:%08RX64/%s: rax=%08RX64 / rcx=%08RX64 / rdx=%08RX64 / rbx=%08RX64 -> %08RX32 / %08RX32 / %08RX32 / %08RX32 (hv: %08RX64 / %08RX64 / %08RX64 / %08RX64)\n", 2492 2632 pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), 2493 2633 pExit->CpuidAccess.Rax, pExit->CpuidAccess.Rcx, pExit->CpuidAccess.Rdx, pExit->CpuidAccess.Rbx, 2494 p Ctx->eax, pCtx->ecx, pCtx->edx, pCtx->ebx,2634 pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.ebx, 2495 2635 pExit->CpuidAccess.DefaultResultRax, pExit->CpuidAccess.DefaultResultRcx, pExit->CpuidAccess.DefaultResultRdx, pExit->CpuidAccess.DefaultResultRbx)); 2496 2636 2497 2637 /* Move RIP and we're done. */ 2498 nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pExit->VpContext);2638 nemR3WinAdvanceGuestRipAndClearRF(pVCpu, &pVCpu->cpum.GstCtx, &pExit->VpContext); 2499 2639 2500 2640 RT_NOREF_PV(pVM); … … 2502 2642 } 2503 2643 2504 /* Get state and call EMHistoryExec. */ 2505 pCtx->rax = pExit->CpuidAccess.Rax; 2506 pCtx->rcx = pExit->CpuidAccess.Rcx; 2507 pCtx->rdx = pExit->CpuidAccess.Rdx; 2508 pCtx->rbx = pExit->CpuidAccess.Rbx; 2509 pCtx->fExtrn &= ~(CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RCX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RBX); 2644 /* 2645 * Frequent exit or something needing probing. 2646 * Get state and call EMHistoryExec. 2647 */ 2648 nemR3WinCopyStateFromX64Header(pVCpu, &pVCpu->cpum.GstCtx, &pExit->VpContext); 2649 pVCpu->cpum.GstCtx.rax = pExit->CpuidAccess.Rax; 2650 pVCpu->cpum.GstCtx.rcx = pExit->CpuidAccess.Rcx; 2651 pVCpu->cpum.GstCtx.rdx = pExit->CpuidAccess.Rdx; 2652 pVCpu->cpum.GstCtx.rbx = pExit->CpuidAccess.Rbx; 2653 pVCpu->cpum.GstCtx.fExtrn &= ~(CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RCX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RBX); 2510 2654 Log4(("CpuIdExit/%u: %04x:%08RX64/%s: rax=%08RX64 / rcx=%08RX64 / rdx=%08RX64 / rbx=%08RX64 (hv: %08RX64 / %08RX64 / %08RX64 / %08RX64) ==> EMHistoryExec\n", 2511 2655 pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), 2512 2656 pExit->CpuidAccess.Rax, pExit->CpuidAccess.Rcx, pExit->CpuidAccess.Rdx, pExit->CpuidAccess.Rbx, 2513 2657 pExit->CpuidAccess.DefaultResultRax, pExit->CpuidAccess.DefaultResultRcx, pExit->CpuidAccess.DefaultResultRdx, pExit->CpuidAccess.DefaultResultRbx)); 2514 2515 int rc = nemHCWinCopyStateFromHyperV(pVM, pVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM); 2658 int rc = nemHCWinCopyStateFromHyperV(pVM, pVCpu, &pVCpu->cpum.GstCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM); 2516 2659 AssertRCReturn(rc, rc); 2517 2518 2660 VBOXSTRICTRC rcStrict = EMHistoryExec(pVCpu, pExitRec, 0); 2661 Log4(("CpuIdExit/%u: %04x:%08RX64/%s: EMHistoryExec -> %Rrc + %04x:%08RX64\n", 2662 pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), 2663 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip)); 2519 2664 return rcStrict; 2520 2665 } 2521 2666 #endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */ 2667 2522 2668 2523 2669 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API … … 2548 2694 if (pMsg->Header.ExecutionState.Cpl == 0) 2549 2695 { 2550 EMHistoryAddExit(pVCpu,2551 pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE2552 ? EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_MSR_WRITE)2553 : EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_MSR_READ),2554 pMsg->Header.Rip + pMsg->Header.CsSegment.Base, ASMReadTSC());2555 2556 2696 /* 2557 2697 * Get all the MSR state. Since we're getting EFER, we also need to 2558 2698 * get CR0, CR4 and CR3. 2559 2699 */ 2700 PCEMEXITREC pExitRec = EMHistoryAddExit(pVCpu, 2701 pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE 2702 ? EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_MSR_WRITE) 2703 : EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_MSR_READ), 2704 pMsg->Header.Rip + pMsg->Header.CsSegment.Base, ASMReadTSC()); 2705 2560 2706 nemHCWinCopyStateFromX64Header(pVCpu, pCtx, &pMsg->Header); 2561 2707 rcStrict = nemHCWinImportStateIfNeededStrict(pVCpu, pGVCpu, pCtx, 2562 CPUMCTX_EXTRN_ALL_MSRS | CPUMCTX_EXTRN_CR0 2708 (!pExitRec ? 0 : IEM_CPUMCTX_EXTRN_MUST_MASK) 2709 | CPUMCTX_EXTRN_ALL_MSRS | CPUMCTX_EXTRN_CR0 2563 2710 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4, 2564 2711 "MSRs"); 2565 2712 if (rcStrict == VINF_SUCCESS) 2566 2713 { 2567 2568 /* 2569 * Handle writes. 2570 */ 2571 if (pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE) 2714 if (!pExitRec) 2572 2715 { 2573 rcStrict = CPUMSetGuestMsr(pVCpu, pMsg->MsrNumber, RT_MAKE_U64((uint32_t)pMsg->Rax, (uint32_t)pMsg->Rdx)); 2574 Log4(("MsrExit/%u: %04x:%08RX64/%s: WRMSR %08x, %08x:%08x -> %Rrc\n", 2575 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header), 2576 pMsg->MsrNumber, (uint32_t)pMsg->Rax, (uint32_t)pMsg->Rdx, VBOXSTRICTRC_VAL(rcStrict) )); 2577 if (rcStrict == VINF_SUCCESS) 2716 /* 2717 * Handle writes. 2718 */ 2719 if (pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE) 2578 2720 { 2579 nemHCWinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pMsg->Header); 2580 return VINF_SUCCESS; 2721 rcStrict = CPUMSetGuestMsr(pVCpu, pMsg->MsrNumber, RT_MAKE_U64((uint32_t)pMsg->Rax, (uint32_t)pMsg->Rdx)); 2722 Log4(("MsrExit/%u: %04x:%08RX64/%s: WRMSR %08x, %08x:%08x -> %Rrc\n", 2723 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header), 2724 pMsg->MsrNumber, (uint32_t)pMsg->Rax, (uint32_t)pMsg->Rdx, VBOXSTRICTRC_VAL(rcStrict) )); 2725 if (rcStrict == VINF_SUCCESS) 2726 { 2727 nemHCWinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pMsg->Header); 2728 return VINF_SUCCESS; 2729 } 2730 # ifndef IN_RING3 2731 /* move to ring-3 and handle the trap/whatever there, as we want to LogRel this. */ 2732 if (rcStrict == VERR_CPUM_RAISE_GP_0) 2733 rcStrict = VINF_CPUM_R3_MSR_WRITE; 2734 return rcStrict; 2735 # else 2736 LogRel(("MsrExit/%u: %04x:%08RX64/%s: WRMSR %08x, %08x:%08x -> %Rrc!\n", 2737 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header), 2738 pMsg->MsrNumber, (uint32_t)pMsg->Rax, (uint32_t)pMsg->Rdx, VBOXSTRICTRC_VAL(rcStrict) )); 2739 # endif 2581 2740 } 2741 /* 2742 * Handle reads. 2743 */ 2744 else 2745 { 2746 uint64_t uValue = 0; 2747 rcStrict = CPUMQueryGuestMsr(pVCpu, pMsg->MsrNumber, &uValue); 2748 Log4(("MsrExit/%u: %04x:%08RX64/%s: RDMSR %08x -> %08RX64 / %Rrc\n", 2749 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header), 2750 pMsg->MsrNumber, uValue, VBOXSTRICTRC_VAL(rcStrict) )); 2751 if (rcStrict == VINF_SUCCESS) 2752 { 2753 pCtx->rax = (uint32_t)uValue; 2754 pCtx->rdx = uValue >> 32; 2755 pCtx->fExtrn &= ~(CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX); 2756 nemHCWinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pMsg->Header); 2757 return VINF_SUCCESS; 2758 } 2582 2759 # ifndef IN_RING3 2583 /* move to ring-3 and handle the trap/whatever there, as we want to LogRel this. */2584 if (rcStrict == VERR_CPUM_RAISE_GP_0)2585 rcStrict = VINF_CPUM_R3_MSR_WRITE;2586 return rcStrict;2760 /* move to ring-3 and handle the trap/whatever there, as we want to LogRel this. */ 2761 if (rcStrict == VERR_CPUM_RAISE_GP_0) 2762 rcStrict = VINF_CPUM_R3_MSR_READ; 2763 return rcStrict; 2587 2764 # else 2588 LogRel(("MsrExit/%u: %04x:%08RX64/%s: WRMSR %08x, %08x:%08x -> %Rrc!\n",2589 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header),2590 pMsg->MsrNumber, (uint32_t)pMsg->Rax, (uint32_t)pMsg->Rdx, VBOXSTRICTRC_VAL(rcStrict) ));2765 LogRel(("MsrExit/%u: %04x:%08RX64/%s: RDMSR %08x -> %08RX64 / %Rrc\n", 2766 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header), 2767 pMsg->MsrNumber, uValue, VBOXSTRICTRC_VAL(rcStrict) )); 2591 2768 # endif 2769 } 2592 2770 } 2593 /*2594 * Handle reads.2595 */2596 2771 else 2597 2772 { 2598 uint64_t uValue = 0; 2599 rcStrict = CPUMQueryGuestMsr(pVCpu, pMsg->MsrNumber, &uValue); 2600 Log4(("MsrExit/%u: %04x:%08RX64/%s: RDMSR %08x -> %08RX64 / %Rrc\n", 2773 /* 2774 * Handle frequent exit or something needing probing. 2775 */ 2776 Log4(("MsrExit/%u: %04x:%08RX64/%s: %sMSR %#08x\n", 2601 2777 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header), 2602 pMsg->MsrNumber, uValue, VBOXSTRICTRC_VAL(rcStrict) )); 2603 if (rcStrict == VINF_SUCCESS) 2604 { 2605 pCtx->rax = (uint32_t)uValue; 2606 pCtx->rdx = uValue >> 32; 2607 pCtx->fExtrn &= ~(CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX); 2608 nemHCWinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pMsg->Header); 2609 return VINF_SUCCESS; 2610 } 2611 # ifndef IN_RING3 2612 /* move to ring-3 and handle the trap/whatever there, as we want to LogRel this. */ 2613 if (rcStrict == VERR_CPUM_RAISE_GP_0) 2614 rcStrict = VINF_CPUM_R3_MSR_READ; 2778 pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE ? "WR" : "RD", pMsg->MsrNumber)); 2779 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0); 2780 Log4(("MsrExit/%u: %04x:%08RX64/%s: EMHistoryExec -> %Rrc + %04x:%08RX64\n", 2781 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header), 2782 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip)); 2615 2783 return rcStrict; 2616 # else2617 LogRel(("MsrExit/%u: %04x:%08RX64/%s: RDMSR %08x -> %08RX64 / %Rrc\n",2618 pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header),2619 pMsg->MsrNumber, uValue, VBOXSTRICTRC_VAL(rcStrict) ));2620 # endif2621 2784 } 2622 2785 } … … 2680 2843 * get CR0, CR4 and CR3. 2681 2844 */ 2682 EMHistoryAddExit(pVCpu, 2683 pExit->MsrAccess.AccessInfo.IsWrite 2684 ? EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_MSR_WRITE) 2685 : EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_MSR_READ), 2686 pExit->VpContext.Rip + pExit->VpContext.Cs.Base, ASMReadTSC()); 2687 2845 PCEMEXITREC pExitRec = EMHistoryAddExit(pVCpu, 2846 pExit->MsrAccess.AccessInfo.IsWrite 2847 ? EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_MSR_WRITE) 2848 : EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_MSR_READ), 2849 pExit->VpContext.Rip + pExit->VpContext.Cs.Base, ASMReadTSC()); 2688 2850 nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext); 2689 2851 rcStrict = nemHCWinImportStateIfNeededStrict(pVCpu, NULL, pCtx, 2690 CPUMCTX_EXTRN_ALL_MSRS | CPUMCTX_EXTRN_CR0 2852 (!pExitRec ? 0 : IEM_CPUMCTX_EXTRN_MUST_MASK) 2853 | CPUMCTX_EXTRN_ALL_MSRS | CPUMCTX_EXTRN_CR0 2691 2854 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4, 2692 2855 "MSRs"); 2693 2856 if (rcStrict == VINF_SUCCESS) 2694 2857 { 2695 /* 2696 * Handle writes. 2697 */ 2698 if (pExit->MsrAccess.AccessInfo.IsWrite) 2858 if (!pExitRec) 2699 2859 { 2700 rcStrict = CPUMSetGuestMsr(pVCpu, pExit->MsrAccess.MsrNumber, 2701 RT_MAKE_U64((uint32_t)pExit->MsrAccess.Rax, (uint32_t)pExit->MsrAccess.Rdx)); 2702 Log4(("MsrExit/%u: %04x:%08RX64/%s: WRMSR %08x, %08x:%08x -> %Rrc\n", pVCpu->idCpu, pExit->VpContext.Cs.Selector, 2703 pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), pExit->MsrAccess.MsrNumber, 2704 (uint32_t)pExit->MsrAccess.Rax, (uint32_t)pExit->MsrAccess.Rdx, VBOXSTRICTRC_VAL(rcStrict) )); 2705 if (rcStrict == VINF_SUCCESS) 2860 /* 2861 * Handle writes. 2862 */ 2863 if (pExit->MsrAccess.AccessInfo.IsWrite) 2706 2864 { 2707 nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pExit->VpContext); 2708 return VINF_SUCCESS; 2865 rcStrict = CPUMSetGuestMsr(pVCpu, pExit->MsrAccess.MsrNumber, 2866 RT_MAKE_U64((uint32_t)pExit->MsrAccess.Rax, (uint32_t)pExit->MsrAccess.Rdx)); 2867 Log4(("MsrExit/%u: %04x:%08RX64/%s: WRMSR %08x, %08x:%08x -> %Rrc\n", pVCpu->idCpu, pExit->VpContext.Cs.Selector, 2868 pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), pExit->MsrAccess.MsrNumber, 2869 (uint32_t)pExit->MsrAccess.Rax, (uint32_t)pExit->MsrAccess.Rdx, VBOXSTRICTRC_VAL(rcStrict) )); 2870 if (rcStrict == VINF_SUCCESS) 2871 { 2872 nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pExit->VpContext); 2873 return VINF_SUCCESS; 2874 } 2875 LogRel(("MsrExit/%u: %04x:%08RX64/%s: WRMSR %08x, %08x:%08x -> %Rrc!\n", pVCpu->idCpu, 2876 pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), 2877 pExit->MsrAccess.MsrNumber, (uint32_t)pExit->MsrAccess.Rax, (uint32_t)pExit->MsrAccess.Rdx, 2878 VBOXSTRICTRC_VAL(rcStrict) )); 2709 2879 } 2710 LogRel(("MsrExit/%u: %04x:%08RX64/%s: WRMSR %08x, %08x:%08x -> %Rrc!\n", pVCpu->idCpu, 2711 pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), 2712 pExit->MsrAccess.MsrNumber, (uint32_t)pExit->MsrAccess.Rax, (uint32_t)pExit->MsrAccess.Rdx, 2713 VBOXSTRICTRC_VAL(rcStrict) )); 2880 /* 2881 * Handle reads. 2882 */ 2883 else 2884 { 2885 uint64_t uValue = 0; 2886 rcStrict = CPUMQueryGuestMsr(pVCpu, pExit->MsrAccess.MsrNumber, &uValue); 2887 Log4(("MsrExit/%u: %04x:%08RX64/%s: RDMSR %08x -> %08RX64 / %Rrc\n", pVCpu->idCpu, 2888 pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), 2889 pExit->MsrAccess.MsrNumber, uValue, VBOXSTRICTRC_VAL(rcStrict) )); 2890 if (rcStrict == VINF_SUCCESS) 2891 { 2892 pCtx->rax = (uint32_t)uValue; 2893 pCtx->rdx = uValue >> 32; 2894 pCtx->fExtrn &= ~(CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX); 2895 nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pExit->VpContext); 2896 return VINF_SUCCESS; 2897 } 2898 LogRel(("MsrExit/%u: %04x:%08RX64/%s: RDMSR %08x -> %08RX64 / %Rrc\n", pVCpu->idCpu, pExit->VpContext.Cs.Selector, 2899 pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), pExit->MsrAccess.MsrNumber, 2900 uValue, VBOXSTRICTRC_VAL(rcStrict) )); 2901 } 2714 2902 } 2715 /*2716 * Handle reads.2717 */2718 2903 else 2719 2904 { 2720 uint64_t uValue = 0; 2721 rcStrict = CPUMQueryGuestMsr(pVCpu, pExit->MsrAccess.MsrNumber, &uValue); 2722 Log4(("MsrExit/%u: %04x:%08RX64/%s: RDMSR %08x -> %08RX64 / %Rrc\n", pVCpu->idCpu, 2723 pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), 2724 pExit->MsrAccess.MsrNumber, uValue, VBOXSTRICTRC_VAL(rcStrict) )); 2725 if (rcStrict == VINF_SUCCESS) 2726 { 2727 pCtx->rax = (uint32_t)uValue; 2728 pCtx->rdx = uValue >> 32; 2729 pCtx->fExtrn &= ~(CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX); 2730 nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pExit->VpContext); 2731 return VINF_SUCCESS; 2732 } 2733 LogRel(("MsrExit/%u: %04x:%08RX64/%s: RDMSR %08x -> %08RX64 / %Rrc\n", pVCpu->idCpu, pExit->VpContext.Cs.Selector, 2734 pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), pExit->MsrAccess.MsrNumber, 2735 uValue, VBOXSTRICTRC_VAL(rcStrict) )); 2905 /* 2906 * Handle frequent exit or something needing probing. 2907 */ 2908 Log4(("MsrExit/%u: %04x:%08RX64/%s: %sMSR %#08x\n", 2909 pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), 2910 pExit->MsrAccess.AccessInfo.IsWrite ? "WR" : "RD", pExit->MsrAccess.MsrNumber)); 2911 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0); 2912 Log4(("MsrExit/%u: %04x:%08RX64/%s: EMHistoryExec -> %Rrc + %04x:%08RX64\n", 2913 pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), 2914 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip)); 2915 return rcStrict; 2736 2916 } 2737 2917 } … … 3284 3464 Assert(pMsg->Header.PayloadSize == sizeof(pMsg->X64CpuIdIntercept)); 3285 3465 STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitCpuId); 3286 return nemHCWinHandleMessageCpuId(pV Cpu, &pMsg->X64CpuIdIntercept, pCtx);3466 return nemHCWinHandleMessageCpuId(pVM, pVCpu, &pMsg->X64CpuIdIntercept, pGVCpu); 3287 3467 3288 3468 case HvMessageTypeX64MsrIntercept: … … 3369 3549 case WHvRunVpExitReasonX64Cpuid: 3370 3550 STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitCpuId); 3371 return nemR3WinHandleExitCpuId(pVM, pVCpu, pExit , pCtx);3551 return nemR3WinHandleExitCpuId(pVM, pVCpu, pExit); 3372 3552 3373 3553 case WHvRunVpExitReasonX64MsrAccess: -
trunk/src/VBox/VMM/VMMR3/NEMR3.cpp
r72555 r72575 345 345 case NEMEXITTYPE_XCPT_BP: return "NEM #BP"; 346 346 case NEMEXITTYPE_CANCELED: return "NEM canceled"; 347 case NEMEXITTYPE_MEMORY_ACCESS: return "NEM memory access"; 347 348 } 348 349 -
trunk/src/VBox/VMM/include/NEMInternal.h
r72569 r72575 45 45 */ 46 46 # define NEM_WIN_USE_HYPERCALLS_FOR_PAGES 47 //# define NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS48 //# define NEM_WIN_USE_OUR_OWN_RUN_API47 # define NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS 48 # define NEM_WIN_USE_OUR_OWN_RUN_API 49 49 # if defined(NEM_WIN_USE_OUR_OWN_RUN_API) && !defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS) 50 50 # error "NEM_WIN_USE_OUR_OWN_RUN_API requires NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS" … … 122 122 NEMEXITTYPE_XCPT_DB, 123 123 NEMEXITTYPE_XCPT_BP, 124 NEMEXITTYPE_CANCELED 124 NEMEXITTYPE_CANCELED, 125 NEMEXITTYPE_MEMORY_ACCESS 125 126 } NEMEXITTYPE; 126 127
Note:
See TracChangeset
for help on using the changeset viewer.