VBoxRecompiler.c revision 6f034db983236115a93bf29695b6314bcd840727
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * VBox Recompiler - QEMU.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * available from http://www.virtualbox.org. This file is free software;
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * you can redistribute it and/or modify it under the terms of the GNU
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * General Public License (GPL) as published by the Free Software
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * additional information or have any questions.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync/*******************************************************************************
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync* Header Files *
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync*******************************************************************************/
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync/* Don't wanna include everything. */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncextern void cpu_exec_init_all(unsigned long tb_size);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncextern void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncextern void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncextern void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncextern void tlb_flush_page(CPUX86State *env, target_ulong addr);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncextern void tlb_flush(CPUState *env, int flush_global);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncextern void sync_seg(CPUX86State *env1, int seg_reg, int selector);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncextern void sync_ldtr(CPUX86State *env1, int selector);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncunsigned long get_phys_page_offset(target_ulong addr);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync/*******************************************************************************
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync* Defined Constants And Macros *
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync*******************************************************************************/
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync/** Copy 80-bit fpu register at pSrc to pDst.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * This is probably faster than *calling* memcpy.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync do { *(PX86FPUMMX)(pDst) = *(const X86FPUMMX *)(pSrc); } while (0)
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync/*******************************************************************************
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync* Internal Functions *
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync*******************************************************************************/
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncstatic DECLCALLBACK(int) remR3Save(PVM pVM, PSSMHANDLE pSSM);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncstatic DECLCALLBACK(int) remR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncstatic void remR3StateUpdate(PVM pVM, PVMCPU pVCpu);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncstatic int remR3InitPhysRamSizeAndDirtyMap(PVM pVM, bool fGuarded);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncstatic uint32_t remR3MMIOReadU8(void *pvVM, target_phys_addr_t GCPhys);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncstatic uint32_t remR3MMIOReadU16(void *pvVM, target_phys_addr_t GCPhys);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncstatic uint32_t remR3MMIOReadU32(void *pvVM, target_phys_addr_t GCPhys);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncstatic void remR3MMIOWriteU8(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncstatic void remR3MMIOWriteU16(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncstatic void remR3MMIOWriteU32(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncstatic uint32_t remR3HandlerReadU8(void *pvVM, target_phys_addr_t GCPhys);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncstatic uint32_t remR3HandlerReadU16(void *pvVM, target_phys_addr_t GCPhys);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncstatic uint32_t remR3HandlerReadU32(void *pvVM, target_phys_addr_t GCPhys);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncstatic void remR3HandlerWriteU8(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncstatic void remR3HandlerWriteU16(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncstatic void remR3HandlerWriteU32(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync/*******************************************************************************
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync* Global Variables *
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync*******************************************************************************/
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync/** @todo Move stats to REM::s some rainy day we have nothing do to. */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Global stuff.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync/** MMIO read callbacks. */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync/** MMIO write callbacks. */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync/** Handler read callbacks. */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync/** Handler write callbacks. */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync#if defined(VBOX_WITH_DEBUGGER) && !(defined(RT_OS_WINDOWS) && defined(RT_ARCH_AMD64))
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Debugger commands.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncstatic DECLCALLBACK(int) remR3CmdDisasEnableStepping(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync/** '.remstep' arguments. */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync { 0, ~0, DBGCVAR_CAT_NUMBER, 0, "on/off", "Boolean value/mnemonic indicating the new state." },
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync/** Command descriptors. */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync .pszDescription = "Enable or disable the single stepping with logged disassembly. "
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync "If no arguments show the current state."
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync/** Prologue code, must be in lower 4G to simplify jumps to/from generated code. */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync/*******************************************************************************
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync* Internal Functions *
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync*******************************************************************************/
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncextern int testmath(void);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync/* Put them here to avoid unused variable warning. */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncAssertCompile(RT_SIZEOFMEMB(VM, rem.padding) >= RT_SIZEOFMEMB(VM, rem.s));
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync#if !defined(IPRT_NO_CRT) && (defined(RT_OS_LINUX) || defined(RT_OS_DARWIN) || defined(RT_OS_WINDOWS))
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync//AssertCompileMemberSize(REM, Env, REM_ENV_SIZE);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync/* Why did this have to be identical?? */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncAssertCompile(RT_SIZEOFMEMB(REM, Env) <= REM_ENV_SIZE);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncAssertCompile(RT_SIZEOFMEMB(REM, Env) <= REM_ENV_SIZE);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Initializes the REM.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * @returns VBox status code.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * @param pVM The VM to operate on.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Assert sanity.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync 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)));
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync AssertReleaseMsg(sizeof(pVM->rem.s.Env) <= REM_ENV_SIZE, ("%#x == %#x\n", sizeof(pVM->rem.s.Env), REM_ENV_SIZE));
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync AssertReleaseMsg(!(RT_OFFSETOF(VM, rem) & 31), ("off=%#x\n", RT_OFFSETOF(VM, rem)));
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync#if defined(DEBUG) && !defined(RT_OS_SOLARIS) && !defined(RT_OS_FREEBSD) /// @todo fix the solaris and freebsd math stuff.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Init some internal data members.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync pVM->rem.s.pCtx = NULL; /* set when executing code. */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync AssertMsg(MMR3PhysGetRamSize(pVM) == 0, ("Init order has changed! REM depends on notification about ALL physical memory registrations\n"));
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync /* ignore all notifications */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync AssertLogRelReturn(code_gen_prologue, VERR_NO_MEMORY);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Init the recompiler.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync AssertMsgFailed(("cpu_x86_init failed - impossible!\n"));
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync CPUMGetGuestCpuId(pVCpu, 1, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext_features, &pVM->rem.s.Env.cpuid_features);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync CPUMGetGuestCpuId(pVCpu, 0x80000001, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext3_features, &pVM->rem.s.Env.cpuid_ext2_features);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync /* allocate code buffer for single instruction emulation. */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync pVM->rem.s.Env.pvCodeBuffer = RTMemExecAlloc(pVM->rem.s.Env.cbCodeBuffer);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync AssertMsgReturn(pVM->rem.s.Env.pvCodeBuffer, ("Failed to allocate code buffer!\n"), VERR_NO_MEMORY);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync /* finally, set the cpu_single_env global. */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync /* Nothing is pending by default */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync pVM->rem.s.u32PendingInterrupt = REM_NO_PENDING_IRQ;
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Register ram types.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync pVM->rem.s.iMMIOMemType = cpu_register_io_memory(-1, g_apfnMMIORead, g_apfnMMIOWrite, pVM);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync AssertReleaseMsg(pVM->rem.s.iMMIOMemType >= 0, ("pVM->rem.s.iMMIOMemType=%d\n", pVM->rem.s.iMMIOMemType));
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync pVM->rem.s.iHandlerMemType = cpu_register_io_memory(-1, g_apfnHandlerRead, g_apfnHandlerWrite, pVM);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync AssertReleaseMsg(pVM->rem.s.iHandlerMemType >= 0, ("pVM->rem.s.iHandlerMemType=%d\n", pVM->rem.s.iHandlerMemType));
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync Log2(("REM: iMMIOMemType=%d iHandlerMemType=%d\n", pVM->rem.s.iMMIOMemType, pVM->rem.s.iHandlerMemType));
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync /* stop ignoring. */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Register the saved state data unit.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync rc = SSMR3RegisterInternal(pVM, "rem", 1, REM_SAVED_STATE_VERSION, sizeof(uint32_t) * 10,
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync#if defined(VBOX_WITH_DEBUGGER) && !(defined(RT_OS_WINDOWS) && defined(RT_ARCH_AMD64))
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Debugger commands.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync static bool fRegisteredCmds = false;
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync int rc = DBGCRegisterCommands(&g_aCmds[0], RT_ELEMENTS(g_aCmds));
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Statistics.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatExecuteSingleInstr, STAMTYPE_PROFILE, "/PROF/REM/SingleInstr",STAMUNIT_TICKS_PER_CALL, "Profiling single instruction emulation.");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatCompilationQEmu, STAMTYPE_PROFILE, "/PROF/REM/Compile", STAMUNIT_TICKS_PER_CALL, "Profiling QEmu compilation.");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatRunCodeQEmu, STAMTYPE_PROFILE, "/PROF/REM/Runcode", STAMUNIT_TICKS_PER_CALL, "Profiling QEmu code execution.");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatTotalTimeQEmu, STAMTYPE_PROFILE, "/PROF/REM/Emulate", STAMUNIT_TICKS_PER_CALL, "Profiling code emulation.");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatTimers, STAMTYPE_PROFILE, "/PROF/REM/Timers", STAMUNIT_TICKS_PER_CALL, "Profiling timer scheduling.");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatTBLookup, STAMTYPE_PROFILE, "/PROF/REM/TBLookup", STAMUNIT_TICKS_PER_CALL, "Profiling timer scheduling.");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatIRQ, STAMTYPE_PROFILE, "/PROF/REM/IRQ", STAMUNIT_TICKS_PER_CALL, "Profiling timer scheduling.");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatRawCheck, STAMTYPE_PROFILE, "/PROF/REM/RawCheck", STAMUNIT_TICKS_PER_CALL, "Profiling timer scheduling.");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatMemRead, STAMTYPE_PROFILE, "/PROF/REM/MemRead", STAMUNIT_TICKS_PER_CALL, "Profiling memory access.");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatMemWrite, STAMTYPE_PROFILE, "/PROF/REM/MemWrite", STAMUNIT_TICKS_PER_CALL, "Profiling memory access.");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatHCVirt2GCPhys, STAMTYPE_PROFILE, "/PROF/REM/HCVirt2GCPhys", STAMUNIT_TICKS_PER_CALL, "Profiling memory convertion.");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatGCPhys2HCVirt, STAMTYPE_PROFILE, "/PROF/REM/GCPhys2HCVirt", STAMUNIT_TICKS_PER_CALL, "Profiling memory convertion.");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatCpuGetTSC, STAMTYPE_COUNTER, "/REM/CpuGetTSC", STAMUNIT_OCCURENCES, "cpu_get_tsc calls");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatRefuseTFInhibit, STAMTYPE_COUNTER, "/REM/Refuse/TFInibit", STAMUNIT_OCCURENCES, "Raw mode refused because of TF or irq inhibit");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatRefuseVM86, STAMTYPE_COUNTER, "/REM/Refuse/VM86", STAMUNIT_OCCURENCES, "Raw mode refused because of VM86");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatRefusePaging, STAMTYPE_COUNTER, "/REM/Refuse/Paging", STAMUNIT_OCCURENCES, "Raw mode refused because of disabled paging/pm");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatRefusePAE, STAMTYPE_COUNTER, "/REM/Refuse/PAE", STAMUNIT_OCCURENCES, "Raw mode refused because of PAE");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatRefuseIOPLNot0, STAMTYPE_COUNTER, "/REM/Refuse/IOPLNot0", STAMUNIT_OCCURENCES, "Raw mode refused because of IOPL != 0");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatRefuseIF0, STAMTYPE_COUNTER, "/REM/Refuse/IF0", STAMUNIT_OCCURENCES, "Raw mode refused because of IF=0");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatRefuseCode16, STAMTYPE_COUNTER, "/REM/Refuse/Code16", STAMUNIT_OCCURENCES, "Raw mode refused because of 16 bit code");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatRefuseWP0, STAMTYPE_COUNTER, "/REM/Refuse/WP0", STAMUNIT_OCCURENCES, "Raw mode refused because of WP=0");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatRefuseRing1or2, STAMTYPE_COUNTER, "/REM/Refuse/Ring1or2", STAMUNIT_OCCURENCES, "Raw mode refused because of ring 1/2 execution");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatRefuseCanExecute, STAMTYPE_COUNTER, "/REM/Refuse/CanExecuteRaw", STAMUNIT_OCCURENCES, "Raw mode refused because of cCanExecuteRaw");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatFlushTBs, STAMTYPE_COUNTER, "/REM/FlushTB", STAMUNIT_OCCURENCES, "Number of TB flushes");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatREMGDTChange, STAMTYPE_COUNTER, "/REM/Change/GDTBase", STAMUNIT_OCCURENCES, "GDT base changes");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatREMLDTRChange, STAMTYPE_COUNTER, "/REM/Change/LDTR", STAMUNIT_OCCURENCES, "LDTR changes");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatREMIDTChange, STAMTYPE_COUNTER, "/REM/Change/IDTBase", STAMUNIT_OCCURENCES, "IDT base changes");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatREMTRChange, STAMTYPE_COUNTER, "/REM/Change/TR", STAMUNIT_OCCURENCES, "TR selector changes");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatSelOutOfSync[0], STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/ES", STAMUNIT_OCCURENCES, "ES out of sync");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatSelOutOfSync[1], STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/CS", STAMUNIT_OCCURENCES, "CS out of sync");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatSelOutOfSync[2], STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/SS", STAMUNIT_OCCURENCES, "SS out of sync");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatSelOutOfSync[3], STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/DS", STAMUNIT_OCCURENCES, "DS out of sync");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatSelOutOfSync[4], STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/FS", STAMUNIT_OCCURENCES, "FS out of sync");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatSelOutOfSync[5], STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/GS", STAMUNIT_OCCURENCES, "GS out of sync");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatSelOutOfSyncStateBack[0], STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/ES", STAMUNIT_OCCURENCES, "ES out of sync");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatSelOutOfSyncStateBack[1], STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/CS", STAMUNIT_OCCURENCES, "CS out of sync");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatSelOutOfSyncStateBack[2], STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/SS", STAMUNIT_OCCURENCES, "SS out of sync");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatSelOutOfSyncStateBack[3], STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/DS", STAMUNIT_OCCURENCES, "DS out of sync");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatSelOutOfSyncStateBack[4], STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/FS", STAMUNIT_OCCURENCES, "FS out of sync");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &gStatSelOutOfSyncStateBack[5], STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/GS", STAMUNIT_OCCURENCES, "GS out of sync");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REG(pVM, &pVM->rem.s.Env.StatTbFlush, STAMTYPE_PROFILE, "/REM/TbFlush", STAMUNIT_TICKS_PER_CALL, "profiling tb_flush().");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync#endif /* VBOX_WITH_STATISTICS */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REL_REG(pVM, &tb_flush_count, STAMTYPE_U32_RESET, "/REM/TbFlushCount", STAMUNIT_OCCURENCES, "tb_flush() calls");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REL_REG(pVM, &tb_phys_invalidate_count, STAMTYPE_U32_RESET, "/REM/TbPhysInvldCount", STAMUNIT_OCCURENCES, "tb_phys_invalidate() calls");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync STAM_REL_REG(pVM, &tlb_flush_count, STAMTYPE_U32_RESET, "/REM/TlbFlushCount", STAMUNIT_OCCURENCES, "tlb_flush() calls");
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Finalizes the REM initialization.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * This is called after all components, devices and drivers has
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * been initialized. Its main purpose it to finish the RAM related
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * initialization.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * @returns VBox status code.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * @param pVM The VM handle.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Ram size & dirty bit map.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync rc = remR3InitPhysRamSizeAndDirtyMap(pVM, true /* fGuarded */);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync rc = remR3InitPhysRamSizeAndDirtyMap(pVM, false /* fGuarded */);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Initializes phys_ram_size, phys_ram_dirty and phys_ram_dirty_size.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * @returns VBox status code.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * @param pVM The VM handle.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * @param fGuarded Whether to guard the map.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncstatic int remR3InitPhysRamSizeAndDirtyMap(PVM pVM, bool fGuarded)
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync AssertLogRelMsgReturn(cb > pVM->rem.s.GCPhysLastRam,
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync ("GCPhysLastRam=%RGp - out of range\n", pVM->rem.s.GCPhysLastRam),
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync AssertMsg(((RTGCPHYS)phys_ram_dirty_size << PAGE_SHIFT) == cb, ("%RGp\n", cb));
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync phys_ram_dirty = MMR3HeapAlloc(pVM, MM_TAG_REM, phys_ram_dirty_size);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync AssertLogRelMsgReturn(phys_ram_dirty, ("Failed to allocate %u bytes of dirty page map bytes\n", phys_ram_dirty_size), VERR_NO_MEMORY);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Fill it up the nearest 4GB RAM and leave at least _64KB of guard after it.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync uint32_t cbBitmapAligned = RT_ALIGN_32(phys_ram_dirty_size, PAGE_SIZE);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync uint32_t cbBitmapFull = RT_ALIGN_32(phys_ram_dirty_size, (_4G >> PAGE_SHIFT));
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync AssertLogRelMsgReturn(phys_ram_dirty, ("Failed to allocate %u bytes of dirty page map bytes\n", cbBitmapFull), VERR_NO_MEMORY);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync rc = RTMemProtect(phys_ram_dirty + cbBitmapAligned, cbBitmapFull - cbBitmapAligned, RTMEM_PROT_NONE);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync phys_ram_dirty += cbBitmapAligned - phys_ram_dirty_size;
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync /* initialize it. */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Terminates the REM.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Termination means cleaning up and freeing all resources,
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * the VM it self is at this point powered off or suspended.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * @returns VBox status code.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * @param pVM The VM to operate on.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Statistics.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync#endif /* VBOX_WITH_STATISTICS */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * The VM is being reset.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * For the REM component this means to call the cpu_reset() and
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * reinitialize some state variables.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * @param pVM VM handle.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Reset the REM cpu.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync /* Clear raw ring 0 init state */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync /* Flush the TBs the next time we execute code here. */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Execute state save operation.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * @returns VBox status code.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * @param pVM VM Handle.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * @param pSSM SSM operation handle.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncstatic DECLCALLBACK(int) remR3Save(PVM pVM, PSSMHANDLE pSSM)
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Save the required CPU Env bits.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * (Not much because we're never in REM when doing the save.)
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync /* Remember if we've entered raw mode (vital for ring 1 checks in e.g. iret emulation). */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync SSMR3PutU32(pSSM, !!(pRem->Env.state & CPU_RAW_RING0));
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync SSMR3PutUInt(pSSM, pVM->rem.s.u32PendingInterrupt);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Execute state load operation.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * @returns VBox status code.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * @param pVM VM Handle.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * @param pSSM SSM operation handle.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * @param u32Version Data layout version.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsyncstatic DECLCALLBACK(int) remR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version)
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync unsigned i;
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Validate version.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync AssertMsgFailed(("remR3Load: Invalid version u32Version=%d!\n", u32Version));
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Do a reset to be on the safe side...
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Ignore all ignorable notifications.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * (Not doing this will cause serious trouble.)
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Load the required CPU Env bits.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * (Not much because we're never in REM when doing the save.)
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync /* Redundant REM CPU state has to be loaded, but can be ignored. */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync SSMR3GetMem(pSSM, &temp, RT_OFFSETOF(CPUX86State_Ver16, jmp_env));
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync /* Remember if we've entered raw mode (vital for ring 1 checks in e.g. iret emulation). */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Load the REM stuff.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync if (pRem->cInvalidatedPages > RT_ELEMENTS(pRem->aGCPtrInvalidatedPages))
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync AssertMsgFailed(("cInvalidatedPages=%#x\n", pRem->cInvalidatedPages));
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync SSMR3GetGCPtr(pSSM, &pRem->aGCPtrInvalidatedPages[i]);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync rc = SSMR3GetUInt(pSSM, &pVM->rem.s.u32PendingInterrupt);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync /* check the terminator. */
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Get the CPUID features.
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync CPUMGetGuestCpuId(pVCpu, 1, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext_features, &pVM->rem.s.Env.cpuid_features);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync CPUMGetGuestCpuId(pVCpu, 0x80000001, &u32Dummy, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext2_features);
03532efdc331b598d3dedc8cc7477641c3b0dd12vboxsync * Sync the Load Flush the TLB
return VINF_SUCCESS;
bool fBp;
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_HLT:
case EXCP_RC:
case EXCP_EXECUTE_RAW:
case EXCP_EXECUTE_HWACC:
if (fBp)
return rc;
return VINF_SUCCESS;
return VERR_REM_NO_MORE_BP_SLOTS;
return VINF_SUCCESS;
return VERR_REM_BP_NOT_FOUND;
bool fFlushTBs;
Log2(("REMR3EmulateInstruction: (cs:eip=%04x:%08x)\n", CPUMGetGuestCS(pVCpu), CPUMGetGuestEIP(pVCpu)));
/* Skip the TB flush as that's rather expensive and not necessary for single instruction emulation. */
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=%Rrc iBP=%d GCPtrPC=%RGv\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:
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:
/** @todo missing VBOX_WITH_VMI/EXECP_PARAV_CALL */
* 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;
#ifndef REM_PHYS_ADDR_IN_TLB
void *pv;
int rc;
return pv;
fGlobal = true;
Log(("remR3FlushTLB: CR0=%08RX64 CR3=%08RX64 CR4=%08RX64 %s\n", (uint64_t)env->cr[0], (uint64_t)env->cr[3], (uint64_t)env->cr[4], fGlobal ? " global" : ""));
int rc;
#ifdef TARGET_X86_64
efer = 0;
Log(("PGMChangeMode(, %RX64, %RX64, %RX64) -> %Rrc -> remR3RaiseRC\n", env->cr[0], env->cr[4], 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, 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, 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)
CPUMGetGuestCpuId(pVCpu, 1, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext_features, &pVM->rem.s.Env.cpuid_features);
CPUMGetGuestCpuId(pVCpu, 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
(pVM->rem.s.Env.tr.flags >> 8) & 0xF0FF ? (pVM->rem.s.Env.tr.flags | DESC_TSS_BUSY_MASK) >> 8 : 0));
#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(pVCpu, 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
(pVM->rem.s.Env.tr.flags >> 8) & 0xF0FF ? (pVM->rem.s.Env.tr.flags | DESC_TSS_BUSY_MASK) >> 8 : 0));
#ifdef TARGET_X86_64
bool fSaved;
RTUINT i;
RTUINT i;
int rc;
return VINF_SUCCESS;
AssertMsg(fFlags == REM_NOTIFY_PHYS_RAM_FLAGS_RAM || fFlags == REM_NOTIFY_PHYS_RAM_FLAGS_MMIO2, ("#x\n", fFlags));
REMR3DECL(void) REMR3NotifyPhysRomRegister(PVM pVM, RTGCPHYS GCPhys, RTUINT cb, void *pvCopy, bool 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;
return ret;
LogRel(("\nTrying to execute code with memory type addr_code=%RGv addend=%RGp at %RGv! (iHandlerMemType=%#x iMMIOMemType=%#x IOTLB=%RGp)\n"
(RTGCPTR)pTLBEntry->addr_code, (RTGCPHYS)pTLBEntry->addend, (RTGCPTR)addr, pVM->rem.s.iHandlerMemType, pVM->rem.s.iMMIOMemType, (RTGCPHYS)ioTLBEntry));
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);
#ifdef VBOX_DEBUG_PHYS
#ifdef VBOX_DEBUG_PHYS
return val;
#ifdef VBOX_DEBUG_PHYS
return val;
#ifdef VBOX_DEBUG_PHYS
return val;
#ifdef VBOX_DEBUG_PHYS
return val;
#ifdef VBOX_DEBUG_PHYS
return val;
#ifdef VBOX_DEBUG_PHYS
return val;
#ifdef VBOX_DEBUG_PHYS
return val;
#ifdef VBOX_DEBUG_PHYS
return val;
#ifdef VBOX_DEBUG_PHYS
#ifdef VBOX_DEBUG_PHYS
#ifdef VBOX_DEBUG_PHYS
#ifdef VBOX_DEBUG_PHYS
#ifdef VBOX_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, VMCPUID_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;
if (!fLog2)
if (fLog)
#ifdef DEBUG_TMP_LOGGING
if (LogIs2Enabled())
unsigned off = 0;
#ifdef RT_ARCH_X86
#ifdef DEBUG_TMP_LOGGING
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
LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_5, LOG_GROUP_TM, ("REMR3NotifyTimerPending: pVCpu:%p != pVCpuDst:%p\n", pVM->rem.s.Env.pVCpu, pVCpuDst));
LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_5, LOG_GROUP_TM, ("REMR3NotifyTimerPending: !fInREM; cpu state=%d\n", VMCPU_GET_STATE(pVCpuDst)));
#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->pVCpu, uOperator, (uint32_t *)pvEAX, (uint32_t *)pvEBX, (uint32_t *)pvECX, (uint32_t *)pvEDX);
unsigned cArgs = 0;
switch (cArgs)
case 4: RTStrPrintf(szMsg, sizeof(szMsg), pszFormat, auArgs[0], auArgs[1], auArgs[2], auArgs[3]); break;
case 5: RTStrPrintf(szMsg, sizeof(szMsg), pszFormat, auArgs[0], auArgs[1], auArgs[2], auArgs[3], auArgs[4]); break;
case 6: RTStrPrintf(szMsg, sizeof(szMsg), pszFormat, auArgs[0], auArgs[1], auArgs[2], auArgs[3], auArgs[4], auArgs[5]); break;
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;