VirtualBox

root/trunk/src/recompiler/VBoxRecompiler.c

Revision 15012, 157.8 kB (checked in by vboxsync, 1 month ago)

Wrong casts

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /* $Id$ */
2 /** @file
3  * VBox Recompiler - QEMU.
4  */
5
6 /*
7  * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8  *
9  * This file is part of VirtualBox Open Source Edition (OSE), as
10  * available from http://www.virtualbox.org. This file is free software;
11  * you can redistribute it and/or modify it under the terms of the GNU
12  * General Public License (GPL) as published by the Free Software
13  * Foundation, in version 2 as it comes in the "COPYING" file of the
14  * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15  * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16  *
17  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18  * Clara, CA 95054 USA or visit http://www.sun.com if you need
19  * additional information or have any questions.
20  */
21
22
23 /*******************************************************************************
24 *   Header Files                                                               *
25 *******************************************************************************/
26 #define LOG_GROUP LOG_GROUP_REM
27 #include "vl.h"
28 #include "exec-all.h"
29
30 #include <VBox/rem.h>
31 #include <VBox/vmapi.h>
32 #include <VBox/tm.h>
33 #include <VBox/ssm.h>
34 #include <VBox/em.h>
35 #include <VBox/trpm.h>
36 #include <VBox/iom.h>
37 #include <VBox/mm.h>
38 #include <VBox/pgm.h>
39 #include <VBox/pdm.h>
40 #include <VBox/dbgf.h>
41 #include <VBox/dbg.h>
42 #include <VBox/hwaccm.h>
43 #include <VBox/patm.h>
44 #include <VBox/csam.h>
45 #include "REMInternal.h"
46 #include <VBox/vm.h>
47 #include <VBox/param.h>
48 #include <VBox/err.h>
49
50 #include <VBox/log.h>
51 #include <iprt/semaphore.h>
52 #include <iprt/asm.h>
53 #include <iprt/assert.h>
54 #include <iprt/thread.h>
55 #include <iprt/string.h>
56
57 /* Don't wanna include everything. */
58 extern void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3);
59 extern void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0);
60 extern void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4);
61 extern void tlb_flush_page(CPUX86State *env, target_ulong addr);
62 extern void tlb_flush(CPUState *env, int flush_global);
63 extern void sync_seg(CPUX86State *env1, int seg_reg, int selector);
64 extern void sync_ldtr(CPUX86State *env1, int selector);
65 extern int  sync_tr(CPUX86State *env1, int selector);
66
67 #ifdef VBOX_STRICT
68 unsigned long get_phys_page_offset(target_ulong addr);
69 #endif
70
71
72 /*******************************************************************************
73 *   Defined Constants And Macros                                               *
74 *******************************************************************************/
75
76 /** Copy 80-bit fpu register at pSrc to pDst.
77  * This is probably faster than *calling* memcpy.
78  */
79 #define REM_COPY_FPU_REG(pDst, pSrc) \
80     do { *(PX86FPUMMX)(pDst) = *(const X86FPUMMX *)(pSrc); } while (0)
81
82
83 /*******************************************************************************
84 *   Internal Functions                                                         *
85 *******************************************************************************/
86 static DECLCALLBACK(int) remR3Save(PVM pVM, PSSMHANDLE pSSM);
87 static DECLCALLBACK(int) remR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version);
88 static void     remR3StateUpdate(PVM pVM);
89
90 static uint32_t remR3MMIOReadU8(void *pvVM, target_phys_addr_t GCPhys);
91 static uint32_t remR3MMIOReadU16(void *pvVM, target_phys_addr_t GCPhys);
92 static uint32_t remR3MMIOReadU32(void *pvVM, target_phys_addr_t GCPhys);
93 static void     remR3MMIOWriteU8(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
94 static void     remR3MMIOWriteU16(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
95 static void     remR3MMIOWriteU32(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
96
97 static uint32_t remR3HandlerReadU8(void *pvVM, target_phys_addr_t GCPhys);
98 static uint32_t remR3HandlerReadU16(void *pvVM, target_phys_addr_t GCPhys);
99 static uint32_t remR3HandlerReadU32(void *pvVM, target_phys_addr_t GCPhys);
100 static void     remR3HandlerWriteU8(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
101 static void     remR3HandlerWriteU16(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
102 static void     remR3HandlerWriteU32(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
103
104
105 /*******************************************************************************
106 *   Global Variables                                                           *
107 *******************************************************************************/
108
109 /** @todo Move stats to REM::s some rainy day we have nothing do to. */
110 #ifdef VBOX_WITH_STATISTICS
111 static STAMPROFILEADV gStatExecuteSingleInstr;
112 static STAMPROFILEADV gStatCompilationQEmu;
113 static STAMPROFILEADV gStatRunCodeQEmu;
114 static STAMPROFILEADV gStatTotalTimeQEmu;
115 static STAMPROFILEADV gStatTimers;
116 static STAMPROFILEADV gStatTBLookup;
117 static STAMPROFILEADV gStatIRQ;
118 static STAMPROFILEADV gStatRawCheck;
119 static STAMPROFILEADV gStatMemRead;
120 static STAMPROFILEADV gStatMemWrite;
121 static STAMPROFILE    gStatGCPhys2HCVirt;
122 static STAMPROFILE    gStatHCVirt2GCPhys;
123 static STAMCOUNTER    gStatCpuGetTSC;
124 static STAMCOUNTER    gStatRefuseTFInhibit;
125 static STAMCOUNTER    gStatRefuseVM86;
126 static STAMCOUNTER    gStatRefusePaging;
127 static STAMCOUNTER    gStatRefusePAE;
128 static STAMCOUNTER    gStatRefuseIOPLNot0;
129 static STAMCOUNTER    gStatRefuseIF0;
130 static STAMCOUNTER    gStatRefuseCode16;
131 static STAMCOUNTER    gStatRefuseWP0;
132 static STAMCOUNTER    gStatRefuseRing1or2;
133 static STAMCOUNTER    gStatRefuseCanExecute;
134 static STAMCOUNTER    gStatREMGDTChange;
135 static STAMCOUNTER    gStatREMIDTChange;
136 static STAMCOUNTER    gStatREMLDTRChange;
137 static STAMCOUNTER    gStatREMTRChange;
138 static STAMCOUNTER    gStatSelOutOfSync[6];
139 static STAMCOUNTER    gStatSelOutOfSyncStateBack[6];
140 static STAMCOUNTER    gStatFlushTBs;
141 /* in exec.c */
142 extern uint32_t       tlb_flush_count;
143 extern uint32_t       tb_flush_count;
144 extern uint32_t       tb_phys_invalidate_count;
145 #endif
146
147 /*
148  * Global stuff.
149  */
150
151 /** MMIO read callbacks. */
152 CPUReadMemoryFunc  *g_apfnMMIORead[3] =
153 {
154     remR3MMIOReadU8,
155     remR3MMIOReadU16,
156     remR3MMIOReadU32
157 };
158
159 /** MMIO write callbacks. */
160 CPUWriteMemoryFunc *g_apfnMMIOWrite[3] =
161 {
162     remR3MMIOWriteU8,
163     remR3MMIOWriteU16,
164     remR3MMIOWriteU32
165 };
166
167 /** Handler read callbacks. */
168 CPUReadMemoryFunc  *g_apfnHandlerRead[3] =
169 {
170     remR3HandlerReadU8,
171     remR3HandlerReadU16,
172     remR3HandlerReadU32
173 };
174
175 /** Handler write callbacks. */
176 CPUWriteMemoryFunc *g_apfnHandlerWrite[3] =
177 {
178     remR3HandlerWriteU8,
179     remR3HandlerWriteU16,
180     remR3HandlerWriteU32
181 };
182
183
184 #if defined(VBOX_WITH_DEBUGGER) && !(defined(RT_OS_WINDOWS) && defined(RT_ARCH_AMD64))
185 /*
186  * Debugger commands.
187  */
188 static DECLCALLBACK(int) remR3CmdDisasEnableStepping(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
189
190 /** '.remstep' arguments. */
191 static const DBGCVARDESC    g_aArgRemStep[] =
192 {
193     /* cTimesMin,   cTimesMax,  enmCategory,            fFlags,                         pszName,        pszDescription */
194     {  0,           ~0,         DBGCVAR_CAT_NUMBER,     0,                              "on/off",       "Boolean value/mnemonic indicating the new state." },
195 };
196
197 /** Command descriptors. */
198 static const DBGCCMD    g_aCmds[] =
199 {
200     {
201         .pszCmd ="remstep",
202         .cArgsMin = 0,
203         .cArgsMax = 1,
204         .paArgDescs = &g_aArgRemStep[0],
205         .cArgDescs = RT_ELEMENTS(g_aArgRemStep),
206         .pResultDesc = NULL,
207         .fFlags = 0,
208         .pfnHandler = remR3CmdDisasEnableStepping,
209         .pszSyntax = "[on/off]",
210         .pszDescription = "Enable or disable the single stepping with logged disassembly. "
211                           "If no arguments show the current state."
212     }
213 };
214 #endif
215
216
217 /* Instantiate the structure signatures. */
218 #define REM_STRUCT_OP 0
219 #include "Sun/structs.h"
220
221
222
223 /*******************************************************************************
224 *   Internal Functions                                                         *
225 *******************************************************************************/
226 static void remAbort(int rc, const char *pszTip);
227 extern int testmath(void);
228
229 /* Put them here to avoid unused variable warning. */
230 AssertCompile(RT_SIZEOFMEMB(VM, rem.padding) >= RT_SIZEOFMEMB(VM, rem.s));
231 #if !defined(IPRT_NO_CRT) && (defined(RT_OS_LINUX) || defined(RT_OS_DARWIN) || defined(RT_OS_WINDOWS))
232 //AssertCompileMemberSize(REM, Env, REM_ENV_SIZE);
233 /* Why did this have to be identical?? */
234 AssertCompile(RT_SIZEOFMEMB(REM, Env) <= REM_ENV_SIZE);
235 #else
236 AssertCompile(RT_SIZEOFMEMB(REM, Env) <= REM_ENV_SIZE);
237 #endif
238
239
240 /**
241  * Initializes the REM.
242  *
243  * @returns VBox status code.
244  * @param   pVM         The VM to operate on.
245  */
246 REMR3DECL(int) REMR3Init(PVM pVM)
247 {
248     uint32_t u32Dummy;
249     unsigned i;
250
251     /*
252      * Assert sanity.
253      */
254     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)));
255     AssertReleaseMsg(sizeof(pVM->rem.s.Env) <= REM_ENV_SIZE, ("%#x == %#x\n", sizeof(pVM->rem.s.Env), REM_ENV_SIZE));
256     AssertReleaseMsg(!(RT_OFFSETOF(VM, rem) & 31), ("off=%#x\n", RT_OFFSETOF(VM, rem)));
257 #if defined(DEBUG) && !defined(RT_OS_SOLARIS) /// @todo fix the solaris math stuff.
258     Assert(!testmath());
259 #endif
260     ASSERT_STRUCT_TABLE(Misc);
261     ASSERT_STRUCT_TABLE(TLB);
262     ASSERT_STRUCT_TABLE(SegmentCache);
263     ASSERT_STRUCT_TABLE(XMMReg);
264     ASSERT_STRUCT_TABLE(MMXReg);
265     ASSERT_STRUCT_TABLE(float_status);
266     ASSERT_STRUCT_TABLE(float32u);
267     ASSERT_STRUCT_TABLE(float64u);
268     ASSERT_STRUCT_TABLE(floatx80u);
269     ASSERT_STRUCT_TABLE(CPUState);
270
271     /*
272      * Init some internal data members.
273      */
274     pVM->rem.s.offVM = RT_OFFSETOF(VM, rem.s);
275     pVM->rem.s.Env.pVM = pVM;
276 #ifdef CPU_RAW_MODE_INIT
277     pVM->rem.s.state |= CPU_RAW_MODE_INIT;
278 #endif
279
280     /* ctx. */
281     pVM->rem.s.pCtx = CPUMQueryGuestCtxPtr(pVM);
282     AssertMsg(MMR3PhysGetRamSize(pVM) == 0, ("Init order have changed! REM depends on notification about ALL physical memory registrations\n"));
283
284     /* ignore all notifications */
285     pVM->rem.s.fIgnoreAll = true;
286
287     /*
288      * Init the recompiler.
289      */
290     if (!cpu_x86_init(&pVM->rem.s.Env))
291     {
292         AssertMsgFailed(("cpu_x86_init failed - impossible!\n"));
293         return VERR_GENERAL_FAILURE;
294     }
295     CPUMGetGuestCpuId(pVM,          1, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext_features, &pVM->rem.s.Env.cpuid_features);
296     CPUMGetGuestCpuId(pVM, 0x80000001, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext3_features, &pVM->rem.s.Env.cpuid_ext2_features);
297
298     /* allocate code buffer for single instruction emulation. */
299     pVM->rem.s.Env.cbCodeBuffer = 4096;
300     pVM->rem.s.Env.pvCodeBuffer = RTMemExecAlloc(pVM->rem.s.Env.cbCodeBuffer);
301     AssertMsgReturn(pVM->rem.s.Env.pvCodeBuffer, ("Failed to allocate code buffer!\n"), VERR_NO_MEMORY);
302
303     /* finally, set the cpu_single_env global. */
304     cpu_single_env = &pVM->rem.s.Env;
305
306     /* Nothing is pending by default */
307     pVM->rem.s.u32PendingInterrupt = REM_NO_PENDING_IRQ;
308
309     /*
310      * Register ram types.
311      */
312     pVM->rem.s.iMMIOMemType    = cpu_register_io_memory(-1, g_apfnMMIORead, g_apfnMMIOWrite, pVM);
313     AssertReleaseMsg(pVM->rem.s.iMMIOMemType >= 0, ("pVM->rem.s.iMMIOMemType=%d\n", pVM->rem.s.iMMIOMemType));
314     pVM->rem.s.iHandlerMemType = cpu_register_io_memory(-1, g_apfnHandlerRead, g_apfnHandlerWrite, pVM);
315     AssertReleaseMsg(pVM->rem.s.iHandlerMemType >= 0, ("pVM->rem.s.iHandlerMemType=%d\n", pVM->rem.s.iHandlerMemType));
316     Log2(("REM: iMMIOMemType=%d iHandlerMemType=%d\n", pVM->rem.s.iMMIOMemType, pVM->rem.s.iHandlerMemType));
317
318     /* stop ignoring. */
319     pVM->rem.s.fIgnoreAll = false;
320
321     /*
322      * Register the saved state data unit.
323      */
324     int rc = SSMR3RegisterInternal(pVM, "rem", 1, REM_SAVED_STATE_VERSION, sizeof(uint32_t) * 10,
325                                    NULL, remR3Save, NULL,
326                                    NULL, remR3Load, NULL);
327     if (RT_FAILURE(rc))
328         return rc;
329
330 #if defined(VBOX_WITH_DEBUGGER) && !(defined(RT_OS_WINDOWS) && defined(RT_ARCH_AMD64))
331     /*
332      * Debugger commands.
333      */
334     static bool fRegisteredCmds = false;
335     if (!fRegisteredCmds)
336     {
337         int rc = DBGCRegisterCommands(&g_aCmds[0], RT_ELEMENTS(g_aCmds));
338         if (RT_SUCCESS(rc))
339             fRegisteredCmds = true;
340     }
341 #endif
342
343 #ifdef VBOX_WITH_STATISTICS
344     /*
345      * Statistics.
346      */
347     STAM_REG(pVM, &gStatExecuteSingleInstr, STAMTYPE_PROFILE, "/PROF/REM/SingleInstr",STAMUNIT_TICKS_PER_CALL, "Profiling single instruction emulation.");
348     STAM_REG(pVM, &gStatCompilationQEmu,    STAMTYPE_PROFILE, "/PROF/REM/Compile",    STAMUNIT_TICKS_PER_CALL, "Profiling QEmu compilation.");
349     STAM_REG(pVM, &gStatRunCodeQEmu,        STAMTYPE_PROFILE, "/PROF/REM/Runcode",    STAMUNIT_TICKS_PER_CALL, "Profiling QEmu code execution.");
350     STAM_REG(pVM, &gStatTotalTimeQEmu,      STAMTYPE_PROFILE, "/PROF/REM/Emulate",    STAMUNIT_TICKS_PER_CALL, "Profiling code emulation.");
351     STAM_REG(pVM, &gStatTimers,             STAMTYPE_PROFILE, "/PROF/REM/Timers",     STAMUNIT_TICKS_PER_CALL, "Profiling timer scheduling.");
352     STAM_REG(pVM, &gStatTBLookup,           STAMTYPE_PROFILE, "/PROF/REM/TBLookup",   STAMUNIT_TICKS_PER_CALL, "Profiling timer scheduling.");
353     STAM_REG(pVM, &gStatIRQ,                STAMTYPE_PROFILE, "/PROF/REM/IRQ",        STAMUNIT_TICKS_PER_CALL, "Profiling timer scheduling.");
354     STAM_REG(pVM, &gStatRawCheck,           STAMTYPE_PROFILE, "/PROF/REM/RawCheck",   STAMUNIT_TICKS_PER_CALL, "Profiling timer scheduling.");
355     STAM_REG(pVM, &gStatMemRead,            STAMTYPE_PROFILE, "/PROF/REM/MemRead",    STAMUNIT_TICKS_PER_CALL, "Profiling memory access.");
356     STAM_REG(pVM, &gStatMemWrite,           STAMTYPE_PROFILE, "/PROF/REM/MemWrite",   STAMUNIT_TICKS_PER_CALL, "Profiling memory access.");
357     STAM_REG(pVM, &gStatHCVirt2GCPhys,      STAMTYPE_PROFILE, "/PROF/REM/HCVirt2GCPhys", STAMUNIT_TICKS_PER_CALL, "Profiling memory convertion.");
358     STAM_REG(pVM, &gStatGCPhys2HCVirt,      STAMTYPE_PROFILE, "/PROF/REM/GCPhys2HCVirt", STAMUNIT_TICKS_PER_CALL, "Profiling memory convertion.");
359
360     STAM_REG(pVM, &gStatCpuGetTSC,          STAMTYPE_COUNTER, "/REM/CpuGetTSC",         STAMUNIT_OCCURENCES,     "cpu_get_tsc calls");
361
362     STAM_REG(pVM, &gStatRefuseTFInhibit,    STAMTYPE_COUNTER, "/REM/Refuse/TFInibit", STAMUNIT_OCCURENCES,     "Raw mode refused because of TF or irq inhibit");
363     STAM_REG(pVM, &gStatRefuseVM86,         STAMTYPE_COUNTER, "/REM/Refuse/VM86",     STAMUNIT_OCCURENCES,     "Raw mode refused because of VM86");
364     STAM_REG(pVM, &gStatRefusePaging,       STAMTYPE_COUNTER, "/REM/Refuse/Paging",   STAMUNIT_OCCURENCES,     "Raw mode refused because of disabled paging/pm");
365     STAM_REG(pVM, &gStatRefusePAE,          STAMTYPE_COUNTER, "/REM/Refuse/PAE",      STAMUNIT_OCCURENCES,     "Raw mode refused because of PAE");
366     STAM_REG(pVM, &gStatRefuseIOPLNot0,     STAMTYPE_COUNTER, "/REM/Refuse/IOPLNot0", STAMUNIT_OCCURENCES,     "Raw mode refused because of IOPL != 0");
367     STAM_REG(pVM, &gStatRefuseIF0,          STAMTYPE_COUNTER, "/REM/Refuse/IF0",      STAMUNIT_OCCURENCES,     "Raw mode refused because of IF=0");
368     STAM_REG(pVM, &gStatRefuseCode16,       STAMTYPE_COUNTER, "/REM/Refuse/Code16",   STAMUNIT_OCCURENCES,     "Raw mode refused because of 16 bit code");
369     STAM_REG(pVM, &gStatRefuseWP0,          STAMTYPE_COUNTER, "/REM/Refuse/WP0",      STAMUNIT_OCCURENCES,     "Raw mode refused because of WP=0");
370     STAM_REG(pVM, &gStatRefuseRing1or2,     STAMTYPE_COUNTER, "/REM/Refuse/Ring1or2", STAMUNIT_OCCURENCES,     "Raw mode refused because of ring 1/2 execution");
371     STAM_REG(pVM, &gStatRefuseCanExecute,   STAMTYPE_COUNTER, "/REM/Refuse/CanExecuteRaw", STAMUNIT_OCCURENCES,     "Raw mode refused because of cCanExecuteRaw");
372     STAM_REG(pVM, &gStatFlushTBs,           STAMTYPE_COUNTER, "/REM/FlushTB",         STAMUNIT_OCCURENCES,     "Number of TB flushes");
373
374     STAM_REG(pVM, &gStatREMGDTChange,       STAMTYPE_COUNTER, "/REM/Change/GDTBase",   STAMUNIT_OCCURENCES,     "GDT base changes");
375     STAM_REG(pVM, &gStatREMLDTRChange,      STAMTYPE_COUNTER, "/REM/Change/LDTR",      STAMUNIT_OCCURENCES,     "LDTR changes");
376     STAM_REG(pVM, &gStatREMIDTChange,       STAMTYPE_COUNTER, "/REM/Change/IDTBase",   STAMUNIT_OCCURENCES,     "IDT base changes");
377     STAM_REG(pVM, &gStatREMTRChange,        STAMTYPE_COUNTER, "/REM/Change/TR",        STAMUNIT_OCCURENCES,     "TR selector changes");
378
379     STAM_REG(pVM, &gStatSelOutOfSync[0],    STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/ES",        STAMUNIT_OCCURENCES,     "ES out of sync");
380     STAM_REG(pVM, &gStatSelOutOfSync[1],    STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/CS",        STAMUNIT_OCCURENCES,     "CS out of sync");
381     STAM_REG(pVM, &gStatSelOutOfSync[2],    STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/SS",        STAMUNIT_OCCURENCES,     "SS out of sync");
382     STAM_REG(pVM, &gStatSelOutOfSync[3],    STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/DS",        STAMUNIT_OCCURENCES,     "DS out of sync");
383     STAM_REG(pVM, &gStatSelOutOfSync[4],    STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/FS",        STAMUNIT_OCCURENCES,     "FS out of sync");
384     STAM_REG(pVM, &gStatSelOutOfSync[5],    STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/GS",        STAMUNIT_OCCURENCES,     "GS out of sync");
385
386     STAM_REG(pVM, &gStatSelOutOfSyncStateBack[0],    STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/ES",        STAMUNIT_OCCURENCES,     "ES out of sync");
387     STAM_REG(pVM, &gStatSelOutOfSyncStateBack[1],    STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/CS",        STAMUNIT_OCCURENCES,     "CS out of sync");
388     STAM_REG(pVM, &gStatSelOutOfSyncStateBack[2],    STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/SS",        STAMUNIT_OCCURENCES,     "SS out of sync");
389     STAM_REG(pVM, &gStatSelOutOfSyncStateBack[3],    STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/DS",        STAMUNIT_OCCURENCES,     "DS out of sync");
390     STAM_REG(pVM, &gStatSelOutOfSyncStateBack[4],    STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/FS",        STAMUNIT_OCCURENCES,     "FS out of sync");
391     STAM_REG(pVM, &gStatSelOutOfSyncStateBack[5],    STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/GS",        STAMUNIT_OCCURENCES,     "GS out of sync");
392
393     STAM_REG(pVM, &tb_flush_count,          STAMTYPE_U32_RESET, "/REM/TbFlushCount",     STAMUNIT_OCCURENCES, "tb_flush() calls");
394     STAM_REG(pVM, &tb_phys_invalidate_count,STAMTYPE_U32_RESET, "/REM/TbPhysInvldCount", STAMUNIT_OCCURENCES, "tb_phys_invalidate() calls");
395     STAM_REG(pVM, &tlb_flush_count,         STAMTYPE_U32_RESET, "/REM/TlbFlushCount",    STAMUNIT_OCCURENCES, "tlb_flush() calls");
396
397
398 #endif
399
400 #ifdef DEBUG_ALL_LOGGING
401     loglevel = ~0;
402 #endif
403
404     return rc;
405 }
406
407
408 /**
409  * Terminates the REM.
410  *
411  * Termination means cleaning up and freeing all resources,
412  * the VM it self is at this point powered off or suspended.
413  *
414  * @returns VBox status code.
415  * @param   pVM         The VM to operate on.
416  */
417 REMR3DECL(int) REMR3Term(PVM pVM)
418 {
419     return VINF_SUCCESS;
420 }
421
422
423 /**
424  * The VM is being reset.
425  *
426  * For the REM component this means to call the cpu_reset() and
427  * reinitialize some state variables.
428  *
429  * @param   pVM     VM handle.
430  */
431 REMR3DECL(void) REMR3Reset(PVM pVM)
432 {
433     /*
434      * Reset the REM cpu.
435      */
436     pVM->rem.s.fIgnoreAll = true;
437     cpu_reset(&pVM->rem.s.Env);
438     pVM->rem.s.cInvalidatedPages = 0;
439     pVM->rem.s.fIgnoreAll = false;
440
441     /* Clear raw ring 0 init state */
442     pVM->rem.s.Env.state &= ~CPU_RAW_RING0;
443
444     /* Flush the TBs the next time we execute code here. */
445     pVM->rem.s.fFlushTBs = true;
446 }
447
448
449 /**
450  * Execute state save operation.
451  *
452  * @returns VBox status code.
453  * @param   pVM             VM Handle.
454  * @param   pSSM            SSM operation handle.
455  */
456 static DECLCALLBACK(int) remR3Save(PVM pVM, PSSMHANDLE pSSM)
457 {
458     LogFlow(("remR3Save:\n"));
459
460     /*
461      * Save the required CPU Env bits.
462      * (Not much because we're never in REM when doing the save.)
463      */
464     PREM pRem = &pVM->rem.s;
465     Assert(!pRem->fInREM);
466     SSMR3PutU32(pSSM,   pRem->Env.hflags);
467     SSMR3PutU32(pSSM,   ~0);            /* separator */
468
469     /* Remember if we've entered raw mode (vital for ring 1 checks in e.g. iret emulation). */
470     SSMR3PutU32(pSSM, !!(pRem->Env.state & CPU_RAW_RING0));
471     SSMR3PutUInt(pSSM, pVM->rem.s.u32PendingInterrupt);
472
473     return SSMR3PutU32(pSSM, ~0);       /* terminator */
474 }
475
476
477 /**
478  * Execute state load operation.
479  *
480  * @returns VBox status code.
481  * @param   pVM             VM Handle.
482  * @param   pSSM            SSM operation handle.
483  * @param   u32Version      Data layout version.
484  */
485 static DECLCALLBACK(int) remR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version)
486 {
487     uint32_t u32Dummy;
488     uint32_t fRawRing0 = false;
489     LogFlow(("remR3Load:\n"));
490
491     /*
492      * Validate version.
493      */
494     if (    u32Version != REM_SAVED_STATE_VERSION
495         &&  u32Version != REM_SAVED_STATE_VERSION_VER1_6)
496     {
497         AssertMsgFailed(("remR3Load: Invalid version u32Version=%d!\n", u32Version));
498         return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
499     }
500
501     /*
502      * Do a reset to be on the safe side...
503      */
504     REMR3Reset(pVM);
505
506     /*
507      * Ignore all ignorable notifications.
508      * (Not doing this will cause serious trouble.)
509      */
510     pVM->rem.s.fIgnoreAll = true;
511
512     /*
513      * Load the required CPU Env bits.
514      * (Not much because we're never in REM when doing the save.)
515      */
516     PREM pRem = &pVM->rem.s;
517     Assert(!pRem->fInREM);
518     SSMR3GetU32(pSSM,   &pRem->Env.hflags);
519     if (u32Version == REM_SAVED_STATE_VERSION_VER1_6)
520     {
521         /* Redundant REM CPU state has to be loaded, but can be ignored. */
522         CPUX86State_Ver16 temp;
523         SSMR3GetMem(pSSM,   &temp, RT_OFFSETOF(CPUX86State_Ver16, jmp_env));
524     }
525
526     uint32_t u32Sep;
527     int rc = SSMR3GetU32(pSSM, &u32Sep);            /* separator */
528     if (RT_FAILURE(rc))
529         return rc;
530     if (u32Sep != ~0U)
531     {
532         AssertMsgFailed(("u32Sep=%#x\n", u32Sep));
533         return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
534     }
535
536     /* Remember if we've entered raw mode (vital for ring 1 checks in e.g. iret emulation). */
537     SSMR3GetUInt(pSSM, &fRawRing0);
538     if (fRawRing0)
539         pRem->Env.state |= CPU_RAW_RING0;
540
541     if (u32Version == REM_SAVED_STATE_VERSION_VER1_6)
542     {
543         /*
544          * Load the REM stuff.
545          */
546         rc = SSMR3GetUInt(pSSM, &pRem->cInvalidatedPages);
547         if (RT_FAILURE(rc))
548             return rc;
549         if (pRem->cInvalidatedPages > RT_ELEMENTS(pRem->aGCPtrInvalidatedPages))
550         {
551             AssertMsgFailed(("cInvalidatedPages=%#x\n", pRem->cInvalidatedPages));
552             return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
553         }
554         unsigned i;
555         for (i = 0; i < pRem->cInvalidatedPages; i++)
556             SSMR3GetGCPtr(pSSM, &pRem->aGCPtrInvalidatedPages[i]);
557     }
558
559     rc = SSMR3GetUInt(pSSM, &pVM->rem.s.u32PendingInterrupt);
560     if (RT_FAILURE(rc))
561         return rc;
562
563     /* check the terminator. */
564     rc = SSMR3GetU32(pSSM, &u32Sep);
565     if (RT_FAILURE(rc))
566         return rc;
567     if (u32Sep != ~0U)
568     {
569         AssertMsgFailed(("u32Sep=%#x (term)\n", u32Sep));
570         return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
571     }
572
573     /*
574      * Get the CPUID features.
575      */
576     CPUMGetGuestCpuId(pVM,          1, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext_features, &pVM->rem.s.Env.cpuid_features);
577     CPUMGetGuestCpuId(pVM, 0x80000001, &u32Dummy, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext2_features);
578
579     /*
580      * Sync the Load Flush the TLB
581      */
582     tlb_flush(&pRem->Env, 1);
583
584     /*
585      * Stop ignoring ignornable notifications.
586      */
587     pVM->rem.s.fIgnoreAll = false;
588
589     /*
590      * Sync the whole CPU state when executing code in the recompiler.
591      */
592     CPUMSetChangedFlags(pVM, CPUM_CHANGED_ALL);
593     return VINF_SUCCESS;
594 }
595
596
597
598 #undef LOG_GROUP
599 #define LOG_GROUP LOG_GROUP_REM_RUN
600
601 /**
602  * Single steps an instruction in recompiled mode.
603  *
604  * Before calling this function the REM state needs to be in sync with
605  * the VM. Call REMR3State() to perform the sync. It's only necessary
606  * (and permitted) to sync at the first call to REMR3Step()/REMR3Run()
607  * and after calling REMR3StateBack().
608  *
609  * @returns VBox status code.
610  *
611  * @param   pVM         VM Handle.
612  */
613 REMR3DECL(int) REMR3Step(PVM pVM)
614 {
615     /*
616      * Lock the REM - we don't wanna have anyone interrupting us
617      * while stepping - and enabled single stepping. We also ignore
618      * pending interrupts and suchlike.
619      */
620     int interrupt_request = pVM->rem.s.Env.interrupt_request;
621     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)));
622     pVM->rem.s.Env.interrupt_request = 0;
623     cpu_single_step(&pVM->rem.s.Env, 1);
624
625     /*
626      * If we're standing at a breakpoint, that have to be disabled before we start stepping.
627      */
628     RTGCPTR     GCPtrPC = pVM->rem.s.Env.eip + pVM->rem.s.Env.segs[R_CS].base;
629     bool        fBp = !cpu_breakpoint_remove(&pVM->rem.s.Env, GCPtrPC);
630
631     /*
632      * Execute and handle the return code.
633      * We execute without enabling the cpu tick, so on success we'll
634      * just flip it on and off to make sure it moves
635      */
636     int rc = cpu_exec(&pVM->rem.s.Env);
637     if (rc == EXCP_DEBUG)
638     {
639         TMCpuTickResume(pVM);
640         TMCpuTickPause(pVM);
641         TMVirtualResume(pVM);
642         TMVirtualPause(pVM);
643         rc = VINF_EM_DBG_STEPPED;
644     }
645     else
646     {
647         AssertMsgFailed(("Damn, this shouldn't happen! cpu_exec returned %d while singlestepping\n", rc));
648         switch (rc)
649         {
650             case EXCP_INTERRUPT:    rc = VINF_SUCCESS; break;
651             case EXCP_HLT:
652             case EXCP_HALTED:       rc = VINF_EM_HALT; break;
653             case EXCP_RC:
654                 rc = pVM->rem.s.rc;
655                 pVM->rem.s.rc = VERR_INTERNAL_ERROR;
656                 break;
657             default:
658                 AssertReleaseMsgFailed(("This really shouldn't happen, rc=%d!\n", rc));
659                 rc = VERR_INTERNAL_ERROR;
660                 break;
661         }
662     }
663
664     /*
665      * Restore the stuff we changed to prevent interruption.
666      * Unlock the REM.
667      */
668     if (fBp)
669     {
670         int rc2 = cpu_breakpoint_insert(&pVM->rem.s.Env, GCPtrPC);
671         Assert(rc2 == 0); NOREF(rc2);
672     }
673     cpu_single_step(&pVM->rem.s.Env, 0);
674     pVM->rem.s.Env.interrupt_request = interrupt_request;
675
676     return rc;
677 }
678
679
680 /**
681  * Set a breakpoint using the REM facilities.
682  *
683  * @returns VBox status code.
684  * @param   pVM             The VM handle.
685  * @param   Address         The breakpoint address.
686  * @thread  The emulation thread.
687  */
688 REMR3DECL(int) REMR3BreakpointSet(PVM pVM, RTGCUINTPTR Address)
689 {
690     VM_ASSERT_EMT(pVM);
691     if (!cpu_breakpoint_insert(&pVM->rem.s.Env, Address))
692     {
693         LogFlow(("REMR3BreakpointSet: Address=%RGv\n", Address));
694         return VINF_SUCCESS;
695     }
696     LogFlow(("REMR3BreakpointSet: Address=%RGv - failed!\n", Address));
697     return VERR_REM_NO_MORE_BP_SLOTS;
698 }
699
700
701 /**
702  * Clears a breakpoint set by REMR3BreakpointSet().
703  *
704  * @returns VBox status code.
705  * @param   pVM             The VM handle.
706  * @param   Address         The breakpoint address.
707  * @thread  The emulation thread.
708  */
709 REMR3DECL(int) REMR3BreakpointClear(PVM pVM, RTGCUINTPTR Address)
710 {
711     VM_ASSERT_EMT(pVM);
712     if (!cpu_breakpoint_remove(&pVM->rem.s.Env, Address))
713     {
714         LogFlow(("REMR3BreakpointClear: Address=%RGv\n", Address));
715         return VINF_SUCCESS;
716     }
717     LogFlow(("REMR3BreakpointClear: Address=%RGv - not found!\n", Address));
718     return VERR_REM_BP_NOT_FOUND;
719 }
720
721
722 /**
723  * Emulate an instruction.
724  *
725  * This function executes one instruction without letting anyone
726  * interrupt it. This is intended for being called while being in
727  * raw mode and thus will take care of all the state syncing between
728  * REM and the rest.
729  *
730  * @returns VBox status code.
731  * @param   pVM         VM handle.
732  */
733 REMR3DECL(int) REMR3EmulateInstruction(PVM pVM)
734 {
735     bool fFlushTBs;
736
737     Log2(("REMR3EmulateInstruction: (cs:eip=%04x:%08x)\n", CPUMGetGuestCS(pVM), CPUMGetGuestEIP(pVM)));
738
739     /* Make sure this flag is set; we might never execute remR3CanExecuteRaw in the AMD-V case.
740      * CPU_RAW_HWACC makes sure we never execute interrupt handlers in the recompiler.
741      */
742     if (HWACCMIsEnabled(pVM))
743         pVM->rem.s.Env.state |= CPU_RAW_HWACC;
744
745     /* Skip the TB flush as that's rather expensive and not necessary for single instruction emulation. */
746     fFlushTBs = pVM->rem.s.fFlushTBs;
747     pVM->rem.s.fFlushTBs = false;
748
749     /*
750      * Sync the state and enable single instruction / single stepping.
751      */
752     int rc = REMR3State(pVM);
753     pVM->rem.s.fFlushTBs = fFlushTBs;
754     if (RT_SUCCESS(rc))
755     {
756         int interrupt_request = pVM->rem.s.Env.interrupt_request;
757         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)));
758         Assert(!pVM->rem.s.Env.singlestep_enabled);
759 #if 1
760
761         /*
762          * Now we set the execute single instruction flag and enter the cpu_exec loop.
763          */
764         TMNotifyStartOfExecution(pVM);
765         pVM->rem.s.Env.interrupt_request = CPU_INTERRUPT_SINGLE_INSTR;
766         rc = cpu_exec(&pVM->rem.s.Env);
767         TMNotifyEndOfExecution(pVM);
768         switch (rc)
769         {
770             /*
771              * Executed without anything out of the way happening.
772              */
773             case EXCP_SINGLE_INSTR:
774                 rc = VINF_EM_RESCHEDULE;
775                 Log2(("REMR3EmulateInstruction: cpu_exec -> EXCP_SINGLE_INSTR\n"));
776                 break;
777
778             /*
779              * If we take a trap or start servicing a pending interrupt, we might end up here.
780              * (Timer thread or some other thread wishing EMT's attention.)
781              */
782             case EXCP_INTERRUPT:
783                 Log2(("REMR3EmulateInstruction: cpu_exec -> EXCP_INTERRUPT\n"));
784                 rc = VINF_EM_RESCHEDULE;
785                 break;
786
787             /*
788              * Single step, we assume!
789              * If there was a breakpoint there we're fucked now.
790              */
791             case EXCP_DEBUG:
792             {
793                 /* breakpoint or single step? */
794                 RTGCPTR     GCPtrPC = pVM->rem.s.Env.eip + pVM->rem.s.Env.segs[R_CS].base;
795                 int         iBP;
796                 rc = VINF_EM_DBG_STEPPED;
797                 for (iBP = 0; iBP < pVM->rem.s.Env.nb_breakpoints; iBP++)
798                     if (pVM->rem.s.Env.breakpoints[iBP] == GCPtrPC)
799                     {
800                         rc = VINF_EM_DBG_BREAKPOINT;
801                         break;
802                     }
803                 Log2(("REMR3EmulateInstruction: cpu_exec -> EXCP_DEBUG rc=%Rrc iBP=%d GCPtrPC=%RGv\n", rc, iBP, GCPtrPC));
804                 break;
805             }
806
807             /*
808              * hlt instruction.
809              */
810             case EXCP_HLT:
811                 Log2(("REMR3EmulateInstruction: cpu_exec -> EXCP_HLT\n"));
812                 rc = VINF_EM_HALT;
813                 break;
814
815             /*
816              * The VM has halted.
817              */
818             case EXCP_HALTED:
819                 Log2(("REMR3EmulateInstruction: cpu_exec -> EXCP_HALTED\n"));
820                 rc = VINF_EM_HALT;
821                 break;
822
823             /*