summaryrefslogtreecommitdiff
path: root/src/VBox/VMM/VMMAll/EMAll.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/VMM/VMMAll/EMAll.cpp')
-rw-r--r--src/VBox/VMM/VMMAll/EMAll.cpp725
1 files changed, 396 insertions, 329 deletions
diff --git a/src/VBox/VMM/VMMAll/EMAll.cpp b/src/VBox/VMM/VMMAll/EMAll.cpp
index 565aacab..4c4a595b 100644
--- a/src/VBox/VMM/VMMAll/EMAll.cpp
+++ b/src/VBox/VMM/VMMAll/EMAll.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2012 Oracle Corporation
+ * Copyright (C) 2006-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -33,7 +33,7 @@
#include "EMInternal.h"
#include <VBox/vmm/vm.h>
#include <VBox/vmm/vmm.h>
-#include <VBox/vmm/hwaccm.h>
+#include <VBox/vmm/hm.h>
#include <VBox/vmm/tm.h>
#include <VBox/vmm/pdmapi.h>
#include <VBox/param.h>
@@ -55,6 +55,11 @@
//# define VBOX_COMPARE_IEM_LAST
#endif
+#ifdef VBOX_WITH_RAW_RING1
+# define EM_EMULATE_SMSW
+#endif
+
+
/*******************************************************************************
* Defined Constants And Macros *
*******************************************************************************/
@@ -117,7 +122,7 @@ static size_t g_cbIemWrote;
* @returns Current status.
* @param pVCpu Pointer to the VMCPU.
*/
-VMMDECL(EMSTATE) EMGetState(PVMCPU pVCpu)
+VMM_INT_DECL(EMSTATE) EMGetState(PVMCPU pVCpu)
{
return pVCpu->em.s.enmState;
}
@@ -127,7 +132,7 @@ VMMDECL(EMSTATE) EMGetState(PVMCPU pVCpu)
*
* @param pVCpu Pointer to the VMCPU.
*/
-VMMDECL(void) EMSetState(PVMCPU pVCpu, EMSTATE enmNewState)
+VMM_INT_DECL(void) EMSetState(PVMCPU pVCpu, EMSTATE enmNewState)
{
/* Only allowed combination: */
Assert(pVCpu->em.s.enmState == EMSTATE_WAIT_SIPI && enmNewState == EMSTATE_HALTED);
@@ -175,13 +180,15 @@ VMMDECL(RTGCUINTPTR) EMGetInhibitInterruptsPC(PVMCPU pVCpu)
* @param rax The content of RAX.
* @param rcx The content of RCX.
* @param rdx The content of RDX.
+ * @param GCPhys The physical address corresponding to rax.
*/
-VMM_INT_DECL(int) EMMonitorWaitPrepare(PVMCPU pVCpu, uint64_t rax, uint64_t rcx, uint64_t rdx)
+VMM_INT_DECL(int) EMMonitorWaitPrepare(PVMCPU pVCpu, uint64_t rax, uint64_t rcx, uint64_t rdx, RTGCPHYS GCPhys)
{
pVCpu->em.s.MWait.uMonitorRAX = rax;
pVCpu->em.s.MWait.uMonitorRCX = rcx;
pVCpu->em.s.MWait.uMonitorRDX = rdx;
pVCpu->em.s.MWait.fWait |= EMMWAIT_FLAG_MONITOR_ACTIVE;
+ /** @todo Make use of GCPhys. */
/** @todo Complete MONITOR implementation. */
return VINF_SUCCESS;
}
@@ -211,23 +218,25 @@ VMM_INT_DECL(int) EMMonitorWaitPerform(PVMCPU pVCpu, uint64_t rax, uint64_t rcx)
/**
- * Determine if we should continue after encountering a hlt or mwait
- * instruction.
+ * Determine if we should continue after encountering a mwait instruction.
*
* Clears MWAIT flags if returning @c true.
*
- * @returns boolean
+ * @returns true if we should continue, false if we should halt.
* @param pVCpu Pointer to the VMCPU.
* @param pCtx Current CPU context.
*/
-VMM_INT_DECL(bool) EMShouldContinueAfterHalt(PVMCPU pVCpu, PCPUMCTX pCtx)
+VMM_INT_DECL(bool) EMMonitorWaitShouldContinue(PVMCPU pVCpu, PCPUMCTX pCtx)
{
if ( pCtx->eflags.Bits.u1IF
|| ( (pVCpu->em.s.MWait.fWait & (EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0))
== (EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0)) )
{
- pVCpu->em.s.MWait.fWait &= ~(EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0);
- return !!VMCPU_FF_ISPENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC));
+ if (VMCPU_FF_IS_PENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)))
+ {
+ pVCpu->em.s.MWait.fWait &= ~(EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0);
+ return true;
+ }
}
return false;
@@ -235,6 +244,21 @@ VMM_INT_DECL(bool) EMShouldContinueAfterHalt(PVMCPU pVCpu, PCPUMCTX pCtx)
/**
+ * Determine if we should continue after encountering a hlt instruction.
+ *
+ * @returns true if we should continue, false if we should halt.
+ * @param pVCpu Pointer to the VMCPU.
+ * @param pCtx Current CPU context.
+ */
+VMM_INT_DECL(bool) EMShouldContinueAfterHalt(PVMCPU pVCpu, PCPUMCTX pCtx)
+{
+ if (pCtx->eflags.Bits.u1IF)
+ return !!VMCPU_FF_IS_PENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC));
+ return false;
+}
+
+
+/**
* Locks REM execution to a single VCPU.
*
* @param pVM Pointer to the VM.
@@ -246,7 +270,7 @@ VMMDECL(void) EMRemLock(PVM pVM)
return; /* early init */
Assert(!PGMIsLockOwner(pVM));
- Assert(!IOMIsLockOwner(pVM));
+ Assert(!IOMIsLockWriteOwner(pVM));
int rc = PDMCritSectEnter(&pVM->em.s.CritSectREM, VERR_SEM_BUSY);
AssertRCSuccess(rc);
#endif
@@ -294,7 +318,7 @@ VMMDECL(bool) EMRemIsLockOwner(PVM pVM)
* @returns VBox status code
* @param pVM Pointer to the VM.
*/
-VMMDECL(int) EMRemTryLock(PVM pVM)
+VMM_INT_DECL(int) EMRemTryLock(PVM pVM)
{
#ifdef VBOX_WITH_REM
if (!PDMCritSectIsInitialized(&pVM->em.s.CritSectREM))
@@ -328,7 +352,7 @@ static DECLCALLBACK(int) emReadBytes(PDISCPUSTATE pDis, uint8_t offInstr, uint8_
else if (cbToRead < cbMinRead)
cbToRead = cbMinRead;
-#if defined(IN_RC) || defined(IN_RING3)
+#if defined(VBOX_WITH_RAW_MODE) && (defined(IN_RC) || defined(IN_RING3))
/*
* We might be called upon to interpret an instruction in a patch.
*/
@@ -377,9 +401,9 @@ static DECLCALLBACK(int) emReadBytes(PDISCPUSTATE pDis, uint8_t offInstr, uint8_
*/
if (rc == VERR_PAGE_TABLE_NOT_PRESENT || rc == VERR_PAGE_NOT_PRESENT)
{
- HWACCMInvalidatePage(pVCpu, uSrcAddr);
+ HMInvalidatePage(pVCpu, uSrcAddr);
if (((uSrcAddr + cbToRead - 1) >> PAGE_SHIFT) != (uSrcAddr >> PAGE_SHIFT))
- HWACCMInvalidatePage(pVCpu, uSrcAddr + cbToRead - 1);
+ HMInvalidatePage(pVCpu, uSrcAddr + cbToRead - 1);
}
#endif
}
@@ -403,14 +427,13 @@ DECLINLINE(int) emDisCoreOne(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, RTGCUINTP
*
* @returns VBox status code, see SELMToFlatEx and EMInterpretDisasOneEx for
* details.
- * @retval VERR_EM_INTERNAL_DISAS_ERROR on DISCoreOneEx failure.
*
* @param pVM Pointer to the VM.
* @param pVCpu Pointer to the VMCPU.
* @param pDis Where to return the parsed instruction info.
* @param pcbInstr Where to return the instruction size. (optional)
*/
-VMMDECL(int) EMInterpretDisasCurrent(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, unsigned *pcbInstr)
+VMM_INT_DECL(int) EMInterpretDisasCurrent(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, unsigned *pcbInstr)
{
PCPUMCTXCORE pCtxCore = CPUMCTX2CORE(CPUMQueryGuestCtxPtr(pVCpu));
RTGCPTR GCPtrInstr;
@@ -437,7 +460,6 @@ VMMDECL(int) EMInterpretDisasCurrent(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, u
* This is used by internally by the interpreter and by trap/access handlers.
*
* @returns VBox status code.
- * @retval VERR_EM_INTERNAL_DISAS_ERROR on DISCoreOneEx failure.
*
* @param pVM Pointer to the VM.
* @param pVCpu Pointer to the VMCPU.
@@ -446,8 +468,8 @@ VMMDECL(int) EMInterpretDisasCurrent(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, u
* @param pDis Where to return the parsed instruction info.
* @param pcbInstr Where to return the instruction size. (optional)
*/
-VMMDECL(int) EMInterpretDisasOneEx(PVM pVM, PVMCPU pVCpu, RTGCUINTPTR GCPtrInstr, PCCPUMCTXCORE pCtxCore,
- PDISCPUSTATE pDis, unsigned *pcbInstr)
+VMM_INT_DECL(int) EMInterpretDisasOneEx(PVM pVM, PVMCPU pVCpu, RTGCUINTPTR GCPtrInstr, PCCPUMCTXCORE pCtxCore,
+ PDISCPUSTATE pDis, unsigned *pcbInstr)
{
Assert(pCtxCore == CPUMGetGuestCtxCore(pVCpu));
DISCPUMODE enmCpuMode = CPUMGetGuestDisMode(pVCpu);
@@ -456,8 +478,8 @@ VMMDECL(int) EMInterpretDisasOneEx(PVM pVM, PVMCPU pVCpu, RTGCUINTPTR GCPtrInstr
int rc = DISInstrWithReader(GCPtrInstr, enmCpuMode, emReadBytes, pVCpu, pDis, pcbInstr);
if (RT_SUCCESS(rc))
return VINF_SUCCESS;
- AssertMsgFailed(("DISCoreOne failed to GCPtrInstr=%RGv rc=%Rrc\n", GCPtrInstr, rc));
- return VERR_EM_INTERNAL_DISAS_ERROR;
+ AssertMsg(rc == VERR_PAGE_NOT_PRESENT || rc == VERR_PAGE_TABLE_NOT_PRESENT, ("DISCoreOne failed to GCPtrInstr=%RGv rc=%Rrc\n", GCPtrInstr, rc));
+ return rc;
}
@@ -679,7 +701,7 @@ static void emCompareWithIem(PVMCPU pVCpu, PCCPUMCTX pEmCtx, PCCPUMCTX pIemCtx,
* Architecture System Developers Manual, Vol 3, 5.5) so we don't need
* to worry about e.g. invalid modrm combinations (!)
*/
-VMMDECL(VBOXSTRICTRC) EMInterpretInstruction(PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault)
+VMM_INT_DECL(VBOXSTRICTRC) EMInterpretInstruction(PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault)
{
Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
LogFlow(("EMInterpretInstruction %RGv fault %RGv\n", (RTGCPTR)pRegFrame->rip, pvFault));
@@ -808,7 +830,7 @@ VMMDECL(VBOXSTRICTRC) EMInterpretInstruction(PVMCPU pVCpu, PCPUMCTXCORE pRegFram
* Architecture System Developers Manual, Vol 3, 5.5) so we don't need
* to worry about e.g. invalid modrm combinations (!)
*/
-VMMDECL(VBOXSTRICTRC) EMInterpretInstructionEx(PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbWritten)
+VMM_INT_DECL(VBOXSTRICTRC) EMInterpretInstructionEx(PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbWritten)
{
LogFlow(("EMInterpretInstructionEx %RGv fault %RGv\n", (RTGCPTR)pRegFrame->rip, pvFault));
Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
@@ -950,8 +972,8 @@ VMMDECL(VBOXSTRICTRC) EMInterpretInstructionEx(PVMCPU pVCpu, PCPUMCTXCORE pRegFr
* @todo At this time we do NOT check if the instruction overwrites vital information.
* Make sure this can't happen!! (will add some assertions/checks later)
*/
-VMMDECL(VBOXSTRICTRC) EMInterpretInstructionDisasState(PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame,
- RTGCPTR pvFault, EMCODETYPE enmCodeType)
+VMM_INT_DECL(VBOXSTRICTRC) EMInterpretInstructionDisasState(PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame,
+ RTGCPTR pvFault, EMCODETYPE enmCodeType)
{
LogFlow(("EMInterpretInstructionDisasState %RGv fault %RGv\n", (RTGCPTR)pRegFrame->rip, pvFault));
Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
@@ -1028,7 +1050,7 @@ VMMDECL(VBOXSTRICTRC) EMInterpretInstructionDisasState(PVMCPU pVCpu, PDISCPUSTAT
#endif
}
-#if defined(IN_RC) /*&& defined(VBOX_WITH_PATM)*/
+#ifdef IN_RC
DECLINLINE(int) emRCStackRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, void *pvDst, RTGCPTR GCPtrSrc, uint32_t cb)
{
@@ -1048,7 +1070,7 @@ DECLINLINE(int) emRCStackRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, void
* @param pRegFrame The register frame.
*
*/
-VMMDECL(int) EMInterpretIretV86ForPatm(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
+VMM_INT_DECL(int) EMInterpretIretV86ForPatm(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
{
RTGCUINTPTR pIretStack = (RTGCUINTPTR)pRegFrame->esp;
RTGCUINTPTR eip, cs, esp, ss, eflags, ds, es, fs, gs, uMask;
@@ -1094,7 +1116,74 @@ VMMDECL(int) EMInterpretIretV86ForPatm(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegF
return VINF_SUCCESS;
}
-#endif /* IN_RC && VBOX_WITH_PATM */
+/**
+ * IRET Emulation.
+ */
+static int emInterpretIret(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
+{
+#ifdef VBOX_WITH_RAW_RING1
+ NOREF(pvFault); NOREF(pcbSize);
+ if (EMIsRawRing1Enabled(pVM))
+ {
+ RTGCUINTPTR pIretStack = (RTGCUINTPTR)pRegFrame->esp;
+ RTGCUINTPTR eip, cs, esp, ss, eflags, uMask;
+ int rc;
+ uint32_t cpl, rpl;
+
+ /* We only execute 32-bits protected mode code in raw mode, so no need to bother to check for 16-bits code here. */
+ /* @todo: we don't verify all the edge cases that generate #GP faults */
+
+ Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
+ Assert(!CPUMIsGuestIn64BitCode(pVCpu));
+ /** @todo Rainy day: Test what happens when VERR_EM_INTERPRETER is returned by
+ * this function. Fear that it may guru on us, thus not converted to
+ * IEM. */
+
+ rc = emRCStackRead(pVM, pVCpu, pRegFrame, &eip, (RTGCPTR)pIretStack , 4);
+ rc |= emRCStackRead(pVM, pVCpu, pRegFrame, &cs, (RTGCPTR)(pIretStack + 4), 4);
+ rc |= emRCStackRead(pVM, pVCpu, pRegFrame, &eflags, (RTGCPTR)(pIretStack + 8), 4);
+ AssertRCReturn(rc, VERR_EM_INTERPRETER);
+ AssertReturn(eflags & X86_EFL_VM, VERR_EM_INTERPRETER);
+
+ /* Deal with V86 above. */
+ if (eflags & X86_EFL_VM)
+ return EMInterpretIretV86ForPatm(pVM, pVCpu, pRegFrame);
+
+ cpl = CPUMRCGetGuestCPL(pVCpu, pRegFrame);
+ rpl = cs & X86_SEL_RPL;
+
+ Log(("emInterpretIret: iret to CS:EIP=%04X:%08X eflags=%x\n", cs, eip, eflags));
+ if (rpl != cpl)
+ {
+ rc |= emRCStackRead(pVM, pVCpu, pRegFrame, &esp, (RTGCPTR)(pIretStack + 12), 4);
+ rc |= emRCStackRead(pVM, pVCpu, pRegFrame, &ss, (RTGCPTR)(pIretStack + 16), 4);
+ AssertRCReturn(rc, VERR_EM_INTERPRETER);
+ Log(("emInterpretIret: return to different privilege level (rpl=%d cpl=%d)\n", rpl, cpl));
+ Log(("emInterpretIret: SS:ESP=%04X:08X\n", ss, esp));
+ pRegFrame->ss.Sel = ss;
+ pRegFrame->esp = esp;
+ }
+ pRegFrame->cs.Sel = cs;
+ pRegFrame->eip = eip;
+
+ /* Adjust CS & SS as required. */
+ CPUMRCRecheckRawState(pVCpu, pRegFrame);
+
+ /* Mask away all reserved bits */
+ uMask = X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_TF | X86_EFL_IF | X86_EFL_DF | X86_EFL_OF | X86_EFL_IOPL | X86_EFL_NT | X86_EFL_RF | X86_EFL_VM | X86_EFL_AC | X86_EFL_VIF | X86_EFL_VIP | X86_EFL_ID;
+ eflags &= uMask;
+
+ CPUMRawSetEFlags(pVCpu, eflags);
+ Assert((pRegFrame->eflags.u32 & (X86_EFL_IF|X86_EFL_IOPL)) == X86_EFL_IF);
+ return VINF_SUCCESS;
+ }
+#else
+ NOREF(pVM); NOREF(pVCpu); NOREF(pDis); NOREF(pRegFrame); NOREF(pvFault); NOREF(pcbSize);
+#endif
+ return VERR_EM_INTERPRETER;
+}
+
+#endif /* IN_RC */
@@ -1118,7 +1207,7 @@ VMMDECL(int) EMInterpretIretV86ForPatm(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegF
* @param pRegFrame The register frame.
*
*/
-VMMDECL(int) EMInterpretCpuId(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
+VMM_INT_DECL(int) EMInterpretCpuId(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
{
Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
uint32_t iLeaf = pRegFrame->eax;
@@ -1146,7 +1235,7 @@ VMMDECL(int) EMInterpretCpuId(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
* @param pRegFrame The register frame.
*
*/
-VMMDECL(int) EMInterpretRdtsc(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
+VMM_INT_DECL(int) EMInterpretRdtsc(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
{
Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
unsigned uCR4 = CPUMGetGuestCR4(pVCpu);
@@ -1176,7 +1265,7 @@ VMMDECL(int) EMInterpretRdtsc(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
* @param pCtx The CPU context.
*
*/
-VMMDECL(int) EMInterpretRdtscp(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
+VMM_INT_DECL(int) EMInterpretRdtscp(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
{
Assert(pCtx == CPUMQueryGuestCtxPtr(pVCpu));
uint32_t uCR4 = CPUMGetGuestCR4(pVCpu);
@@ -1214,7 +1303,7 @@ VMMDECL(int) EMInterpretRdtscp(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
* @param pRegFrame The register frame.
*
*/
-VMMDECL(int) EMInterpretRdpmc(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
+VMM_INT_DECL(int) EMInterpretRdpmc(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
{
Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
uint32_t uCR4 = CPUMGetGuestCR4(pVCpu);
@@ -1241,7 +1330,7 @@ VMMDECL(int) EMInterpretRdpmc(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
/**
* MWAIT Emulation.
*/
-VMMDECL(VBOXSTRICTRC) EMInterpretMWait(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
+VMM_INT_DECL(VBOXSTRICTRC) EMInterpretMWait(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
{
Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
uint32_t u32Dummy, u32ExtFeatures, cpl, u32MWaitFeatures;
@@ -1280,7 +1369,7 @@ VMMDECL(VBOXSTRICTRC) EMInterpretMWait(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegF
/**
* MONITOR Emulation.
*/
-VMMDECL(int) EMInterpretMonitor(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
+VMM_INT_DECL(int) EMInterpretMonitor(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
{
uint32_t u32Dummy, u32ExtFeatures, cpl;
Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
@@ -1301,7 +1390,7 @@ VMMDECL(int) EMInterpretMonitor(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
if (!(u32ExtFeatures & X86_CPUID_FEATURE_ECX_MONITOR))
return VERR_EM_INTERPRETER; /* not supported */
- EMMonitorWaitPrepare(pVCpu, pRegFrame->rax, pRegFrame->rcx, pRegFrame->rdx);
+ EMMonitorWaitPrepare(pVCpu, pRegFrame->rax, pRegFrame->rcx, pRegFrame->rdx, NIL_RTGCPHYS);
return VINF_SUCCESS;
}
@@ -1318,7 +1407,7 @@ VMMDECL(int) EMInterpretMonitor(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
* @param pAddrGC Operand address.
*
*/
-VMMDECL(VBOXSTRICTRC) EMInterpretInvlpg(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pAddrGC)
+VMM_INT_DECL(VBOXSTRICTRC) EMInterpretInvlpg(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pAddrGC)
{
/** @todo is addr always a flat linear address or ds based
* (in absence of segment override prefixes)????
@@ -1396,14 +1485,14 @@ static int emUpdateCRx(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t D
if (pRegFrame->cs.Attr.n.u1Long)
{
AssertMsgFailed(("Illegal enabling of paging with CS.u1Long = 1!!\n"));
- return VERR_EM_INTERPRETER; /* @todo generate #GP(0) */
+ return VERR_EM_INTERPRETER; /** @todo generate #GP(0) */
}
/* Illegal to switch to long mode before activating PAE first (AMD Arch. Programmer's Manual Volume 2: Table 14-5) */
if (!(CPUMGetGuestCR4(pVCpu) & X86_CR4_PAE))
{
AssertMsgFailed(("Illegal enabling of paging with PAE disabled!!\n"));
- return VERR_EM_INTERPRETER; /* @todo generate #GP(0) */
+ return VERR_EM_INTERPRETER; /** @todo generate #GP(0) */
}
msrEFER |= MSR_K6_EFER_LMA;
}
@@ -1412,7 +1501,7 @@ static int emUpdateCRx(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t D
&& !(val & X86_CR0_PG))
{
msrEFER &= ~MSR_K6_EFER_LMA;
- /* @todo Do we need to cut off rip here? High dword of rip is undefined, so it shouldn't really matter. */
+ /** @todo Do we need to cut off rip here? High dword of rip is undefined, so it shouldn't really matter. */
}
CPUMSetGuestEFER(pVCpu, msrEFER);
}
@@ -1466,8 +1555,10 @@ static int emUpdateCRx(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t D
VMCPU_FF_SET(pVCpu, VMCPU_FF_TO_R3);
}
# endif
- if ((val ^ oldval) & X86_CR4_VME)
+# ifdef VBOX_WITH_RAW_MODE
+ if (((val ^ oldval) & X86_CR4_VME) && !HMIsEnabled(pVM))
VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_TSS);
+# endif
rc2 = PGMChangeMode(pVCpu, CPUMGetGuestCR0(pVCpu), CPUMGetGuestCR4(pVCpu), CPUMGetGuestEFER(pVCpu));
return rc2 == VINF_SUCCESS ? rc : rc2;
@@ -1495,7 +1586,7 @@ static int emUpdateCRx(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t D
* @param SrcRegGen General purpose register index (USE_REG_E**))
*
*/
-VMMDECL(int) EMInterpretCRxWrite(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegCrx, uint32_t SrcRegGen)
+VMM_INT_DECL(int) EMInterpretCRxWrite(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegCrx, uint32_t SrcRegGen)
{
uint64_t val;
int rc;
@@ -1526,7 +1617,7 @@ VMMDECL(int) EMInterpretCRxWrite(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame,
* @param u16Data LMSW source data.
*
*/
-VMMDECL(int) EMInterpretLMSW(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint16_t u16Data)
+VMM_INT_DECL(int) EMInterpretLMSW(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint16_t u16Data)
{
Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
uint64_t OldCr0 = CPUMGetGuestCR0(pVCpu);
@@ -1547,7 +1638,7 @@ VMMDECL(int) EMInterpretLMSW(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint
* @param pVCpu Pointer to the VMCPU.
*
*/
-VMMDECL(int) EMInterpretCLTS(PVM pVM, PVMCPU pVCpu)
+VMM_INT_DECL(int) EMInterpretCLTS(PVM pVM, PVMCPU pVCpu)
{
NOREF(pVM);
@@ -1558,6 +1649,127 @@ VMMDECL(int) EMInterpretCLTS(PVM pVM, PVMCPU pVCpu)
}
+#ifdef LOG_ENABLED
+static const char *emMSRtoString(uint32_t uMsr)
+{
+ switch (uMsr)
+ {
+ case MSR_IA32_APICBASE: return "MSR_IA32_APICBASE";
+ case MSR_IA32_CR_PAT: return "MSR_IA32_CR_PAT";
+ case MSR_IA32_SYSENTER_CS: return "MSR_IA32_SYSENTER_CS";
+ case MSR_IA32_SYSENTER_EIP: return "MSR_IA32_SYSENTER_EIP";
+ case MSR_IA32_SYSENTER_ESP: return "MSR_IA32_SYSENTER_ESP";
+ case MSR_K6_EFER: return "MSR_K6_EFER";
+ case MSR_K8_SF_MASK: return "MSR_K8_SF_MASK";
+ case MSR_K6_STAR: return "MSR_K6_STAR";
+ case MSR_K8_LSTAR: return "MSR_K8_LSTAR";
+ case MSR_K8_CSTAR: return "MSR_K8_CSTAR";
+ case MSR_K8_FS_BASE: return "MSR_K8_FS_BASE";
+ case MSR_K8_GS_BASE: return "MSR_K8_GS_BASE";
+ case MSR_K8_KERNEL_GS_BASE: return "MSR_K8_KERNEL_GS_BASE";
+ case MSR_K8_TSC_AUX: return "MSR_K8_TSC_AUX";
+ case MSR_IA32_BIOS_SIGN_ID: return "Unsupported MSR_IA32_BIOS_SIGN_ID";
+ case MSR_IA32_PLATFORM_ID: return "Unsupported MSR_IA32_PLATFORM_ID";
+ case MSR_IA32_BIOS_UPDT_TRIG: return "Unsupported MSR_IA32_BIOS_UPDT_TRIG";
+ case MSR_IA32_TSC: return "MSR_IA32_TSC";
+ case MSR_IA32_MISC_ENABLE: return "MSR_IA32_MISC_ENABLE";
+ case MSR_IA32_MTRR_CAP: return "MSR_IA32_MTRR_CAP";
+ case MSR_IA32_MCG_CAP: return "Unsupported MSR_IA32_MCG_CAP";
+ case MSR_IA32_MCG_STATUS: return "Unsupported MSR_IA32_MCG_STATUS";
+ case MSR_IA32_MCG_CTRL: return "Unsupported MSR_IA32_MCG_CTRL";
+ case MSR_IA32_MTRR_DEF_TYPE: return "MSR_IA32_MTRR_DEF_TYPE";
+ case MSR_K7_EVNTSEL0: return "Unsupported MSR_K7_EVNTSEL0";
+ case MSR_K7_EVNTSEL1: return "Unsupported MSR_K7_EVNTSEL1";
+ case MSR_K7_EVNTSEL2: return "Unsupported MSR_K7_EVNTSEL2";
+ case MSR_K7_EVNTSEL3: return "Unsupported MSR_K7_EVNTSEL3";
+ case MSR_IA32_MC0_CTL: return "Unsupported MSR_IA32_MC0_CTL";
+ case MSR_IA32_MC0_STATUS: return "Unsupported MSR_IA32_MC0_STATUS";
+ case MSR_IA32_PERFEVTSEL0: return "Unsupported MSR_IA32_PERFEVTSEL0";
+ case MSR_IA32_PERFEVTSEL1: return "Unsupported MSR_IA32_PERFEVTSEL1";
+ case MSR_IA32_PERF_STATUS: return "MSR_IA32_PERF_STATUS";
+ case MSR_IA32_PLATFORM_INFO: return "MSR_IA32_PLATFORM_INFO";
+ case MSR_IA32_PERF_CTL: return "Unsupported MSR_IA32_PERF_CTL";
+ case MSR_K7_PERFCTR0: return "Unsupported MSR_K7_PERFCTR0";
+ case MSR_K7_PERFCTR1: return "Unsupported MSR_K7_PERFCTR1";
+ case MSR_K7_PERFCTR2: return "Unsupported MSR_K7_PERFCTR2";
+ case MSR_K7_PERFCTR3: return "Unsupported MSR_K7_PERFCTR3";
+ case MSR_IA32_PMC0: return "Unsupported MSR_IA32_PMC0";
+ case MSR_IA32_PMC1: return "Unsupported MSR_IA32_PMC1";
+ case MSR_IA32_PMC2: return "Unsupported MSR_IA32_PMC2";
+ case MSR_IA32_PMC3: return "Unsupported MSR_IA32_PMC3";
+ }
+ return "Unknown MSR";
+}
+#endif /* LOG_ENABLED */
+
+
+/**
+ * Interpret RDMSR
+ *
+ * @returns VBox status code.
+ * @param pVM Pointer to the VM.
+ * @param pVCpu Pointer to the VMCPU.
+ * @param pRegFrame The register frame.
+ */
+VMM_INT_DECL(int) EMInterpretRdmsr(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
+{
+ NOREF(pVM);
+
+ /* Get the current privilege level. */
+ if (CPUMGetGuestCPL(pVCpu) != 0)
+ {
+ Log4(("EM: Refuse RDMSR: CPL != 0\n"));
+ return VERR_EM_INTERPRETER; /* supervisor only */
+ }
+
+ uint64_t uValue;
+ int rc = CPUMQueryGuestMsr(pVCpu, pRegFrame->ecx, &uValue);
+ if (RT_UNLIKELY(rc != VINF_SUCCESS))
+ {
+ Assert(rc == VERR_CPUM_RAISE_GP_0);
+ Log4(("EM: Refuse RDMSR: rc=%Rrc\n", rc));
+ return VERR_EM_INTERPRETER;
+ }
+ pRegFrame->rax = (uint32_t) uValue;
+ pRegFrame->rdx = (uint32_t)(uValue >> 32);
+ LogFlow(("EMInterpretRdmsr %s (%x) -> %RX64\n", emMSRtoString(pRegFrame->ecx), pRegFrame->ecx, uValue));
+ return rc;
+}
+
+
+/**
+ * Interpret WRMSR
+ *
+ * @returns VBox status code.
+ * @param pVM Pointer to the VM.
+ * @param pVCpu Pointer to the VMCPU.
+ * @param pRegFrame The register frame.
+ */
+VMM_INT_DECL(int) EMInterpretWrmsr(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
+{
+ Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
+
+ /* Check the current privilege level, this instruction is supervisor only. */
+ if (CPUMGetGuestCPL(pVCpu) != 0)
+ {
+ Log4(("EM: Refuse WRMSR: CPL != 0\n"));
+ return VERR_EM_INTERPRETER; /** @todo raise \#GP(0) */
+ }
+
+ int rc = CPUMSetGuestMsr(pVCpu, pRegFrame->ecx, RT_MAKE_U64(pRegFrame->eax, pRegFrame->edx));
+ if (rc != VINF_SUCCESS)
+ {
+ Assert(rc == VERR_CPUM_RAISE_GP_0);
+ Log4(("EM: Refuse WRMSR: rc=%d\n", rc));
+ return VERR_EM_INTERPRETER;
+ }
+ LogFlow(("EMInterpretWrmsr %s (%x) val=%RX64\n", emMSRtoString(pRegFrame->ecx), pRegFrame->ecx,
+ RT_MAKE_U64(pRegFrame->eax, pRegFrame->edx)));
+ NOREF(pVM);
+ return rc;
+}
+
+
/**
* Interpret CRx read.
*
@@ -1569,7 +1781,7 @@ VMMDECL(int) EMInterpretCLTS(PVM pVM, PVMCPU pVCpu)
* @param SrcRegCRx CRx register index (DISUSE_REG_CR*)
*
*/
-VMMDECL(int) EMInterpretCRxRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegGen, uint32_t SrcRegCrx)
+VMM_INT_DECL(int) EMInterpretCRxRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegGen, uint32_t SrcRegCrx)
{
Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
uint64_t val64;
@@ -1602,26 +1814,37 @@ VMMDECL(int) EMInterpretCRxRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, u
* @param SrcRegGen General purpose register index (USE_REG_E**))
*
*/
-VMMDECL(int) EMInterpretDRxWrite(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegDrx, uint32_t SrcRegGen)
+VMM_INT_DECL(int) EMInterpretDRxWrite(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegDrx, uint32_t SrcRegGen)
{
Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
- uint64_t val;
+ uint64_t uNewDrX;
int rc;
NOREF(pVM);
if (CPUMIsGuestIn64BitCode(pVCpu))
- rc = DISFetchReg64(pRegFrame, SrcRegGen, &val);
+ rc = DISFetchReg64(pRegFrame, SrcRegGen, &uNewDrX);
else
{
uint32_t val32;
rc = DISFetchReg32(pRegFrame, SrcRegGen, &val32);
- val = val32;
+ uNewDrX = val32;
}
if (RT_SUCCESS(rc))
{
+ if (DestRegDrx == 6)
+ {
+ uNewDrX |= X86_DR6_RA1_MASK;
+ uNewDrX &= ~X86_DR6_RAZ_MASK;
+ }
+ else if (DestRegDrx == 7)
+ {
+ uNewDrX |= X86_DR7_RA1_MASK;
+ uNewDrX &= ~X86_DR7_RAZ_MASK;
+ }
+
/** @todo we don't fail if illegal bits are set/cleared for e.g. dr7 */
- rc = CPUMSetGuestDRx(pVCpu, DestRegDrx, val);
+ rc = CPUMSetGuestDRx(pVCpu, DestRegDrx, uNewDrX);
if (RT_SUCCESS(rc))
return rc;
AssertMsgFailed(("CPUMSetGuestDRx %d failed\n", DestRegDrx));
@@ -1641,7 +1864,7 @@ VMMDECL(int) EMInterpretDRxWrite(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame,
* @param SrcRegDRx DRx register index (USE_REG_DR*)
*
*/
-VMMDECL(int) EMInterpretDRxRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegGen, uint32_t SrcRegDrx)
+VMM_INT_DECL(int) EMInterpretDRxRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegGen, uint32_t SrcRegDrx)
{
uint64_t val64;
Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
@@ -2507,121 +2730,134 @@ static int emInterpretMov(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE
if(RT_FAILURE(rc))
return VERR_EM_INTERPRETER;
-#ifdef IN_RC
- if (TRPMHasTrap(pVCpu))
+ if (param1.type == DISQPV_TYPE_ADDRESS)
{
- if (TRPMGetErrorCode(pVCpu) & X86_TRAP_PF_RW)
- {
-#else
- /** @todo Make this the default and don't rely on TRPM information. */
- if (param1.type == DISQPV_TYPE_ADDRESS)
- {
-#endif
- RTGCPTR pDest;
- uint64_t val64;
+ RTGCPTR pDest;
+ uint64_t val64;
- switch(param1.type)
- {
- case DISQPV_TYPE_IMMEDIATE:
- if(!(param1.flags & (DISQPV_FLAG_32|DISQPV_FLAG_64)))
- return VERR_EM_INTERPRETER;
- /* fallthru */
+ switch(param1.type)
+ {
+ case DISQPV_TYPE_IMMEDIATE:
+ if(!(param1.flags & (DISQPV_FLAG_32|DISQPV_FLAG_64)))
+ return VERR_EM_INTERPRETER;
+ /* fallthru */
- case DISQPV_TYPE_ADDRESS:
- pDest = (RTGCPTR)param1.val.val64;
- pDest = emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->Param1, pDest);
- break;
+ case DISQPV_TYPE_ADDRESS:
+ pDest = (RTGCPTR)param1.val.val64;
+ pDest = emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->Param1, pDest);
+ break;
- default:
- AssertFailed();
- return VERR_EM_INTERPRETER;
- }
+ default:
+ AssertFailed();
+ return VERR_EM_INTERPRETER;
+ }
- switch(param2.type)
- {
- case DISQPV_TYPE_IMMEDIATE: /* register type is translated to this one too */
- val64 = param2.val.val64;
- break;
+ switch(param2.type)
+ {
+ case DISQPV_TYPE_IMMEDIATE: /* register type is translated to this one too */
+ val64 = param2.val.val64;
+ break;
- default:
- Log(("emInterpretMov: unexpected type=%d rip=%RGv\n", param2.type, (RTGCPTR)pRegFrame->rip));
- return VERR_EM_INTERPRETER;
- }
+ default:
+ Log(("emInterpretMov: unexpected type=%d rip=%RGv\n", param2.type, (RTGCPTR)pRegFrame->rip));
+ return VERR_EM_INTERPRETER;
+ }
#ifdef LOG_ENABLED
- if (pDis->uCpuMode == DISCPUMODE_64BIT)
- LogFlow(("EMInterpretInstruction at %RGv: OP_MOV %RGv <- %RX64 (%d) &val64=%RHv\n", (RTGCPTR)pRegFrame->rip, pDest, val64, param2.size, &val64));
- else
- LogFlow(("EMInterpretInstruction at %08RX64: OP_MOV %RGv <- %08X (%d) &val64=%RHv\n", pRegFrame->rip, pDest, (uint32_t)val64, param2.size, &val64));
+ if (pDis->uCpuMode == DISCPUMODE_64BIT)
+ LogFlow(("EMInterpretInstruction at %RGv: OP_MOV %RGv <- %RX64 (%d) &val64=%RHv\n", (RTGCPTR)pRegFrame->rip, pDest, val64, param2.size, &val64));
+ else
+ LogFlow(("EMInterpretInstruction at %08RX64: OP_MOV %RGv <- %08X (%d) &val64=%RHv\n", pRegFrame->rip, pDest, (uint32_t)val64, param2.size, &val64));
#endif
- Assert(param2.size <= 8 && param2.size > 0);
- EM_ASSERT_FAULT_RETURN(pDest == pvFault, VERR_EM_INTERPRETER);
- rc = emRamWrite(pVM, pVCpu, pRegFrame, pDest, &val64, param2.size);
- if (RT_FAILURE(rc))
- return VERR_EM_INTERPRETER;
+ Assert(param2.size <= 8 && param2.size > 0);
+ EM_ASSERT_FAULT_RETURN(pDest == pvFault, VERR_EM_INTERPRETER);
+ rc = emRamWrite(pVM, pVCpu, pRegFrame, pDest, &val64, param2.size);
+ if (RT_FAILURE(rc))
+ return VERR_EM_INTERPRETER;
- *pcbSize = param2.size;
- }
- else
- { /* read fault */
- RTGCPTR pSrc;
- uint64_t val64;
+ *pcbSize = param2.size;
+ }
+#if defined(IN_RC) && defined(VBOX_WITH_RAW_RING1)
+ /* mov xx, cs instruction is dangerous in raw mode and replaced by an 'int3' by csam/patm. */
+ else if ( param1.type == DISQPV_TYPE_REGISTER
+ && param2.type == DISQPV_TYPE_REGISTER)
+ {
+ AssertReturn((pDis->Param1.fUse & (DISUSE_REG_GEN8|DISUSE_REG_GEN16|DISUSE_REG_GEN32)), VERR_EM_INTERPRETER);
+ AssertReturn(pDis->Param2.fUse == DISUSE_REG_SEG, VERR_EM_INTERPRETER);
+ AssertReturn(pDis->Param2.Base.idxSegReg == DISSELREG_CS, VERR_EM_INTERPRETER);
- /* Source */
- switch(param2.type)
- {
- case DISQPV_TYPE_IMMEDIATE:
- if(!(param2.flags & (DISQPV_FLAG_32|DISQPV_FLAG_64)))
- return VERR_EM_INTERPRETER;
- /* fallthru */
+ uint32_t u32Cpl = CPUMRCGetGuestCPL(pVCpu, pRegFrame);
+ uint32_t uValCS = (pRegFrame->cs.Sel & ~X86_SEL_RPL) | u32Cpl;
- case DISQPV_TYPE_ADDRESS:
- pSrc = (RTGCPTR)param2.val.val64;
- pSrc = emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->Param2, pSrc);
- break;
+ Log(("EMInterpretInstruction: OP_MOV cs=%x->%x\n", pRegFrame->cs.Sel, uValCS));
+ switch (param1.size)
+ {
+ case 1: rc = DISWriteReg8(pRegFrame, pDis->Param1.Base.idxGenReg, (uint8_t) uValCS); break;
+ case 2: rc = DISWriteReg16(pRegFrame, pDis->Param1.Base.idxGenReg, (uint16_t)uValCS); break;
+ case 4: rc = DISWriteReg32(pRegFrame, pDis->Param1.Base.idxGenReg, (uint32_t)uValCS); break;
+ default:
+ AssertFailed();
+ return VERR_EM_INTERPRETER;
+ }
+ AssertRCReturn(rc, rc);
+ }
+#endif
+ else
+ { /* read fault */
+ RTGCPTR pSrc;
+ uint64_t val64;
- default:
+ /* Source */
+ switch(param2.type)
+ {
+ case DISQPV_TYPE_IMMEDIATE:
+ if(!(param2.flags & (DISQPV_FLAG_32|DISQPV_FLAG_64)))
return VERR_EM_INTERPRETER;
- }
+ /* fallthru */
- Assert(param1.size <= 8 && param1.size > 0);
- EM_ASSERT_FAULT_RETURN(pSrc == pvFault, VERR_EM_INTERPRETER);
- rc = emRamRead(pVM, pVCpu, pRegFrame, &val64, pSrc, param1.size);
- if (RT_FAILURE(rc))
- return VERR_EM_INTERPRETER;
+ case DISQPV_TYPE_ADDRESS:
+ pSrc = (RTGCPTR)param2.val.val64;
+ pSrc = emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->Param2, pSrc);
+ break;
- /* Destination */
- switch(param1.type)
- {
- case DISQPV_TYPE_REGISTER:
- switch(param1.size)
- {
- case 1: rc = DISWriteReg8(pRegFrame, pDis->Param1.Base.idxGenReg, (uint8_t) val64); break;
- case 2: rc = DISWriteReg16(pRegFrame, pDis->Param1.Base.idxGenReg, (uint16_t)val64); break;
- case 4: rc = DISWriteReg32(pRegFrame, pDis->Param1.Base.idxGenReg, (uint32_t)val64); break;
- case 8: rc = DISWriteReg64(pRegFrame, pDis->Param1.Base.idxGenReg, val64); break;
- default:
- return VERR_EM_INTERPRETER;
- }
- if (RT_FAILURE(rc))
- return rc;
- break;
+ default:
+ return VERR_EM_INTERPRETER;
+ }
+
+ Assert(param1.size <= 8 && param1.size > 0);
+ EM_ASSERT_FAULT_RETURN(pSrc == pvFault, VERR_EM_INTERPRETER);
+ rc = emRamRead(pVM, pVCpu, pRegFrame, &val64, pSrc, param1.size);
+ if (RT_FAILURE(rc))
+ return VERR_EM_INTERPRETER;
+ /* Destination */
+ switch(param1.type)
+ {
+ case DISQPV_TYPE_REGISTER:
+ switch(param1.size)
+ {
+ case 1: rc = DISWriteReg8(pRegFrame, pDis->Param1.Base.idxGenReg, (uint8_t) val64); break;
+ case 2: rc = DISWriteReg16(pRegFrame, pDis->Param1.Base.idxGenReg, (uint16_t)val64); break;
+ case 4: rc = DISWriteReg32(pRegFrame, pDis->Param1.Base.idxGenReg, (uint32_t)val64); break;
+ case 8: rc = DISWriteReg64(pRegFrame, pDis->Param1.Base.idxGenReg, val64); break;
default:
return VERR_EM_INTERPRETER;
}
+ if (RT_FAILURE(rc))
+ return rc;
+ break;
+
+ default:
+ return VERR_EM_INTERPRETER;
+ }
#ifdef LOG_ENABLED
- if (pDis->uCpuMode == DISCPUMODE_64BIT)
- LogFlow(("EMInterpretInstruction: OP_MOV %RGv -> %RX64 (%d)\n", pSrc, val64, param1.size));
- else
- LogFlow(("EMInterpretInstruction: OP_MOV %RGv -> %08X (%d)\n", pSrc, (uint32_t)val64, param1.size));
+ if (pDis->uCpuMode == DISCPUMODE_64BIT)
+ LogFlow(("EMInterpretInstruction: OP_MOV %RGv -> %RX64 (%d)\n", pSrc, val64, param1.size));
+ else
+ LogFlow(("EMInterpretInstruction: OP_MOV %RGv -> %08X (%d)\n", pSrc, (uint32_t)val64, param1.size));
#endif
- }
- return VINF_SUCCESS;
-#ifdef IN_RC
}
- return VERR_EM_INTERPRETER;
-#endif
+ return VINF_SUCCESS;
}
@@ -2871,7 +3107,6 @@ static int emInterpretCmpXchg(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTX
*/
static int emInterpretCmpXchg8b(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
{
- Assert(pDis->uCpuMode != DISCPUMODE_64BIT); /** @todo check */
DISQPVPARAMVAL param1;
NOREF(pvFault);
@@ -2925,7 +3160,7 @@ static int emInterpretCmpXchg8b(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMC
}
-#ifdef IN_RC /** @todo test+enable for HWACCM as well. */
+#ifdef IN_RC /** @todo test+enable for HM as well. */
/**
* [LOCK] XADD emulation.
*/
@@ -3016,16 +3251,6 @@ static int emInterpretXAdd(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCOR
/**
- * IRET Emulation.
- */
-static int emInterpretIret(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
-{
- /* only allow direct calls to EMInterpretIret for now */
- NOREF(pVM); NOREF(pVCpu); NOREF(pDis); NOREF(pRegFrame); NOREF(pvFault); NOREF(pcbSize);
- return VERR_EM_INTERPRETER;
-}
-
-/**
* WBINVD Emulation.
*/
static int emInterpretWbInvd(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
@@ -3325,7 +3550,7 @@ static int emInterpretLIGdt(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCO
static int emInterpretSti(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
{
NOREF(pcbSize);
- PPATMGCSTATE pGCState = PATMQueryGCState(pVM);
+ PPATMGCSTATE pGCState = PATMGetGCState(pVM);
if(!pGCState)
{
@@ -3389,139 +3614,6 @@ static VBOXSTRICTRC emInterpretMWait(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, P
}
-#ifdef LOG_ENABLED
-static const char *emMSRtoString(uint32_t uMsr)
-{
- switch (uMsr)
- {
- case MSR_IA32_APICBASE:
- return "MSR_IA32_APICBASE";
- case MSR_IA32_CR_PAT:
- return "MSR_IA32_CR_PAT";
- case MSR_IA32_SYSENTER_CS:
- return "MSR_IA32_SYSENTER_CS";
- case MSR_IA32_SYSENTER_EIP:
- return "MSR_IA32_SYSENTER_EIP";
- case MSR_IA32_SYSENTER_ESP:
- return "MSR_IA32_SYSENTER_ESP";
- case MSR_K6_EFER:
- return "MSR_K6_EFER";
- case MSR_K8_SF_MASK:
- return "MSR_K8_SF_MASK";
- case MSR_K6_STAR:
- return "MSR_K6_STAR";
- case MSR_K8_LSTAR:
- return "MSR_K8_LSTAR";
- case MSR_K8_CSTAR:
- return "MSR_K8_CSTAR";
- case MSR_K8_FS_BASE:
- return "MSR_K8_FS_BASE";
- case MSR_K8_GS_BASE:
- return "MSR_K8_GS_BASE";
- case MSR_K8_KERNEL_GS_BASE:
- return "MSR_K8_KERNEL_GS_BASE";
- case MSR_K8_TSC_AUX:
- return "MSR_K8_TSC_AUX";
- case MSR_IA32_BIOS_SIGN_ID:
- return "Unsupported MSR_IA32_BIOS_SIGN_ID";
- case MSR_IA32_PLATFORM_ID:
- return "Unsupported MSR_IA32_PLATFORM_ID";
- case MSR_IA32_BIOS_UPDT_TRIG:
- return "Unsupported MSR_IA32_BIOS_UPDT_TRIG";
- case MSR_IA32_TSC:
- return "MSR_IA32_TSC";
- case MSR_IA32_MISC_ENABLE:
- return "MSR_IA32_MISC_ENABLE";
- case MSR_IA32_MTRR_CAP:
- return "MSR_IA32_MTRR_CAP";
- case MSR_IA32_MCP_CAP:
- return "Unsupported MSR_IA32_MCP_CAP";
- case MSR_IA32_MCP_STATUS:
- return "Unsupported MSR_IA32_MCP_STATUS";
- case MSR_IA32_MCP_CTRL:
- return "Unsupported MSR_IA32_MCP_CTRL";
- case MSR_IA32_MTRR_DEF_TYPE:
- return "MSR_IA32_MTRR_DEF_TYPE";
- case MSR_K7_EVNTSEL0:
- return "Unsupported MSR_K7_EVNTSEL0";
- case MSR_K7_EVNTSEL1:
- return "Unsupported MSR_K7_EVNTSEL1";
- case MSR_K7_EVNTSEL2:
- return "Unsupported MSR_K7_EVNTSEL2";
- case MSR_K7_EVNTSEL3:
- return "Unsupported MSR_K7_EVNTSEL3";
- case MSR_IA32_MC0_CTL:
- return "Unsupported MSR_IA32_MC0_CTL";
- case MSR_IA32_MC0_STATUS:
- return "Unsupported MSR_IA32_MC0_STATUS";
- case MSR_IA32_PERFEVTSEL0:
- return "Unsupported MSR_IA32_PERFEVTSEL0";
- case MSR_IA32_PERFEVTSEL1:
- return "Unsupported MSR_IA32_PERFEVTSEL1";
- case MSR_IA32_PERF_STATUS:
- return "MSR_IA32_PERF_STATUS";
- case MSR_IA32_PLATFORM_INFO:
- return "MSR_IA32_PLATFORM_INFO";
- case MSR_IA32_PERF_CTL:
- return "Unsupported MSR_IA32_PERF_CTL";
- case MSR_K7_PERFCTR0:
- return "Unsupported MSR_K7_PERFCTR0";
- case MSR_K7_PERFCTR1:
- return "Unsupported MSR_K7_PERFCTR1";
- case MSR_K7_PERFCTR2:
- return "Unsupported MSR_K7_PERFCTR2";
- case MSR_K7_PERFCTR3:
- return "Unsupported MSR_K7_PERFCTR3";
- case MSR_IA32_PMC0:
- return "Unsupported MSR_IA32_PMC0";
- case MSR_IA32_PMC1:
- return "Unsupported MSR_IA32_PMC1";
- case MSR_IA32_PMC2:
- return "Unsupported MSR_IA32_PMC2";
- case MSR_IA32_PMC3:
- return "Unsupported MSR_IA32_PMC3";
- }
- return "Unknown MSR";
-}
-#endif /* LOG_ENABLED */
-
-
-/**
- * Interpret RDMSR
- *
- * @returns VBox status code.
- * @param pVM Pointer to the VM.
- * @param pVCpu Pointer to the VMCPU.
- * @param pRegFrame The register frame.
- */
-VMMDECL(int) EMInterpretRdmsr(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
-{
- /** @todo According to the Intel manuals, there's a REX version of RDMSR that is slightly different.
- * That version clears the high dwords of both RDX & RAX */
- NOREF(pVM);
-
- /* Get the current privilege level. */
- if (CPUMGetGuestCPL(pVCpu) != 0)
- {
- Log4(("EM: Refuse RDMSR: CPL != 0\n"));
- return VERR_EM_INTERPRETER; /* supervisor only */
- }
-
- uint64_t uValue;
- int rc = CPUMQueryGuestMsr(pVCpu, pRegFrame->ecx, &uValue);
- if (RT_UNLIKELY(rc != VINF_SUCCESS))
- {
- Assert(rc == VERR_CPUM_RAISE_GP_0);
- Log4(("EM: Refuse RDMSR: rc=%Rrc\n", rc));
- return VERR_EM_INTERPRETER;
- }
- pRegFrame->rax = (uint32_t) uValue;
- pRegFrame->rdx = (uint32_t)(uValue >> 32);
- LogFlow(("EMInterpretRdmsr %s (%x) -> %RX64\n", emMSRtoString(pRegFrame->ecx), pRegFrame->ecx, uValue));
- return rc;
-}
-
-
/**
* RDMSR Emulation.
*/
@@ -3536,39 +3628,6 @@ static int emInterpretRdmsr(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCO
/**
- * Interpret WRMSR
- *
- * @returns VBox status code.
- * @param pVM Pointer to the VM.
- * @param pVCpu Pointer to the VMCPU.
- * @param pRegFrame The register frame.
- */
-VMMDECL(int) EMInterpretWrmsr(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame)
-{
- Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu));
-
- /* Check the current privilege level, this instruction is supervisor only. */
- if (CPUMGetGuestCPL(pVCpu) != 0)
- {
- Log4(("EM: Refuse WRMSR: CPL != 0\n"));
- return VERR_EM_INTERPRETER; /** @todo raise \#GP(0) */
- }
-
- int rc = CPUMSetGuestMsr(pVCpu, pRegFrame->ecx, RT_MAKE_U64(pRegFrame->eax, pRegFrame->edx));
- if (rc != VINF_SUCCESS)
- {
- Assert(rc == VERR_CPUM_RAISE_GP_0);
- Log4(("EM: Refuse WRMSR: rc=%d\n", rc));
- return VERR_EM_INTERPRETER;
- }
- LogFlow(("EMInterpretWrmsr %s (%x) val=%RX64\n", emMSRtoString(pRegFrame->ecx), pRegFrame->ecx,
- RT_MAKE_U64(pRegFrame->eax, pRegFrame->edx)));
- NOREF(pVM);
- return rc;
-}
-
-
-/**
* WRMSR Emulation.
*/
static int emInterpretWrmsr(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
@@ -3598,12 +3657,20 @@ DECLINLINE(VBOXSTRICTRC) emInterpretInstructionCPU(PVM pVM, PVMCPU pVCpu, PDISCP
*/
/* Get the current privilege level. */
uint32_t cpl = CPUMGetGuestCPL(pVCpu);
- if ( cpl != 0
- && pDis->pCurInstr->uOpcode != OP_RDTSC) /* rdtsc requires emulation in ring 3 as well */
+#ifdef VBOX_WITH_RAW_RING1
+ if ( !EMIsRawRing1Enabled(pVM)
+ || cpl > 1
+ || pRegFrame->eflags.Bits.u2IOPL > cpl
+ )
+#endif
{
- Log(("WARNING: refusing instruction emulation for user-mode code!!\n"));
- STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,FailedUserMode));
- return VERR_EM_INTERPRETER;
+ if ( cpl != 0
+ && pDis->pCurInstr->uOpcode != OP_RDTSC) /* rdtsc requires emulation in ring 3 as well */
+ {
+ Log(("WARNING: refusing instruction emulation for user-mode code!!\n"));
+ STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,FailedUserMode));
+ return VERR_EM_INTERPRETER;
+ }
}
}
else
@@ -3836,10 +3903,10 @@ DECLINLINE(VBOXSTRICTRC) emInterpretInstructionCPU(PVM pVM, PVMCPU pVCpu, PDISCP
#ifdef IN_RC
INTERPRET_CASE(OP_STI,Sti);
INTERPRET_CASE(OP_XADD, XAdd);
+ INTERPRET_CASE(OP_IRET,Iret);
#endif
INTERPRET_CASE(OP_CMPXCHG8B, CmpXchg8b);
INTERPRET_CASE(OP_HLT,Hlt);
- INTERPRET_CASE(OP_IRET,Iret);
INTERPRET_CASE(OP_WBINVD,WbInvd);
#ifdef VBOX_WITH_STATISTICS
# ifndef IN_RC