VBoxRecompiler.c revision 7bb3c0bce2906236dbb84a55d90f3b1d0b4b02cd
0f70ed40798198e1d9099c6ae3bdb239d2b8cf0dvboxsync * VBox Recompiler - QEMU.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * available from http://www.virtualbox.org. This file is free software;
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * you can redistribute it and/or modify it under the terms of the GNU
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * General Public License (GPL) as published by the Free Software
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * additional information or have any questions.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync/*******************************************************************************
2e2dec6e64c09dd7e3fe4ad0ee8bb5cf7d63762evboxsync* Header Files *
2e2dec6e64c09dd7e3fe4ad0ee8bb5cf7d63762evboxsync*******************************************************************************/
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync/* Don't wanna include everything. */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncextern void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncextern void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncextern void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncextern void tlb_flush_page(CPUX86State *env, target_ulong addr);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncextern void tlb_flush(CPUState *env, int flush_global);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncextern void sync_seg(CPUX86State *env1, int seg_reg, int selector);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncextern void sync_ldtr(CPUX86State *env1, int selector);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncextern int sync_tr(CPUX86State *env1, int selector);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsyncunsigned long get_phys_page_offset(target_ulong addr);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync/*******************************************************************************
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync* Defined Constants And Macros *
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync*******************************************************************************/
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync/** Copy 80-bit fpu register at pSrc to pDst.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * This is probably faster than *calling* memcpy.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync do { *(PX86FPUMMX)(pDst) = *(const X86FPUMMX *)(pSrc); } while (0)
b73558f2e00416e86d24d6704100021758131e9bvboxsync/*******************************************************************************
b73558f2e00416e86d24d6704100021758131e9bvboxsync* Internal Functions *
b73558f2e00416e86d24d6704100021758131e9bvboxsync*******************************************************************************/
b73558f2e00416e86d24d6704100021758131e9bvboxsyncstatic DECLCALLBACK(int) remR3Save(PVM pVM, PSSMHANDLE pSSM);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsyncstatic DECLCALLBACK(int) remR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsyncstatic uint32_t remR3MMIOReadU8(void *pvVM, target_phys_addr_t GCPhys);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsyncstatic uint32_t remR3MMIOReadU16(void *pvVM, target_phys_addr_t GCPhys);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsyncstatic uint32_t remR3MMIOReadU32(void *pvVM, target_phys_addr_t GCPhys);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsyncstatic void remR3MMIOWriteU8(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsyncstatic void remR3MMIOWriteU16(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsyncstatic void remR3MMIOWriteU32(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsyncstatic uint32_t remR3HandlerReadU8(void *pvVM, target_phys_addr_t GCPhys);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsyncstatic uint32_t remR3HandlerReadU16(void *pvVM, target_phys_addr_t GCPhys);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsyncstatic uint32_t remR3HandlerReadU32(void *pvVM, target_phys_addr_t GCPhys);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsyncstatic void remR3HandlerWriteU8(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsyncstatic void remR3HandlerWriteU16(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsyncstatic void remR3HandlerWriteU32(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync/*******************************************************************************
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync* Global Variables *
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync*******************************************************************************/
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync/** @todo Move stats to REM::s some rainy day we have nothing do to. */
b73558f2e00416e86d24d6704100021758131e9bvboxsync * Global stuff.
b73558f2e00416e86d24d6704100021758131e9bvboxsync/** MMIO read callbacks. */
b73558f2e00416e86d24d6704100021758131e9bvboxsync/** MMIO write callbacks. */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync/** Handler read callbacks. */
1f81eb5400025393fd9b496ccde15364d6852ec9vboxsync/** Handler write callbacks. */
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync#if defined(VBOX_WITH_DEBUGGER) && !(defined(RT_OS_WINDOWS) && defined(RT_ARCH_AMD64))
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * Debugger commands.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsyncstatic DECLCALLBACK(int) remR3CmdDisasEnableStepping(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync/** '.remstep' arguments. */
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync { 0, ~0, DBGCVAR_CAT_NUMBER, 0, "on/off", "Boolean value/mnemonic indicating the new state." },
1f81eb5400025393fd9b496ccde15364d6852ec9vboxsync/** Command descriptors. */
011bebd8930c3fa3df178d1c82ae88cc73c70d39vboxsync .pszDescription = "Enable or disable the single stepping with logged disassembly. "
011bebd8930c3fa3df178d1c82ae88cc73c70d39vboxsync "If no arguments show the current state."
2e2dec6e64c09dd7e3fe4ad0ee8bb5cf7d63762evboxsync/*******************************************************************************
2e2dec6e64c09dd7e3fe4ad0ee8bb5cf7d63762evboxsync* Internal Functions *
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync*******************************************************************************/
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsyncextern int testmath(void);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync/* Put them here to avoid unused variable warning. */
b73558f2e00416e86d24d6704100021758131e9bvboxsyncAssertCompile(RT_SIZEOFMEMB(VM, rem.padding) >= RT_SIZEOFMEMB(VM, rem.s));
b73558f2e00416e86d24d6704100021758131e9bvboxsync#if !defined(IPRT_NO_CRT) && (defined(RT_OS_LINUX) || defined(RT_OS_DARWIN) || defined(RT_OS_WINDOWS))
b73558f2e00416e86d24d6704100021758131e9bvboxsync//AssertCompileMemberSize(REM, Env, REM_ENV_SIZE);
b73558f2e00416e86d24d6704100021758131e9bvboxsync/* Why did this have to be identical?? */
b73558f2e00416e86d24d6704100021758131e9bvboxsyncAssertCompile(RT_SIZEOFMEMB(REM, Env) <= REM_ENV_SIZE);
b73558f2e00416e86d24d6704100021758131e9bvboxsyncAssertCompile(RT_SIZEOFMEMB(REM, Env) <= REM_ENV_SIZE);
b73558f2e00416e86d24d6704100021758131e9bvboxsync/* Prologue code, must be in lower 4G to simplify jumps to/from generated code */
b73558f2e00416e86d24d6704100021758131e9bvboxsync * Initializes the REM.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @returns VBox status code.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param pVM The VM to operate on.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync unsigned i;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Assert sanity.
e2843ed205192b88e54eef60ad541d00bbbc932avboxsync AssertReleaseMsg(sizeof(pVM->rem.padding) >= sizeof(pVM->rem.s), ("%#x >= %#x; sizeof(Env)=%#x\n", sizeof(pVM->rem.padding), sizeof(pVM->rem.s), sizeof(pVM->rem.s.Env)));
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync AssertReleaseMsg(sizeof(pVM->rem.s.Env) <= REM_ENV_SIZE, ("%#x == %#x\n", sizeof(pVM->rem.s.Env), REM_ENV_SIZE));
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync AssertReleaseMsg(!(RT_OFFSETOF(VM, rem) & 31), ("off=%#x\n", RT_OFFSETOF(VM, rem)));
2622c26c6b4105d944a29c5e2c77b6ef26e10101vboxsync#if defined(DEBUG) && !defined(RT_OS_SOLARIS) /// @todo fix the solaris math stuff.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Init some internal data members.
84d24b25be3d7e4004bf1601d8e0754398111a04vboxsync AssertMsg(MMR3PhysGetRamSize(pVM) == 0, ("Init order have changed! REM depends on notification about ALL physical memory registrations\n"));
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* ignore all notifications */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Init the recompiler.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync AssertMsgFailed(("cpu_x86_init failed - impossible!\n"));
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync CPUMGetGuestCpuId(pVM, 1, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext_features, &pVM->rem.s.Env.cpuid_features);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync CPUMGetGuestCpuId(pVM, 0x80000001, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext3_features, &pVM->rem.s.Env.cpuid_ext2_features);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync /* allocate code buffer for single instruction emulation. */
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync pVM->rem.s.Env.pvCodeBuffer = RTMemExecAlloc(pVM->rem.s.Env.cbCodeBuffer);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync AssertMsgReturn(pVM->rem.s.Env.pvCodeBuffer, ("Failed to allocate code buffer!\n"), VERR_NO_MEMORY);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* finally, set the cpu_single_env global. */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* Nothing is pending by default */
84d24b25be3d7e4004bf1601d8e0754398111a04vboxsync pVM->rem.s.u32PendingInterrupt = REM_NO_PENDING_IRQ;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Register ram types.
84d24b25be3d7e4004bf1601d8e0754398111a04vboxsync pVM->rem.s.iMMIOMemType = cpu_register_io_memory(-1, g_apfnMMIORead, g_apfnMMIOWrite, pVM);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync AssertReleaseMsg(pVM->rem.s.iMMIOMemType >= 0, ("pVM->rem.s.iMMIOMemType=%d\n", pVM->rem.s.iMMIOMemType));
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync pVM->rem.s.iHandlerMemType = cpu_register_io_memory(-1, g_apfnHandlerRead, g_apfnHandlerWrite, pVM);
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync AssertReleaseMsg(pVM->rem.s.iHandlerMemType >= 0, ("pVM->rem.s.iHandlerMemType=%d\n", pVM->rem.s.iHandlerMemType));
1f81eb5400025393fd9b496ccde15364d6852ec9vboxsync Log2(("REM: iMMIOMemType=%d iHandlerMemType=%d\n", pVM->rem.s.iMMIOMemType, pVM->rem.s.iHandlerMemType));
84d24b25be3d7e4004bf1601d8e0754398111a04vboxsync /* stop ignoring. */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Register the saved state data unit.
84d24b25be3d7e4004bf1601d8e0754398111a04vboxsync rc = SSMR3RegisterInternal(pVM, "rem", 1, REM_SAVED_STATE_VERSION, sizeof(uint32_t) * 10,
011bebd8930c3fa3df178d1c82ae88cc73c70d39vboxsync#if defined(VBOX_WITH_DEBUGGER) && !(defined(RT_OS_WINDOWS) && defined(RT_ARCH_AMD64))
84d24b25be3d7e4004bf1601d8e0754398111a04vboxsync * Debugger commands.
8ffcab9595cc0d56977968cd496363502fd814aevboxsync static bool fRegisteredCmds = false;
2e2dec6e64c09dd7e3fe4ad0ee8bb5cf7d63762evboxsync int rc = DBGCRegisterCommands(&g_aCmds[0], RT_ELEMENTS(g_aCmds));
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * Statistics.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatExecuteSingleInstr, STAMTYPE_PROFILE, "/PROF/REM/SingleInstr",STAMUNIT_TICKS_PER_CALL, "Profiling single instruction emulation.");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatCompilationQEmu, STAMTYPE_PROFILE, "/PROF/REM/Compile", STAMUNIT_TICKS_PER_CALL, "Profiling QEmu compilation.");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatRunCodeQEmu, STAMTYPE_PROFILE, "/PROF/REM/Runcode", STAMUNIT_TICKS_PER_CALL, "Profiling QEmu code execution.");
e2843ed205192b88e54eef60ad541d00bbbc932avboxsync STAM_REG(pVM, &gStatTotalTimeQEmu, STAMTYPE_PROFILE, "/PROF/REM/Emulate", STAMUNIT_TICKS_PER_CALL, "Profiling code emulation.");
e2843ed205192b88e54eef60ad541d00bbbc932avboxsync STAM_REG(pVM, &gStatTimers, STAMTYPE_PROFILE, "/PROF/REM/Timers", STAMUNIT_TICKS_PER_CALL, "Profiling timer scheduling.");
e2843ed205192b88e54eef60ad541d00bbbc932avboxsync STAM_REG(pVM, &gStatTBLookup, STAMTYPE_PROFILE, "/PROF/REM/TBLookup", STAMUNIT_TICKS_PER_CALL, "Profiling timer scheduling.");
e2843ed205192b88e54eef60ad541d00bbbc932avboxsync STAM_REG(pVM, &gStatIRQ, STAMTYPE_PROFILE, "/PROF/REM/IRQ", STAMUNIT_TICKS_PER_CALL, "Profiling timer scheduling.");
e2843ed205192b88e54eef60ad541d00bbbc932avboxsync STAM_REG(pVM, &gStatRawCheck, STAMTYPE_PROFILE, "/PROF/REM/RawCheck", STAMUNIT_TICKS_PER_CALL, "Profiling timer scheduling.");
e2843ed205192b88e54eef60ad541d00bbbc932avboxsync STAM_REG(pVM, &gStatMemRead, STAMTYPE_PROFILE, "/PROF/REM/MemRead", STAMUNIT_TICKS_PER_CALL, "Profiling memory access.");
e2843ed205192b88e54eef60ad541d00bbbc932avboxsync STAM_REG(pVM, &gStatMemWrite, STAMTYPE_PROFILE, "/PROF/REM/MemWrite", STAMUNIT_TICKS_PER_CALL, "Profiling memory access.");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatHCVirt2GCPhys, STAMTYPE_PROFILE, "/PROF/REM/HCVirt2GCPhys", STAMUNIT_TICKS_PER_CALL, "Profiling memory convertion.");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatGCPhys2HCVirt, STAMTYPE_PROFILE, "/PROF/REM/GCPhys2HCVirt", STAMUNIT_TICKS_PER_CALL, "Profiling memory convertion.");
e2843ed205192b88e54eef60ad541d00bbbc932avboxsync STAM_REG(pVM, &gStatCpuGetTSC, STAMTYPE_COUNTER, "/REM/CpuGetTSC", STAMUNIT_OCCURENCES, "cpu_get_tsc calls");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatRefuseTFInhibit, STAMTYPE_COUNTER, "/REM/Refuse/TFInibit", STAMUNIT_OCCURENCES, "Raw mode refused because of TF or irq inhibit");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatRefuseVM86, STAMTYPE_COUNTER, "/REM/Refuse/VM86", STAMUNIT_OCCURENCES, "Raw mode refused because of VM86");
2e2dec6e64c09dd7e3fe4ad0ee8bb5cf7d63762evboxsync STAM_REG(pVM, &gStatRefusePaging, STAMTYPE_COUNTER, "/REM/Refuse/Paging", STAMUNIT_OCCURENCES, "Raw mode refused because of disabled paging/pm");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatRefusePAE, STAMTYPE_COUNTER, "/REM/Refuse/PAE", STAMUNIT_OCCURENCES, "Raw mode refused because of PAE");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatRefuseIOPLNot0, STAMTYPE_COUNTER, "/REM/Refuse/IOPLNot0", STAMUNIT_OCCURENCES, "Raw mode refused because of IOPL != 0");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatRefuseIF0, STAMTYPE_COUNTER, "/REM/Refuse/IF0", STAMUNIT_OCCURENCES, "Raw mode refused because of IF=0");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatRefuseCode16, STAMTYPE_COUNTER, "/REM/Refuse/Code16", STAMUNIT_OCCURENCES, "Raw mode refused because of 16 bit code");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatRefuseWP0, STAMTYPE_COUNTER, "/REM/Refuse/WP0", STAMUNIT_OCCURENCES, "Raw mode refused because of WP=0");
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync STAM_REG(pVM, &gStatRefuseRing1or2, STAMTYPE_COUNTER, "/REM/Refuse/Ring1or2", STAMUNIT_OCCURENCES, "Raw mode refused because of ring 1/2 execution");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatRefuseCanExecute, STAMTYPE_COUNTER, "/REM/Refuse/CanExecuteRaw", STAMUNIT_OCCURENCES, "Raw mode refused because of cCanExecuteRaw");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatFlushTBs, STAMTYPE_COUNTER, "/REM/FlushTB", STAMUNIT_OCCURENCES, "Number of TB flushes");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatREMGDTChange, STAMTYPE_COUNTER, "/REM/Change/GDTBase", STAMUNIT_OCCURENCES, "GDT base changes");
8a8d7629deae8875b70c6899e8b0f683b2a543e1vboxsync STAM_REG(pVM, &gStatREMLDTRChange, STAMTYPE_COUNTER, "/REM/Change/LDTR", STAMUNIT_OCCURENCES, "LDTR changes");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatREMIDTChange, STAMTYPE_COUNTER, "/REM/Change/IDTBase", STAMUNIT_OCCURENCES, "IDT base changes");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatREMTRChange, STAMTYPE_COUNTER, "/REM/Change/TR", STAMUNIT_OCCURENCES, "TR selector changes");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatSelOutOfSync[0], STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/ES", STAMUNIT_OCCURENCES, "ES out of sync");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatSelOutOfSync[1], STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/CS", STAMUNIT_OCCURENCES, "CS out of sync");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatSelOutOfSync[2], STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/SS", STAMUNIT_OCCURENCES, "SS out of sync");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatSelOutOfSync[3], STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/DS", STAMUNIT_OCCURENCES, "DS out of sync");
8a8d7629deae8875b70c6899e8b0f683b2a543e1vboxsync STAM_REG(pVM, &gStatSelOutOfSync[4], STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/FS", STAMUNIT_OCCURENCES, "FS out of sync");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatSelOutOfSync[5], STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/GS", STAMUNIT_OCCURENCES, "GS out of sync");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatSelOutOfSyncStateBack[0], STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/ES", STAMUNIT_OCCURENCES, "ES out of sync");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatSelOutOfSyncStateBack[1], STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/CS", STAMUNIT_OCCURENCES, "CS out of sync");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatSelOutOfSyncStateBack[2], STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/SS", STAMUNIT_OCCURENCES, "SS out of sync");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatSelOutOfSyncStateBack[3], STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/DS", STAMUNIT_OCCURENCES, "DS out of sync");
8a8d7629deae8875b70c6899e8b0f683b2a543e1vboxsync STAM_REG(pVM, &gStatSelOutOfSyncStateBack[4], STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/FS", STAMUNIT_OCCURENCES, "FS out of sync");
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync STAM_REG(pVM, &gStatSelOutOfSyncStateBack[5], STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/GS", STAMUNIT_OCCURENCES, "GS out of sync");
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * Terminates the REM.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * Termination means cleaning up and freeing all resources,
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * the VM it self is at this point powered off or suspended.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @returns VBox status code.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param pVM The VM to operate on.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * The VM is being reset.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * For the REM component this means to call the cpu_reset() and
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * reinitialize some state variables.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param pVM VM handle.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * Reset the REM cpu.
9a12ad9a1028187595f21d9264898220c1ea565fvboxsync /* Clear raw ring 0 init state */
9a12ad9a1028187595f21d9264898220c1ea565fvboxsync /* Flush the TBs the next time we execute code here. */
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Execute state save operation.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @returns VBox status code.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param pVM VM Handle.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * @param pSSM SSM operation handle.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsyncstatic DECLCALLBACK(int) remR3Save(PVM pVM, PSSMHANDLE pSSM)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * Save the required CPU Env bits.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync * (Not much because we're never in REM when doing the save.)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* Remember if we've entered raw mode (vital for ring 1 checks in e.g. iret emulation). */
2e2dec6e64c09dd7e3fe4ad0ee8bb5cf7d63762evboxsync SSMR3PutU32(pSSM, !!(pRem->Env.state & CPU_RAW_RING0));
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync SSMR3PutUInt(pSSM, pVM->rem.s.u32PendingInterrupt);
9b11211f1a9ed6c980794d624ce1af60f2033f2avboxsync * Execute state load operation.
9b11211f1a9ed6c980794d624ce1af60f2033f2avboxsync * @returns VBox status code.
9b11211f1a9ed6c980794d624ce1af60f2033f2avboxsync * @param pVM VM Handle.
9b11211f1a9ed6c980794d624ce1af60f2033f2avboxsync * @param pSSM SSM operation handle.
9b11211f1a9ed6c980794d624ce1af60f2033f2avboxsync * @param u32Version Data layout version.
9b11211f1a9ed6c980794d624ce1af60f2033f2avboxsyncstatic DECLCALLBACK(int) remR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version)
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * Validate version.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync AssertMsgFailed(("remR3Load: Invalid version u32Version=%d!\n", u32Version));
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * Do a reset to be on the safe side...
2622c26c6b4105d944a29c5e2c77b6ef26e10101vboxsync * Ignore all ignorable notifications.
2622c26c6b4105d944a29c5e2c77b6ef26e10101vboxsync * (Not doing this will cause serious trouble.)
2622c26c6b4105d944a29c5e2c77b6ef26e10101vboxsync * Load the required CPU Env bits.
2622c26c6b4105d944a29c5e2c77b6ef26e10101vboxsync * (Not much because we're never in REM when doing the save.)
2622c26c6b4105d944a29c5e2c77b6ef26e10101vboxsync /* Redundant REM CPU state has to be loaded, but can be ignored. */
2622c26c6b4105d944a29c5e2c77b6ef26e10101vboxsync SSMR3GetMem(pSSM, &temp, RT_OFFSETOF(CPUX86State_Ver16, jmp_env));
2622c26c6b4105d944a29c5e2c77b6ef26e10101vboxsync /* Remember if we've entered raw mode (vital for ring 1 checks in e.g. iret emulation). */
2622c26c6b4105d944a29c5e2c77b6ef26e10101vboxsync unsigned i;
2622c26c6b4105d944a29c5e2c77b6ef26e10101vboxsync * Load the REM stuff.
2622c26c6b4105d944a29c5e2c77b6ef26e10101vboxsync if (pRem->cInvalidatedPages > RT_ELEMENTS(pRem->aGCPtrInvalidatedPages))
2622c26c6b4105d944a29c5e2c77b6ef26e10101vboxsync AssertMsgFailed(("cInvalidatedPages=%#x\n", pRem->cInvalidatedPages));
2622c26c6b4105d944a29c5e2c77b6ef26e10101vboxsync SSMR3GetGCPtr(pSSM, &pRem->aGCPtrInvalidatedPages[i]);
2622c26c6b4105d944a29c5e2c77b6ef26e10101vboxsync rc = SSMR3GetUInt(pSSM, &pVM->rem.s.u32PendingInterrupt);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync /* check the terminator. */
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * Get the CPUID features.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync CPUMGetGuestCpuId(pVM, 1, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext_features, &pVM->rem.s.Env.cpuid_features);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync CPUMGetGuestCpuId(pVM, 0x80000001, &u32Dummy, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext2_features);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * Sync the Load Flush the TLB
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * Stop ignoring ignornable notifications.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * Sync the whole CPU state when executing code in the recompiler.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * Single steps an instruction in recompiled mode.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * Before calling this function the REM state needs to be in sync with
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * the VM. Call REMR3State() to perform the sync. It's only necessary
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * (and permitted) to sync at the first call to REMR3Step()/REMR3Run()
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * and after calling REMR3StateBack().
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * @returns VBox status code.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * @param pVM VM Handle.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * Lock the REM - we don't wanna have anyone interrupting us
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * while stepping - and enabled single stepping. We also ignore
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * pending interrupts and suchlike.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync interrupt_request = pVM->rem.s.Env.interrupt_request;
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync 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)));
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * If we're standing at a breakpoint, that have to be disabled before we start stepping.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync GCPtrPC = pVM->rem.s.Env.eip + pVM->rem.s.Env.segs[R_CS].base;
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync fBp = !cpu_breakpoint_remove(&pVM->rem.s.Env, GCPtrPC);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * Execute and handle the return code.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * We execute without enabling the cpu tick, so on success we'll
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * just flip it on and off to make sure it moves
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync AssertMsgFailed(("Damn, this shouldn't happen! cpu_exec returned %d while singlestepping\n", rc));
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync AssertReleaseMsgFailed(("This really shouldn't happen, rc=%d!\n", rc));
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * Restore the stuff we changed to prevent interruption.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * Unlock the REM.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync int rc2 = cpu_breakpoint_insert(&pVM->rem.s.Env, GCPtrPC);
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync pVM->rem.s.Env.interrupt_request = interrupt_request;
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * Set a breakpoint using the REM facilities.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * @returns VBox status code.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * @param pVM The VM handle.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * @param Address The breakpoint address.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * @thread The emulation thread.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsyncREMR3DECL(int) REMR3BreakpointSet(PVM pVM, RTGCUINTPTR Address)
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync if (!cpu_breakpoint_insert(&pVM->rem.s.Env, Address))
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync LogFlow(("REMR3BreakpointSet: Address=%RGv\n", Address));
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync LogFlow(("REMR3BreakpointSet: Address=%RGv - failed!\n", Address));
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * Clears a breakpoint set by REMR3BreakpointSet().
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * @returns VBox status code.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * @param pVM The VM handle.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * @param Address The breakpoint address.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * @thread The emulation thread.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsyncREMR3DECL(int) REMR3BreakpointClear(PVM pVM, RTGCUINTPTR Address)
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync if (!cpu_breakpoint_remove(&pVM->rem.s.Env, Address))
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync LogFlow(("REMR3BreakpointClear: Address=%RGv\n", Address));
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync LogFlow(("REMR3BreakpointClear: Address=%RGv - not found!\n", Address));
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * Emulate an instruction.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * This function executes one instruction without letting anyone
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * interrupt it. This is intended for being called while being in
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * raw mode and thus will take care of all the state syncing between
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * REM and the rest.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * @returns VBox status code.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * @param pVM VM handle.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync Log2(("REMR3EmulateInstruction: (cs:eip=%04x:%08x)\n", CPUMGetGuestCS(pVM), CPUMGetGuestEIP(pVM)));
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync /* Make sure this flag is set; we might never execute remR3CanExecuteRaw in the AMD-V case.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * CPU_RAW_HWACC makes sure we never execute interrupt handlers in the recompiler.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync /* Skip the TB flush as that's rather expensive and not necessary for single instruction emulation. */
0d49a2fbc9857ad8dd29542de7fb37202f1a283fvboxsync * Sync the state and enable single instruction / single stepping.
b73558f2e00416e86d24d6704100021758131e9bvboxsync int interrupt_request = pVM->rem.s.Env.interrupt_request;
b73558f2e00416e86d24d6704100021758131e9bvboxsync 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)));
b73558f2e00416e86d24d6704100021758131e9bvboxsync * Now we set the execute single instruction flag and enter the cpu_exec loop.
b73558f2e00416e86d24d6704100021758131e9bvboxsync pVM->rem.s.Env.interrupt_request = CPU_INTERRUPT_SINGLE_INSTR;
9b11211f1a9ed6c980794d624ce1af60f2033f2avboxsync * Executed without anything out of the way happening.
b73558f2e00416e86d24d6704100021758131e9bvboxsync Log2(("REMR3EmulateInstruction: cpu_exec -> EXCP_SINGLE_INSTR\n"));
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * If we take a trap or start servicing a pending interrupt, we might end up here.
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * (Timer thread or some other thread wishing EMT's attention.)
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync Log2(("REMR3EmulateInstruction: cpu_exec -> EXCP_INTERRUPT\n"));
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * Single step, we assume!
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * If there was a breakpoint there we're fucked now.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync /* breakpoint or single step? */
2e2dec6e64c09dd7e3fe4ad0ee8bb5cf7d63762evboxsync RTGCPTR GCPtrPC = pVM->rem.s.Env.eip + pVM->rem.s.Env.segs[R_CS].base;
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync for (iBP = 0; iBP < pVM->rem.s.Env.nb_breakpoints; iBP++)
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync Log2(("REMR3EmulateInstruction: cpu_exec -> EXCP_DEBUG rc=%Rrc iBP=%d GCPtrPC=%RGv\n", rc, iBP, GCPtrPC));
2e2dec6e64c09dd7e3fe4ad0ee8bb5cf7d63762evboxsync * hlt instruction.
d1a00c93378091ef28db9d959b2d692cc8143a07vboxsync Log2(("REMR3EmulateInstruction: cpu_exec -> EXCP_HLT\n"));
e2843ed205192b88e54eef60ad541d00bbbc932avboxsync * The VM has halted.
e2843ed205192b88e54eef60ad541d00bbbc932avboxsync Log2(("REMR3EmulateInstruction: cpu_exec -> EXCP_HALTED\n"));
0e1eea910a209a7a8edeed71c9be066a02f59202vboxsync * Switch to RAW-mode.
e2843ed205192b88e54eef60ad541d00bbbc932avboxsync Log2(("REMR3EmulateInstruction: cpu_exec -> EXCP_EXECUTE_RAW\n"));
case EXCP_EXECUTE_HWACC:
* An EM RC was raised (VMR3Reset/Suspend/PowerOff/some-fatal-error).
case EXCP_RC:
# ifdef DEBUG_bird
&& --cTimesMax > 0);
switch (rc)
case EXCP_DEBUG:
case EXCP_INTERRUPT:
case EXCP_HLT:
case EXCP_HALTED:
case EXCP_EXECUTE_RAW:
case EXCP_EXECUTE_HWACC:
* An EM RC was raised (VMR3Reset/Suspend/PowerOff/some-fatal-error).
case EXCP_RC:
return rc;
int rc;
Log2(("REMR3Run: (cs:eip=%04x:%RGv)\n", pVM->rem.s.Env.segs[R_CS].selector, (RTGCPTR)pVM->rem.s.Env.eip));
switch (rc)
case EXCP_INTERRUPT:
case EXCP_HLT:
case EXCP_HALTED:
* Breakpoint/single step.
case EXCP_DEBUG:
static int iBP = 0;
switch (iBP)
//pVM->rem.s.Env.interrupt_request = 0;
//pVM->rem.s.Env.exception_index = -1;
iBP++;
int iBP;
case EXCP_EXECUTE_RAW:
case EXCP_EXECUTE_HWACC:
* An EM RC was raised (VMR3Reset/Suspend/PowerOff/some-fatal-error).
case EXCP_RC:
Log2(("REMR3Run: returns %Rrc (cs:eip=%04x:%RGv)\n", rc, pVM->rem.s.Env.segs[R_CS].selector, (RTGCPTR)pVM->rem.s.Env.eip));
return rc;
* @param piException Stores EXCP_EXECUTE_RAW/HWACC in case raw mode is supported in this context
* @remark This function must be kept in perfect sync with the scheduler in EM.cpp!
#ifndef VBOX_RAW_V86
#ifndef DEBUG_bird
//Log2(("raw mode refused: %s%s%s\n", (u32CR0 & X86_CR0_PG) ? "" : " !PG", (u32CR0 & X86_CR0_PE) ? "" : " !PE", (u32CR0 & X86_CR0_AM) ? "" : " !AM"));
int rc;
fGlobal = true;
Log(("remR3FlushTLB: CR0=%RGr CR3=%RGr CR4=%RGr %s\n", env->cr[0], env->cr[3], env->cr[4], fGlobal ? " global" : ""));
int rc;
#ifdef TARGET_X86_64
cpu_abort(env, "PGMChangeMode(, %RX64, %RX64, %RX64) -> %Rrc\n", env->cr[0], env->cr[4], env->efer, rc);
#ifdef VBOX_WITH_STATISTICS
#ifdef VBOX_WITH_STATISTICS
STAM_REG(env->pVM, &s_aStatTrap[uTrap], STAMTYPE_COUNTER, szStatName, STAMUNIT_OCCURENCES, "Trap stats.");
Log(("remR3NotifyTrap: uTrap=%x error=%x next_eip=%RGv eip=%RGv cr2=%RGv\n", uTrap, uErrorCode, (RTGCPTR)pvNextEIP, (RTGCPTR)env->eip, (RTGCPTR)env->cr[2]));
#ifdef DEBUG
LogRel(("VERR_REM_TOO_MANY_TRAPS -> uTrap=%x error=%x next_eip=%RGv eip=%RGv cr2=%RGv\n", uTrap, uErrorCode, (RTGCPTR)pvNextEIP, (RTGCPTR)env->eip, (RTGCPTR)env->cr[2]));
return VERR_REM_TOO_MANY_TRAPS;
if(pVM->rem.s.uPendingException != uTrap || pVM->rem.s.uPendingExcptEIP != env->eip || pVM->rem.s.uPendingExcptCR2 != env->cr[2])
return VINF_SUCCESS;
register unsigned fFlags;
bool fHiddenSelRegsValid;
int rc;
#ifdef TARGET_X86_64
/* Note that the high dwords of 64 bits registers are undefined in 32 bits mode and are undefined after a mode change. */
RTUINT i;
#ifdef TARGET_X86_64
if (fHiddenSelRegsValid)
if (fHiddenSelRegsValid)
CPUMGetGuestCpuId(pVM, 1, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext_features, &pVM->rem.s.Env.cpuid_features);
CPUMGetGuestCpuId(pVM, 0x80000001, &u32Dummy, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext2_features);
if (fHiddenSelRegsValid)
cpu_x86_load_seg_cache(&pVM->rem.s.Env, R_CS, pCtx->cs, pCtx->csHid.u64Base, pCtx->csHid.u32Limit, (pCtx->csHid.Attr.u << 8) & 0xFFFFFF);
cpu_x86_load_seg_cache(&pVM->rem.s.Env, R_SS, pCtx->ss, pCtx->ssHid.u64Base, pCtx->ssHid.u32Limit, (pCtx->ssHid.Attr.u << 8) & 0xFFFFFF);
cpu_x86_load_seg_cache(&pVM->rem.s.Env, R_DS, pCtx->ds, pCtx->dsHid.u64Base, pCtx->dsHid.u32Limit, (pCtx->dsHid.Attr.u << 8) & 0xFFFFFF);
cpu_x86_load_seg_cache(&pVM->rem.s.Env, R_ES, pCtx->es, pCtx->esHid.u64Base, pCtx->esHid.u32Limit, (pCtx->esHid.Attr.u << 8) & 0xFFFFFF);
cpu_x86_load_seg_cache(&pVM->rem.s.Env, R_FS, pCtx->fs, pCtx->fsHid.u64Base, pCtx->fsHid.u32Limit, (pCtx->fsHid.Attr.u << 8) & 0xFFFFFF);
cpu_x86_load_seg_cache(&pVM->rem.s.Env, R_GS, pCtx->gs, pCtx->gsHid.u64Base, pCtx->gsHid.u32Limit, (pCtx->gsHid.Attr.u << 8) & 0xFFFFFF);
Log2(("REMR3State: SS changed from %04x to %04x!\n", pVM->rem.s.Env.segs[R_SS].selector, pCtx->ss));
#ifdef VBOX_WITH_STATISTICS
Log2(("REMR3State: ES changed from %04x to %04x!\n", pVM->rem.s.Env.segs[R_ES].selector, pCtx->es));
#ifdef VBOX_WITH_STATISTICS
Log2(("REMR3State: CS changed from %04x to %04x!\n", pVM->rem.s.Env.segs[R_CS].selector, pCtx->cs));
#ifdef VBOX_WITH_STATISTICS
Log2(("REMR3State: DS changed from %04x to %04x!\n", pVM->rem.s.Env.segs[R_DS].selector, pCtx->ds));
#ifdef VBOX_WITH_STATISTICS
/** @todo need to find a way to communicate potential GDT/LDT changes and thread switches. The selector might
Log2(("REMR3State: FS changed from %04x to %04x!\n", pVM->rem.s.Env.segs[R_FS].selector, pCtx->fs));
#ifdef VBOX_WITH_STATISTICS
Log2(("REMR3State: GS changed from %04x to %04x!\n", pVM->rem.s.Env.segs[R_GS].selector, pCtx->gs));
#ifdef VBOX_WITH_STATISTICS
#ifdef DEBUG
switch (u8TrapNo)
Log2(("REMR3State: trap=%02x errcd=%RGv cr2=%RGv nexteip=%RGv%s\n", pVM->rem.s.Env.exception_index, (RTGCPTR)pVM->rem.s.Env.error_code,
(RTGCPTR)pVM->rem.s.Env.cr[2], (RTGCPTR)pVM->rem.s.Env.exception_next_eip, pVM->rem.s.Env.exception_is_int ? " software" : ""));
pVM->rem.s.Env.interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXIT | CPU_INTERRUPT_EXITTB | CPU_INTERRUPT_TIMER);
return VINF_SUCCESS;
//// dprintf2(("FPU state CW=%04X TT=%04X SW=%04X (%04X)\n", env->fpuc, env->fpstt, env->fpus, pVMCtx->fpu.FSW));
#ifdef TARGET_X86_64
/* Note that the high dwords of 64 bits registers are undefined in 32 bits mode and are undefined after a mode change. */
#ifdef VBOX_WITH_STATISTICS
#ifdef TARGET_X86_64
#ifdef TARGET_X86_64
int rc;
Log(("REMR3StateBack: Pending trap %x %d\n", pVM->rem.s.Env.exception_index, pVM->rem.s.Env.exception_is_int));
rc = TRPMAssertTrap(pVM, pVM->rem.s.Env.exception_index, (pVM->rem.s.Env.exception_is_int) ? TRPM_SOFTWARE_INT : TRPM_HARDWARE_INT);
return VINF_SUCCESS;
//// dprintf2(("FPU state CW=%04X TT=%04X SW=%04X (%04X)\n", env->fpuc, env->fpstt, env->fpus, pVMCtx->fpu.FSW));
#ifdef TARGET_X86_64
#ifdef TARGET_X86_64
#ifdef TARGET_X86_64
bool fSaved;
RTUINT i;
RTUINT i;
int rc;
return VINF_SUCCESS;
int rc;
if (!GCPhys)
#ifndef VBOX_STRICT
AssertReleaseMsg(phys_ram_dirty, ("failed to allocate %d bytes of dirty bytes\n", phys_ram_dirty_size));
AssertReleaseMsg(phys_ram_dirty, ("failed to allocate %d bytes of dirty bytes\n", _4G >> PAGE_SHIFT));
#ifdef VBOX_WITH_NEW_PHYS_CODE
if (!GCPhys)
#ifndef VBOX_WITH_NEW_PHYS_CODE
REMR3DECL(void) REMR3NotifyPhysRamChunkRegister(PVM pVM, RTGCPHYS GCPhys, RTUINT cb, RTHCUINTPTR pvRam, unsigned fFlags)
Log(("REMR3NotifyPhysRamChunkRegister: GCPhys=%RGp cb=%d pvRam=%p fFlags=%d\n", GCPhys, cb, pvRam, fFlags));
int rc;
REMR3DECL(void) REMR3NotifyPhysRomRegister(PVM pVM, RTGCPHYS GCPhys, RTUINT cb, void *pvCopy, bool fShadow)
Log(("REMR3NotifyPhysRomRegister: GCPhys=%RGp cb=%d pvCopy=%p fShadow=%RTbool\n", GCPhys, cb, pvCopy, fShadow));
REMR3DECL(void) REMR3NotifyHandlerPhysicalRegister(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS cb, bool fHasHCHandler)
else if (fHasHCHandler)
REMR3DECL(void) REMR3NotifyHandlerPhysicalDeregister(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS cb, bool fHasHCHandler, bool fRestoreAsRAM)
Log(("REMR3NotifyHandlerPhysicalDeregister: enmType=%d GCPhys=%RGp cb=%RGp fHasHCHandler=%RTbool fRestoreAsRAM=%RTbool RAM=%08x\n",
else if (fHasHCHandler)
if (!fRestoreAsRAM)
REMR3DECL(void) REMR3NotifyHandlerPhysicalModify(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhysOld, RTGCPHYS GCPhysNew, RTGCPHYS cb, bool fHasHCHandler, bool fRestoreAsRAM)
Log(("REMR3NotifyHandlerPhysicalModify: enmType=%d GCPhysOld=%RGp GCPhysNew=%RGp cb=%RGp fHasHCHandler=%RTbool fRestoreAsRAM=%RTbool\n",
if (fHasHCHandler)
if (!fRestoreAsRAM)
#ifdef VBOX_STRICT
unsigned long off;
target_ulong remR3PhysGetPhysicalAddressCode(CPUState *env, target_ulong addr, CPUTLBEntry *pTLBEntry)
return ret;
LogRel(("\nTrying to execute code with memory type addr_code=%RGv addend=%RGp at %RGv! (iHandlerMemType=%#x iMMIOMemType=%#x)\n"
(RTGCPTR)pTLBEntry->addr_code, (RTGCPHYS)pTLBEntry->addend, (RTGCPTR)addr, pVM->rem.s.iHandlerMemType, pVM->rem.s.iMMIOMemType));
cpu_abort(env, "Trying to execute code with memory type addr_code=%RGv addend=%RGp at %RGv. (iHandlerMemType=%#x iMMIOMemType=%#x)\n",
(RTGCPTR)pTLBEntry->addr_code, (RTGCPHYS)pTLBEntry->addend, (RTGCPTR)addr, pVM->rem.s.iHandlerMemType, pVM->rem.s.iMMIOMemType);
# define VBOX_CHECK_ADDR(GCPhys) AssertMsg(PGMPhysIsGCPhysValid(cpu_single_env->pVM, (GCPhys)), ("%RGp\n", (GCPhys)))
#ifdef DEBUG_PHYS
#ifdef DEBUG_PHYS
return val;
#ifdef DEBUG_PHYS
return val;
#ifdef DEBUG_PHYS
return val;
#ifdef DEBUG_PHYS
return val;
#ifdef DEBUG_PHYS
return val;
#ifdef DEBUG_PHYS
return val;
return val;
return val;
#ifdef DEBUG_PHYS
#ifdef DEBUG_PHYS
#ifdef DEBUG_PHYS
#ifdef DEBUG_PHYS
return u32;
return u32;
return u32;
int rc;
int rc;
int rc;
/* !!!WARNING!!! This is extremely hackish right now, we assume it's only for LFB access! !!!WARNING!!! */
return u8;
return u16;
return u32;
if (fEnable)
return VINF_SUCCESS;
int rc;
rc = VMR3ReqCall(pVM, VMREQDEST_ANY, &pReq, RT_INDEFINITE_WAIT, (PFNRT)remR3DisasEnableStepping, 2, pVM, fEnable);
return rc;
static DECLCALLBACK(int) remR3CmdDisasEnableStepping(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
bool fEnable;
int rc;
if (cArgs == 0)
return rc;
int i, rc;
(void**)&pvPC);
(void**)&pvPC);
for (i=0;i<nrInstructions;i++)
if (pszPrefix)
#define USE_OLD_DUMP_AND_DISASSEMBLY
#ifdef USE_OLD_DUMP_AND_DISASSEMBLY
if (LogIs2Enabled())
(void**)&pvPC);
if (!f32BitCode)
if (pszPrefix)
if (pszPrefix)
if (!fLog2)
if (fLog)
if (LogIs2Enabled())
unsigned off = 0;
#ifdef RT_ARCH_X86
if (LogIs2Enabled())
cs,
eip,
&cbInstr);
if (!off)
else if (off > 0)
return szSym;
(pVM->rem.s.Env.eflags & IF_MASK) && !(pVM->rem.s.Env.hflags & HF_INHIBIT_IRQ_MASK) ? "enabled" : "disabled"));
#ifndef DEBUG_bird
#ifdef VBOX_WITH_STATISTICS
switch(statcode)
case STATS_QEMU_COMPILATION:
case STATS_QEMU_TOTAL:
case STATS_QEMU_RUN_TIMERS:
case STATS_TLB_LOOKUP:
case STATS_IRQ_HANDLING:
case STATS_RAW_CHECK:
switch(statcode)
case STATS_QEMU_COMPILATION:
case STATS_QEMU_TOTAL:
case STATS_QEMU_RUN_TIMERS:
case STATS_TLB_LOOKUP:
case STATS_IRQ_HANDLING:
case STATS_RAW_CHECK:
int rc;
/** @todo r=bird: In the long run we should just do the interrupt handling in EM/CPUM/TRPM/somewhere and
* if we cannot execute the interrupt handler in raw-mode just reschedule to REM. Once that is done we
return u8Interrupt;
return u64;
return u8;
return value;
return value;
int rc;
int rc;
return (int)u32;
return (int)u32;
return (int)u32;
return (int)u32;
return (int)u32;
return (int)u32;
void remR3CpuId(CPUState *env, unsigned uOperator, void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX)
CPUMGetGuestCpuId(env->pVM, uOperator, (uint32_t *)pvEAX, (uint32_t *)pvEBX, (uint32_t *)pvECX, (uint32_t *)pvEDX);
#ifndef _MSC_VER
static const char *apsz[] =
switch (uEAX)
Log(("REM: linux syscall %3d: %s (eip=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x ebp=%08x)\n",
static const char *apsz[] =
if (!LogIsEnabled())
switch (uEAX)
while (size-- > 0)
return dst;