summaryrefslogtreecommitdiff
path: root/src/recompiler/VBoxRecompiler.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/recompiler/VBoxRecompiler.c')
-rw-r--r--src/recompiler/VBoxRecompiler.c633
1 files changed, 438 insertions, 195 deletions
diff --git a/src/recompiler/VBoxRecompiler.c b/src/recompiler/VBoxRecompiler.c
index bfb87362c..6a9ca4e35 100644
--- a/src/recompiler/VBoxRecompiler.c
+++ b/src/recompiler/VBoxRecompiler.c
@@ -1,4 +1,4 @@
-/* $Id: VBoxRecompiler.c $ */
+/* $Id: VBoxRecompiler.c 37852 2011-07-08 19:18:05Z vboxsync $ */
/** @file
* VBox Recompiler - QEMU.
*/
@@ -20,11 +20,12 @@
* Header Files *
*******************************************************************************/
#define LOG_GROUP LOG_GROUP_REM
-#include "vl.h"
+#include <stdio.h> /* FILE */
#include "osdep.h"
-#include "exec-all.h"
#include "config.h"
-#include "cpu-all.h"
+#include "cpu.h"
+#include "exec-all.h"
+#include "ioport.h"
#include <VBox/vmm/rem.h>
#include <VBox/vmm/vmapi.h>
@@ -59,7 +60,7 @@ extern void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3);
extern void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0);
extern void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4);
extern void tlb_flush_page(CPUX86State *env, target_ulong addr);
-extern void tlb_flush(CPUState *env, int flush_global);
+extern void tlb_flush(CPUX86State *env, int flush_global);
extern void sync_seg(CPUX86State *env1, int seg_reg, int selector);
extern void sync_ldtr(CPUX86State *env1, int selector);
@@ -78,6 +79,9 @@ unsigned long get_phys_page_offset(target_ulong addr);
#define REM_COPY_FPU_REG(pDst, pSrc) \
do { *(PX86FPUMMX)(pDst) = *(const X86FPUMMX *)(pSrc); } while (0)
+/** How remR3RunLoggingStep operates. */
+#define REM_USE_QEMU_SINGLE_STEP_FOR_LOGGING
+
/*******************************************************************************
* Internal Functions *
@@ -188,7 +192,7 @@ CPUWriteMemoryFunc *g_apfnHandlerWrite[3] =
/*
* Debugger commands.
*/
-static DECLCALLBACK(int) remR3CmdDisasEnableStepping(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
+static DECLCALLBACK(int) remR3CmdDisasEnableStepping(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs);
/** '.remstep' arguments. */
static const DBGCVARDESC g_aArgRemStep[] =
@@ -206,7 +210,6 @@ static const DBGCCMD g_aCmds[] =
.cArgsMax = 1,
.paArgDescs = &g_aArgRemStep[0],
.cArgDescs = RT_ELEMENTS(g_aArgRemStep),
- .pResultDesc = NULL,
.fFlags = 0,
.pfnHandler = remR3CmdDisasEnableStepping,
.pszSyntax = "[on/off]",
@@ -216,7 +219,9 @@ static const DBGCCMD g_aCmds[] =
};
#endif
-/** Prologue code, must be in lower 4G to simplify jumps to/from generated code. */
+/** Prologue code, must be in lower 4G to simplify jumps to/from generated code.
+ * @todo huh??? That cannot be the case on the mac... So, this
+ * point is probably not valid any longer. */
uint8_t *code_gen_prologue;
@@ -307,12 +312,16 @@ REMR3DECL(int) REMR3Init(PVM pVM)
CPUMGetGuestCpuId(pVCpu, 1, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext_features, &pVM->rem.s.Env.cpuid_features);
CPUMGetGuestCpuId(pVCpu, 0x80000001, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext3_features, &pVM->rem.s.Env.cpuid_ext2_features);
+ EMRemLock(pVM);
+ cpu_reset(&pVM->rem.s.Env);
+ EMRemUnlock(pVM);
+
/* allocate code buffer for single instruction emulation. */
pVM->rem.s.Env.cbCodeBuffer = 4096;
pVM->rem.s.Env.pvCodeBuffer = RTMemExecAlloc(pVM->rem.s.Env.cbCodeBuffer);
AssertMsgReturn(pVM->rem.s.Env.pvCodeBuffer, ("Failed to allocate code buffer!\n"), VERR_NO_MEMORY);
- /* finally, set the cpu_single_env global. */
+ /* Finally, set the cpu_single_env global. */
cpu_single_env = &pVM->rem.s.Env;
/* Nothing is pending by default */
@@ -321,9 +330,9 @@ REMR3DECL(int) REMR3Init(PVM pVM)
/*
* Register ram types.
*/
- pVM->rem.s.iMMIOMemType = cpu_register_io_memory(-1, g_apfnMMIORead, g_apfnMMIOWrite, pVM);
+ pVM->rem.s.iMMIOMemType = cpu_register_io_memory(g_apfnMMIORead, g_apfnMMIOWrite, pVM);
AssertReleaseMsg(pVM->rem.s.iMMIOMemType >= 0, ("pVM->rem.s.iMMIOMemType=%d\n", pVM->rem.s.iMMIOMemType));
- pVM->rem.s.iHandlerMemType = cpu_register_io_memory(-1, g_apfnHandlerRead, g_apfnHandlerWrite, pVM);
+ pVM->rem.s.iHandlerMemType = cpu_register_io_memory(g_apfnHandlerRead, g_apfnHandlerWrite, pVM);
AssertReleaseMsg(pVM->rem.s.iHandlerMemType >= 0, ("pVM->rem.s.iHandlerMemType=%d\n", pVM->rem.s.iHandlerMemType));
Log2(("REM: iMMIOMemType=%d iHandlerMemType=%d\n", pVM->rem.s.iMMIOMemType, pVM->rem.s.iHandlerMemType));
@@ -405,6 +414,8 @@ REMR3DECL(int) REMR3Init(PVM pVM)
STAM_REG(pVM, &pVM->rem.s.Env.StatTbFlush, STAMTYPE_PROFILE, "/REM/TbFlush", STAMUNIT_TICKS_PER_CALL, "profiling tb_flush().");
#endif /* VBOX_WITH_STATISTICS */
+ AssertCompileMemberAlignment(CPUX86State, StatTbFlush, 4);
+ AssertCompileMemberAlignment(CPUX86State, StatTbFlush, 8);
STAM_REL_REG(pVM, &tb_flush_count, STAMTYPE_U32_RESET, "/REM/TbFlushCount", STAMUNIT_OCCURENCES, "tb_flush() calls");
STAM_REL_REG(pVM, &tb_phys_invalidate_count, STAMTYPE_U32_RESET, "/REM/TbPhysInvldCount", STAMUNIT_OCCURENCES, "tb_phys_invalidate() calls");
@@ -413,9 +424,6 @@ REMR3DECL(int) REMR3Init(PVM pVM)
#ifdef DEBUG_ALL_LOGGING
loglevel = ~0;
-# ifdef DEBUG_TMP_LOGGING
- logfile = fopen("/tmp/vbox-qemu.log", "w");
-# endif
#endif
/*
@@ -464,9 +472,8 @@ REMR3DECL(int) REMR3InitFinalize(PVM pVM)
return rc;
}
-
/**
- * Initializes phys_ram_size, phys_ram_dirty and phys_ram_dirty_size.
+ * Initializes ram_list.phys_dirty and ram_list.phys_dirty_size.
*
* @returns VBox status code.
* @param pVM The VM handle.
@@ -477,46 +484,48 @@ static int remR3InitPhysRamSizeAndDirtyMap(PVM pVM, bool fGuarded)
int rc = VINF_SUCCESS;
RTGCPHYS cb;
+ AssertLogRelReturn(QLIST_EMPTY(&ram_list.blocks), VERR_INTERNAL_ERROR_2);
+
cb = pVM->rem.s.GCPhysLastRam + 1;
AssertLogRelMsgReturn(cb > pVM->rem.s.GCPhysLastRam,
("GCPhysLastRam=%RGp - out of range\n", pVM->rem.s.GCPhysLastRam),
VERR_OUT_OF_RANGE);
- phys_ram_size = cb;
- phys_ram_dirty_size = cb >> PAGE_SHIFT;
- AssertMsg(((RTGCPHYS)phys_ram_dirty_size << PAGE_SHIFT) == cb, ("%RGp\n", cb));
+
+ ram_list.phys_dirty_size = cb >> PAGE_SHIFT;
+ AssertMsg(((RTGCPHYS)ram_list.phys_dirty_size << PAGE_SHIFT) == cb, ("%RGp\n", cb));
if (!fGuarded)
{
- phys_ram_dirty = MMR3HeapAlloc(pVM, MM_TAG_REM, phys_ram_dirty_size);
- AssertLogRelMsgReturn(phys_ram_dirty, ("Failed to allocate %u bytes of dirty page map bytes\n", phys_ram_dirty_size), VERR_NO_MEMORY);
+ ram_list.phys_dirty = MMR3HeapAlloc(pVM, MM_TAG_REM, ram_list.phys_dirty_size);
+ AssertLogRelMsgReturn(ram_list.phys_dirty, ("Failed to allocate %u bytes of dirty page map bytes\n", ram_list.phys_dirty_size), VERR_NO_MEMORY);
}
else
{
/*
* Fill it up the nearest 4GB RAM and leave at least _64KB of guard after it.
*/
- uint32_t cbBitmapAligned = RT_ALIGN_32(phys_ram_dirty_size, PAGE_SIZE);
- uint32_t cbBitmapFull = RT_ALIGN_32(phys_ram_dirty_size, (_4G >> PAGE_SHIFT));
+ uint32_t cbBitmapAligned = RT_ALIGN_32(ram_list.phys_dirty_size, PAGE_SIZE);
+ uint32_t cbBitmapFull = RT_ALIGN_32(ram_list.phys_dirty_size, (_4G >> PAGE_SHIFT));
if (cbBitmapFull == cbBitmapAligned)
cbBitmapFull += _4G >> PAGE_SHIFT;
else if (cbBitmapFull - cbBitmapAligned < _64K)
cbBitmapFull += _64K;
- phys_ram_dirty = RTMemPageAlloc(cbBitmapFull);
- AssertLogRelMsgReturn(phys_ram_dirty, ("Failed to allocate %u bytes of dirty page map bytes\n", cbBitmapFull), VERR_NO_MEMORY);
+ ram_list.phys_dirty = RTMemPageAlloc(cbBitmapFull);
+ AssertLogRelMsgReturn(ram_list.phys_dirty, ("Failed to allocate %u bytes of dirty page map bytes\n", cbBitmapFull), VERR_NO_MEMORY);
- rc = RTMemProtect(phys_ram_dirty + cbBitmapAligned, cbBitmapFull - cbBitmapAligned, RTMEM_PROT_NONE);
+ rc = RTMemProtect(ram_list.phys_dirty + cbBitmapAligned, cbBitmapFull - cbBitmapAligned, RTMEM_PROT_NONE);
if (RT_FAILURE(rc))
{
- RTMemPageFree(phys_ram_dirty, cbBitmapFull);
+ RTMemPageFree(ram_list.phys_dirty, cbBitmapFull);
AssertLogRelRCReturn(rc, rc);
}
- phys_ram_dirty += cbBitmapAligned - phys_ram_dirty_size;
+ ram_list.phys_dirty += cbBitmapAligned - ram_list.phys_dirty_size;
}
/* initialize it. */
- memset(phys_ram_dirty, 0xff, phys_ram_dirty_size);
+ memset(ram_list.phys_dirty, 0xff, ram_list.phys_dirty_size);
return rc;
}
@@ -603,6 +612,8 @@ REMR3DECL(int) REMR3Term(PVM pVM)
*/
REMR3DECL(void) REMR3Reset(PVM pVM)
{
+ EMRemLock(pVM); /* Only pro forma, we're in a rendezvous. */
+
/*
* Reset the REM cpu.
*/
@@ -618,6 +629,8 @@ REMR3DECL(void) REMR3Reset(PVM pVM)
/* Flush the TBs the next time we execute code here. */
pVM->rem.s.fFlushTBs = true;
+
+ EMRemUnlock(pVM);
}
@@ -760,11 +773,6 @@ static DECLCALLBACK(int) remR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion,
CPUMGetGuestCpuId(pVCpu, 0x80000001, &u32Dummy, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext2_features);
/*
- * Sync the Load Flush the TLB
- */
- tlb_flush(&pRem->Env, 1);
-
- /*
* Stop ignoring ignorable notifications.
*/
ASMAtomicDecU32(&pVM->rem.s.cIgnoreAll);
@@ -810,7 +818,7 @@ REMR3DECL(int) REMR3Step(PVM pVM, PVMCPU pVCpu)
* pending interrupts and suchlike.
*/
interrupt_request = pVM->rem.s.Env.interrupt_request;
- Assert(!(interrupt_request & ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXIT | CPU_INTERRUPT_EXITTB | CPU_INTERRUPT_TIMER | CPU_INTERRUPT_EXTERNAL_HARD | CPU_INTERRUPT_EXTERNAL_EXIT | CPU_INTERRUPT_EXTERNAL_TIMER)));
+ Assert(!(interrupt_request & ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB | CPU_INTERRUPT_TIMER | CPU_INTERRUPT_EXTERNAL_HARD | CPU_INTERRUPT_EXTERNAL_EXIT | CPU_INTERRUPT_EXTERNAL_FLUSH_TLB | CPU_INTERRUPT_EXTERNAL_TIMER)));
pVM->rem.s.Env.interrupt_request = 0;
cpu_single_step(&pVM->rem.s.Env, 1);
@@ -818,7 +826,7 @@ REMR3DECL(int) REMR3Step(PVM pVM, PVMCPU pVCpu)
* If we're standing at a breakpoint, that have to be disabled before we start stepping.
*/
GCPtrPC = pVM->rem.s.Env.eip + pVM->rem.s.Env.segs[R_CS].base;
- fBp = !cpu_breakpoint_remove(&pVM->rem.s.Env, GCPtrPC);
+ fBp = !cpu_breakpoint_remove(&pVM->rem.s.Env, GCPtrPC, BP_GDB);
/*
* Execute and handle the return code.
@@ -861,7 +869,7 @@ REMR3DECL(int) REMR3Step(PVM pVM, PVMCPU pVCpu)
*/
if (fBp)
{
- int rc2 = cpu_breakpoint_insert(&pVM->rem.s.Env, GCPtrPC);
+ int rc2 = cpu_breakpoint_insert(&pVM->rem.s.Env, GCPtrPC, BP_GDB, NULL);
Assert(rc2 == 0); NOREF(rc2);
}
cpu_single_step(&pVM->rem.s.Env, 0);
@@ -882,7 +890,7 @@ REMR3DECL(int) REMR3Step(PVM pVM, PVMCPU pVCpu)
REMR3DECL(int) REMR3BreakpointSet(PVM pVM, RTGCUINTPTR Address)
{
VM_ASSERT_EMT(pVM);
- if (!cpu_breakpoint_insert(&pVM->rem.s.Env, Address))
+ if (!cpu_breakpoint_insert(&pVM->rem.s.Env, Address, BP_GDB, NULL))
{
LogFlow(("REMR3BreakpointSet: Address=%RGv\n", Address));
return VINF_SUCCESS;
@@ -903,7 +911,7 @@ REMR3DECL(int) REMR3BreakpointSet(PVM pVM, RTGCUINTPTR Address)
REMR3DECL(int) REMR3BreakpointClear(PVM pVM, RTGCUINTPTR Address)
{
VM_ASSERT_EMT(pVM);
- if (!cpu_breakpoint_remove(&pVM->rem.s.Env, Address))
+ if (!cpu_breakpoint_remove(&pVM->rem.s.Env, Address, BP_GDB))
{
LogFlow(("REMR3BreakpointClear: Address=%RGv\n", Address));
return VINF_SUCCESS;
@@ -950,8 +958,12 @@ REMR3DECL(int) REMR3EmulateInstruction(PVM pVM, PVMCPU pVCpu)
if (RT_SUCCESS(rc))
{
int interrupt_request = pVM->rem.s.Env.interrupt_request;
- Assert(!(interrupt_request & ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXIT | CPU_INTERRUPT_EXITTB | CPU_INTERRUPT_TIMER | CPU_INTERRUPT_EXTERNAL_HARD | CPU_INTERRUPT_EXTERNAL_EXIT | CPU_INTERRUPT_EXTERNAL_TIMER)));
+ Assert(!(interrupt_request & ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB | CPU_INTERRUPT_TIMER | CPU_INTERRUPT_EXTERNAL_HARD | CPU_INTERRUPT_EXTERNAL_EXIT | CPU_INTERRUPT_EXTERNAL_FLUSH_TLB | CPU_INTERRUPT_EXTERNAL_TIMER)));
+#ifdef REM_USE_QEMU_SINGLE_STEP_FOR_LOGGING
+ cpu_single_step(&pVM->rem.s.Env, 0);
+#endif
Assert(!pVM->rem.s.Env.singlestep_enabled);
+
/*
* Now we set the execute single instruction flag and enter the cpu_exec loop.
*/
@@ -983,20 +995,23 @@ REMR3DECL(int) REMR3EmulateInstruction(PVM pVM, PVMCPU pVCpu)
* If there was a breakpoint there we're fucked now.
*/
case EXCP_DEBUG:
- {
- /* breakpoint or single step? */
- RTGCPTR GCPtrPC = pVM->rem.s.Env.eip + pVM->rem.s.Env.segs[R_CS].base;
- int iBP;
- rc = VINF_EM_DBG_STEPPED;
- for (iBP = 0; iBP < pVM->rem.s.Env.nb_breakpoints; iBP++)
- if (pVM->rem.s.Env.breakpoints[iBP] == GCPtrPC)
- {
- rc = VINF_EM_DBG_BREAKPOINT;
- break;
- }
- Log2(("REMR3EmulateInstruction: cpu_exec -> EXCP_DEBUG rc=%Rrc iBP=%d GCPtrPC=%RGv\n", rc, iBP, GCPtrPC));
+ if (pVM->rem.s.Env.watchpoint_hit)
+ {
+ /** @todo deal with watchpoints */
+ Log2(("REMR3EmulateInstruction: cpu_exec -> EXCP_DEBUG rc=%Rrc !watchpoint_hit!\n", rc));
+ rc = VINF_EM_DBG_BREAKPOINT;
+ }
+ else
+ {
+ CPUBreakpoint *pBP;
+ RTGCPTR GCPtrPC = pVM->rem.s.Env.eip + pVM->rem.s.Env.segs[R_CS].base;
+ QTAILQ_FOREACH(pBP, &pVM->rem.s.Env.breakpoints, entry)
+ if (pBP->pc == GCPtrPC)
+ break;
+ rc = pBP ? VINF_EM_DBG_BREAKPOINT : VINF_EM_DBG_STEPPED;
+ Log2(("REMR3EmulateInstruction: cpu_exec -> EXCP_DEBUG rc=%Rrc pBP=%p GCPtrPC=%RGv\n", rc, pBP, GCPtrPC));
+ }
break;
- }
/*
* hlt instruction.
@@ -1064,6 +1079,207 @@ REMR3DECL(int) REMR3EmulateInstruction(PVM pVM, PVMCPU pVCpu)
/**
+ * Used by REMR3Run to handle the case where CPU_EMULATE_SINGLE_STEP is set.
+ *
+ * @returns VBox status code.
+ *
+ * @param pVM The VM handle.
+ * @param pVCpu The Virtual CPU handle.
+ */
+static int remR3RunLoggingStep(PVM pVM, PVMCPU pVCpu)
+{
+ int rc;
+
+ Assert(pVM->rem.s.fInREM);
+#ifdef REM_USE_QEMU_SINGLE_STEP_FOR_LOGGING
+ cpu_single_step(&pVM->rem.s.Env, 1);
+#else
+ Assert(!pVM->rem.s.Env.singlestep_enabled);
+#endif
+
+ /*
+ * Now we set the execute single instruction flag and enter the cpu_exec loop.
+ */
+ for (;;)
+ {
+ char szBuf[256];
+
+ /*
+ * Log the current registers state and instruction.
+ */
+ remR3StateUpdate(pVM, pVCpu);
+ DBGFR3Info(pVM, "cpumguest", NULL, NULL);
+ szBuf[0] = '\0';
+ rc = DBGFR3DisasInstrEx(pVM,
+ pVCpu->idCpu,
+ 0, /* Sel */
+ 0, /* GCPtr */
+ DBGF_DISAS_FLAGS_CURRENT_GUEST
+ | DBGF_DISAS_FLAGS_DEFAULT_MODE
+ | DBGF_DISAS_FLAGS_HID_SEL_REGS_VALID,
+ szBuf,
+ sizeof(szBuf),
+ NULL);
+ if (RT_FAILURE(rc))
+ RTStrPrintf(szBuf, sizeof(szBuf), "DBGFR3DisasInstrEx failed with rc=%Rrc\n", rc);
+ RTLogPrintf("CPU%d: %s\n", pVCpu->idCpu, szBuf);
+
+ /*
+ * Execute the instruction.
+ */
+ TMNotifyStartOfExecution(pVCpu);
+
+ if ( pVM->rem.s.Env.exception_index < 0
+ || pVM->rem.s.Env.exception_index > 256)
+ pVM->rem.s.Env.exception_index = -1; /** @todo We need to do similar stuff elsewhere, I think. */
+
+#ifdef REM_USE_QEMU_SINGLE_STEP_FOR_LOGGING
+ pVM->rem.s.Env.interrupt_request = 0;
+#else
+ pVM->rem.s.Env.interrupt_request = CPU_INTERRUPT_SINGLE_INSTR;
+#endif
+ if ( VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
+ || pVM->rem.s.u32PendingInterrupt != REM_NO_PENDING_IRQ)
+ pVM->rem.s.Env.interrupt_request |= CPU_INTERRUPT_HARD;
+ RTLogPrintf("remR3RunLoggingStep: interrupt_request=%#x halted=%d exception_index=%#x\n", rc,
+ pVM->rem.s.Env.interrupt_request,
+ pVM->rem.s.Env.halted,
+ pVM->rem.s.Env.exception_index
+ );
+
+ rc = cpu_exec(&pVM->rem.s.Env);
+
+ RTLogPrintf("remR3RunLoggingStep: cpu_exec -> %#x interrupt_request=%#x halted=%d exception_index=%#x\n", rc,
+ pVM->rem.s.Env.interrupt_request,
+ pVM->rem.s.Env.halted,
+ pVM->rem.s.Env.exception_index
+ );
+
+ TMNotifyEndOfExecution(pVCpu);
+
+ switch (rc)
+ {
+#ifndef REM_USE_QEMU_SINGLE_STEP_FOR_LOGGING
+ /*
+ * The normal exit.
+ */
+ case EXCP_SINGLE_INSTR:
+ if ( !VM_FF_ISPENDING(pVM, VM_FF_ALL_REM_MASK)
+ && !VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_ALL_REM_MASK))
+ continue;
+ RTLogPrintf("remR3RunLoggingStep: rc=VINF_SUCCESS w/ FFs (%#x/%#x)\n",
+ pVM->fGlobalForcedActions, pVCpu->fLocalForcedActions);
+ rc = VINF_SUCCESS;
+ break;
+
+#else
+ /*
+ * The normal exit, check for breakpoints at PC just to be sure.
+ */
+#endif
+ case EXCP_DEBUG:
+ if (pVM->rem.s.Env.watchpoint_hit)
+ {
+ /** @todo deal with watchpoints */
+ Log2(("remR3RunLoggingStep: cpu_exec -> EXCP_DEBUG rc=%Rrc !watchpoint_hit!\n", rc));
+ rc = VINF_EM_DBG_BREAKPOINT;
+ }
+ else
+ {
+ CPUBreakpoint *pBP;
+ RTGCPTR GCPtrPC = pVM->rem.s.Env.eip + pVM->rem.s.Env.segs[R_CS].base;
+ QTAILQ_FOREACH(pBP, &pVM->rem.s.Env.breakpoints, entry)
+ if (pBP->pc == GCPtrPC)
+ break;
+ rc = pBP ? VINF_EM_DBG_BREAKPOINT : VINF_EM_DBG_STEPPED;
+ Log2(("remR3RunLoggingStep: cpu_exec -> EXCP_DEBUG rc=%Rrc pBP=%p GCPtrPC=%RGv\n", rc, pBP, GCPtrPC));
+ }
+#ifdef REM_USE_QEMU_SINGLE_STEP_FOR_LOGGING
+ if (rc == VINF_EM_DBG_STEPPED)
+ {
+ if ( !VM_FF_ISPENDING(pVM, VM_FF_ALL_REM_MASK)
+ && !VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_ALL_REM_MASK))
+ continue;
+
+ RTLogPrintf("remR3RunLoggingStep: rc=VINF_SUCCESS w/ FFs (%#x/%#x)\n",
+ pVM->fGlobalForcedActions, pVCpu->fLocalForcedActions);
+ rc = VINF_SUCCESS;
+ }
+#endif
+ break;
+
+ /*
+ * If we take a trap or start servicing a pending interrupt, we might end up here.
+ * (Timer thread or some other thread wishing EMT's attention.)
+ */
+ case EXCP_INTERRUPT:
+ RTLogPrintf("remR3RunLoggingStep: cpu_exec -> EXCP_INTERRUPT rc=VINF_SUCCESS\n");
+ rc = VINF_SUCCESS;
+ break;
+
+ /*
+ * hlt instruction.
+ */
+ case EXCP_HLT:
+ RTLogPrintf("remR3RunLoggingStep: cpu_exec -> EXCP_HLT rc=VINF_EM_HALT\n");
+ rc = VINF_EM_HALT;
+ break;
+
+ /*
+ * The VM has halted.
+ */
+ case EXCP_HALTED:
+ RTLogPrintf("remR3RunLoggingStep: cpu_exec -> EXCP_HALTED rc=VINF_EM_HALT\n");
+ rc = VINF_EM_HALT;
+ break;
+
+ /*
+ * Switch to RAW-mode.
+ */
+ case EXCP_EXECUTE_RAW:
+ RTLogPrintf("remR3RunLoggingStep: cpu_exec -> EXCP_EXECUTE_RAW rc=VINF_EM_RESCHEDULE_RAW\n");
+ rc = VINF_EM_RESCHEDULE_RAW;
+ break;
+
+ /*
+ * Switch to hardware accelerated RAW-mode.
+ */
+ case EXCP_EXECUTE_HWACC:
+ RTLogPrintf("remR3RunLoggingStep: cpu_exec -> EXCP_EXECUTE_HWACC rc=VINF_EM_RESCHEDULE_HWACC\n");
+ rc = VINF_EM_RESCHEDULE_HWACC;
+ break;
+
+ /*
+ * An EM RC was raised (VMR3Reset/Suspend/PowerOff/some-fatal-error).
+ */
+ case EXCP_RC:
+ RTLogPrintf("remR3RunLoggingStep: cpu_exec -> EXCP_RC rc=%Rrc\n", pVM->rem.s.rc);
+ rc = pVM->rem.s.rc;
+ pVM->rem.s.rc = VERR_INTERNAL_ERROR;
+ break;
+
+ /*
+ * Figure out the rest when they arrive....
+ */
+ default:
+ AssertMsgFailed(("rc=%d\n", rc));
+ RTLogPrintf("remR3RunLoggingStep: cpu_exec -> %d rc=VINF_EM_RESCHEDULE\n", rc);
+ rc = VINF_EM_RESCHEDULE;
+ break;
+ }
+ break;
+ }
+
+#ifdef REM_USE_QEMU_SINGLE_STEP_FOR_LOGGING
+// cpu_single_step(&pVM->rem.s.Env, 0);
+#else
+ pVM->rem.s.Env.interrupt_request &= ~(CPU_INTERRUPT_SINGLE_INSTR | CPU_INTERRUPT_SINGLE_INSTR_IN_FLIGHT);
+#endif
+ return rc;
+}
+
+
+/**
* Runs code in recompiled mode.
*
* Before calling this function the REM state needs to be in sync with
@@ -1079,8 +1295,12 @@ REMR3DECL(int) REMR3EmulateInstruction(PVM pVM, PVMCPU pVCpu)
REMR3DECL(int) REMR3Run(PVM pVM, PVMCPU pVCpu)
{
int rc;
- Log2(("REMR3Run: (cs:eip=%04x:%RGv)\n", pVM->rem.s.Env.segs[R_CS].selector, (RTGCPTR)pVM->rem.s.Env.eip));
+
+ if (RT_UNLIKELY(pVM->rem.s.Env.state & CPU_EMULATE_SINGLE_STEP))
+ return remR3RunLoggingStep(pVM, pVCpu);
+
Assert(pVM->rem.s.fInREM);
+ Log2(("REMR3Run: (cs:eip=%04x:%RGv)\n", pVM->rem.s.Env.segs[R_CS].selector, (RTGCPTR)pVM->rem.s.Env.eip));
TMNotifyStartOfExecution(pVCpu);
rc = cpu_exec(&pVM->rem.s.Env);
@@ -1116,41 +1336,23 @@ REMR3DECL(int) REMR3Run(PVM pVM, PVMCPU pVCpu)
* Breakpoint/single step.
*/
case EXCP_DEBUG:
- {
-#if 0//def DEBUG_bird
- static int iBP = 0;
- printf("howdy, breakpoint! iBP=%d\n", iBP);
- switch (iBP)
+ if (pVM->rem.s.Env.watchpoint_hit)
{
- case 0:
- cpu_breakpoint_remove(&pVM->rem.s.Env, pVM->rem.s.Env.eip + pVM->rem.s.Env.segs[R_CS].base);
- pVM->rem.s.Env.state |= CPU_EMULATE_SINGLE_STEP;
- //pVM->rem.s.Env.interrupt_request = 0;
- //pVM->rem.s.Env.exception_index = -1;
- //g_fInterruptDisabled = 1;
- rc = VINF_SUCCESS;
- asm("int3");
- break;
- default:
- asm("int3");
- break;
+ /** @todo deal with watchpoints */
+ Log2(("REMR3Run: cpu_exec -> EXCP_DEBUG rc=%Rrc !watchpoint_hit!\n", rc));
+ rc = VINF_EM_DBG_BREAKPOINT;
+ }
+ else
+ {
+ CPUBreakpoint *pBP;
+ RTGCPTR GCPtrPC = pVM->rem.s.Env.eip + pVM->rem.s.Env.segs[R_CS].base;
+ QTAILQ_FOREACH(pBP, &pVM->rem.s.Env.breakpoints, entry)
+ if (pBP->pc == GCPtrPC)
+ break;
+ rc = pBP ? VINF_EM_DBG_BREAKPOINT : VINF_EM_DBG_STEPPED;
+ Log2(("REMR3Run: cpu_exec -> EXCP_DEBUG rc=%Rrc pBP=%p GCPtrPC=%RGv\n", rc, pBP, GCPtrPC));
}
- iBP++;
-#else
- /* breakpoint or single step? */
- RTGCPTR GCPtrPC = pVM->rem.s.Env.eip + pVM->rem.s.Env.segs[R_CS].base;
- int iBP;
- rc = VINF_EM_DBG_STEPPED;
- for (iBP = 0; iBP < pVM->rem.s.Env.nb_breakpoints; iBP++)
- if (pVM->rem.s.Env.breakpoints[iBP] == GCPtrPC)
- {
- rc = VINF_EM_DBG_BREAKPOINT;
- break;
- }
- Log2(("REMR3Run: cpu_exec -> EXCP_DEBUG rc=%Rrc iBP=%d GCPtrPC=%RGv\n", rc, iBP, GCPtrPC));
-#endif
break;
- }
/*
* Switch to RAW-mode.
@@ -1195,7 +1397,8 @@ REMR3DECL(int) REMR3Run(PVM pVM, PVMCPU pVCpu)
/**
* Check if the cpu state is suitable for Raw execution.
*
- * @returns boolean
+ * @returns true if RAW/HWACC mode is ok, false if we should stay in REM.
+ *
* @param env The CPU env struct.
* @param eip The EIP to check this for (might differ from env->eip).
* @param fFlags hflags OR'ed with IOPL, TF and VM from eflags.
@@ -1203,16 +1406,24 @@ REMR3DECL(int) REMR3Run(PVM pVM, PVMCPU pVCpu)
*
* @remark This function must be kept in perfect sync with the scheduler in EM.cpp!
*/
-bool remR3CanExecuteRaw(CPUState *env, RTGCPTR eip, unsigned fFlags, int *piException)
+bool remR3CanExecuteRaw(CPUX86State *env, RTGCPTR eip, unsigned fFlags, int *piException)
{
/* !!! THIS MUST BE IN SYNC WITH emR3Reschedule !!! */
/* !!! THIS MUST BE IN SYNC WITH emR3Reschedule !!! */
/* !!! THIS MUST BE IN SYNC WITH emR3Reschedule !!! */
uint32_t u32CR0;
+#ifdef IEM_VERIFICATION_MODE
+ return false;
+#endif
+
/* Update counter. */
env->pVM->rem.s.cCanExecuteRaw++;
+ /* Never when single stepping+logging guest code. */
+ if (env->state & CPU_EMULATE_SINGLE_STEP)
+ return false;
+
if (HWACCMIsEnabled(env->pVM))
{
CPUMCTX Ctx;
@@ -1326,12 +1537,18 @@ bool remR3CanExecuteRaw(CPUState *env, RTGCPTR eip, unsigned fFlags, int *piExce
return false;
}
- if (env->nb_breakpoints > 0)
+ if (!QTAILQ_EMPTY(&env->breakpoints))
{
//Log2(("raw mode refused: Breakpoints\n"));
return false;
}
+ if (!QTAILQ_EMPTY(&env->watchpoints))
+ {
+ //Log2(("raw mode refused: Watchpoints\n"));
+ return false;
+ }
+
u32CR0 = env->cr[0];
if ((u32CR0 & (X86_CR0_PG | X86_CR0_PE)) != (X86_CR0_PG | X86_CR0_PE))
{
@@ -1441,7 +1658,7 @@ bool remR3CanExecuteRaw(CPUState *env, RTGCPTR eip, unsigned fFlags, int *piExce
* @param GCPtrInstr Where to fetch code.
* @param pu8Byte Where to store the byte on success
*/
-bool remR3GetOpcode(CPUState *env, RTGCPTR GCPtrInstr, uint8_t *pu8Byte)
+bool remR3GetOpcode(CPUX86State *env, RTGCPTR GCPtrInstr, uint8_t *pu8Byte)
{
int rc = PATMR3QueryOpcode(env->pVM, GCPtrInstr, pu8Byte);
if (RT_SUCCESS(rc))
@@ -1458,12 +1675,14 @@ bool remR3GetOpcode(CPUState *env, RTGCPTR GCPtrInstr, uint8_t *pu8Byte)
* @param env Pointer to cpu environment.
* @param GCPtr The virtual address which page table/dir entry should be invalidated.
*/
-void remR3FlushPage(CPUState *env, RTGCPTR GCPtr)
+void remR3FlushPage(CPUX86State *env, RTGCPTR GCPtr)
{
PVM pVM = env->pVM;
PCPUMCTX pCtx;
int rc;
+ Assert(EMRemIsLockOwner(env->pVM));
+
/*
* When we're replaying invlpg instructions or restoring a saved
* state we disable this path.
@@ -1502,7 +1721,7 @@ void remR3FlushPage(CPUState *env, RTGCPTR GCPtr)
#ifndef REM_PHYS_ADDR_IN_TLB
/** Wrapper for PGMR3PhysTlbGCPhys2Ptr. */
-void *remR3TlbGCPhys2Ptr(CPUState *env1, target_ulong physAddr, int fWritable)
+void *remR3TlbGCPhys2Ptr(CPUX86State *env1, target_ulong physAddr, int fWritable)
{
void *pv;
int rc;
@@ -1530,7 +1749,7 @@ void *remR3TlbGCPhys2Ptr(CPUState *env1, target_ulong physAddr, int fWritable)
* @param env Pointer to the CPU environment.
* @param GCPtr Code page to monitor
*/
-void remR3ProtectCode(CPUState *env, RTGCPTR GCPtr)
+void remR3ProtectCode(CPUX86State *env, RTGCPTR GCPtr)
{
#ifdef VBOX_REM_PROTECT_PAGES_FROM_SMC
Assert(env->pVM->rem.s.fInREM);
@@ -1550,7 +1769,7 @@ void remR3ProtectCode(CPUState *env, RTGCPTR GCPtr)
* @param env Pointer to the CPU environment.
* @param GCPtr Code page to monitor
*/
-void remR3UnprotectCode(CPUState *env, RTGCPTR GCPtr)
+void remR3UnprotectCode(CPUX86State *env, RTGCPTR GCPtr)
{
Assert(env->pVM->rem.s.fInREM);
#ifdef VBOX_REM_PROTECT_PAGES_FROM_SMC
@@ -1571,10 +1790,11 @@ void remR3UnprotectCode(CPUState *env, RTGCPTR GCPtr)
* @param env Pointer to the CPU environment.
* @param fGlobal Set if the flush is global.
*/
-void remR3FlushTLB(CPUState *env, bool fGlobal)
+void remR3FlushTLB(CPUX86State *env, bool fGlobal)
{
- PVM pVM = env->pVM;
+ PVM pVM = env->pVM;
PCPUMCTX pCtx;
+ Assert(EMRemIsLockOwner(pVM));
/*
* When we're replaying invlpg instructions or restoring a saved
@@ -1615,7 +1835,7 @@ void remR3FlushTLB(CPUState *env, bool fGlobal)
*
* @param env Pointer to the CPU environment.
*/
-void remR3ChangeCpuMode(CPUState *env)
+void remR3ChangeCpuMode(CPUX86State *env)
{
PVM pVM = env->pVM;
uint64_t efer;
@@ -1667,7 +1887,7 @@ void remR3ChangeCpuMode(CPUState *env)
*
* @param env Pointer to the CPU environment.
*/
-void remR3DmaRun(CPUState *env)
+void remR3DmaRun(CPUX86State *env)
{
remR3ProfileStop(STATS_QEMU_RUN_EMULATED_CODE);
PDMR3DmaRun(env->pVM);
@@ -1680,7 +1900,7 @@ void remR3DmaRun(CPUState *env)
*
* @param env Pointer to the CPU environment.
*/
-void remR3TimersRun(CPUState *env)
+void remR3TimersRun(CPUX86State *env)
{
LogFlow(("remR3TimersRun:\n"));
LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_5, LOG_GROUP_TM, ("remR3TimersRun\n"));
@@ -1701,7 +1921,7 @@ void remR3TimersRun(CPUState *env)
* @param uErrorCode Error code
* @param pvNextEIP Next EIP
*/
-int remR3NotifyTrap(CPUState *env, uint32_t uTrap, uint32_t uErrorCode, RTGCPTR pvNextEIP)
+int remR3NotifyTrap(CPUX86State *env, uint32_t uTrap, uint32_t uErrorCode, RTGCPTR pvNextEIP)
{
PVM pVM = env->pVM;
#ifdef VBOX_WITH_STATISTICS
@@ -1772,7 +1992,7 @@ void remR3TrapClear(PVM pVM)
*
* @param env Pointer to the CPU environment.
*/
-void remR3RecordCall(CPUState *env)
+void remR3RecordCall(CPUX86State *env)
{
CSAMR3RecordCallAddress(env->pVM, env->eip);
}
@@ -1886,26 +2106,35 @@ REMR3DECL(int) REMR3State(PVM pVM, PVMCPU pVCpu)
for (i=0;i<8;i++)
pVM->rem.s.Env.dr[i] = pCtx->dr[i];
+#ifdef HF_HALTED_MASK /** @todo remove me when we're up to date again. */
/*
* Clear the halted hidden flag (the interrupt waking up the CPU can
* have been dispatched in raw mode).
*/
pVM->rem.s.Env.hflags &= ~HF_HALTED_MASK;
+#endif
/*
- * Replay invlpg?
+ * Replay invlpg? Only if we're not flushing the TLB.
*/
+ fFlags = CPUMR3RemEnter(pVCpu, &uCpl);
+ LogFlow(("CPUMR3RemEnter %x %x\n", fFlags, uCpl));
if (pVM->rem.s.cInvalidatedPages)
{
- RTUINT i;
-
- pVM->rem.s.fIgnoreInvlPg = true;
- for (i = 0; i < pVM->rem.s.cInvalidatedPages; i++)
+ if (!(fFlags & CPUM_CHANGED_GLOBAL_TLB_FLUSH))
{
- Log2(("REMR3State: invlpg %RGv\n", pVM->rem.s.aGCPtrInvalidatedPages[i]));
- tlb_flush_page(&pVM->rem.s.Env, pVM->rem.s.aGCPtrInvalidatedPages[i]);
+ RTUINT i;
+
+ pVM->rem.s.fIgnoreCR3Load = true;
+ pVM->rem.s.fIgnoreInvlPg = true;
+ for (i = 0; i < pVM->rem.s.cInvalidatedPages; i++)
+ {
+ Log2(("REMR3State: invlpg %RGv\n", pVM->rem.s.aGCPtrInvalidatedPages[i]));
+ tlb_flush_page(&pVM->rem.s.Env, pVM->rem.s.aGCPtrInvalidatedPages[i]);
+ }
+ pVM->rem.s.fIgnoreInvlPg = false;
+ pVM->rem.s.fIgnoreCR3Load = false;
}
- pVM->rem.s.fIgnoreInvlPg = false;
pVM->rem.s.cInvalidatedPages = 0;
}
@@ -1932,8 +2161,6 @@ REMR3DECL(int) REMR3State(PVM pVM, PVMCPU pVCpu)
/*
* Registers which are rarely changed and require special handling / order when changed.
*/
- fFlags = CPUMR3RemEnter(pVCpu, &uCpl);
- LogFlow(("CPUMR3RemEnter %x %x\n", fFlags, uCpl));
if (fFlags & ( CPUM_CHANGED_GLOBAL_TLB_FLUSH
| CPUM_CHANGED_CR4
| CPUM_CHANGED_CR0
@@ -2201,20 +2428,25 @@ REMR3DECL(int) REMR3State(PVM pVM, PVMCPU pVCpu)
}
/* get error code and cr2 if needed. */
- switch (u8TrapNo)
+ if (enmType == TRPM_TRAP)
{
- case 0x0e:
- pVM->rem.s.Env.cr[2] = TRPMGetFaultAddress(pVCpu);
- /* fallthru */
- case 0x0a: case 0x0b: case 0x0c: case 0x0d:
- pVM->rem.s.Env.error_code = TRPMGetErrorCode(pVCpu);
- break;
+ switch (u8TrapNo)
+ {
+ case 0x0e:
+ pVM->rem.s.Env.cr[2] = TRPMGetFaultAddress(pVCpu);
+ /* fallthru */
+ case 0x0a: case 0x0b: case 0x0c: case 0x0d:
+ pVM->rem.s.Env.error_code = TRPMGetErrorCode(pVCpu);
+ break;
- case 0x11: case 0x08:
- default:
- pVM->rem.s.Env.error_code = 0;
- break;
+ case 0x11: case 0x08:
+ default:
+ pVM->rem.s.Env.error_code = 0;
+ break;
+ }
}
+ else
+ pVM->rem.s.Env.error_code = 0;
/*
* We can now reset the active trap since the recompiler is gonna have a go at it.
@@ -2229,7 +2461,7 @@ REMR3DECL(int) REMR3State(PVM pVM, PVMCPU pVCpu)
* Clear old interrupt request flags; Check for pending hardware interrupts.
* (See @remark for why we don't check for other FFs.)
*/
- pVM->rem.s.Env.interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXIT | CPU_INTERRUPT_EXITTB | CPU_INTERRUPT_TIMER);
+ pVM->rem.s.Env.interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB | CPU_INTERRUPT_TIMER);
if ( pVM->rem.s.u32PendingInterrupt != REM_NO_PENDING_IRQ
|| VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC))
pVM->rem.s.Env.interrupt_request |= CPU_INTERRUPT_HARD;
@@ -2937,7 +3169,7 @@ REMR3DECL(void) REMR3NotifyPhysRamRegister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb
ASMAtomicIncU32(&pVM->rem.s.cIgnoreAll);
PDMCritSectEnter(&pVM->rem.s.CritSectRegister, VERR_SEM_BUSY);
- cpu_register_physical_memory(GCPhys, cb, GCPhys);
+ cpu_register_physical_memory_offset(GCPhys, cb, GCPhys, GCPhys);
PDMCritSectLeave(&pVM->rem.s.CritSectRegister);
ASMAtomicDecU32(&pVM->rem.s.cIgnoreAll);
@@ -2973,7 +3205,7 @@ REMR3DECL(void) REMR3NotifyPhysRomRegister(PVM pVM, RTGCPHYS GCPhys, RTUINT cb,
ASMAtomicIncU32(&pVM->rem.s.cIgnoreAll);
PDMCritSectEnter(&pVM->rem.s.CritSectRegister, VERR_SEM_BUSY);
- cpu_register_physical_memory(GCPhys, cb, GCPhys | (fShadow ? 0 : IO_MEM_ROM));
+ cpu_register_physical_memory_offset(GCPhys, cb, GCPhys | (fShadow ? 0 : IO_MEM_ROM), GCPhys);
PDMCritSectLeave(&pVM->rem.s.CritSectRegister);
ASMAtomicDecU32(&pVM->rem.s.cIgnoreAll);
@@ -3005,7 +3237,7 @@ REMR3DECL(void) REMR3NotifyPhysRamDeregister(PVM pVM, RTGCPHYS GCPhys, RTUINT cb
ASMAtomicIncU32(&pVM->rem.s.cIgnoreAll);
PDMCritSectEnter(&pVM->rem.s.CritSectRegister, VERR_SEM_BUSY);
- cpu_register_physical_memory(GCPhys, cb, IO_MEM_UNASSIGNED);
+ cpu_register_physical_memory_offset(GCPhys, cb, IO_MEM_UNASSIGNED, GCPhys);
PDMCritSectLeave(&pVM->rem.s.CritSectRegister);
ASMAtomicDecU32(&pVM->rem.s.cIgnoreAll);
@@ -3038,9 +3270,9 @@ static void remR3NotifyHandlerPhysicalRegister(PVM pVM, PGMPHYSHANDLERTYPE enmTy
PDMCritSectEnter(&pVM->rem.s.CritSectRegister, VERR_SEM_BUSY);
if (enmType == PGMPHYSHANDLERTYPE_MMIO)
- cpu_register_physical_memory(GCPhys, cb, pVM->rem.s.iMMIOMemType);
+ cpu_register_physical_memory_offset(GCPhys, cb, pVM->rem.s.iMMIOMemType, GCPhys);
else if (fHasHCHandler)
- cpu_register_physical_memory(GCPhys, cb, pVM->rem.s.iHandlerMemType);
+ cpu_register_physical_memory_offset(GCPhys, cb, pVM->rem.s.iHandlerMemType, GCPhys);
PDMCritSectLeave(&pVM->rem.s.CritSectRegister);
ASMAtomicDecU32(&pVM->rem.s.cIgnoreAll);
@@ -3087,19 +3319,19 @@ static void remR3NotifyHandlerPhysicalDeregister(PVM pVM, PGMPHYSHANDLERTYPE enm
PDMCritSectEnter(&pVM->rem.s.CritSectRegister, VERR_SEM_BUSY);
/** @todo this isn't right, MMIO can (in theory) be restored as RAM. */
if (enmType == PGMPHYSHANDLERTYPE_MMIO)
- cpu_register_physical_memory(GCPhys, cb, IO_MEM_UNASSIGNED);
+ cpu_register_physical_memory_offset(GCPhys, cb, IO_MEM_UNASSIGNED, GCPhys);
else if (fHasHCHandler)
{
if (!fRestoreAsRAM)
{
Assert(GCPhys > MMR3PhysGetRamSize(pVM));
- cpu_register_physical_memory(GCPhys, cb, IO_MEM_UNASSIGNED);
+ cpu_register_physical_memory_offset(GCPhys, cb, IO_MEM_UNASSIGNED, GCPhys);
}
else
{
Assert(RT_ALIGN_T(GCPhys, PAGE_SIZE, RTGCPHYS) == GCPhys);
Assert(RT_ALIGN_T(cb, PAGE_SIZE, RTGCPHYS) == cb);
- cpu_register_physical_memory(GCPhys, cb, GCPhys);
+ cpu_register_physical_memory_offset(GCPhys, cb, GCPhys, GCPhys);
}
}
PDMCritSectLeave(&pVM->rem.s.CritSectRegister);
@@ -3151,13 +3383,13 @@ static void remR3NotifyHandlerPhysicalModify(PVM pVM, PGMPHYSHANDLERTYPE enmType
*/
PDMCritSectEnter(&pVM->rem.s.CritSectRegister, VERR_SEM_BUSY);
if (!fRestoreAsRAM)
- cpu_register_physical_memory(GCPhysOld, cb, IO_MEM_UNASSIGNED);
+ cpu_register_physical_memory_offset(GCPhysOld, cb, IO_MEM_UNASSIGNED, GCPhysOld);
else
{
/* This is not perfect, but it'll do for PD monitoring... */
Assert(cb == PAGE_SIZE);
Assert(RT_ALIGN_T(GCPhysOld, PAGE_SIZE, RTGCPHYS) == GCPhysOld);
- cpu_register_physical_memory(GCPhysOld, cb, GCPhysOld);
+ cpu_register_physical_memory_offset(GCPhysOld, cb, GCPhysOld, GCPhysOld);
}
/*
@@ -3165,7 +3397,7 @@ static void remR3NotifyHandlerPhysicalModify(PVM pVM, PGMPHYSHANDLERTYPE enmType
*/
Assert(RT_ALIGN_T(GCPhysNew, PAGE_SIZE, RTGCPHYS) == GCPhysNew);
Assert(RT_ALIGN_T(cb, PAGE_SIZE, RTGCPHYS) == cb);
- cpu_register_physical_memory(GCPhysNew, cb, pVM->rem.s.iHandlerMemType);
+ cpu_register_physical_memory_offset(GCPhysNew, cb, pVM->rem.s.iHandlerMemType, GCPhysNew);
PDMCritSectLeave(&pVM->rem.s.CritSectRegister);
ASMAtomicDecU32(&pVM->rem.s.cIgnoreAll);
@@ -3227,9 +3459,9 @@ REMR3DECL(bool) REMR3IsPageAccessHandled(PVM pVM, RTGCPHYS GCPhys)
* @param addr The virtual address.
* @param pTLBEntry The TLB entry.
*/
-target_ulong remR3PhysGetPhysicalAddressCode(CPUState* env,
+target_ulong remR3PhysGetPhysicalAddressCode(CPUX86State *env,
target_ulong addr,
- CPUTLBEntry* pTLBEntry,
+ CPUTLBEntry *pTLBEntry,
target_phys_addr_t ioTLBEntry)
{
PVM pVM = env->pVM;
@@ -3646,6 +3878,9 @@ static DECLCALLBACK(int) remR3DisasEnableStepping(PVM pVM, bool fEnable)
pVM->rem.s.Env.state |= CPU_EMULATE_SINGLE_STEP;
else
pVM->rem.s.Env.state &= ~CPU_EMULATE_SINGLE_STEP;
+#ifdef REM_USE_QEMU_SINGLE_STEP_FOR_LOGGING
+ cpu_single_step(&pVM->rem.s.Env, fEnable);
+#endif
return VINF_SUCCESS;
}
@@ -3675,26 +3910,37 @@ REMR3DECL(int) REMR3DisasEnableStepping(PVM pVM, bool fEnable)
/**
* External Debugger Command: .remstep [on|off|1|0]
*/
-static DECLCALLBACK(int) remR3CmdDisasEnableStepping(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
+static DECLCALLBACK(int) remR3CmdDisasEnableStepping(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs)
{
- bool fEnable;
int rc;
- /* print status */
if (cArgs == 0)
- return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "DisasStepping is %s\n",
- pVM->rem.s.Env.state & CPU_EMULATE_SINGLE_STEP ? "enabled" : "disabled");
-
- /* convert the argument and change the mode. */
- rc = pCmdHlp->pfnVarToBool(pCmdHlp, &paArgs[0], &fEnable);
- if (RT_FAILURE(rc))
- return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "boolean conversion failed!\n");
- rc = REMR3DisasEnableStepping(pVM, fEnable);
- if (RT_FAILURE(rc))
- return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "REMR3DisasEnableStepping failed!\n");
+ /*
+ * Print the current status.
+ */
+ rc = DBGCCmdHlpPrintf(pCmdHlp, "DisasStepping is %s\n",
+ pVM->rem.s.Env.state & CPU_EMULATE_SINGLE_STEP ? "enabled" : "disabled");
+ else
+ {
+ /*
+ * Convert the argument and change the mode.
+ */
+ bool fEnable;
+ rc = DBGCCmdHlpVarToBool(pCmdHlp, &paArgs[0], &fEnable);
+ if (RT_SUCCESS(rc))
+ {
+ rc = REMR3DisasEnableStepping(pVM, fEnable);
+ if (RT_SUCCESS(rc))
+ rc = DBGCCmdHlpPrintf(pCmdHlp, "DisasStepping was %s\n", fEnable ? "enabled" : "disabled");
+ else
+ rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "REMR3DisasEnableStepping");
+ }
+ else
+ rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "DBGCCmdHlpVarToBool");
+ }
return rc;
}
-#endif
+#endif /* VBOX_WITH_DEBUGGER && !win.amd64 */
/**
@@ -3707,7 +3953,7 @@ static DECLCALLBACK(int) remR3CmdDisasEnableStepping(PCDBGCCMD pCmd, PDBGCCMDHLP
* selector will be inspected.
* @param pszPrefix
*/
-bool remR3DisasInstr(CPUState *env, int f32BitCode, char *pszPrefix)
+bool remR3DisasInstr(CPUX86State *env, int f32BitCode, char *pszPrefix)
{
PVM pVM = env->pVM;
const bool fLog = LogIsEnabled();
@@ -3728,7 +3974,7 @@ bool remR3DisasInstr(CPUState *env, int f32BitCode, char *pszPrefix)
/*
* Log registers if requested.
*/
- if (!fLog2)
+ if (fLog2)
DBGFR3InfoLog(pVM, "cpumguest", pszPrefix);
/*
@@ -3770,12 +4016,7 @@ bool remR3DisasInstr(CPUState *env, int f32BitCode, char *pszPrefix)
*/
void disas(FILE *phFile, void *pvCode, unsigned long cb)
{
-#ifdef DEBUG_TMP_LOGGING
-# define DISAS_PRINTF(x...) fprintf(phFile, x)
-#else
-# define DISAS_PRINTF(x...) RTLogPrintf(x)
if (LogIs2Enabled())
-#endif
{
unsigned off = 0;
char szOutput[256];
@@ -3788,15 +4029,15 @@ void disas(FILE *phFile, void *pvCode, unsigned long cb)
Cpu.mode = CPUMODE_64BIT;
#endif
- DISAS_PRINTF("Recompiled Code: %p %#lx (%ld) bytes\n", pvCode, cb, cb);
+ RTLogPrintf("Recompiled Code: %p %#lx (%ld) bytes\n", pvCode, cb, cb);
while (off < cb)
{
uint32_t cbInstr;
if (RT_SUCCESS(DISInstr(&Cpu, (uintptr_t)pvCode + off, 0, &cbInstr, szOutput)))
- DISAS_PRINTF("%s", szOutput);
+ RTLogPrintf("%s", szOutput);
else
{
- DISAS_PRINTF("disas error\n");
+ RTLogPrintf("disas error\n");
cbInstr = 1;
#ifdef RT_ARCH_AMD64 /** @todo remove when DISInstr starts supporting 64-bit code. */
break;
@@ -3805,8 +4046,6 @@ void disas(FILE *phFile, void *pvCode, unsigned long cb)
off += cbInstr;
}
}
-
-#undef DISAS_PRINTF
}
@@ -3820,12 +4059,7 @@ void disas(FILE *phFile, void *pvCode, unsigned long cb)
*/
void target_disas(FILE *phFile, target_ulong uCode, target_ulong cb, int fFlags)
{
-#ifdef DEBUG_TMP_LOGGING
-# define DISAS_PRINTF(x...) fprintf(phFile, x)
-#else
-# define DISAS_PRINTF(x...) RTLogPrintf(x)
if (LogIs2Enabled())
-#endif
{
PVM pVM = cpu_single_env->pVM;
PVMCPU pVCpu = cpu_single_env->pVCpu;
@@ -3842,7 +4076,7 @@ void target_disas(FILE *phFile, target_ulong uCode, target_ulong cb, int fFlags)
/*
* Do the disassembling.
*/
- DISAS_PRINTF("Guest Code: PC=%llx %llx bytes fFlags=%d\n", (uint64_t)uCode, (uint64_t)cb, fFlags);
+ RTLogPrintf("Guest Code: PC=%llx %llx bytes fFlags=%d\n", (uint64_t)uCode, (uint64_t)cb, fFlags);
cs = cpu_single_env->segs[R_CS].selector;
eip = uCode - cpu_single_env->segs[R_CS].base;
for (;;)
@@ -3857,10 +4091,10 @@ void target_disas(FILE *phFile, target_ulong uCode, target_ulong cb, int fFlags)
szBuf, sizeof(szBuf),
&cbInstr);
if (RT_SUCCESS(rc))
- DISAS_PRINTF("%llx %s\n", (uint64_t)uCode, szBuf);
+ RTLogPrintf("%llx %s\n", (uint64_t)uCode, szBuf);
else
{
- DISAS_PRINTF("%llx %04x:%llx: %s\n", (uint64_t)uCode, cs, (uint64_t)eip, szBuf);
+ RTLogPrintf("%llx %04x:%llx: %s\n", (uint64_t)uCode, cs, (uint64_t)eip, szBuf);
cbInstr = 1;
}
@@ -3872,7 +4106,6 @@ void target_disas(FILE *phFile, target_ulong uCode, target_ulong cb, int fFlags)
eip += cbInstr;
}
}
-#undef DISAS_PRINTF
}
@@ -3948,6 +4181,7 @@ REMR3DECL(uint32_t) REMR3QueryPendingInterrupt(PVM pVM, PVMCPU pVCpu)
*/
REMR3DECL(void) REMR3NotifyInterruptSet(PVM pVM, PVMCPU pVCpu)
{
+#ifndef IEM_VERIFICATION_MODE
LogFlow(("REMR3NotifyInterruptSet: fInRem=%d interrupts %s\n", pVM->rem.s.fInREM,
(pVM->rem.s.Env.eflags & IF_MASK) && !(pVM->rem.s.Env.hflags & HF_INHIBIT_IRQ_MASK) ? "enabled" : "disabled"));
if (pVM->rem.s.fInREM)
@@ -3955,6 +4189,7 @@ REMR3DECL(void) REMR3NotifyInterruptSet(PVM pVM, PVMCPU pVCpu)
ASMAtomicOrS32((int32_t volatile *)&cpu_single_env->interrupt_request,
CPU_INTERRUPT_EXTERNAL_HARD);
}
+#endif
}
@@ -3985,6 +4220,7 @@ REMR3DECL(void) REMR3NotifyInterruptClear(PVM pVM, PVMCPU pVCpu)
*/
REMR3DECL(void) REMR3NotifyTimerPending(PVM pVM, PVMCPU pVCpuDst)
{
+#ifndef IEM_VERIFICATION_MODE
#ifndef DEBUG_bird
LogFlow(("REMR3NotifyTimerPending: fInRem=%d\n", pVM->rem.s.fInREM));
#endif
@@ -4001,6 +4237,7 @@ REMR3DECL(void) REMR3NotifyTimerPending(PVM pVM, PVMCPU pVCpuDst)
}
else
LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_5, LOG_GROUP_TM, ("REMR3NotifyTimerPending: !fInREM; cpu state=%d\n", VMCPU_GET_STATE(pVCpuDst)));
+#endif
}
@@ -4012,12 +4249,14 @@ REMR3DECL(void) REMR3NotifyTimerPending(PVM pVM, PVMCPU pVCpuDst)
*/
REMR3DECL(void) REMR3NotifyDmaPending(PVM pVM)
{
+#ifndef IEM_VERIFICATION_MODE
LogFlow(("REMR3NotifyDmaPending: fInRem=%d\n", pVM->rem.s.fInREM));
if (pVM->rem.s.fInREM)
{
ASMAtomicOrS32((int32_t volatile *)&cpu_single_env->interrupt_request,
CPU_INTERRUPT_EXTERNAL_DMA);
}
+#endif
}
@@ -4029,12 +4268,14 @@ REMR3DECL(void) REMR3NotifyDmaPending(PVM pVM)
*/
REMR3DECL(void) REMR3NotifyQueuePending(PVM pVM)
{
+#ifndef IEM_VERIFICATION_MODE
LogFlow(("REMR3NotifyQueuePending: fInRem=%d\n", pVM->rem.s.fInREM));
if (pVM->rem.s.fInREM)
{
ASMAtomicOrS32((int32_t volatile *)&cpu_single_env->interrupt_request,
CPU_INTERRUPT_EXTERNAL_EXIT);
}
+#endif
}
@@ -4046,12 +4287,14 @@ REMR3DECL(void) REMR3NotifyQueuePending(PVM pVM)
*/
REMR3DECL(void) REMR3NotifyFF(PVM pVM)
{
+#ifndef IEM_VERIFICATION_MODE
LogFlow(("REMR3NotifyFF: fInRem=%d\n", pVM->rem.s.fInREM));
if (pVM->rem.s.fInREM)
{
ASMAtomicOrS32((int32_t volatile *)&cpu_single_env->interrupt_request,
CPU_INTERRUPT_EXTERNAL_EXIT);
}
+#endif
}
@@ -4164,7 +4407,7 @@ void cpu_set_ferr(CPUX86State *env)
LogFlow(("cpu_set_ferr: rc=%d\n", rc)); NOREF(rc);
}
-int cpu_get_pic_interrupt(CPUState *env)
+int cpu_get_pic_interrupt(CPUX86State *env)
{
uint8_t u8Interrupt;
int rc;
@@ -4276,7 +4519,7 @@ int cpu_wrmsr(CPUX86State *env, uint32_t idMsr, uint64_t uValue)
#undef LOG_GROUP
#define LOG_GROUP LOG_GROUP_REM_IOPORT
-void cpu_outb(CPUState *env, int addr, int val)
+void cpu_outb(CPUX86State *env, pio_addr_t addr, uint8_t val)
{
int rc;
@@ -4295,7 +4538,7 @@ void cpu_outb(CPUState *env, int addr, int val)
remAbort(rc, __FUNCTION__);
}
-void cpu_outw(CPUState *env, int addr, int val)
+void cpu_outw(CPUX86State *env, pio_addr_t addr, uint16_t val)
{
//Log2(("cpu_outw: addr=%#06x val=%#x\n", addr, val));
int rc = IOMIOPortWrite(env->pVM, (RTIOPORT)addr, val, 2);
@@ -4310,7 +4553,7 @@ void cpu_outw(CPUState *env, int addr, int val)
remAbort(rc, __FUNCTION__);
}
-void cpu_outl(CPUState *env, int addr, int val)
+void cpu_outl(CPUX86State *env, pio_addr_t addr, uint32_t val)
{
int rc;
Log2(("cpu_outl: addr=%#06x val=%#x\n", addr, val));
@@ -4326,7 +4569,7 @@ void cpu_outl(CPUState *env, int addr, int val)
remAbort(rc, __FUNCTION__);
}
-int cpu_inb(CPUState *env, int addr)
+uint8_t cpu_inb(CPUX86State *env, pio_addr_t addr)
{
uint32_t u32 = 0;
int rc = IOMIOPortRead(env->pVM, (RTIOPORT)addr, &u32, 1);
@@ -4334,38 +4577,38 @@ int cpu_inb(CPUState *env, int addr)
{
if (/*addr != 0x61 && */addr != 0x71)
Log2(("cpu_inb: addr=%#06x -> %#x\n", addr, u32));
- return (int)u32;
+ return (uint8_t)u32;
}
if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
{
Log(("cpu_inb: addr=%#06x -> %#x rc=%Rrc\n", addr, u32, rc));
remR3RaiseRC(env->pVM, rc);
- return (int)u32;
+ return (uint8_t)u32;
}
remAbort(rc, __FUNCTION__);
- return 0xff;
+ return UINT8_C(0xff);
}
-int cpu_inw(CPUState *env, int addr)
+uint16_t cpu_inw(CPUX86State *env, pio_addr_t addr)
{
uint32_t u32 = 0;
int rc = IOMIOPortRead(env->pVM, (RTIOPORT)addr, &u32, 2);
if (RT_LIKELY(rc == VINF_SUCCESS))
{
Log2(("cpu_inw: addr=%#06x -> %#x\n", addr, u32));
- return (int)u32;
+ return (uint16_t)u32;
}
if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
{
Log(("cpu_inw: addr=%#06x -> %#x rc=%Rrc\n", addr, u32, rc));
remR3RaiseRC(env->pVM, rc);
- return (int)u32;
+ return (uint16_t)u32;
}
remAbort(rc, __FUNCTION__);
- return 0xffff;
+ return UINT16_C(0xffff);
}
-int cpu_inl(CPUState *env, int addr)
+uint32_t cpu_inl(CPUX86State *env, pio_addr_t addr)
{
uint32_t u32 = 0;
int rc = IOMIOPortRead(env->pVM, (RTIOPORT)addr, &u32, 4);
@@ -4374,16 +4617,16 @@ int cpu_inl(CPUState *env, int addr)
//if (addr==0x01f0 && u32 == 0x6b6d)
// loglevel = ~0;
Log2(("cpu_inl: addr=%#06x -> %#x\n", addr, u32));
- return (int)u32;
+ return u32;
}
if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
{
Log(("cpu_inl: addr=%#06x -> %#x rc=%Rrc\n", addr, u32, rc));
remR3RaiseRC(env->pVM, rc);
- return (int)u32;
+ return u32;
}
remAbort(rc, __FUNCTION__);
- return 0xffffffff;
+ return UINT32_C(0xffffffff);
}
#undef LOG_GROUP
@@ -4395,19 +4638,19 @@ int cpu_inl(CPUState *env, int addr)
/**
* Perform the CPUID instruction.
*
- * ASMCpuId cannot be invoked from some source files where this is used because of global
- * register allocations.
- *
* @param env Pointer to the recompiler CPU structure.
- * @param uOperator CPUID operation (eax).
+ * @param idx The CPUID leaf (eax).
+ * @param idxSub The CPUID sub-leaf (ecx) where applicable.
* @param pvEAX Where to store eax.
* @param pvEBX Where to store ebx.
* @param pvECX Where to store ecx.
* @param pvEDX Where to store edx.
*/
-void remR3CpuId(CPUState *env, unsigned uOperator, void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX)
+void cpu_x86_cpuid(CPUX86State *env, uint32_t idx, uint32_t idxSub,
+ uint32_t *pEAX, uint32_t *pEBX, uint32_t *pECX, uint32_t *pEDX)
{
- CPUMGetGuestCpuId(env->pVCpu, uOperator, (uint32_t *)pvEAX, (uint32_t *)pvEBX, (uint32_t *)pvECX, (uint32_t *)pvEDX);
+ NOREF(idxSub);
+ CPUMGetGuestCpuId(env->pVCpu, idx, pEAX, pEBX, pECX, pEDX);
}
@@ -4445,7 +4688,7 @@ void hw_error(const char *pszFormat, ...)
* Interface for the qemu cpu to report unhandled situation
* raising a fatal VM error.
*/
-void cpu_abort(CPUState *env, const char *pszFormat, ...)
+void cpu_abort(CPUX86State *env, const char *pszFormat, ...)
{
va_list va;
PVM pVM;
@@ -5186,6 +5429,6 @@ void *memcpy(void *dst, const void *src, size_t size)
#endif
-void cpu_smm_update(CPUState *env)
+void cpu_smm_update(CPUX86State *env)
{
}