VBoxRecompiler.c revision e74787f0d05ffd95e46f33b6c4b19f9765f64b66
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * VBox Recompiler - QEMU.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
5f0c5b2d5afe87dfb928856ca44aa3945208a41cvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
5f0c5b2d5afe87dfb928856ca44aa3945208a41cvboxsync * available from http://www.virtualbox.org. This file is free software;
5f0c5b2d5afe87dfb928856ca44aa3945208a41cvboxsync * you can redistribute it and/or modify it under the terms of the GNU
5f0c5b2d5afe87dfb928856ca44aa3945208a41cvboxsync * General Public License (GPL) as published by the Free Software
5f0c5b2d5afe87dfb928856ca44aa3945208a41cvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
5f0c5b2d5afe87dfb928856ca44aa3945208a41cvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
5f0c5b2d5afe87dfb928856ca44aa3945208a41cvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * additional information or have any questions.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync/*******************************************************************************
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync* Header Files *
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync*******************************************************************************/
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync/* Don't wanna include everything. */
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncextern void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncextern void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncextern void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncextern void tlb_flush_page(CPUX86State *env, target_ulong addr);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncextern void tlb_flush(CPUState *env, int flush_global);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncextern void sync_seg(CPUX86State *env1, int seg_reg, int selector);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncextern void sync_ldtr(CPUX86State *env1, int selector);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncextern int sync_tr(CPUX86State *env1, int selector);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncunsigned long get_phys_page_offset(target_ulong addr);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync/*******************************************************************************
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync* Defined Constants And Macros *
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync*******************************************************************************/
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync/** Copy 80-bit fpu register at pSrc to pDst.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * This is probably faster than *calling* memcpy.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync do { *(PX86FPUMMX)(pDst) = *(const X86FPUMMX *)(pSrc); } while (0)
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync/*******************************************************************************
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync* Internal Functions *
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync*******************************************************************************/
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncstatic DECLCALLBACK(int) remR3Save(PVM pVM, PSSMHANDLE pSSM);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncstatic DECLCALLBACK(int) remR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncstatic uint32_t remR3MMIOReadU8(void *pvVM, target_phys_addr_t GCPhys);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncstatic uint32_t remR3MMIOReadU16(void *pvVM, target_phys_addr_t GCPhys);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncstatic uint32_t remR3MMIOReadU32(void *pvVM, target_phys_addr_t GCPhys);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncstatic void remR3MMIOWriteU8(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncstatic void remR3MMIOWriteU16(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncstatic void remR3MMIOWriteU32(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncstatic uint32_t remR3HandlerReadU8(void *pvVM, target_phys_addr_t GCPhys);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncstatic uint32_t remR3HandlerReadU16(void *pvVM, target_phys_addr_t GCPhys);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncstatic uint32_t remR3HandlerReadU32(void *pvVM, target_phys_addr_t GCPhys);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncstatic void remR3HandlerWriteU8(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncstatic void remR3HandlerWriteU16(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncstatic void remR3HandlerWriteU32(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync/*******************************************************************************
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync* Global Variables *
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync*******************************************************************************/
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync/** @todo Move stats to REM::s some rainy day we have nothing do to. */
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Global stuff.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync/** MMIO read callbacks. */
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync/** MMIO write callbacks. */
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync/** Handler read callbacks. */
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync/** Handler write callbacks. */
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync#if defined(VBOX_WITH_DEBUGGER) && !(defined(RT_OS_WINDWS) && defined(RT_ARCH_AMD64))
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Debugger commands.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncstatic DECLCALLBACK(int) remR3CmdDisasEnableStepping(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync/** '.remstep' arguments. */
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync { 0, ~0, DBGCVAR_CAT_NUMBER, 0, "on/off", "Boolean value/mnemonic indicating the new state." },
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync/** Command descriptors. */
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync .pszDescription = "Enable or disable the single stepping with logged disassembly. "
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync "If no arguments show the current state."
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync/* Instantiate the structure signatures. */
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync/*******************************************************************************
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync* Internal Functions *
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync*******************************************************************************/
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncextern int testmath(void);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync/* Put them here to avoid unused variable warning. */
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncAssertCompile(RT_SIZEOFMEMB(VM, rem.padding) >= RT_SIZEOFMEMB(VM, rem.s));
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync#if !defined(IPRT_NO_CRT) && (defined(RT_OS_LINUX) || defined(RT_OS_DARWIN) || defined(RT_OS_WINDOWS))
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync//AssertCompileMemberSize(REM, Env, REM_ENV_SIZE);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync/* Why did this have to be identical?? */
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncAssertCompile(RT_SIZEOFMEMB(REM, Env) <= REM_ENV_SIZE);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncAssertCompile(RT_SIZEOFMEMB(REM, Env) <= REM_ENV_SIZE);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Initializes the REM.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * @returns VBox status code.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * @param pVM The VM to operate on.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync unsigned i;
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Assert sanity.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync 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)));
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync AssertReleaseMsg(sizeof(pVM->rem.s.Env) <= REM_ENV_SIZE, ("%#x == %#x\n", sizeof(pVM->rem.s.Env), REM_ENV_SIZE));
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync AssertReleaseMsg(!(RT_OFFSETOF(VM, rem) & 31), ("off=%#x\n", RT_OFFSETOF(VM, rem)));
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync#if defined(DEBUG) && !defined(RT_OS_SOLARIS) /// @todo fix the solaris math stuff.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Init some internal data members.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync int rc = CPUMQueryGuestCtxPtr(pVM, &pVM->rem.s.pCtx);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync AssertMsgFailed(("Failed to obtain guest ctx pointer. rc=%Vrc\n", rc));
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync AssertMsg(MMR3PhysGetRamSize(pVM) == 0, ("Init order have changed! REM depends on notification about ALL physical memory registrations\n"));
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync /* ignore all notifications */
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Init the recompiler.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync AssertMsgFailed(("cpu_x86_init failed - impossible!\n"));
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync CPUMGetGuestCpuId(pVM, 1, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext_features, &pVM->rem.s.Env.cpuid_features);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync CPUMGetGuestCpuId(pVM, 0x80000001, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext3_features, &pVM->rem.s.Env.cpuid_ext2_features);
2c7d4e9e38744aab50f42ed520e4b337f453bdd2vboxsync /* allocate code buffer for single instruction emulation. */
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync pVM->rem.s.Env.pvCodeBuffer = RTMemExecAlloc(pVM->rem.s.Env.cbCodeBuffer);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync AssertMsgReturn(pVM->rem.s.Env.pvCodeBuffer, ("Failed to allocate code buffer!\n"), VERR_NO_MEMORY);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync /* finally, set the cpu_single_env global. */
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync /* Nothing is pending by default */
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync pVM->rem.s.u32PendingInterrupt = REM_NO_PENDING_IRQ;
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Register ram types.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync pVM->rem.s.iMMIOMemType = cpu_register_io_memory(-1, g_apfnMMIORead, g_apfnMMIOWrite, pVM);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync AssertReleaseMsg(pVM->rem.s.iMMIOMemType >= 0, ("pVM->rem.s.iMMIOMemType=%d\n", pVM->rem.s.iMMIOMemType));
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync pVM->rem.s.iHandlerMemType = cpu_register_io_memory(-1, g_apfnHandlerRead, g_apfnHandlerWrite, pVM);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync AssertReleaseMsg(pVM->rem.s.iHandlerMemType >= 0, ("pVM->rem.s.iHandlerMemType=%d\n", pVM->rem.s.iHandlerMemType));
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync Log2(("REM: iMMIOMemType=%d iHandlerMemType=%d\n", pVM->rem.s.iMMIOMemType, pVM->rem.s.iHandlerMemType));
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync /* stop ignoring. */
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Register the saved state data unit.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync rc = SSMR3RegisterInternal(pVM, "rem", 1, REM_SAVED_STATE_VERSION, sizeof(uint32_t) * 10,
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync#if defined(VBOX_WITH_DEBUGGER) && !(defined(RT_OS_WINDOWS) && defined(RT_ARCH_AMD64))
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Debugger commands.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync static bool fRegisteredCmds = false;
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync int rc = DBGCRegisterCommands(&g_aCmds[0], ELEMENTS(g_aCmds));
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Statistics.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatExecuteSingleInstr, STAMTYPE_PROFILE, "/PROF/REM/SingleInstr",STAMUNIT_TICKS_PER_CALL, "Profiling single instruction emulation.");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatCompilationQEmu, STAMTYPE_PROFILE, "/PROF/REM/Compile", STAMUNIT_TICKS_PER_CALL, "Profiling QEmu compilation.");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatRunCodeQEmu, STAMTYPE_PROFILE, "/PROF/REM/Runcode", STAMUNIT_TICKS_PER_CALL, "Profiling QEmu code execution.");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatTotalTimeQEmu, STAMTYPE_PROFILE, "/PROF/REM/Emulate", STAMUNIT_TICKS_PER_CALL, "Profiling code emulation.");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatTimers, STAMTYPE_PROFILE, "/PROF/REM/Timers", STAMUNIT_TICKS_PER_CALL, "Profiling timer scheduling.");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatTBLookup, STAMTYPE_PROFILE, "/PROF/REM/TBLookup", STAMUNIT_TICKS_PER_CALL, "Profiling timer scheduling.");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatIRQ, STAMTYPE_PROFILE, "/PROF/REM/IRQ", STAMUNIT_TICKS_PER_CALL, "Profiling timer scheduling.");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatRawCheck, STAMTYPE_PROFILE, "/PROF/REM/RawCheck", STAMUNIT_TICKS_PER_CALL, "Profiling timer scheduling.");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatMemRead, STAMTYPE_PROFILE, "/PROF/REM/MemRead", STAMUNIT_TICKS_PER_CALL, "Profiling memory access.");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatMemWrite, STAMTYPE_PROFILE, "/PROF/REM/MemWrite", STAMUNIT_TICKS_PER_CALL, "Profiling memory access.");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatHCVirt2GCPhys, STAMTYPE_PROFILE, "/PROF/REM/HCVirt2GCPhys", STAMUNIT_TICKS_PER_CALL, "Profiling memory convertion.");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatGCPhys2HCVirt, STAMTYPE_PROFILE, "/PROF/REM/GCPhys2HCVirt", STAMUNIT_TICKS_PER_CALL, "Profiling memory convertion.");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatCpuGetTSC, STAMTYPE_COUNTER, "/REM/CpuGetTSC", STAMUNIT_OCCURENCES, "cpu_get_tsc calls");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatRefuseTFInhibit, STAMTYPE_COUNTER, "/REM/Refuse/TFInibit", STAMUNIT_OCCURENCES, "Raw mode refused because of TF or irq inhibit");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatRefuseVM86, STAMTYPE_COUNTER, "/REM/Refuse/VM86", STAMUNIT_OCCURENCES, "Raw mode refused because of VM86");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatRefusePaging, STAMTYPE_COUNTER, "/REM/Refuse/Paging", STAMUNIT_OCCURENCES, "Raw mode refused because of disabled paging/pm");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatRefusePAE, STAMTYPE_COUNTER, "/REM/Refuse/PAE", STAMUNIT_OCCURENCES, "Raw mode refused because of PAE");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatRefuseIOPLNot0, STAMTYPE_COUNTER, "/REM/Refuse/IOPLNot0", STAMUNIT_OCCURENCES, "Raw mode refused because of IOPL != 0");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatRefuseIF0, STAMTYPE_COUNTER, "/REM/Refuse/IF0", STAMUNIT_OCCURENCES, "Raw mode refused because of IF=0");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatRefuseCode16, STAMTYPE_COUNTER, "/REM/Refuse/Code16", STAMUNIT_OCCURENCES, "Raw mode refused because of 16 bit code");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatRefuseWP0, STAMTYPE_COUNTER, "/REM/Refuse/WP0", STAMUNIT_OCCURENCES, "Raw mode refused because of WP=0");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatRefuseRing1or2, STAMTYPE_COUNTER, "/REM/Refuse/Ring1or2", STAMUNIT_OCCURENCES, "Raw mode refused because of ring 1/2 execution");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatRefuseCanExecute, STAMTYPE_COUNTER, "/REM/Refuse/CanExecuteRaw", STAMUNIT_OCCURENCES, "Raw mode refused because of cCanExecuteRaw");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatREMGDTChange, STAMTYPE_COUNTER, "/REM/Change/GDTBase", STAMUNIT_OCCURENCES, "GDT base changes");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatREMLDTRChange, STAMTYPE_COUNTER, "/REM/Change/LDTR", STAMUNIT_OCCURENCES, "LDTR changes");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatREMIDTChange, STAMTYPE_COUNTER, "/REM/Change/IDTBase", STAMUNIT_OCCURENCES, "IDT base changes");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatREMTRChange, STAMTYPE_COUNTER, "/REM/Change/TR", STAMUNIT_OCCURENCES, "TR selector changes");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatSelOutOfSync[0], STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/ES", STAMUNIT_OCCURENCES, "ES out of sync");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatSelOutOfSync[1], STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/CS", STAMUNIT_OCCURENCES, "CS out of sync");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatSelOutOfSync[2], STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/SS", STAMUNIT_OCCURENCES, "SS out of sync");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatSelOutOfSync[3], STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/DS", STAMUNIT_OCCURENCES, "DS out of sync");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatSelOutOfSync[4], STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/FS", STAMUNIT_OCCURENCES, "FS out of sync");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatSelOutOfSync[5], STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/GS", STAMUNIT_OCCURENCES, "GS out of sync");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatSelOutOfSyncStateBack[0], STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/ES", STAMUNIT_OCCURENCES, "ES out of sync");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatSelOutOfSyncStateBack[1], STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/CS", STAMUNIT_OCCURENCES, "CS out of sync");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatSelOutOfSyncStateBack[2], STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/SS", STAMUNIT_OCCURENCES, "SS out of sync");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatSelOutOfSyncStateBack[3], STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/DS", STAMUNIT_OCCURENCES, "DS out of sync");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatSelOutOfSyncStateBack[4], STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/FS", STAMUNIT_OCCURENCES, "FS out of sync");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync STAM_REG(pVM, &gStatSelOutOfSyncStateBack[5], STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/GS", STAMUNIT_OCCURENCES, "GS out of sync");
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Terminates the REM.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Termination means cleaning up and freeing all resources,
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * the VM it self is at this point powered off or suspended.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * @returns VBox status code.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * @param pVM The VM to operate on.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * The VM is being reset.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * For the REM component this means to call the cpu_reset() and
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * reinitialize some state variables.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * @param pVM VM handle.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Reset the REM cpu.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync /* Clear raw ring 0 init state */
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Execute state save operation.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * @returns VBox status code.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * @param pVM VM Handle.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * @param pSSM SSM operation handle.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncstatic DECLCALLBACK(int) remR3Save(PVM pVM, PSSMHANDLE pSSM)
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Save the required CPU Env bits.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * (Not much because we're never in REM when doing the save.)
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync SSMR3PutMem(pSSM, &pRem->Env, RT_OFFSETOF(CPUState, jmp_env));
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync /* Remember if we've entered raw mode (vital for ring 1 checks in e.g. iret emulation). */
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync SSMR3PutU32(pSSM, !!(pRem->Env.state & CPU_RAW_RING0));
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Save the REM stuff.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync unsigned i;
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync SSMR3PutGCPtr(pSSM, pRem->aGCPtrInvalidatedPages[i]);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync SSMR3PutUInt(pSSM, pVM->rem.s.u32PendingInterrupt);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Execute state load operation.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * @returns VBox status code.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * @param pVM VM Handle.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * @param pSSM SSM operation handle.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * @param u32Version Data layout version.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsyncstatic DECLCALLBACK(int) remR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version)
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Validate version.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync Log(("remR3Load: Invalid version u32Version=%d!\n", u32Version));
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Do a reset to be on the safe side...
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Ignore all ignorable notifications.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * (Not doing this will cause serious trouble.)
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Load the required CPU Env bits.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * (Not much because we're never in REM when doing the save.)
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync SSMR3GetMem(pSSM, &pRem->Env, RT_OFFSETOF(CPUState, jmp_env));
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync int rc = SSMR3GetU32(pSSM, &u32Sep); /* separator */
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync /* Remember if we've entered raw mode (vital for ring 1 checks in e.g. iret emulation). */
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Load the REM stuff.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync if (pRem->cInvalidatedPages > ELEMENTS(pRem->aGCPtrInvalidatedPages))
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync AssertMsgFailed(("cInvalidatedPages=%#x\n", pRem->cInvalidatedPages));
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync unsigned i;
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync SSMR3GetGCPtr(pSSM, &pRem->aGCPtrInvalidatedPages[i]);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync rc = SSMR3GetUInt(pSSM, &pVM->rem.s.u32PendingInterrupt);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync /* check the terminator. */
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Get the CPUID features.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync CPUMGetGuestCpuId(pVM, 1, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext_features, &pVM->rem.s.Env.cpuid_features);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync CPUMGetGuestCpuId(pVM, 0x80000001, &u32Dummy, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext2_features);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Sync the Load Flush the TLB
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync#if 0 /** @todo r=bird: this doesn't make sense. WHY? */
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Clear all lazy flags (only FPU sync for now).
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Stop ignoring ignornable notifications.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Single steps an instruction in recompiled mode.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Before calling this function the REM state needs to be in sync with
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * the VM. Call REMR3State() to perform the sync. It's only necessary
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * (and permitted) to sync at the first call to REMR3Step()/REMR3Run()
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * and after calling REMR3StateBack().
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * @returns VBox status code.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * @param pVM VM Handle.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Lock the REM - we don't wanna have anyone interrupting us
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * while stepping - and enabled single stepping. We also ignore
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * pending interrupts and suchlike.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync int interrupt_request = pVM->rem.s.Env.interrupt_request;
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync 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)));
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * If we're standing at a breakpoint, that have to be disabled before we start stepping.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync RTGCPTR GCPtrPC = pVM->rem.s.Env.eip + pVM->rem.s.Env.segs[R_CS].base;
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync bool fBp = !cpu_breakpoint_remove(&pVM->rem.s.Env, GCPtrPC);
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Execute and handle the return code.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * We execute without enabling the cpu tick, so on success we'll
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * just flip it on and off to make sure it moves
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync AssertMsgFailed(("Damn, this shouldn't happen! cpu_exec returned %d while singlestepping\n", rc));
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync AssertReleaseMsgFailed(("This really shouldn't happen, rc=%d!\n", rc));
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Restore the stuff we changed to prevent interruption.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync * Unlock the REM.
cac6f24ef29dfb7bea51e8846272e278b16ee5d8vboxsync int rc2 = cpu_breakpoint_insert(&pVM->rem.s.Env, GCPtrPC);
return rc;
return VINF_SUCCESS;
return VERR_REM_NO_MORE_BP_SLOTS;
return VINF_SUCCESS;
return VERR_REM_BP_NOT_FOUND;
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)));
switch (rc)
case EXCP_SINGLE_INSTR:
case EXCP_INTERRUPT:
case EXCP_DEBUG:
int iBP;
Log2(("REMR3EmulateInstruction: cpu_exec -> EXCP_DEBUG rc=%Vrc iBP=%d GCPtrPC=%VGv\n", rc, iBP, GCPtrPC));
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:
# 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;
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 %Vrc (cs:eip=%04x:%08x)\n", rc, pVM->rem.s.Env.segs[R_CS].selector, 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"));
fGlobal = true;
Log(("remR3FlushTLB: CR0=%VGp CR3=%VGp CR4=%VGp %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) -> %Vrc\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=%VGv eip=%VGv cr2=%08x\n", uTrap, uErrorCode, pvNextEIP, env->eip, env->cr[2]));
#ifdef DEBUG
LogRel(("VERR_REM_TOO_MANY_TRAPS -> uTrap=%x error=%x next_eip=%VGv eip=%VGv cr2=%08x\n", uTrap, uErrorCode, pvNextEIP, env->eip, 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;
#ifdef TARGET_X86_64
RTUINT i;
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 TARGET_X86_64
/* Note that FS_BASE & GS_BASE are already synced; QEmu keeps them in the hidden selector registers.
#ifdef DEBUG
switch (u8TrapNo)
Log2(("REMR3State: trap=%02x errcd=%VGv cr2=%VGv nexteip=%VGv%s\n", pVM->rem.s.Env.exception_index, pVM->rem.s.Env.error_code,
pVM->rem.s.Env.cr[2], 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
#ifdef VBOX_WITH_STATISTICS
#ifdef TARGET_X86_64
#ifdef TARGET_X86_64
Log(("REMR3StateBack: Pending trap %x %d\n", pVM->rem.s.Env.exception_index, pVM->rem.s.Env.exception_is_int));
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
RTUINT i;
RTUINT i;
int rc;
return VINF_SUCCESS;
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=%VGp 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=%VGp 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=%VGp cb=%VGp 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=%VGp GCPhysNew=%VGp cb=%d fHasHCHandler=%RTbool fRestoreAsRAM=%RTbool\n",
if (fHasHCHandler)
if (!fRestoreAsRAM)
#ifdef VBOX_STRICT
target_ulong remR3PhysGetPhysicalAddressCode(CPUState *env, target_ulong addr, CPUTLBEntry *pTLBEntry)
return ret;
LogRel(("\nTrying to execute code with memory type addr_code=%VGv addend=%VGp at %VGv! (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=%VGv addend=%VGp at %VGv. (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)), ("%VGp\n", (GCPhys)))
return val;
return val;
return val;
return val;
return val;
return val;
return val;
return u32;
return u32;
return u32;
/* !!!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;
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;
void *pvPC;
&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;
&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 (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);
static const char *apsz[] =
switch (uEAX)
Log(("REM: linux syscall %3d: %s (eip=%VGv 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;