VirtualBox

source: vbox/trunk/src/recompiler/VBoxRecompiler.c@ 20426

Last change on this file since 20426 was 20426, checked in by vboxsync, 15 years ago

Protect pgm handler notifications in the recompiler.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 163.6 KB
Line 
1/* $Id: VBoxRecompiler.c 20426 2009-06-09 11:21:44Z vboxsync $ */
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 "osdep.h"
29#include "exec-all.h"
30#include "config.h"
31#include "cpu-all.h"
32
33#include <VBox/rem.h>
34#include <VBox/vmapi.h>
35#include <VBox/tm.h>
36#include <VBox/ssm.h>
37#include <VBox/em.h>
38#include <VBox/trpm.h>
39#include <VBox/iom.h>
40#include <VBox/mm.h>
41#include <VBox/pgm.h>
42#include <VBox/pdm.h>
43#include <VBox/dbgf.h>
44#include <VBox/dbg.h>
45#include <VBox/hwaccm.h>
46#include <VBox/patm.h>
47#include <VBox/csam.h>
48#include "REMInternal.h"
49#include <VBox/vm.h>
50#include <VBox/param.h>
51#include <VBox/err.h>
52
53#include <VBox/log.h>
54#include <iprt/semaphore.h>
55#include <iprt/asm.h>
56#include <iprt/assert.h>
57#include <iprt/thread.h>
58#include <iprt/string.h>
59
60/* Don't wanna include everything. */
61extern void cpu_exec_init_all(unsigned long tb_size);
62extern void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3);
63extern void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0);
64extern void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4);
65extern void tlb_flush_page(CPUX86State *env, target_ulong addr);
66extern void tlb_flush(CPUState *env, int flush_global);
67extern void sync_seg(CPUX86State *env1, int seg_reg, int selector);
68extern void sync_ldtr(CPUX86State *env1, int selector);
69
70#ifdef VBOX_STRICT
71unsigned long get_phys_page_offset(target_ulong addr);
72#endif
73
74
75/*******************************************************************************
76* Defined Constants And Macros *
77*******************************************************************************/
78
79/** Copy 80-bit fpu register at pSrc to pDst.
80 * This is probably faster than *calling* memcpy.
81 */
82#define REM_COPY_FPU_REG(pDst, pSrc) \
83 do { *(PX86FPUMMX)(pDst) = *(const X86FPUMMX *)(pSrc); } while (0)
84
85
86/*******************************************************************************
87* Internal Functions *
88*******************************************************************************/
89static DECLCALLBACK(int) remR3Save(PVM pVM, PSSMHANDLE pSSM);
90static DECLCALLBACK(int) remR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version);
91static void remR3StateUpdate(PVM pVM, PVMCPU pVCpu);
92static int remR3InitPhysRamSizeAndDirtyMap(PVM pVM, bool fGuarded);
93
94static uint32_t remR3MMIOReadU8(void *pvVM, target_phys_addr_t GCPhys);
95static uint32_t remR3MMIOReadU16(void *pvVM, target_phys_addr_t GCPhys);
96static uint32_t remR3MMIOReadU32(void *pvVM, target_phys_addr_t GCPhys);
97static void remR3MMIOWriteU8(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
98static void remR3MMIOWriteU16(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
99static void remR3MMIOWriteU32(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
100
101static uint32_t remR3HandlerReadU8(void *pvVM, target_phys_addr_t GCPhys);
102static uint32_t remR3HandlerReadU16(void *pvVM, target_phys_addr_t GCPhys);
103static uint32_t remR3HandlerReadU32(void *pvVM, target_phys_addr_t GCPhys);
104static void remR3HandlerWriteU8(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
105static void remR3HandlerWriteU16(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
106static void remR3HandlerWriteU32(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
107
108static void remR3NotifyHandlerPhysicalDeregister(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS cb, bool fHasHCHandler, bool fRestoreAsRAM);
109static void remR3NotifyHandlerPhysicalRegister(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS cb, bool fHasHCHandler);
110static void remR3NotifyHandlerPhysicalModify(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhysOld, RTGCPHYS GCPhysNew, RTGCPHYS cb, bool fHasHCHandler, bool fRestoreAsRAM);
111
112/*******************************************************************************
113* Global Variables *
114*******************************************************************************/
115
116/** @todo Move stats to REM::s some rainy day we have nothing do to. */
117#ifdef VBOX_WITH_STATISTICS
118static STAMPROFILEADV gStatExecuteSingleInstr;
119static STAMPROFILEADV gStatCompilationQEmu;
120static STAMPROFILEADV gStatRunCodeQEmu;
121static STAMPROFILEADV gStatTotalTimeQEmu;
122static STAMPROFILEADV gStatTimers;
123static STAMPROFILEADV gStatTBLookup;
124static STAMPROFILEADV gStatIRQ;
125static STAMPROFILEADV gStatRawCheck;
126static STAMPROFILEADV gStatMemRead;
127static STAMPROFILEADV gStatMemWrite;
128static STAMPROFILE gStatGCPhys2HCVirt;
129static STAMPROFILE gStatHCVirt2GCPhys;
130static STAMCOUNTER gStatCpuGetTSC;
131static STAMCOUNTER gStatRefuseTFInhibit;
132static STAMCOUNTER gStatRefuseVM86;
133static STAMCOUNTER gStatRefusePaging;
134static STAMCOUNTER gStatRefusePAE;
135static STAMCOUNTER gStatRefuseIOPLNot0;
136static STAMCOUNTER gStatRefuseIF0;
137static STAMCOUNTER gStatRefuseCode16;
138static STAMCOUNTER gStatRefuseWP0;
139static STAMCOUNTER gStatRefuseRing1or2;
140static STAMCOUNTER gStatRefuseCanExecute;
141static STAMCOUNTER gStatREMGDTChange;
142static STAMCOUNTER gStatREMIDTChange;
143static STAMCOUNTER gStatREMLDTRChange;
144static STAMCOUNTER gStatREMTRChange;
145static STAMCOUNTER gStatSelOutOfSync[6];
146static STAMCOUNTER gStatSelOutOfSyncStateBack[6];
147static STAMCOUNTER gStatFlushTBs;
148#endif
149/* in exec.c */
150extern uint32_t tlb_flush_count;
151extern uint32_t tb_flush_count;
152extern uint32_t tb_phys_invalidate_count;
153
154/*
155 * Global stuff.
156 */
157
158/** MMIO read callbacks. */
159CPUReadMemoryFunc *g_apfnMMIORead[3] =
160{
161 remR3MMIOReadU8,
162 remR3MMIOReadU16,
163 remR3MMIOReadU32
164};
165
166/** MMIO write callbacks. */
167CPUWriteMemoryFunc *g_apfnMMIOWrite[3] =
168{
169 remR3MMIOWriteU8,
170 remR3MMIOWriteU16,
171 remR3MMIOWriteU32
172};
173
174/** Handler read callbacks. */
175CPUReadMemoryFunc *g_apfnHandlerRead[3] =
176{
177 remR3HandlerReadU8,
178 remR3HandlerReadU16,
179 remR3HandlerReadU32
180};
181
182/** Handler write callbacks. */
183CPUWriteMemoryFunc *g_apfnHandlerWrite[3] =
184{
185 remR3HandlerWriteU8,
186 remR3HandlerWriteU16,
187 remR3HandlerWriteU32
188};
189
190
191#if defined(VBOX_WITH_DEBUGGER) && !(defined(RT_OS_WINDOWS) && defined(RT_ARCH_AMD64))
192/*
193 * Debugger commands.
194 */
195static DECLCALLBACK(int) remR3CmdDisasEnableStepping(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
196
197/** '.remstep' arguments. */
198static const DBGCVARDESC g_aArgRemStep[] =
199{
200 /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
201 { 0, ~0, DBGCVAR_CAT_NUMBER, 0, "on/off", "Boolean value/mnemonic indicating the new state." },
202};
203
204/** Command descriptors. */
205static const DBGCCMD g_aCmds[] =
206{
207 {
208 .pszCmd ="remstep",
209 .cArgsMin = 0,
210 .cArgsMax = 1,
211 .paArgDescs = &g_aArgRemStep[0],
212 .cArgDescs = RT_ELEMENTS(g_aArgRemStep),
213 .pResultDesc = NULL,
214 .fFlags = 0,
215 .pfnHandler = remR3CmdDisasEnableStepping,
216 .pszSyntax = "[on/off]",
217 .pszDescription = "Enable or disable the single stepping with logged disassembly. "
218 "If no arguments show the current state."
219 }
220};
221#endif
222
223/** Prologue code, must be in lower 4G to simplify jumps to/from generated code. */
224uint8_t *code_gen_prologue;
225
226
227/*******************************************************************************
228* Internal Functions *
229*******************************************************************************/
230void remAbort(int rc, const char *pszTip);
231extern int testmath(void);
232
233/* Put them here to avoid unused variable warning. */
234AssertCompile(RT_SIZEOFMEMB(VM, rem.padding) >= RT_SIZEOFMEMB(VM, rem.s));
235#if !defined(IPRT_NO_CRT) && (defined(RT_OS_LINUX) || defined(RT_OS_DARWIN) || defined(RT_OS_WINDOWS))
236//AssertCompileMemberSize(REM, Env, REM_ENV_SIZE);
237/* Why did this have to be identical?? */
238AssertCompile(RT_SIZEOFMEMB(REM, Env) <= REM_ENV_SIZE);
239#else
240AssertCompile(RT_SIZEOFMEMB(REM, Env) <= REM_ENV_SIZE);
241#endif
242
243
244/**
245 * Initializes the REM.
246 *
247 * @returns VBox status code.
248 * @param pVM The VM to operate on.
249 */
250REMR3DECL(int) REMR3Init(PVM pVM)
251{
252 uint32_t u32Dummy;
253 int rc;
254
255#ifdef VBOX_ENABLE_VBOXREM64
256 LogRel(("Using 64-bit aware REM\n"));
257#endif
258
259 /*
260 * Assert sanity.
261 */
262 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)));
263 AssertReleaseMsg(sizeof(pVM->rem.s.Env) <= REM_ENV_SIZE, ("%#x == %#x\n", sizeof(pVM->rem.s.Env), REM_ENV_SIZE));
264 AssertReleaseMsg(!(RT_OFFSETOF(VM, rem) & 31), ("off=%#x\n", RT_OFFSETOF(VM, rem)));
265#if defined(DEBUG) && !defined(RT_OS_SOLARIS) && !defined(RT_OS_FREEBSD) /// @todo fix the solaris and freebsd math stuff.
266 Assert(!testmath());
267#endif
268
269 /*
270 * Init some internal data members.
271 */
272 pVM->rem.s.offVM = RT_OFFSETOF(VM, rem.s);
273 pVM->rem.s.Env.pVM = pVM;
274#ifdef CPU_RAW_MODE_INIT
275 pVM->rem.s.state |= CPU_RAW_MODE_INIT;
276#endif
277
278 /*
279 * Initialize the REM critical section.
280 */
281 rc = PDMR3CritSectInit(pVM, &pVM->rem.s.CritSectRegister, "REM-Register");
282 AssertRCReturn(rc, rc);
283
284 /* ctx. */
285 pVM->rem.s.pCtx = NULL; /* set when executing code. */
286 AssertMsg(MMR3PhysGetRamSize(pVM) == 0, ("Init order has changed! REM depends on notification about ALL physical memory registrations\n"));
287
288 /* ignore all notifications */
289 ASMAtomicIncU32(&pVM->rem.s.cIgnoreAll);
290
291 code_gen_prologue = RTMemExecAlloc(_1K);
292 AssertLogRelReturn(code_gen_prologue, VERR_NO_MEMORY);
293
294 cpu_exec_init_all(0);
295
296 /*
297 * Init the recompiler.
298 */
299 if (!cpu_x86_init(&pVM->rem.s.Env, "vbox"))
300 {
301 AssertMsgFailed(("cpu_x86_init failed - impossible!\n"));
302 return VERR_GENERAL_FAILURE;
303 }
304 PVMCPU pVCpu = VMMGetCpu(pVM);
305 CPUMGetGuestCpuId(pVCpu, 1, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext_features, &pVM->rem.s.Env.cpuid_features);
306 CPUMGetGuestCpuId(pVCpu, 0x80000001, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext3_features, &pVM->rem.s.Env.cpuid_ext2_features);
307
308 /* allocate code buffer for single instruction emulation. */
309 pVM->rem.s.Env.cbCodeBuffer = 4096;
310 pVM->rem.s.Env.pvCodeBuffer = RTMemExecAlloc(pVM->rem.s.Env.cbCodeBuffer);
311 AssertMsgReturn(pVM->rem.s.Env.pvCodeBuffer, ("Failed to allocate code buffer!\n"), VERR_NO_MEMORY);
312
313 /* finally, set the cpu_single_env global. */
314 cpu_single_env = &pVM->rem.s.Env;
315
316 /* Nothing is pending by default */
317 pVM->rem.s.u32PendingInterrupt = REM_NO_PENDING_IRQ;
318
319 /*
320 * Register ram types.
321 */
322 pVM->rem.s.iMMIOMemType = cpu_register_io_memory(-1, g_apfnMMIORead, g_apfnMMIOWrite, pVM);
323 AssertReleaseMsg(pVM->rem.s.iMMIOMemType >= 0, ("pVM->rem.s.iMMIOMemType=%d\n", pVM->rem.s.iMMIOMemType));
324 pVM->rem.s.iHandlerMemType = cpu_register_io_memory(-1, g_apfnHandlerRead, g_apfnHandlerWrite, pVM);
325 AssertReleaseMsg(pVM->rem.s.iHandlerMemType >= 0, ("pVM->rem.s.iHandlerMemType=%d\n", pVM->rem.s.iHandlerMemType));
326 Log2(("REM: iMMIOMemType=%d iHandlerMemType=%d\n", pVM->rem.s.iMMIOMemType, pVM->rem.s.iHandlerMemType));
327
328 /* stop ignoring. */
329 ASMAtomicDecU32(&pVM->rem.s.cIgnoreAll);
330
331 /*
332 * Register the saved state data unit.
333 */
334 rc = SSMR3RegisterInternal(pVM, "rem", 1, REM_SAVED_STATE_VERSION, sizeof(uint32_t) * 10,
335 NULL, remR3Save, NULL,
336 NULL, remR3Load, NULL);
337 if (RT_FAILURE(rc))
338 return rc;
339
340#if defined(VBOX_WITH_DEBUGGER) && !(defined(RT_OS_WINDOWS) && defined(RT_ARCH_AMD64))
341 /*
342 * Debugger commands.
343 */
344 static bool fRegisteredCmds = false;
345 if (!fRegisteredCmds)
346 {
347 int rc = DBGCRegisterCommands(&g_aCmds[0], RT_ELEMENTS(g_aCmds));
348 if (RT_SUCCESS(rc))
349 fRegisteredCmds = true;
350 }
351#endif
352
353#ifdef VBOX_WITH_STATISTICS
354 /*
355 * Statistics.
356 */
357 STAM_REG(pVM, &gStatExecuteSingleInstr, STAMTYPE_PROFILE, "/PROF/REM/SingleInstr",STAMUNIT_TICKS_PER_CALL, "Profiling single instruction emulation.");
358 STAM_REG(pVM, &gStatCompilationQEmu, STAMTYPE_PROFILE, "/PROF/REM/Compile", STAMUNIT_TICKS_PER_CALL, "Profiling QEmu compilation.");
359 STAM_REG(pVM, &gStatRunCodeQEmu, STAMTYPE_PROFILE, "/PROF/REM/Runcode", STAMUNIT_TICKS_PER_CALL, "Profiling QEmu code execution.");
360 STAM_REG(pVM, &gStatTotalTimeQEmu, STAMTYPE_PROFILE, "/PROF/REM/Emulate", STAMUNIT_TICKS_PER_CALL, "Profiling code emulation.");
361 STAM_REG(pVM, &gStatTimers, STAMTYPE_PROFILE, "/PROF/REM/Timers", STAMUNIT_TICKS_PER_CALL, "Profiling timer scheduling.");
362 STAM_REG(pVM, &gStatTBLookup, STAMTYPE_PROFILE, "/PROF/REM/TBLookup", STAMUNIT_TICKS_PER_CALL, "Profiling timer scheduling.");
363 STAM_REG(pVM, &gStatIRQ, STAMTYPE_PROFILE, "/PROF/REM/IRQ", STAMUNIT_TICKS_PER_CALL, "Profiling timer scheduling.");
364 STAM_REG(pVM, &gStatRawCheck, STAMTYPE_PROFILE, "/PROF/REM/RawCheck", STAMUNIT_TICKS_PER_CALL, "Profiling timer scheduling.");
365 STAM_REG(pVM, &gStatMemRead, STAMTYPE_PROFILE, "/PROF/REM/MemRead", STAMUNIT_TICKS_PER_CALL, "Profiling memory access.");
366 STAM_REG(pVM, &gStatMemWrite, STAMTYPE_PROFILE, "/PROF/REM/MemWrite", STAMUNIT_TICKS_PER_CALL, "Profiling memory access.");
367 STAM_REG(pVM, &gStatHCVirt2GCPhys, STAMTYPE_PROFILE, "/PROF/REM/HCVirt2GCPhys", STAMUNIT_TICKS_PER_CALL, "Profiling memory convertion.");
368 STAM_REG(pVM, &gStatGCPhys2HCVirt, STAMTYPE_PROFILE, "/PROF/REM/GCPhys2HCVirt", STAMUNIT_TICKS_PER_CALL, "Profiling memory convertion.");
369
370 STAM_REG(pVM, &gStatCpuGetTSC, STAMTYPE_COUNTER, "/REM/CpuGetTSC", STAMUNIT_OCCURENCES, "cpu_get_tsc calls");
371
372 STAM_REG(pVM, &gStatRefuseTFInhibit, STAMTYPE_COUNTER, "/REM/Refuse/TFInibit", STAMUNIT_OCCURENCES, "Raw mode refused because of TF or irq inhibit");
373 STAM_REG(pVM, &gStatRefuseVM86, STAMTYPE_COUNTER, "/REM/Refuse/VM86", STAMUNIT_OCCURENCES, "Raw mode refused because of VM86");
374 STAM_REG(pVM, &gStatRefusePaging, STAMTYPE_COUNTER, "/REM/Refuse/Paging", STAMUNIT_OCCURENCES, "Raw mode refused because of disabled paging/pm");
375 STAM_REG(pVM, &gStatRefusePAE, STAMTYPE_COUNTER, "/REM/Refuse/PAE", STAMUNIT_OCCURENCES, "Raw mode refused because of PAE");
376 STAM_REG(pVM, &gStatRefuseIOPLNot0, STAMTYPE_COUNTER, "/REM/Refuse/IOPLNot0", STAMUNIT_OCCURENCES, "Raw mode refused because of IOPL != 0");
377 STAM_REG(pVM, &gStatRefuseIF0, STAMTYPE_COUNTER, "/REM/Refuse/IF0", STAMUNIT_OCCURENCES, "Raw mode refused because of IF=0");
378 STAM_REG(pVM, &gStatRefuseCode16, STAMTYPE_COUNTER, "/REM/Refuse/Code16", STAMUNIT_OCCURENCES, "Raw mode refused because of 16 bit code");
379 STAM_REG(pVM, &gStatRefuseWP0, STAMTYPE_COUNTER, "/REM/Refuse/WP0", STAMUNIT_OCCURENCES, "Raw mode refused because of WP=0");
380 STAM_REG(pVM, &gStatRefuseRing1or2, STAMTYPE_COUNTER, "/REM/Refuse/Ring1or2", STAMUNIT_OCCURENCES, "Raw mode refused because of ring 1/2 execution");
381 STAM_REG(pVM, &gStatRefuseCanExecute, STAMTYPE_COUNTER, "/REM/Refuse/CanExecuteRaw", STAMUNIT_OCCURENCES, "Raw mode refused because of cCanExecuteRaw");
382 STAM_REG(pVM, &gStatFlushTBs, STAMTYPE_COUNTER, "/REM/FlushTB", STAMUNIT_OCCURENCES, "Number of TB flushes");
383
384 STAM_REG(pVM, &gStatREMGDTChange, STAMTYPE_COUNTER, "/REM/Change/GDTBase", STAMUNIT_OCCURENCES, "GDT base changes");
385 STAM_REG(pVM, &gStatREMLDTRChange, STAMTYPE_COUNTER, "/REM/Change/LDTR", STAMUNIT_OCCURENCES, "LDTR changes");
386 STAM_REG(pVM, &gStatREMIDTChange, STAMTYPE_COUNTER, "/REM/Change/IDTBase", STAMUNIT_OCCURENCES, "IDT base changes");
387 STAM_REG(pVM, &gStatREMTRChange, STAMTYPE_COUNTER, "/REM/Change/TR", STAMUNIT_OCCURENCES, "TR selector changes");
388
389 STAM_REG(pVM, &gStatSelOutOfSync[0], STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/ES", STAMUNIT_OCCURENCES, "ES out of sync");
390 STAM_REG(pVM, &gStatSelOutOfSync[1], STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/CS", STAMUNIT_OCCURENCES, "CS out of sync");
391 STAM_REG(pVM, &gStatSelOutOfSync[2], STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/SS", STAMUNIT_OCCURENCES, "SS out of sync");
392 STAM_REG(pVM, &gStatSelOutOfSync[3], STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/DS", STAMUNIT_OCCURENCES, "DS out of sync");
393 STAM_REG(pVM, &gStatSelOutOfSync[4], STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/FS", STAMUNIT_OCCURENCES, "FS out of sync");
394 STAM_REG(pVM, &gStatSelOutOfSync[5], STAMTYPE_COUNTER, "/REM/State/SelOutOfSync/GS", STAMUNIT_OCCURENCES, "GS out of sync");
395
396 STAM_REG(pVM, &gStatSelOutOfSyncStateBack[0], STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/ES", STAMUNIT_OCCURENCES, "ES out of sync");
397 STAM_REG(pVM, &gStatSelOutOfSyncStateBack[1], STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/CS", STAMUNIT_OCCURENCES, "CS out of sync");
398 STAM_REG(pVM, &gStatSelOutOfSyncStateBack[2], STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/SS", STAMUNIT_OCCURENCES, "SS out of sync");
399 STAM_REG(pVM, &gStatSelOutOfSyncStateBack[3], STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/DS", STAMUNIT_OCCURENCES, "DS out of sync");
400 STAM_REG(pVM, &gStatSelOutOfSyncStateBack[4], STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/FS", STAMUNIT_OCCURENCES, "FS out of sync");
401 STAM_REG(pVM, &gStatSelOutOfSyncStateBack[5], STAMTYPE_COUNTER, "/REM/StateBack/SelOutOfSync/GS", STAMUNIT_OCCURENCES, "GS out of sync");
402
403 STAM_REG(pVM, &pVM->rem.s.Env.StatTbFlush, STAMTYPE_PROFILE, "/REM/TbFlush", STAMUNIT_TICKS_PER_CALL, "profiling tb_flush().");
404#endif /* VBOX_WITH_STATISTICS */
405
406 STAM_REL_REG(pVM, &tb_flush_count, STAMTYPE_U32_RESET, "/REM/TbFlushCount", STAMUNIT_OCCURENCES, "tb_flush() calls");
407 STAM_REL_REG(pVM, &tb_phys_invalidate_count, STAMTYPE_U32_RESET, "/REM/TbPhysInvldCount", STAMUNIT_OCCURENCES, "tb_phys_invalidate() calls");
408 STAM_REL_REG(pVM, &tlb_flush_count, STAMTYPE_U32_RESET, "/REM/TlbFlushCount", STAMUNIT_OCCURENCES, "tlb_flush() calls");
409
410
411#ifdef DEBUG_ALL_LOGGING
412 loglevel = ~0;
413# ifdef DEBUG_TMP_LOGGING
414 logfile = fopen("/tmp/vbox-qemu.log", "w");
415# endif
416#endif
417
418 PREMHANDLERNOTIFICATION pCur;
419 unsigned i;
420
421 pVM->rem.s.idxPendingList = -1;
422 pVM->rem.s.idxFreeList = 0;
423
424 for (i = 0 ; i < RT_ELEMENTS(pVM->rem.s.aHandlerNotifications) - 1; i++)
425 {
426 pCur = &pVM->rem.s.aHandlerNotifications[i];
427 pCur->idxNext = i + 1;
428 pCur->idxSelf = i;
429 }
430
431 pCur = &pVM->rem.s.aHandlerNotifications[RT_ELEMENTS(pVM->rem.s.aHandlerNotifications) - 1];
432 pCur->idxNext = -1;
433 pCur->idxSelf = RT_ELEMENTS(pVM->rem.s.aHandlerNotifications) - 1;
434
435 return rc;
436}
437
438
439/**
440 * Finalizes the REM initialization.
441 *
442 * This is called after all components, devices and drivers has
443 * been initialized. Its main purpose it to finish the RAM related
444 * initialization.
445 *
446 * @returns VBox status code.
447 *
448 * @param pVM The VM handle.
449 */
450REMR3DECL(int) REMR3InitFinalize(PVM pVM)
451{
452 int rc;
453
454 /*
455 * Ram size & dirty bit map.
456 */
457 Assert(!pVM->rem.s.fGCPhysLastRamFixed);
458 pVM->rem.s.fGCPhysLastRamFixed = true;
459#ifdef RT_STRICT
460 rc = remR3InitPhysRamSizeAndDirtyMap(pVM, true /* fGuarded */);
461#else
462 rc = remR3InitPhysRamSizeAndDirtyMap(pVM, false /* fGuarded */);
463#endif
464 return rc;
465}
466
467
468/**
469 * Initializes phys_ram_size, phys_ram_dirty and phys_ram_dirty_size.
470 *
471 * @returns VBox status code.
472 * @param pVM The VM handle.
473 * @param fGuarded Whether to guard the map.
474 */
475static int remR3InitPhysRamSizeAndDirtyMap(PVM pVM, bool fGuarded)
476{
477 int rc = VINF_SUCCESS;
478 RTGCPHYS cb;
479
480 cb = pVM->rem.s.GCPhysLastRam + 1;
481 AssertLogRelMsgReturn(cb > pVM->rem.s.GCPhysLastRam,
482 ("GCPhysLastRam=%RGp - out of range\n", pVM->rem.s.GCPhysLastRam),
483 VERR_OUT_OF_RANGE);
484 phys_ram_size = cb;
485 phys_ram_dirty_size = cb >> PAGE_SHIFT;
486 AssertMsg(((RTGCPHYS)phys_ram_dirty_size << PAGE_SHIFT) == cb, ("%RGp\n", cb));
487
488 if (!fGuarded)
489 {
490 phys_ram_dirty = MMR3HeapAlloc(pVM, MM_TAG_REM, phys_ram_dirty_size);
491 AssertLogRelMsgReturn(phys_ram_dirty, ("Failed to allocate %u bytes of dirty page map bytes\n", phys_ram_dirty_size), VERR_NO_MEMORY);
492 }
493 else
494 {
495 /*
496 * Fill it up the nearest 4GB RAM and leave at least _64KB of guard after it.
497 */
498 uint32_t cbBitmapAligned = RT_ALIGN_32(phys_ram_dirty_size, PAGE_SIZE);
499 uint32_t cbBitmapFull = RT_ALIGN_32(phys_ram_dirty_size, (_4G >> PAGE_SHIFT));
500 if (cbBitmapFull == cbBitmapAligned)
501 cbBitmapFull += _4G >> PAGE_SHIFT;
502 else if (cbBitmapFull - cbBitmapAligned < _64K)
503 cbBitmapFull += _64K;
504
505 phys_ram_dirty = RTMemPageAlloc(cbBitmapFull);
506 AssertLogRelMsgReturn(phys_ram_dirty, ("Failed to allocate %u bytes of dirty page map bytes\n", cbBitmapFull), VERR_NO_MEMORY);
507
508 rc = RTMemProtect(phys_ram_dirty + cbBitmapAligned, cbBitmapFull - cbBitmapAligned, RTMEM_PROT_NONE);
509 if (RT_FAILURE(rc))
510 {
511 RTMemPageFree(phys_ram_dirty);
512 AssertLogRelRCReturn(rc, rc);
513 }
514
515 phys_ram_dirty += cbBitmapAligned - phys_ram_dirty_size;
516 }
517
518 /* initialize it. */
519 memset(phys_ram_dirty, 0xff, phys_ram_dirty_size);
520 return rc;
521}
522
523
524/**
525 * Terminates the REM.
526 *
527 * Termination means cleaning up and freeing all resources,
528 * the VM it self is at this point powered off or suspended.
529 *
530 * @returns VBox status code.
531 * @param pVM The VM to operate on.
532 */
533REMR3DECL(int) REMR3Term(PVM pVM)
534{
535#ifdef VBOX_WITH_STATISTICS
536 /*
537 * Statistics.
538 */
539 STAM_DEREG(pVM, &gStatExecuteSingleInstr);
540 STAM_DEREG(pVM, &gStatCompilationQEmu);
541 STAM_DEREG(pVM, &gStatRunCodeQEmu);
542 STAM_DEREG(pVM, &gStatTotalTimeQEmu);
543 STAM_DEREG(pVM, &gStatTimers);
544 STAM_DEREG(pVM, &gStatTBLookup);
545 STAM_DEREG(pVM, &gStatIRQ);
546 STAM_DEREG(pVM, &gStatRawCheck);
547 STAM_DEREG(pVM, &gStatMemRead);
548 STAM_DEREG(pVM, &gStatMemWrite);
549 STAM_DEREG(pVM, &gStatHCVirt2GCPhys);
550 STAM_DEREG(pVM, &gStatGCPhys2HCVirt);
551
552 STAM_DEREG(pVM, &gStatCpuGetTSC);
553
554 STAM_DEREG(pVM, &gStatRefuseTFInhibit);
555 STAM_DEREG(pVM, &gStatRefuseVM86);
556 STAM_DEREG(pVM, &gStatRefusePaging);
557 STAM_DEREG(pVM, &gStatRefusePAE);
558 STAM_DEREG(pVM, &gStatRefuseIOPLNot0);
559 STAM_DEREG(pVM, &gStatRefuseIF0);
560 STAM_DEREG(pVM, &gStatRefuseCode16);
561 STAM_DEREG(pVM, &gStatRefuseWP0);
562 STAM_DEREG(pVM, &gStatRefuseRing1or2);
563 STAM_DEREG(pVM, &gStatRefuseCanExecute);
564 STAM_DEREG(pVM, &gStatFlushTBs);
565
566 STAM_DEREG(pVM, &gStatREMGDTChange);
567 STAM_DEREG(pVM, &gStatREMLDTRChange);
568 STAM_DEREG(pVM, &gStatREMIDTChange);
569 STAM_DEREG(pVM, &gStatREMTRChange);
570
571 STAM_DEREG(pVM, &gStatSelOutOfSync[0]);
572 STAM_DEREG(pVM, &gStatSelOutOfSync[1]);
573 STAM_DEREG(pVM, &gStatSelOutOfSync[2]);
574 STAM_DEREG(pVM, &gStatSelOutOfSync[3]);
575 STAM_DEREG(pVM, &gStatSelOutOfSync[4]);
576 STAM_DEREG(pVM, &gStatSelOutOfSync[5]);
577
578 STAM_DEREG(pVM, &gStatSelOutOfSyncStateBack[0]);
579 STAM_DEREG(pVM, &gStatSelOutOfSyncStateBack[1]);
580 STAM_DEREG(pVM, &gStatSelOutOfSyncStateBack[2]);
581 STAM_DEREG(pVM, &gStatSelOutOfSyncStateBack[3]);
582 STAM_DEREG(pVM, &gStatSelOutOfSyncStateBack[4]);
583 STAM_DEREG(pVM, &gStatSelOutOfSyncStateBack[5]);
584
585 STAM_DEREG(pVM, &pVM->rem.s.Env.StatTbFlush);
586#endif /* VBOX_WITH_STATISTICS */
587
588 STAM_REL_DEREG(pVM, &tb_flush_count);
589 STAM_REL_DEREG(pVM, &tb_phys_invalidate_count);
590 STAM_REL_DEREG(pVM, &tlb_flush_count);
591
592 return VINF_SUCCESS;
593}
594
595
596/**
597 * The VM is being reset.
598 *
599 * For the REM component this means to call the cpu_reset() and
600 * reinitialize some state variables.
601 *
602 * @param pVM VM handle.
603 */
604REMR3DECL(void) REMR3Reset(PVM pVM)
605{
606 /*
607 * Reset the REM cpu.
608 */
609 Assert(pVM->rem.s.cIgnoreAll == 0);
610 ASMAtomicIncU32(&pVM->rem.s.cIgnoreAll);
611 cpu_reset(&pVM->rem.s.Env);
612 pVM->rem.s.cInvalidatedPages = 0;
613 ASMAtomicDecU32(&pVM->rem.s.cIgnoreAll);
614 Assert(pVM->rem.s.cIgnoreAll == 0);
615
616 /* Clear raw ring 0 init state */
617 pVM->rem.s.Env.state &= ~CPU_RAW_RING0;
618
619 /* Flush the TBs the next time we execute code here. */
620 pVM->rem.s.fFlushTBs = true;
621}
622
623
624/**
625 * Execute state save operation.
626 *
627 * @returns VBox status code.
628 * @param pVM VM Handle.
629 * @param pSSM SSM operation handle.
630 */
631static DECLCALLBACK(int) remR3Save(PVM pVM, PSSMHANDLE pSSM)
632{
633 PREM pRem = &pVM->rem.s;
634
635 /*
636 * Save the required CPU Env bits.
637 * (Not much because we're never in REM when doing the save.)
638 */
639 LogFlow(("remR3Save:\n"));
640 Assert(!pRem->fInREM);
641 SSMR3PutU32(pSSM, pRem->Env.hflags);
642 SSMR3PutU32(pSSM, ~0); /* separator */
643
644 /* Remember if we've entered raw mode (vital for ring 1 checks in e.g. iret emulation). */
645 SSMR3PutU32(pSSM, !!(pRem->Env.state & CPU_RAW_RING0));
646 SSMR3PutUInt(pSSM, pVM->rem.s.u32PendingInterrupt);
647
648 return SSMR3PutU32(pSSM, ~0); /* terminator */
649}
650
651
652/**
653 * Execute state load operation.
654 *
655 * @returns VBox status code.
656 * @param pVM VM Handle.
657 * @param pSSM SSM operation handle.
658 * @param u32Version Data layout version.
659 */
660static DECLCALLBACK(int) remR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version)
661{
662 uint32_t u32Dummy;
663 uint32_t fRawRing0 = false;
664 uint32_t u32Sep;
665 unsigned i;
666 int rc;
667 PREM pRem;
668 LogFlow(("remR3Load:\n"));
669
670 /*
671 * Validate version.
672 */
673 if ( u32Version != REM_SAVED_STATE_VERSION
674 && u32Version != REM_SAVED_STATE_VERSION_VER1_6)
675 {
676 AssertMsgFailed(("remR3Load: Invalid version u32Version=%d!\n", u32Version));
677 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
678 }
679
680 /*
681 * Do a reset to be on the safe side...
682 */
683 REMR3Reset(pVM);
684
685 /*
686 * Ignore all ignorable notifications.
687 * (Not doing this will cause serious trouble.)
688 */
689 ASMAtomicIncU32(&pVM->rem.s.cIgnoreAll);
690
691 /*
692 * Load the required CPU Env bits.
693 * (Not much because we're never in REM when doing the save.)
694 */
695 pRem = &pVM->rem.s;
696 Assert(!pRem->fInREM);
697 SSMR3GetU32(pSSM, &pRem->Env.hflags);
698 if (u32Version == REM_SAVED_STATE_VERSION_VER1_6)
699 {
700 /* Redundant REM CPU state has to be loaded, but can be ignored. */
701 CPUX86State_Ver16 temp;
702 SSMR3GetMem(pSSM, &temp, RT_OFFSETOF(CPUX86State_Ver16, jmp_env));
703 }
704
705 rc = SSMR3GetU32(pSSM, &u32Sep); /* separator */
706 if (RT_FAILURE(rc))
707 return rc;
708 if (u32Sep != ~0U)
709 {
710 AssertMsgFailed(("u32Sep=%#x\n", u32Sep));
711 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
712 }
713
714 /* Remember if we've entered raw mode (vital for ring 1 checks in e.g. iret emulation). */
715 SSMR3GetUInt(pSSM, &fRawRing0);
716 if (fRawRing0)
717 pRem->Env.state |= CPU_RAW_RING0;
718
719 if (u32Version == REM_SAVED_STATE_VERSION_VER1_6)
720 {
721 /*
722 * Load the REM stuff.
723 */
724 rc = SSMR3GetUInt(pSSM, &pRem->cInvalidatedPages);
725 if (RT_FAILURE(rc))
726 return rc;
727 if (pRem->cInvalidatedPages > RT_ELEMENTS(pRem->aGCPtrInvalidatedPages))
728 {
729 AssertMsgFailed(("cInvalidatedPages=%#x\n", pRem->cInvalidatedPages));
730 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
731 }
732 for (i = 0; i < pRem->cInvalidatedPages; i++)
733 SSMR3GetGCPtr(pSSM, &pRem->aGCPtrInvalidatedPages[i]);
734 }
735
736 rc = SSMR3GetUInt(pSSM, &pVM->rem.s.u32PendingInterrupt);
737 if (RT_FAILURE(rc))
738 return rc;
739
740 /* check the terminator. */
741 rc = SSMR3GetU32(pSSM, &u32Sep);
742 if (RT_FAILURE(rc))
743 return rc;
744 if (u32Sep != ~0U)
745 {
746 AssertMsgFailed(("u32Sep=%#x (term)\n", u32Sep));
747 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
748 }
749
750 /*
751 * Get the CPUID features.
752 */
753 PVMCPU pVCpu = VMMGetCpu(pVM);
754 CPUMGetGuestCpuId(pVCpu, 1, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext_features, &pVM->rem.s.Env.cpuid_features);
755 CPUMGetGuestCpuId(pVCpu, 0x80000001, &u32Dummy, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext2_features);
756
757 /*
758 * Sync the Load Flush the TLB
759 */
760 tlb_flush(&pRem->Env, 1);
761
762 /*
763 * Stop ignoring ignornable notifications.
764 */
765 ASMAtomicDecU32(&pVM->rem.s.cIgnoreAll);
766
767 /*
768 * Sync the whole CPU state when executing code in the recompiler.
769 */
770 for (i=0;i<pVM->cCPUs;i++)
771 {
772 PVMCPU pVCpu = &pVM->aCpus[i];
773
774 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_ALL);
775 }
776 return VINF_SUCCESS;
777}
778
779
780
781#undef LOG_GROUP
782#define LOG_GROUP LOG_GROUP_REM_RUN
783
784/**
785 * Single steps an instruction in recompiled mode.
786 *
787 * Before calling this function the REM state needs to be in sync with
788 * the VM. Call REMR3State() to perform the sync. It's only necessary
789 * (and permitted) to sync at the first call to REMR3Step()/REMR3Run()
790 * and after calling REMR3StateBack().
791 *
792 * @returns VBox status code.
793 *
794 * @param pVM VM Handle.
795 * @param pVCpu VMCPU Handle.
796 */
797REMR3DECL(int) REMR3Step(PVM pVM, PVMCPU pVCpu)
798{
799 int rc, interrupt_request;
800 RTGCPTR GCPtrPC;
801 bool fBp;
802
803 /*
804 * Lock the REM - we don't wanna have anyone interrupting us
805 * while stepping - and enabled single stepping. We also ignore
806 * pending interrupts and suchlike.
807 */
808 interrupt_request = pVM->rem.s.Env.interrupt_request;
809 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)));
810 pVM->rem.s.Env.interrupt_request = 0;
811 cpu_single_step(&pVM->rem.s.Env, 1);
812
813 /*
814 * If we're standing at a breakpoint, that have to be disabled before we start stepping.
815 */
816 GCPtrPC = pVM->rem.s.Env.eip + pVM->rem.s.Env.segs[R_CS].base;
817 fBp = !cpu_breakpoint_remove(&pVM->rem.s.Env, GCPtrPC);
818
819 /*
820 * Execute and handle the return code.
821 * We execute without enabling the cpu tick, so on success we'll
822 * just flip it on and off to make sure it moves
823 */
824 rc = cpu_exec(&pVM->rem.s.Env);
825 if (rc == EXCP_DEBUG)
826 {
827 TMR3NotifyResume(pVM, pVCpu);
828 TMR3NotifySuspend(pVM, pVCpu);
829 rc = VINF_EM_DBG_STEPPED;
830 }
831 else
832 {
833 switch (rc)
834 {
835 case EXCP_INTERRUPT: rc = VINF_SUCCESS; break;
836 case EXCP_HLT:
837 case EXCP_HALTED: rc = VINF_EM_HALT; break;
838 case EXCP_RC:
839 rc = pVM->rem.s.rc;
840 pVM->rem.s.rc = VERR_INTERNAL_ERROR;
841 break;
842 case EXCP_EXECUTE_RAW:
843 case EXCP_EXECUTE_HWACC:
844 /** @todo: is it correct? No! */
845 rc = VINF_SUCCESS;
846 break;
847 default:
848 AssertReleaseMsgFailed(("This really shouldn't happen, rc=%d!\n", rc));
849 rc = VERR_INTERNAL_ERROR;
850 break;
851 }
852 }
853
854 /*
855 * Restore the stuff we changed to prevent interruption.
856 * Unlock the REM.
857 */
858 if (fBp)
859 {
860 int rc2 = cpu_breakpoint_insert(&pVM->rem.s.Env, GCPtrPC);
861 Assert(rc2 == 0); NOREF(rc2);
862 }
863 cpu_single_step(&pVM->rem.s.Env, 0);
864 pVM->rem.s.Env.interrupt_request = interrupt_request;
865
866 return rc;
867}
868
869
870/**
871 * Set a breakpoint using the REM facilities.
872 *
873 * @returns VBox status code.
874 * @param pVM The VM handle.
875 * @param Address The breakpoint address.
876 * @thread The emulation thread.
877 */
878REMR3DECL(int) REMR3BreakpointSet(PVM pVM, RTGCUINTPTR Address)
879{
880 VM_ASSERT_EMT(pVM);
881 if (!cpu_breakpoint_insert(&pVM->rem.s.Env, Address))
882 {
883 LogFlow(("REMR3BreakpointSet: Address=%RGv\n", Address));
884 return VINF_SUCCESS;
885 }
886 LogFlow(("REMR3BreakpointSet: Address=%RGv - failed!\n", Address));
887 return VERR_REM_NO_MORE_BP_SLOTS;
888}
889
890
891/**
892 * Clears a breakpoint set by REMR3BreakpointSet().
893 *
894 * @returns VBox status code.
895 * @param pVM The VM handle.
896 * @param Address The breakpoint address.
897 * @thread The emulation thread.
898 */
899REMR3DECL(int) REMR3BreakpointClear(PVM pVM, RTGCUINTPTR Address)
900{
901 VM_ASSERT_EMT(pVM);
902 if (!cpu_breakpoint_remove(&pVM->rem.s.Env, Address))
903 {
904 LogFlow(("REMR3BreakpointClear: Address=%RGv\n", Address));
905 return VINF_SUCCESS;
906 }
907 LogFlow(("REMR3BreakpointClear: Address=%RGv - not found!\n", Address));
908 return VERR_REM_BP_NOT_FOUND;
909}
910
911
912/**
913 * Emulate an instruction.
914 *
915 * This function executes one instruction without letting anyone
916 * interrupt it. This is intended for being called while being in
917 * raw mode and thus will take care of all the state syncing between
918 * REM and the rest.
919 *
920 * @returns VBox status code.
921 * @param pVM VM handle.
922 * @param pVCpu VMCPU Handle.
923 */
924REMR3DECL(int) REMR3EmulateInstruction(PVM pVM, PVMCPU pVCpu)
925{
926 bool fFlushTBs;
927
928 int rc, rc2;
929 Log2(("REMR3EmulateInstruction: (cs:eip=%04x:%08x)\n", CPUMGetGuestCS(pVCpu), CPUMGetGuestEIP(pVCpu)));
930
931 /* Make sure this flag is set; we might never execute remR3CanExecuteRaw in the AMD-V case.
932 * CPU_RAW_HWACC makes sure we never execute interrupt handlers in the recompiler.
933 */
934 if (HWACCMIsEnabled(pVM))
935 pVM->rem.s.Env.state |= CPU_RAW_HWACC;
936
937 /* Skip the TB flush as that's rather expensive and not necessary for single instruction emulation. */
938 fFlushTBs = pVM->rem.s.fFlushTBs;
939 pVM->rem.s.fFlushTBs = false;
940
941 /*
942 * Sync the state and enable single instruction / single stepping.
943 */
944 rc = REMR3State(pVM, pVCpu);
945 pVM->rem.s.fFlushTBs = fFlushTBs;
946 if (RT_SUCCESS(rc))
947 {
948 int interrupt_request = pVM->rem.s.Env.interrupt_request;
949 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)));
950 Assert(!pVM->rem.s.Env.singlestep_enabled);
951 /*
952 * Now we set the execute single instruction flag and enter the cpu_exec loop.
953 */
954 TMNotifyStartOfExecution(pVCpu);
955 pVM->rem.s.Env.interrupt_request = CPU_INTERRUPT_SINGLE_INSTR;
956 rc = cpu_exec(&pVM->rem.s.Env);
957 TMNotifyEndOfExecution(pVCpu);
958 switch (rc)
959 {
960 /*
961 * Executed without anything out of the way happening.
962 */
963 case EXCP_SINGLE_INSTR:
964 rc = VINF_EM_RESCHEDULE;
965 Log2(("REMR3EmulateInstruction: cpu_exec -> EXCP_SINGLE_INSTR\n"));
966 break;
967
968 /*
969 * If we take a trap or start servicing a pending interrupt, we might end up here.
970 * (Timer thread or some other thread wishing EMT's attention.)
971 */
972 case EXCP_INTERRUPT:
973 Log2(("REMR3EmulateInstruction: cpu_exec -> EXCP_INTERRUPT\n"));
974 rc = VINF_EM_RESCHEDULE;
975 break;
976
977 /*
978 * Single step, we assume!
979 * If there was a breakpoint there we're fucked now.
980 */
981 case EXCP_DEBUG:
982 {
983 /* breakpoint or single step? */
984 RTGCPTR GCPtrPC = pVM->rem.s.Env.eip + pVM->rem.s.Env.segs[R_CS].base;
985 int iBP;
986 rc = VINF_EM_DBG_STEPPED;
987 for (iBP = 0; iBP < pVM->rem.s.Env.nb_breakpoints; iBP++)
988 if (pVM->rem.s.Env.breakpoints[iBP] == GCPtrPC)
989 {
990 rc = VINF_EM_DBG_BREAKPOINT;
991 break;
992 }
993 Log2(("REMR3EmulateInstruction: cpu_exec -> EXCP_DEBUG rc=%Rrc iBP=%d GCPtrPC=%RGv\n", rc, iBP, GCPtrPC));
994 break;
995 }
996
997 /*
998 * hlt instruction.
999 */
1000 case EXCP_HLT:
1001 Log2(("REMR3EmulateInstruction: cpu_exec -> EXCP_HLT\n"));
1002 rc = VINF_EM_HALT;
1003 break;
1004
1005 /*
1006 * The VM has halted.
1007 */
1008 case EXCP_HALTED:
1009 Log2(("REMR3EmulateInstruction: cpu_exec -> EXCP_HALTED\n"));
1010 rc = VINF_EM_HALT;
1011 break;
1012
1013 /*
1014 * Switch to RAW-mode.
1015 */
1016 case EXCP_EXECUTE_RAW:
1017 Log2(("REMR3EmulateInstruction: cpu_exec -> EXCP_EXECUTE_RAW\n"));
1018 rc = VINF_EM_RESCHEDULE_RAW;
1019 break;
1020
1021 /*
1022 * Switch to hardware accelerated RAW-mode.
1023 */
1024 case EXCP_EXECUTE_HWACC:
1025 Log2(("REMR3EmulateInstruction: cpu_exec -> EXCP_EXECUTE_HWACC\n"));
1026 rc = VINF_EM_RESCHEDULE_HWACC;
1027 break;
1028
1029 /*
1030 * An EM RC was raised (VMR3Reset/Suspend/PowerOff/some-fatal-error).
1031 */
1032 case EXCP_RC:
1033 Log2(("REMR3EmulateInstruction: cpu_exec -> EXCP_RC\n"));
1034 rc = pVM->rem.s.rc;
1035 pVM->rem.s.rc = VERR_INTERNAL_ERROR;
1036 break;
1037
1038 /*
1039 * Figure out the rest when they arrive....
1040 */
1041 default:
1042 AssertMsgFailed(("rc=%d\n", rc));
1043 Log2(("REMR3EmulateInstruction: cpu_exec -> %d\n", rc));
1044 rc = VINF_EM_RESCHEDULE;
1045 break;
1046 }
1047
1048 /*
1049 * Switch back the state.
1050 */
1051 pVM->rem.s.Env.interrupt_request = interrupt_request;
1052 rc2 = REMR3StateBack(pVM, pVCpu);
1053 AssertRC(rc2);
1054 }
1055
1056 Log2(("REMR3EmulateInstruction: returns %Rrc (cs:eip=%04x:%RGv)\n",
1057 rc, pVM->rem.s.Env.segs[R_CS].selector, (RTGCPTR)pVM->rem.s.Env.eip));
1058 return rc;
1059}
1060
1061
1062/**
1063 * Runs code in recompiled mode.
1064 *
1065 * Before calling this function the REM state needs to be in sync with
1066 * the VM. Call REMR3State() to perform the sync. It's only necessary
1067 * (and permitted) to sync at the first call to REMR3Step()/REMR3Run()
1068 * and after calling REMR3StateBack().
1069 *
1070 * @returns VBox status code.
1071 *
1072 * @param pVM VM Handle.
1073 * @param pVCpu VMCPU Handle.
1074 */
1075REMR3DECL(int) REMR3Run(PVM pVM, PVMCPU pVCpu)
1076{
1077 int rc;
1078 Log2(("REMR3Run: (cs:eip=%04x:%RGv)\n", pVM->rem.s.Env.segs[R_CS].selector, (RTGCPTR)pVM->rem.s.Env.eip));
1079 Assert(pVM->rem.s.fInREM);
1080
1081 TMNotifyStartOfExecution(pVCpu);
1082 rc = cpu_exec(&pVM->rem.s.Env);
1083 TMNotifyEndOfExecution(pVCpu);
1084 switch (rc)
1085 {
1086 /*
1087 * This happens when the execution was interrupted
1088 * by an external event, like pending timers.
1089 */
1090 case EXCP_INTERRUPT:
1091 Log2(("REMR3Run: cpu_exec -> EXCP_INTERRUPT\n"));
1092 rc = VINF_SUCCESS;
1093 break;
1094
1095 /*
1096 * hlt instruction.
1097 */
1098 case EXCP_HLT:
1099 Log2(("REMR3Run: cpu_exec -> EXCP_HLT\n"));
1100 rc = VINF_EM_HALT;
1101 break;
1102
1103 /*
1104 * The VM has halted.
1105 */
1106 case EXCP_HALTED:
1107 Log2(("REMR3Run: cpu_exec -> EXCP_HALTED\n"));
1108 rc = VINF_EM_HALT;
1109 break;
1110
1111 /*
1112 * Breakpoint/single step.
1113 */
1114 case EXCP_DEBUG:
1115 {
1116#if 0//def DEBUG_bird
1117 static int iBP = 0;
1118 printf("howdy, breakpoint! iBP=%d\n", iBP);
1119 switch (iBP)
1120 {
1121 case 0:
1122 cpu_breakpoint_remove(&pVM->rem.s.Env, pVM->rem.s.Env.eip + pVM->rem.s.Env.segs[R_CS].base);
1123 pVM->rem.s.Env.state |= CPU_EMULATE_SINGLE_STEP;
1124 //pVM->rem.s.Env.interrupt_request = 0;
1125 //pVM->rem.s.Env.exception_index = -1;
1126 //g_fInterruptDisabled = 1;
1127 rc = VINF_SUCCESS;
1128 asm("int3");
1129 break;
1130 default:
1131 asm("int3");
1132 break;
1133 }
1134 iBP++;
1135#else
1136 /* breakpoint or single step? */
1137 RTGCPTR GCPtrPC = pVM->rem.s.Env.eip + pVM->rem.s.Env.segs[R_CS].base;
1138 int iBP;
1139 rc = VINF_EM_DBG_STEPPED;
1140 for (iBP = 0; iBP < pVM->rem.s.Env.nb_breakpoints; iBP++)
1141 if (pVM->rem.s.Env.breakpoints[iBP] == GCPtrPC)
1142 {
1143 rc = VINF_EM_DBG_BREAKPOINT;
1144 break;
1145 }
1146 Log2(("REMR3Run: cpu_exec -> EXCP_DEBUG rc=%Rrc iBP=%d GCPtrPC=%RGv\n", rc, iBP, GCPtrPC));
1147#endif
1148 break;
1149 }
1150
1151 /*
1152 * Switch to RAW-mode.
1153 */
1154 case EXCP_EXECUTE_RAW:
1155 Log2(("REMR3Run: cpu_exec -> EXCP_EXECUTE_RAW\n"));
1156 rc = VINF_EM_RESCHEDULE_RAW;
1157 break;
1158
1159 /*
1160 * Switch to hardware accelerated RAW-mode.
1161 */
1162 case EXCP_EXECUTE_HWACC:
1163 Log2(("REMR3Run: cpu_exec -> EXCP_EXECUTE_HWACC\n"));
1164 rc = VINF_EM_RESCHEDULE_HWACC;
1165 break;
1166
1167 /** @todo missing VBOX_WITH_VMI/EXECP_PARAV_CALL */
1168 /*
1169 * An EM RC was raised (VMR3Reset/Suspend/PowerOff/some-fatal-error).
1170 */
1171 case EXCP_RC:
1172 Log2(("REMR3Run: cpu_exec -> EXCP_RC rc=%Rrc\n", pVM->rem.s.rc));
1173 rc = pVM->rem.s.rc;
1174 pVM->rem.s.rc = VERR_INTERNAL_ERROR;
1175 break;
1176
1177 /*
1178 * Figure out the rest when they arrive....
1179 */
1180 default:
1181 AssertMsgFailed(("rc=%d\n", rc));
1182 Log2(("REMR3Run: cpu_exec -> %d\n", rc));
1183 rc = VINF_SUCCESS;
1184 break;
1185 }
1186
1187 Log2(("REMR3Run: returns %Rrc (cs:eip=%04x:%RGv)\n", rc, pVM->rem.s.Env.segs[R_CS].selector, (RTGCPTR)pVM->rem.s.Env.eip));
1188 return rc;
1189}
1190
1191
1192/**
1193 * Check if the cpu state is suitable for Raw execution.
1194 *
1195 * @returns boolean
1196 * @param env The CPU env struct.
1197 * @param eip The EIP to check this for (might differ from env->eip).
1198 * @param fFlags hflags OR'ed with IOPL, TF and VM from eflags.
1199 * @param piException Stores EXCP_EXECUTE_RAW/HWACC in case raw mode is supported in this context
1200 *
1201 * @remark This function must be kept in perfect sync with the scheduler in EM.cpp!
1202 */
1203bool remR3CanExecuteRaw(CPUState *env, RTGCPTR eip, unsigned fFlags, int *piException)
1204{
1205 /* !!! THIS MUST BE IN SYNC WITH emR3Reschedule !!! */
1206 /* !!! THIS MUST BE IN SYNC WITH emR3Reschedule !!! */
1207 /* !!! THIS MUST BE IN SYNC WITH emR3Reschedule !!! */
1208 uint32_t u32CR0;
1209
1210 /* Update counter. */
1211 env->pVM->rem.s.cCanExecuteRaw++;
1212
1213 if (HWACCMIsEnabled(env->pVM))
1214 {
1215 CPUMCTX Ctx;
1216
1217 env->state |= CPU_RAW_HWACC;
1218
1219 /*
1220 * Create partial context for HWACCMR3CanExecuteGuest
1221 */
1222 Ctx.cr0 = env->cr[0];
1223 Ctx.cr3 = env->cr[3];
1224 Ctx.cr4 = env->cr[4];
1225
1226 Ctx.tr = env->tr.selector;
1227 Ctx.trHid.u64Base = env->tr.base;
1228 Ctx.trHid.u32Limit = env->tr.limit;
1229 Ctx.trHid.Attr.u = (env->tr.flags >> 8) & 0xF0FF;
1230
1231 Ctx.idtr.cbIdt = env->idt.limit;
1232 Ctx.idtr.pIdt = env->idt.base;
1233
1234 Ctx.gdtr.cbGdt = env->gdt.limit;
1235 Ctx.gdtr.pGdt = env->gdt.base;
1236
1237 Ctx.rsp = env->regs[R_ESP];
1238 Ctx.rip = env->eip;
1239
1240 Ctx.eflags.u32 = env->eflags;
1241
1242 Ctx.cs = env->segs[R_CS].selector;
1243 Ctx.csHid.u64Base = env->segs[R_CS].base;
1244 Ctx.csHid.u32Limit = env->segs[R_CS].limit;
1245 Ctx.csHid.Attr.u = (env->segs[R_CS].flags >> 8) & 0xF0FF;
1246
1247 Ctx.ds = env->segs[R_DS].selector;
1248 Ctx.dsHid.u64Base = env->segs[R_DS].base;
1249 Ctx.dsHid.u32Limit = env->segs[R_DS].limit;
1250 Ctx.dsHid.Attr.u = (env->segs[R_DS].flags >> 8) & 0xF0FF;
1251
1252 Ctx.es = env->segs[R_ES].selector;
1253 Ctx.esHid.u64Base = env->segs[R_ES].base;
1254 Ctx.esHid.u32Limit = env->segs[R_ES].limit;
1255 Ctx.esHid.Attr.u = (env->segs[R_ES].flags >> 8) & 0xF0FF;
1256
1257 Ctx.fs = env->segs[R_FS].selector;
1258 Ctx.fsHid.u64Base = env->segs[R_FS].base;
1259 Ctx.fsHid.u32Limit = env->segs[R_FS].limit;
1260 Ctx.fsHid.Attr.u = (env->segs[R_FS].flags >> 8) & 0xF0FF;
1261
1262 Ctx.gs = env->segs[R_GS].selector;
1263 Ctx.gsHid.u64Base = env->segs[R_GS].base;
1264 Ctx.gsHid.u32Limit = env->segs[R_GS].limit;
1265 Ctx.gsHid.Attr.u = (env->segs[R_GS].flags >> 8) & 0xF0FF;
1266
1267 Ctx.ss = env->segs[R_SS].selector;
1268 Ctx.ssHid.u64Base = env->segs[R_SS].base;
1269 Ctx.ssHid.u32Limit = env->segs[R_SS].limit;
1270 Ctx.ssHid.Attr.u = (env->segs[R_SS].flags >> 8) & 0xF0FF;
1271
1272 Ctx.msrEFER = env->efer;
1273
1274 /* Hardware accelerated raw-mode:
1275 *
1276 * Typically only 32-bits protected mode, with paging enabled, code is allowed here.
1277 */
1278 if (HWACCMR3CanExecuteGuest(env->pVM, &Ctx) == true)
1279 {
1280 *piException = EXCP_EXECUTE_HWACC;
1281 return true;
1282 }
1283 return false;
1284 }
1285
1286 /*
1287 * Here we only support 16 & 32 bits protected mode ring 3 code that has no IO privileges
1288 * or 32 bits protected mode ring 0 code
1289 *
1290 * The tests are ordered by the likelyhood of being true during normal execution.
1291 */
1292 if (fFlags & (HF_TF_MASK | HF_INHIBIT_IRQ_MASK))
1293 {
1294 STAM_COUNTER_INC(&gStatRefuseTFInhibit);
1295 Log2(("raw mode refused: fFlags=%#x\n", fFlags));
1296 return false;
1297 }
1298
1299#ifndef VBOX_RAW_V86
1300 if (fFlags & VM_MASK) {
1301 STAM_COUNTER_INC(&gStatRefuseVM86);
1302 Log2(("raw mode refused: VM_MASK\n"));
1303 return false;
1304 }
1305#endif
1306
1307 if (env->state & CPU_EMULATE_SINGLE_INSTR)
1308 {
1309#ifndef DEBUG_bird
1310 Log2(("raw mode refused: CPU_EMULATE_SINGLE_INSTR\n"));
1311#endif
1312 return false;
1313 }
1314
1315 if (env->singlestep_enabled)
1316 {
1317 //Log2(("raw mode refused: Single step\n"));
1318 return false;
1319 }
1320
1321 if (env->nb_breakpoints > 0)
1322 {
1323 //Log2(("raw mode refused: Breakpoints\n"));
1324 return false;
1325 }
1326
1327 u32CR0 = env->cr[0];
1328 if ((u32CR0 & (X86_CR0_PG | X86_CR0_PE)) != (X86_CR0_PG | X86_CR0_PE))
1329 {
1330 STAM_COUNTER_INC(&gStatRefusePaging);
1331 //Log2(("raw mode refused: %s%s%s\n", (u32CR0 & X86_CR0_PG) ? "" : " !PG", (u32CR0 & X86_CR0_PE) ? "" : " !PE", (u32CR0 & X86_CR0_AM) ? "" : " !AM"));
1332 return false;
1333 }
1334
1335 if (env->cr[4] & CR4_PAE_MASK)
1336 {
1337 if (!(env->cpuid_features & X86_CPUID_FEATURE_EDX_PAE))
1338 {
1339 STAM_COUNTER_INC(&gStatRefusePAE);
1340 return false;
1341 }
1342 }
1343
1344 if (((fFlags >> HF_CPL_SHIFT) & 3) == 3)
1345 {
1346 if (!EMIsRawRing3Enabled(env->pVM))
1347 return false;
1348
1349 if (!(env->eflags & IF_MASK))
1350 {
1351 STAM_COUNTER_INC(&gStatRefuseIF0);
1352 Log2(("raw mode refused: IF (RawR3)\n"));
1353 return false;
1354 }
1355
1356 if (!(u32CR0 & CR0_WP_MASK) && EMIsRawRing0Enabled(env->pVM))
1357 {
1358 STAM_COUNTER_INC(&gStatRefuseWP0);
1359 Log2(("raw mode refused: CR0.WP + RawR0\n"));
1360 return false;
1361 }
1362 }
1363 else
1364 {
1365 if (!EMIsRawRing0Enabled(env->pVM))
1366 return false;
1367
1368 // Let's start with pure 32 bits ring 0 code first
1369 if ((fFlags & (HF_SS32_MASK | HF_CS32_MASK)) != (HF_SS32_MASK | HF_CS32_MASK))
1370 {
1371 STAM_COUNTER_INC(&gStatRefuseCode16);
1372 Log2(("raw r0 mode refused: HF_[S|C]S32_MASK fFlags=%#x\n", fFlags));
1373 return false;
1374 }
1375
1376 // Only R0
1377 if (((fFlags >> HF_CPL_SHIFT) & 3) != 0)
1378 {
1379 STAM_COUNTER_INC(&gStatRefuseRing1or2);
1380 Log2(("raw r0 mode refused: CPL %d\n", ((fFlags >> HF_CPL_SHIFT) & 3) ));
1381 return false;
1382 }
1383
1384 if (!(u32CR0 & CR0_WP_MASK))
1385 {
1386 STAM_COUNTER_INC(&gStatRefuseWP0);
1387 Log2(("raw r0 mode refused: CR0.WP=0!\n"));
1388 return false;
1389 }
1390
1391 if (PATMIsPatchGCAddr(env->pVM, eip))
1392 {
1393 Log2(("raw r0 mode forced: patch code\n"));
1394 *piException = EXCP_EXECUTE_RAW;
1395 return true;
1396 }
1397
1398#if !defined(VBOX_ALLOW_IF0) && !defined(VBOX_RUN_INTERRUPT_GATE_HANDLERS)
1399 if (!(env->eflags & IF_MASK))
1400 {
1401 STAM_COUNTER_INC(&gStatRefuseIF0);
1402 ////Log2(("R0: IF=0 VIF=%d %08X\n", eip, *env->pVMeflags));
1403 //Log2(("RR0: Interrupts turned off; fall back to emulation\n"));
1404 return false;
1405 }
1406#endif
1407
1408 env->state |= CPU_RAW_RING0;
1409 }
1410
1411 /*
1412 * Don't reschedule the first time we're called, because there might be
1413 * special reasons why we're here that is not covered by the above checks.
1414 */
1415 if (env->pVM->rem.s.cCanExecuteRaw == 1)
1416 {
1417 Log2(("raw mode refused: first scheduling\n"));
1418 STAM_COUNTER_INC(&gStatRefuseCanExecute);
1419 return false;
1420 }
1421
1422 Assert(env->pVCpu && PGMPhysIsA20Enabled(env->pVCpu));
1423 *piException = EXCP_EXECUTE_RAW;
1424 return true;
1425}
1426
1427
1428/**
1429 * Fetches a code byte.
1430 *
1431 * @returns Success indicator (bool) for ease of use.
1432 * @param env The CPU environment structure.
1433 * @param GCPtrInstr Where to fetch code.
1434 * @param pu8Byte Where to store the byte on success
1435 */
1436bool remR3GetOpcode(CPUState *env, RTGCPTR GCPtrInstr, uint8_t *pu8Byte)
1437{
1438 int rc = PATMR3QueryOpcode(env->pVM, GCPtrInstr, pu8Byte);
1439 if (RT_SUCCESS(rc))
1440 return true;
1441 return false;
1442}
1443
1444
1445/**
1446 * Flush (or invalidate if you like) page table/dir entry.
1447 *
1448 * (invlpg instruction; tlb_flush_page)
1449 *
1450 * @param env Pointer to cpu environment.
1451 * @param GCPtr The virtual address which page table/dir entry should be invalidated.
1452 */
1453void remR3FlushPage(CPUState *env, RTGCPTR GCPtr)
1454{
1455 PVM pVM = env->pVM;
1456 PCPUMCTX pCtx;
1457 int rc;
1458
1459 /*
1460 * When we're replaying invlpg instructions or restoring a saved
1461 * state we disable this path.
1462 */
1463 if (pVM->rem.s.fIgnoreInvlPg || pVM->rem.s.cIgnoreAll)
1464 return;
1465 Log(("remR3FlushPage: GCPtr=%RGv\n", GCPtr));
1466 Assert(pVM->rem.s.fInREM || pVM->rem.s.fInStateSync);
1467
1468 //RAWEx_ProfileStop(env, STATS_QEMU_TOTAL);
1469
1470 /*
1471 * Update the control registers before calling PGMFlushPage.
1472 */
1473 pCtx = (PCPUMCTX)pVM->rem.s.pCtx;
1474 Assert(pCtx);
1475 pCtx->cr0 = env->cr[0];
1476 pCtx->cr3 = env->cr[3];
1477 if ((env->cr[4] ^ pCtx->cr4) & X86_CR4_VME)
1478 VMCPU_FF_SET(env->pVCpu, VMCPU_FF_SELM_SYNC_TSS);
1479 pCtx->cr4 = env->cr[4];
1480
1481 /*
1482 * Let PGM do the rest.
1483 */
1484 Assert(env->pVCpu);
1485 rc = PGMInvalidatePage(env->pVCpu, GCPtr);
1486 if (RT_FAILURE(rc))
1487 {
1488 AssertMsgFailed(("remR3FlushPage %RGv failed with %d!!\n", GCPtr, rc));
1489 VMCPU_FF_SET(env->pVCpu, VMCPU_FF_PGM_SYNC_CR3);
1490 }
1491 //RAWEx_ProfileStart(env, STATS_QEMU_TOTAL);
1492}
1493
1494
1495#ifndef REM_PHYS_ADDR_IN_TLB
1496/** Wrapper for PGMR3PhysTlbGCPhys2Ptr. */
1497void *remR3TlbGCPhys2Ptr(CPUState *env1, target_ulong physAddr, int fWritable)
1498{
1499 void *pv;
1500 int rc;
1501
1502 /* Address must be aligned enough to fiddle with lower bits */
1503 Assert((physAddr & 0x3) == 0);
1504
1505 rc = PGMR3PhysTlbGCPhys2Ptr(env1->pVM, physAddr, true /*fWritable*/, &pv);
1506 Assert( rc == VINF_SUCCESS
1507 || rc == VINF_PGM_PHYS_TLB_CATCH_WRITE
1508 || rc == VERR_PGM_PHYS_TLB_CATCH_ALL
1509 || rc == VERR_PGM_PHYS_TLB_UNASSIGNED);
1510 if (RT_FAILURE(rc))
1511 return (void *)1;
1512 if (rc == VINF_PGM_PHYS_TLB_CATCH_WRITE)
1513 return (void *)((uintptr_t)pv | 2);
1514 return pv;
1515}
1516#endif /* REM_PHYS_ADDR_IN_TLB */
1517
1518
1519/**
1520 * Called from tlb_protect_code in order to write monitor a code page.
1521 *
1522 * @param env Pointer to the CPU environment.
1523 * @param GCPtr Code page to monitor
1524 */
1525void remR3ProtectCode(CPUState *env, RTGCPTR GCPtr)
1526{
1527#ifdef VBOX_REM_PROTECT_PAGES_FROM_SMC
1528 Assert(env->pVM->rem.s.fInREM);
1529 if ( (env->cr[0] & X86_CR0_PG) /* paging must be enabled */
1530 && !(env->state & CPU_EMULATE_SINGLE_INSTR) /* ignore during single instruction execution */
1531 && (((env->hflags >> HF_CPL_SHIFT) & 3) == 0) /* supervisor mode only */
1532 && !(env->eflags & VM_MASK) /* no V86 mode */
1533 && !HWACCMIsEnabled(env->pVM))
1534 CSAMR3MonitorPage(env->pVM, GCPtr, CSAM_TAG_REM);
1535#endif
1536}
1537
1538
1539/**
1540 * Called from tlb_unprotect_code in order to clear write monitoring for a code page.
1541 *
1542 * @param env Pointer to the CPU environment.
1543 * @param GCPtr Code page to monitor
1544 */
1545void remR3UnprotectCode(CPUState *env, RTGCPTR GCPtr)
1546{
1547 Assert(env->pVM->rem.s.fInREM);
1548#ifdef VBOX_REM_PROTECT_PAGES_FROM_SMC
1549 if ( (env->cr[0] & X86_CR0_PG) /* paging must be enabled */
1550 && !(env->state & CPU_EMULATE_SINGLE_INSTR) /* ignore during single instruction execution */
1551 && (((env->hflags >> HF_CPL_SHIFT) & 3) == 0) /* supervisor mode only */
1552 && !(env->eflags & VM_MASK) /* no V86 mode */
1553 && !HWACCMIsEnabled(env->pVM))
1554 CSAMR3UnmonitorPage(env->pVM, GCPtr, CSAM_TAG_REM);
1555#endif
1556}
1557
1558
1559/**
1560 * Called when the CPU is initialized, any of the CRx registers are changed or
1561 * when the A20 line is modified.
1562 *
1563 * @param env Pointer to the CPU environment.
1564 * @param fGlobal Set if the flush is global.
1565 */
1566void remR3FlushTLB(CPUState *env, bool fGlobal)
1567{
1568 PVM pVM = env->pVM;
1569 PCPUMCTX pCtx;
1570
1571 /*
1572 * When we're replaying invlpg instructions or restoring a saved
1573 * state we disable this path.
1574 */
1575 if (pVM->rem.s.fIgnoreCR3Load || pVM->rem.s.cIgnoreAll)
1576 return;
1577 Assert(pVM->rem.s.fInREM);
1578
1579 /*
1580 * The caller doesn't check cr4, so we have to do that for ourselves.
1581 */
1582 if (!fGlobal && !(env->cr[4] & X86_CR4_PGE))
1583 fGlobal = true;
1584 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" : ""));
1585
1586 /*
1587 * Update the control registers before calling PGMR3FlushTLB.
1588 */
1589 pCtx = (PCPUMCTX)pVM->rem.s.pCtx;
1590 Assert(pCtx);
1591 pCtx->cr0 = env->cr[0];
1592 pCtx->cr3 = env->cr[3];
1593 if ((env->cr[4] ^ pCtx->cr4) & X86_CR4_VME)
1594 VMCPU_FF_SET(env->pVCpu, VMCPU_FF_SELM_SYNC_TSS);
1595 pCtx->cr4 = env->cr[4];
1596
1597 /*
1598 * Let PGM do the rest.
1599 */
1600 Assert(env->pVCpu);
1601 PGMFlushTLB(env->pVCpu, env->cr[3], fGlobal);
1602}
1603
1604
1605/**
1606 * Called when any of the cr0, cr4 or efer registers is updated.
1607 *
1608 * @param env Pointer to the CPU environment.
1609 */
1610void remR3ChangeCpuMode(CPUState *env)
1611{
1612 PVM pVM = env->pVM;
1613 uint64_t efer;
1614 PCPUMCTX pCtx;
1615 int rc;
1616
1617 /*
1618 * When we're replaying loads or restoring a saved
1619 * state this path is disabled.
1620 */
1621 if (pVM->rem.s.fIgnoreCpuMode || pVM->rem.s.cIgnoreAll)
1622 return;
1623 Assert(pVM->rem.s.fInREM);
1624
1625 /*
1626 * Update the control registers before calling PGMChangeMode()
1627 * as it may need to map whatever cr3 is pointing to.
1628 */
1629 pCtx = (PCPUMCTX)pVM->rem.s.pCtx;
1630 Assert(pCtx);
1631 pCtx->cr0 = env->cr[0];
1632 pCtx->cr3 = env->cr[3];
1633 if ((env->cr[4] ^ pCtx->cr4) & X86_CR4_VME)
1634 VMCPU_FF_SET(env->pVCpu, VMCPU_FF_SELM_SYNC_TSS);
1635 pCtx->cr4 = env->cr[4];
1636
1637#ifdef TARGET_X86_64
1638 efer = env->efer;
1639#else
1640 efer = 0;
1641#endif
1642 Assert(env->pVCpu);
1643 rc = PGMChangeMode(env->pVCpu, env->cr[0], env->cr[4], efer);
1644 if (rc != VINF_SUCCESS)
1645 {
1646 if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
1647 {
1648 Log(("PGMChangeMode(, %RX64, %RX64, %RX64) -> %Rrc -> remR3RaiseRC\n", env->cr[0], env->cr[4], efer, rc));
1649 remR3RaiseRC(env->pVM, rc);
1650 }
1651 else
1652 cpu_abort(env, "PGMChangeMode(, %RX64, %RX64, %RX64) -> %Rrc\n", env->cr[0], env->cr[4], efer, rc);
1653 }
1654}
1655
1656
1657/**
1658 * Called from compiled code to run dma.
1659 *
1660 * @param env Pointer to the CPU environment.
1661 */
1662void remR3DmaRun(CPUState *env)
1663{
1664 remR3ProfileStop(STATS_QEMU_RUN_EMULATED_CODE);
1665 PDMR3DmaRun(env->pVM);
1666 remR3ProfileStart(STATS_QEMU_RUN_EMULATED_CODE);
1667}
1668
1669
1670/**
1671 * Called from compiled code to schedule pending timers in VMM
1672 *
1673 * @param env Pointer to the CPU environment.
1674 */
1675void remR3TimersRun(CPUState *env)
1676{
1677 LogFlow(("remR3TimersRun:\n"));
1678 LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_5, LOG_GROUP_TM, ("remR3TimersRun\n"));
1679 remR3ProfileStop(STATS_QEMU_RUN_EMULATED_CODE);
1680 remR3ProfileStart(STATS_QEMU_RUN_TIMERS);
1681 TMR3TimerQueuesDo(env->pVM);
1682 remR3ProfileStop(STATS_QEMU_RUN_TIMERS);
1683 remR3ProfileStart(STATS_QEMU_RUN_EMULATED_CODE);
1684}
1685
1686
1687/**
1688 * Record trap occurance
1689 *
1690 * @returns VBox status code
1691 * @param env Pointer to the CPU environment.
1692 * @param uTrap Trap nr
1693 * @param uErrorCode Error code
1694 * @param pvNextEIP Next EIP
1695 */
1696int remR3NotifyTrap(CPUState *env, uint32_t uTrap, uint32_t uErrorCode, RTGCPTR pvNextEIP)
1697{
1698 PVM pVM = env->pVM;
1699#ifdef VBOX_WITH_STATISTICS
1700 static STAMCOUNTER s_aStatTrap[255];
1701 static bool s_aRegisters[RT_ELEMENTS(s_aStatTrap)];
1702#endif
1703
1704#ifdef VBOX_WITH_STATISTICS
1705 if (uTrap < 255)
1706 {
1707 if (!s_aRegisters[uTrap])
1708 {
1709 char szStatName[64];
1710 s_aRegisters[uTrap] = true;
1711 RTStrPrintf(szStatName, sizeof(szStatName), "/REM/Trap/0x%02X", uTrap);
1712 STAM_REG(env->pVM, &s_aStatTrap[uTrap], STAMTYPE_COUNTER, szStatName, STAMUNIT_OCCURENCES, "Trap stats.");
1713 }
1714 STAM_COUNTER_INC(&s_aStatTrap[uTrap]);
1715 }
1716#endif
1717 Log(("remR3NotifyTrap: uTrap=%x error=%x next_eip=%RGv eip=%RGv cr2=%RGv\n", uTrap, uErrorCode, pvNextEIP, (RTGCPTR)env->eip, (RTGCPTR)env->cr[2]));
1718 if( uTrap < 0x20
1719 && (env->cr[0] & X86_CR0_PE)
1720 && !(env->eflags & X86_EFL_VM))
1721 {
1722#ifdef DEBUG
1723 remR3DisasInstr(env, 1, "remR3NotifyTrap: ");
1724#endif
1725 if(pVM->rem.s.uPendingException == uTrap && ++pVM->rem.s.cPendingExceptions > 512)
1726 {
1727 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]));
1728 remR3RaiseRC(env->pVM, VERR_REM_TOO_MANY_TRAPS);
1729 return VERR_REM_TOO_MANY_TRAPS;
1730 }
1731 if(pVM->rem.s.uPendingException != uTrap || pVM->rem.s.uPendingExcptEIP != env->eip || pVM->rem.s.uPendingExcptCR2 != env->cr[2])
1732 pVM->rem.s.cPendingExceptions = 1;
1733 pVM->rem.s.uPendingException = uTrap;
1734 pVM->rem.s.uPendingExcptEIP = env->eip;
1735 pVM->rem.s.uPendingExcptCR2 = env->cr[2];
1736 }
1737 else
1738 {
1739 pVM->rem.s.cPendingExceptions = 0;
1740 pVM->rem.s.uPendingException = uTrap;
1741 pVM->rem.s.uPendingExcptEIP = env->eip;
1742 pVM->rem.s.uPendingExcptCR2 = env->cr[2];
1743 }
1744 return VINF_SUCCESS;
1745}
1746
1747
1748/*
1749 * Clear current active trap
1750 *
1751 * @param pVM VM Handle.
1752 */
1753void remR3TrapClear(PVM pVM)
1754{
1755 pVM->rem.s.cPendingExceptions = 0;
1756 pVM->rem.s.uPendingException = 0;
1757 pVM->rem.s.uPendingExcptEIP = 0;
1758 pVM->rem.s.uPendingExcptCR2 = 0;
1759}
1760
1761
1762/*
1763 * Record previous call instruction addresses
1764 *
1765 * @param env Pointer to the CPU environment.
1766 */
1767void remR3RecordCall(CPUState *env)
1768{
1769 CSAMR3RecordCallAddress(env->pVM, env->eip);
1770}
1771
1772
1773/**
1774 * Syncs the internal REM state with the VM.
1775 *
1776 * This must be called before REMR3Run() is invoked whenever when the REM
1777 * state is not up to date. Calling it several times in a row is not
1778 * permitted.
1779 *
1780 * @returns VBox status code.
1781 *
1782 * @param pVM VM Handle.
1783 * @param pVCpu VMCPU Handle.
1784 *
1785 * @remark The caller has to check for important FFs before calling REMR3Run. REMR3State will
1786 * no do this since the majority of the callers don't want any unnecessary of events
1787 * pending that would immediatly interrupt execution.
1788 */
1789REMR3DECL(int) REMR3State(PVM pVM, PVMCPU pVCpu)
1790{
1791 register const CPUMCTX *pCtx;
1792 register unsigned fFlags;
1793 bool fHiddenSelRegsValid;
1794 unsigned i;
1795 TRPMEVENT enmType;
1796 uint8_t u8TrapNo;
1797 int rc;
1798
1799 STAM_PROFILE_START(&pVM->rem.s.StatsState, a);
1800 Log2(("REMR3State:\n"));
1801
1802 pVM->rem.s.Env.pVCpu = pVCpu;
1803 pCtx = pVM->rem.s.pCtx = CPUMQueryGuestCtxPtr(pVCpu);
1804 fHiddenSelRegsValid = CPUMAreHiddenSelRegsValid(pVM);
1805
1806 Assert(!pVM->rem.s.fInREM);
1807 pVM->rem.s.fInStateSync = true;
1808
1809 /*
1810 * If we have to flush TBs, do that immediately.
1811 */
1812 if (pVM->rem.s.fFlushTBs)
1813 {
1814 STAM_COUNTER_INC(&gStatFlushTBs);
1815 tb_flush(&pVM->rem.s.Env);
1816 pVM->rem.s.fFlushTBs = false;
1817 }
1818
1819 /*
1820 * Copy the registers which require no special handling.
1821 */
1822#ifdef TARGET_X86_64
1823 /* Note that the high dwords of 64 bits registers are undefined in 32 bits mode and are undefined after a mode change. */
1824 Assert(R_EAX == 0);
1825 pVM->rem.s.Env.regs[R_EAX] = pCtx->rax;
1826 Assert(R_ECX == 1);
1827 pVM->rem.s.Env.regs[R_ECX] = pCtx->rcx;
1828 Assert(R_EDX == 2);
1829 pVM->rem.s.Env.regs[R_EDX] = pCtx->rdx;
1830 Assert(R_EBX == 3);
1831 pVM->rem.s.Env.regs[R_EBX] = pCtx->rbx;
1832 Assert(R_ESP == 4);
1833 pVM->rem.s.Env.regs[R_ESP] = pCtx->rsp;
1834 Assert(R_EBP == 5);
1835 pVM->rem.s.Env.regs[R_EBP] = pCtx->rbp;
1836 Assert(R_ESI == 6);
1837 pVM->rem.s.Env.regs[R_ESI] = pCtx->rsi;
1838 Assert(R_EDI == 7);
1839 pVM->rem.s.Env.regs[R_EDI] = pCtx->rdi;
1840 pVM->rem.s.Env.regs[8] = pCtx->r8;
1841 pVM->rem.s.Env.regs[9] = pCtx->r9;
1842 pVM->rem.s.Env.regs[10] = pCtx->r10;
1843 pVM->rem.s.Env.regs[11] = pCtx->r11;
1844 pVM->rem.s.Env.regs[12] = pCtx->r12;
1845 pVM->rem.s.Env.regs[13] = pCtx->r13;
1846 pVM->rem.s.Env.regs[14] = pCtx->r14;
1847 pVM->rem.s.Env.regs[15] = pCtx->r15;
1848
1849 pVM->rem.s.Env.eip = pCtx->rip;
1850
1851 pVM->rem.s.Env.eflags = pCtx->rflags.u64;
1852#else
1853 Assert(R_EAX == 0);
1854 pVM->rem.s.Env.regs[R_EAX] = pCtx->eax;
1855 Assert(R_ECX == 1);
1856 pVM->rem.s.Env.regs[R_ECX] = pCtx->ecx;
1857 Assert(R_EDX == 2);
1858 pVM->rem.s.Env.regs[R_EDX] = pCtx->edx;
1859 Assert(R_EBX == 3);
1860 pVM->rem.s.Env.regs[R_EBX] = pCtx->ebx;
1861 Assert(R_ESP == 4);
1862 pVM->rem.s.Env.regs[R_ESP] = pCtx->esp;
1863 Assert(R_EBP == 5);
1864 pVM->rem.s.Env.regs[R_EBP] = pCtx->ebp;
1865 Assert(R_ESI == 6);
1866 pVM->rem.s.Env.regs[R_ESI] = pCtx->esi;
1867 Assert(R_EDI == 7);
1868 pVM->rem.s.Env.regs[R_EDI] = pCtx->edi;
1869 pVM->rem.s.Env.eip = pCtx->eip;
1870
1871 pVM->rem.s.Env.eflags = pCtx->eflags.u32;
1872#endif
1873
1874 pVM->rem.s.Env.cr[2] = pCtx->cr2;
1875
1876 /** @todo we could probably benefit from using a CPUM_CHANGED_DRx flag too! */
1877 for (i=0;i<8;i++)
1878 pVM->rem.s.Env.dr[i] = pCtx->dr[i];
1879
1880 /*
1881 * Clear the halted hidden flag (the interrupt waking up the CPU can
1882 * have been dispatched in raw mode).
1883 */
1884 pVM->rem.s.Env.hflags &= ~HF_HALTED_MASK;
1885
1886 /*
1887 * Replay invlpg?
1888 */
1889 if (pVM->rem.s.cInvalidatedPages)
1890 {
1891 RTUINT i;
1892
1893 pVM->rem.s.fIgnoreInvlPg = true;
1894 for (i = 0; i < pVM->rem.s.cInvalidatedPages; i++)
1895 {
1896 Log2(("REMR3State: invlpg %RGv\n", pVM->rem.s.aGCPtrInvalidatedPages[i]));
1897 tlb_flush_page(&pVM->rem.s.Env, pVM->rem.s.aGCPtrInvalidatedPages[i]);
1898 }
1899 pVM->rem.s.fIgnoreInvlPg = false;
1900 pVM->rem.s.cInvalidatedPages = 0;
1901 }
1902
1903 /* Replay notification changes. */
1904 REMR3ReplayHandlerNotifications(pVM);
1905
1906 /* Update MSRs; before CRx registers! */
1907 pVM->rem.s.Env.efer = pCtx->msrEFER;
1908 pVM->rem.s.Env.star = pCtx->msrSTAR;
1909 pVM->rem.s.Env.pat = pCtx->msrPAT;
1910#ifdef TARGET_X86_64
1911 pVM->rem.s.Env.lstar = pCtx->msrLSTAR;
1912 pVM->rem.s.Env.cstar = pCtx->msrCSTAR;
1913 pVM->rem.s.Env.fmask = pCtx->msrSFMASK;
1914 pVM->rem.s.Env.kernelgsbase = pCtx->msrKERNELGSBASE;
1915
1916 /* Update the internal long mode activate flag according to the new EFER value. */
1917 if (pCtx->msrEFER & MSR_K6_EFER_LMA)
1918 pVM->rem.s.Env.hflags |= HF_LMA_MASK;
1919 else
1920 pVM->rem.s.Env.hflags &= ~(HF_LMA_MASK | HF_CS64_MASK);
1921#endif
1922
1923 /*
1924 * Registers which are rarely changed and require special handling / order when changed.
1925 */
1926 fFlags = CPUMGetAndClearChangedFlagsREM(pVCpu);
1927 LogFlow(("CPUMGetAndClearChangedFlagsREM %x\n", fFlags));
1928 if (fFlags & ( CPUM_CHANGED_CR4 | CPUM_CHANGED_CR3 | CPUM_CHANGED_CR0
1929 | CPUM_CHANGED_GDTR | CPUM_CHANGED_IDTR | CPUM_CHANGED_LDTR
1930 | CPUM_CHANGED_FPU_REM | CPUM_CHANGED_SYSENTER_MSR | CPUM_CHANGED_CPUID))
1931 {
1932 if (fFlags & CPUM_CHANGED_GLOBAL_TLB_FLUSH)
1933 {
1934 pVM->rem.s.fIgnoreCR3Load = true;
1935 tlb_flush(&pVM->rem.s.Env, true);
1936 pVM->rem.s.fIgnoreCR3Load = false;
1937 }
1938
1939 /* CR4 before CR0! */
1940 if (fFlags & CPUM_CHANGED_CR4)
1941 {
1942 pVM->rem.s.fIgnoreCR3Load = true;
1943 pVM->rem.s.fIgnoreCpuMode = true;
1944 cpu_x86_update_cr4(&pVM->rem.s.Env, pCtx->cr4);
1945 pVM->rem.s.fIgnoreCpuMode = false;
1946 pVM->rem.s.fIgnoreCR3Load = false;
1947 }
1948
1949 if (fFlags & CPUM_CHANGED_CR0)
1950 {
1951 pVM->rem.s.fIgnoreCR3Load = true;
1952 pVM->rem.s.fIgnoreCpuMode = true;
1953 cpu_x86_update_cr0(&pVM->rem.s.Env, pCtx->cr0);
1954 pVM->rem.s.fIgnoreCpuMode = false;
1955 pVM->rem.s.fIgnoreCR3Load = false;
1956 }
1957
1958 if (fFlags & CPUM_CHANGED_CR3)
1959 {
1960 pVM->rem.s.fIgnoreCR3Load = true;
1961 cpu_x86_update_cr3(&pVM->rem.s.Env, pCtx->cr3);
1962 pVM->rem.s.fIgnoreCR3Load = false;
1963 }
1964
1965 if (fFlags & CPUM_CHANGED_GDTR)
1966 {
1967 pVM->rem.s.Env.gdt.base = pCtx->gdtr.pGdt;
1968 pVM->rem.s.Env.gdt.limit = pCtx->gdtr.cbGdt;
1969 }
1970
1971 if (fFlags & CPUM_CHANGED_IDTR)
1972 {
1973 pVM->rem.s.Env.idt.base = pCtx->idtr.pIdt;
1974 pVM->rem.s.Env.idt.limit = pCtx->idtr.cbIdt;
1975 }
1976
1977 if (fFlags & CPUM_CHANGED_SYSENTER_MSR)
1978 {
1979 pVM->rem.s.Env.sysenter_cs = pCtx->SysEnter.cs;
1980 pVM->rem.s.Env.sysenter_eip = pCtx->SysEnter.eip;
1981 pVM->rem.s.Env.sysenter_esp = pCtx->SysEnter.esp;
1982 }
1983
1984 if (fFlags & CPUM_CHANGED_LDTR)
1985 {
1986 if (fHiddenSelRegsValid)
1987 {
1988 pVM->rem.s.Env.ldt.selector = pCtx->ldtr;
1989 pVM->rem.s.Env.ldt.base = pCtx->ldtrHid.u64Base;
1990 pVM->rem.s.Env.ldt.limit = pCtx->ldtrHid.u32Limit;
1991 pVM->rem.s.Env.ldt.flags = (pCtx->ldtrHid.Attr.u << 8) & 0xFFFFFF;
1992 }
1993 else
1994 sync_ldtr(&pVM->rem.s.Env, pCtx->ldtr);
1995 }
1996
1997 if (fFlags & CPUM_CHANGED_CPUID)
1998 {
1999 uint32_t u32Dummy;
2000
2001 /*
2002 * Get the CPUID features.
2003 */
2004 CPUMGetGuestCpuId(pVCpu, 1, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext_features, &pVM->rem.s.Env.cpuid_features);
2005 CPUMGetGuestCpuId(pVCpu, 0x80000001, &u32Dummy, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext2_features);
2006 }
2007
2008 /* Sync FPU state after CR4, CPUID and EFER (!). */
2009 if (fFlags & CPUM_CHANGED_FPU_REM)
2010 save_raw_fp_state(&pVM->rem.s.Env, (uint8_t *)&pCtx->fpu); /* 'save' is an excellent name. */
2011 }
2012
2013 /*
2014 * Sync TR unconditionally to make life simpler.
2015 */
2016 pVM->rem.s.Env.tr.selector = pCtx->tr;
2017 pVM->rem.s.Env.tr.base = pCtx->trHid.u64Base;
2018 pVM->rem.s.Env.tr.limit = pCtx->trHid.u32Limit;
2019 pVM->rem.s.Env.tr.flags = (pCtx->trHid.Attr.u << 8) & 0xFFFFFF;
2020 /* Note! do_interrupt will fault if the busy flag is still set... */
2021 pVM->rem.s.Env.tr.flags &= ~DESC_TSS_BUSY_MASK;
2022
2023 /*
2024 * Update selector registers.
2025 * This must be done *after* we've synced gdt, ldt and crX registers
2026 * since we're reading the GDT/LDT om sync_seg. This will happen with
2027 * saved state which takes a quick dip into rawmode for instance.
2028 */
2029 /*
2030 * Stack; Note first check this one as the CPL might have changed. The
2031 * wrong CPL can cause QEmu to raise an exception in sync_seg!!
2032 */
2033
2034 if (fHiddenSelRegsValid)
2035 {
2036 /* The hidden selector registers are valid in the CPU context. */
2037 /** @note QEmu saves the 2nd dword of the descriptor; we should convert the attribute word back! */
2038
2039 /* Set current CPL */
2040 cpu_x86_set_cpl(&pVM->rem.s.Env, CPUMGetGuestCPL(pVCpu, CPUMCTX2CORE(pCtx)));
2041
2042 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);
2043 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);
2044 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);
2045 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);
2046 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);
2047 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);
2048 }
2049 else
2050 {
2051 /* In 'normal' raw mode we don't have access to the hidden selector registers. */
2052 if (pVM->rem.s.Env.segs[R_SS].selector != pCtx->ss)
2053 {
2054 Log2(("REMR3State: SS changed from %04x to %04x!\n", pVM->rem.s.Env.segs[R_SS].selector, pCtx->ss));
2055
2056 cpu_x86_set_cpl(&pVM->rem.s.Env, CPUMGetGuestCPL(pVCpu, CPUMCTX2CORE(pCtx)));
2057 sync_seg(&pVM->rem.s.Env, R_SS, pCtx->ss);
2058#ifdef VBOX_WITH_STATISTICS
2059 if (pVM->rem.s.Env.segs[R_SS].newselector)
2060 {
2061 STAM_COUNTER_INC(&gStatSelOutOfSync[R_SS]);
2062 }
2063#endif
2064 }
2065 else
2066 pVM->rem.s.Env.segs[R_SS].newselector = 0;
2067
2068 if (pVM->rem.s.Env.segs[R_ES].selector != pCtx->es)
2069 {
2070 Log2(("REMR3State: ES changed from %04x to %04x!\n", pVM->rem.s.Env.segs[R_ES].selector, pCtx->es));
2071 sync_seg(&pVM->rem.s.Env, R_ES, pCtx->es);
2072#ifdef VBOX_WITH_STATISTICS
2073 if (pVM->rem.s.Env.segs[R_ES].newselector)
2074 {
2075 STAM_COUNTER_INC(&gStatSelOutOfSync[R_ES]);
2076 }
2077#endif
2078 }
2079 else
2080 pVM->rem.s.Env.segs[R_ES].newselector = 0;
2081
2082 if (pVM->rem.s.Env.segs[R_CS].selector != pCtx->cs)
2083 {
2084 Log2(("REMR3State: CS changed from %04x to %04x!\n", pVM->rem.s.Env.segs[R_CS].selector, pCtx->cs));
2085 sync_seg(&pVM->rem.s.Env, R_CS, pCtx->cs);
2086#ifdef VBOX_WITH_STATISTICS
2087 if (pVM->rem.s.Env.segs[R_CS].newselector)
2088 {
2089 STAM_COUNTER_INC(&gStatSelOutOfSync[R_CS]);
2090 }
2091#endif
2092 }
2093 else
2094 pVM->rem.s.Env.segs[R_CS].newselector = 0;
2095
2096 if (pVM->rem.s.Env.segs[R_DS].selector != pCtx->ds)
2097 {
2098 Log2(("REMR3State: DS changed from %04x to %04x!\n", pVM->rem.s.Env.segs[R_DS].selector, pCtx->ds));
2099 sync_seg(&pVM->rem.s.Env, R_DS, pCtx->ds);
2100#ifdef VBOX_WITH_STATISTICS
2101 if (pVM->rem.s.Env.segs[R_DS].newselector)
2102 {
2103 STAM_COUNTER_INC(&gStatSelOutOfSync[R_DS]);
2104 }
2105#endif
2106 }
2107 else
2108 pVM->rem.s.Env.segs[R_DS].newselector = 0;
2109
2110 /** @todo need to find a way to communicate potential GDT/LDT changes and thread switches. The selector might
2111 * be the same but not the base/limit. */
2112 if (pVM->rem.s.Env.segs[R_FS].selector != pCtx->fs)
2113 {
2114 Log2(("REMR3State: FS changed from %04x to %04x!\n", pVM->rem.s.Env.segs[R_FS].selector, pCtx->fs));
2115 sync_seg(&pVM->rem.s.Env, R_FS, pCtx->fs);
2116#ifdef VBOX_WITH_STATISTICS
2117 if (pVM->rem.s.Env.segs[R_FS].newselector)
2118 {
2119 STAM_COUNTER_INC(&gStatSelOutOfSync[R_FS]);
2120 }
2121#endif
2122 }
2123 else
2124 pVM->rem.s.Env.segs[R_FS].newselector = 0;
2125
2126 if (pVM->rem.s.Env.segs[R_GS].selector != pCtx->gs)
2127 {
2128 Log2(("REMR3State: GS changed from %04x to %04x!\n", pVM->rem.s.Env.segs[R_GS].selector, pCtx->gs));
2129 sync_seg(&pVM->rem.s.Env, R_GS, pCtx->gs);
2130#ifdef VBOX_WITH_STATISTICS
2131 if (pVM->rem.s.Env.segs[R_GS].newselector)
2132 {
2133 STAM_COUNTER_INC(&gStatSelOutOfSync[R_GS]);
2134 }
2135#endif
2136 }
2137 else
2138 pVM->rem.s.Env.segs[R_GS].newselector = 0;
2139 }
2140
2141 /*
2142 * Check for traps.
2143 */
2144 pVM->rem.s.Env.exception_index = -1; /** @todo this won't work :/ */
2145 rc = TRPMQueryTrap(pVCpu, &u8TrapNo, &enmType);
2146 if (RT_SUCCESS(rc))
2147 {
2148#ifdef DEBUG
2149 if (u8TrapNo == 0x80)
2150 {
2151 remR3DumpLnxSyscall(pVCpu);
2152 remR3DumpOBsdSyscall(pVCpu);
2153 }
2154#endif
2155
2156 pVM->rem.s.Env.exception_index = u8TrapNo;
2157 if (enmType != TRPM_SOFTWARE_INT)
2158 {
2159 pVM->rem.s.Env.exception_is_int = 0;
2160 pVM->rem.s.Env.exception_next_eip = pVM->rem.s.Env.eip;
2161 }
2162 else
2163 {
2164 /*
2165 * The there are two 1 byte opcodes and one 2 byte opcode for software interrupts.
2166 * We ASSUME that there are no prefixes and sets the default to 2 byte, and checks
2167 * for int03 and into.
2168 */
2169 pVM->rem.s.Env.exception_is_int = 1;
2170 pVM->rem.s.Env.exception_next_eip = pCtx->rip + 2;
2171 /* int 3 may be generated by one-byte 0xcc */
2172 if (u8TrapNo == 3)
2173 {
2174 if (read_byte(&pVM->rem.s.Env, pVM->rem.s.Env.segs[R_CS].base + pCtx->rip) == 0xcc)
2175 pVM->rem.s.Env.exception_next_eip = pCtx->rip + 1;
2176 }
2177 /* int 4 may be generated by one-byte 0xce */
2178 else if (u8TrapNo == 4)
2179 {
2180 if (read_byte(&pVM->rem.s.Env, pVM->rem.s.Env.segs[R_CS].base + pCtx->rip) == 0xce)
2181 pVM->rem.s.Env.exception_next_eip = pCtx->rip + 1;
2182 }
2183 }
2184
2185 /* get error code and cr2 if needed. */
2186 switch (u8TrapNo)
2187 {
2188 case 0x0e:
2189 pVM->rem.s.Env.cr[2] = TRPMGetFaultAddress(pVCpu);
2190 /* fallthru */
2191 case 0x0a: case 0x0b: case 0x0c: case 0x0d:
2192 pVM->rem.s.Env.error_code = TRPMGetErrorCode(pVCpu);
2193 break;
2194
2195 case 0x11: case 0x08:
2196 default:
2197 pVM->rem.s.Env.error_code = 0;
2198 break;
2199 }
2200
2201 /*
2202 * We can now reset the active trap since the recompiler is gonna have a go at it.
2203 */
2204 rc = TRPMResetTrap(pVCpu);
2205 AssertRC(rc);
2206 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,
2207 (RTGCPTR)pVM->rem.s.Env.cr[2], (RTGCPTR)pVM->rem.s.Env.exception_next_eip, pVM->rem.s.Env.exception_is_int ? " software" : ""));
2208 }
2209
2210 /*
2211 * Clear old interrupt request flags; Check for pending hardware interrupts.
2212 * (See @remark for why we don't check for other FFs.)
2213 */
2214 pVM->rem.s.Env.interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXIT | CPU_INTERRUPT_EXITTB | CPU_INTERRUPT_TIMER);
2215 if ( pVM->rem.s.u32PendingInterrupt != REM_NO_PENDING_IRQ
2216 || VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC))
2217 pVM->rem.s.Env.interrupt_request |= CPU_INTERRUPT_HARD;
2218
2219 /*
2220 * We're now in REM mode.
2221 */
2222 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_REM);
2223 pVM->rem.s.fInREM = true;
2224 pVM->rem.s.fInStateSync = false;
2225 pVM->rem.s.cCanExecuteRaw = 0;
2226 STAM_PROFILE_STOP(&pVM->rem.s.StatsState, a);
2227 Log2(("REMR3State: returns VINF_SUCCESS\n"));
2228 return VINF_SUCCESS;
2229}
2230
2231
2232/**
2233 * Syncs back changes in the REM state to the the VM state.
2234 *
2235 * This must be called after invoking REMR3Run().
2236 * Calling it several times in a row is not permitted.
2237 *
2238 * @returns VBox status code.
2239 *
2240 * @param pVM VM Handle.
2241 * @param pVCpu VMCPU Handle.
2242 */
2243REMR3DECL(int) REMR3StateBack(PVM pVM, PVMCPU pVCpu)
2244{
2245 register PCPUMCTX pCtx = pVM->rem.s.pCtx;
2246 Assert(pCtx);
2247 unsigned i;
2248
2249 STAM_PROFILE_START(&pVM->rem.s.StatsStateBack, a);
2250 Log2(("REMR3StateBack:\n"));
2251 Assert(pVM->rem.s.fInREM);
2252
2253 /*
2254 * Copy back the registers.
2255 * This is done in the order they are declared in the CPUMCTX structure.
2256 */
2257
2258 /** @todo FOP */
2259 /** @todo FPUIP */
2260 /** @todo CS */
2261 /** @todo FPUDP */
2262 /** @todo DS */
2263
2264 /** @todo check if FPU/XMM was actually used in the recompiler */
2265 restore_raw_fp_state(&pVM->rem.s.Env, (uint8_t *)&pCtx->fpu);
2266//// dprintf2(("FPU state CW=%04X TT=%04X SW=%04X (%04X)\n", env->fpuc, env->fpstt, env->fpus, pVMCtx->fpu.FSW));
2267
2268#ifdef TARGET_X86_64
2269 /* Note that the high dwords of 64 bits registers are undefined in 32 bits mode and are undefined after a mode change. */
2270 pCtx->rdi = pVM->rem.s.Env.regs[R_EDI];
2271 pCtx->rsi = pVM->rem.s.Env.regs[R_ESI];
2272 pCtx->rbp = pVM->rem.s.Env.regs[R_EBP];
2273 pCtx->rax = pVM->rem.s.Env.regs[R_EAX];
2274 pCtx->rbx = pVM->rem.s.Env.regs[R_EBX];
2275 pCtx->rdx = pVM->rem.s.Env.regs[R_EDX];
2276 pCtx->rcx = pVM->rem.s.Env.regs[R_ECX];
2277 pCtx->r8 = pVM->rem.s.Env.regs[8];
2278 pCtx->r9 = pVM->rem.s.Env.regs[9];
2279 pCtx->r10 = pVM->rem.s.Env.regs[10];
2280 pCtx->r11 = pVM->rem.s.Env.regs[11];
2281 pCtx->r12 = pVM->rem.s.Env.regs[12];
2282 pCtx->r13 = pVM->rem.s.Env.regs[13];
2283 pCtx->r14 = pVM->rem.s.Env.regs[14];
2284 pCtx->r15 = pVM->rem.s.Env.regs[15];
2285
2286 pCtx->rsp = pVM->rem.s.Env.regs[R_ESP];
2287
2288#else
2289 pCtx->edi = pVM->rem.s.Env.regs[R_EDI];
2290 pCtx->esi = pVM->rem.s.Env.regs[R_ESI];
2291 pCtx->ebp = pVM->rem.s.Env.regs[R_EBP];
2292 pCtx->eax = pVM->rem.s.Env.regs[R_EAX];
2293 pCtx->ebx = pVM->rem.s.Env.regs[R_EBX];
2294 pCtx->edx = pVM->rem.s.Env.regs[R_EDX];
2295 pCtx->ecx = pVM->rem.s.Env.regs[R_ECX];
2296
2297 pCtx->esp = pVM->rem.s.Env.regs[R_ESP];
2298#endif
2299
2300 pCtx->ss = pVM->rem.s.Env.segs[R_SS].selector;
2301
2302#ifdef VBOX_WITH_STATISTICS
2303 if (pVM->rem.s.Env.segs[R_SS].newselector)
2304 {
2305 STAM_COUNTER_INC(&gStatSelOutOfSyncStateBack[R_SS]);
2306 }
2307 if (pVM->rem.s.Env.segs[R_GS].newselector)
2308 {
2309 STAM_COUNTER_INC(&gStatSelOutOfSyncStateBack[R_GS]);
2310 }
2311 if (pVM->rem.s.Env.segs[R_FS].newselector)
2312 {
2313 STAM_COUNTER_INC(&gStatSelOutOfSyncStateBack[R_FS]);
2314 }
2315 if (pVM->rem.s.Env.segs[R_ES].newselector)
2316 {
2317 STAM_COUNTER_INC(&gStatSelOutOfSyncStateBack[R_ES]);
2318 }
2319 if (pVM->rem.s.Env.segs[R_DS].newselector)
2320 {
2321 STAM_COUNTER_INC(&gStatSelOutOfSyncStateBack[R_DS]);
2322 }
2323 if (pVM->rem.s.Env.segs[R_CS].newselector)
2324 {
2325 STAM_COUNTER_INC(&gStatSelOutOfSyncStateBack[R_CS]);
2326 }
2327#endif
2328 pCtx->gs = pVM->rem.s.Env.segs[R_GS].selector;
2329 pCtx->fs = pVM->rem.s.Env.segs[R_FS].selector;
2330 pCtx->es = pVM->rem.s.Env.segs[R_ES].selector;
2331 pCtx->ds = pVM->rem.s.Env.segs[R_DS].selector;
2332 pCtx->cs = pVM->rem.s.Env.segs[R_CS].selector;
2333
2334#ifdef TARGET_X86_64
2335 pCtx->rip = pVM->rem.s.Env.eip;
2336 pCtx->rflags.u64 = pVM->rem.s.Env.eflags;
2337#else
2338 pCtx->eip = pVM->rem.s.Env.eip;
2339 pCtx->eflags.u32 = pVM->rem.s.Env.eflags;
2340#endif
2341
2342 pCtx->cr0 = pVM->rem.s.Env.cr[0];
2343 pCtx->cr2 = pVM->rem.s.Env.cr[2];
2344 pCtx->cr3 = pVM->rem.s.Env.cr[3];
2345 if ((pVM->rem.s.Env.cr[4] ^ pCtx->cr4) & X86_CR4_VME)
2346 VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_TSS);
2347 pCtx->cr4 = pVM->rem.s.Env.cr[4];
2348
2349 for (i = 0; i < 8; i++)
2350 pCtx->dr[i] = pVM->rem.s.Env.dr[i];
2351
2352 pCtx->gdtr.cbGdt = pVM->rem.s.Env.gdt.limit;
2353 if (pCtx->gdtr.pGdt != pVM->rem.s.Env.gdt.base)
2354 {
2355 pCtx->gdtr.pGdt = pVM->rem.s.Env.gdt.base;
2356 STAM_COUNTER_INC(&gStatREMGDTChange);
2357 VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_GDT);
2358 }
2359
2360 pCtx->idtr.cbIdt = pVM->rem.s.Env.idt.limit;
2361 if (pCtx->idtr.pIdt != pVM->rem.s.Env.idt.base)
2362 {
2363 pCtx->idtr.pIdt = pVM->rem.s.Env.idt.base;
2364 STAM_COUNTER_INC(&gStatREMIDTChange);
2365 VMCPU_FF_SET(pVCpu, VMCPU_FF_TRPM_SYNC_IDT);
2366 }
2367
2368 if ( pCtx->ldtr != pVM->rem.s.Env.ldt.selector
2369 || pCtx->ldtrHid.u64Base != pVM->rem.s.Env.ldt.base
2370 || pCtx->ldtrHid.u32Limit != pVM->rem.s.Env.ldt.limit
2371 || pCtx->ldtrHid.Attr.u != ((pVM->rem.s.Env.ldt.flags >> 8) & 0xF0FF))
2372 {
2373 pCtx->ldtr = pVM->rem.s.Env.ldt.selector;
2374 pCtx->ldtrHid.u64Base = pVM->rem.s.Env.ldt.base;
2375 pCtx->ldtrHid.u32Limit = pVM->rem.s.Env.ldt.limit;
2376 pCtx->ldtrHid.Attr.u = (pVM->rem.s.Env.ldt.flags >> 8) & 0xF0FF;
2377 STAM_COUNTER_INC(&gStatREMLDTRChange);
2378 VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_LDT);
2379 }
2380
2381 if ( pCtx->tr != pVM->rem.s.Env.tr.selector
2382 || pCtx->trHid.u64Base != pVM->rem.s.Env.tr.base
2383 || pCtx->trHid.u32Limit != pVM->rem.s.Env.tr.limit
2384 /* Qemu and AMD/Intel have different ideas about the busy flag ... */
2385 || pCtx->trHid.Attr.u != ( (pVM->rem.s.Env.tr.flags >> 8) & 0xF0FF
2386 ? (pVM->rem.s.Env.tr.flags | DESC_TSS_BUSY_MASK) >> 8
2387 : 0) )
2388 {
2389 Log(("REM: TR changed! %#x{%#llx,%#x,%#x} -> %#x{%llx,%#x,%#x}\n",
2390 pCtx->tr, pCtx->trHid.u64Base, pCtx->trHid.u32Limit, pCtx->trHid.Attr.u,
2391 pVM->rem.s.Env.tr.selector, (uint64_t)pVM->rem.s.Env.tr.base, pVM->rem.s.Env.tr.limit,
2392 (pVM->rem.s.Env.tr.flags >> 8) & 0xF0FF ? (pVM->rem.s.Env.tr.flags | DESC_TSS_BUSY_MASK) >> 8 : 0));
2393 pCtx->tr = pVM->rem.s.Env.tr.selector;
2394 pCtx->trHid.u64Base = pVM->rem.s.Env.tr.base;
2395 pCtx->trHid.u32Limit = pVM->rem.s.Env.tr.limit;
2396 pCtx->trHid.Attr.u = (pVM->rem.s.Env.tr.flags >> 8) & 0xF0FF;
2397 if (pCtx->trHid.Attr.u)
2398 pCtx->trHid.Attr.u |= DESC_TSS_BUSY_MASK >> 8;
2399 STAM_COUNTER_INC(&gStatREMTRChange);
2400 VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_TSS);
2401 }
2402
2403 /** @todo These values could still be out of sync! */
2404 pCtx->csHid.u64Base = pVM->rem.s.Env.segs[R_CS].base;
2405 pCtx->csHid.u32Limit = pVM->rem.s.Env.segs[R_CS].limit;
2406 /* Note! QEmu saves the 2nd dword of the descriptor; we should store the attribute word only! */
2407 pCtx->csHid.Attr.u = (pVM->rem.s.Env.segs[R_CS].flags >> 8) & 0xF0FF;
2408
2409 pCtx->dsHid.u64Base = pVM->rem.s.Env.segs[R_DS].base;
2410 pCtx->dsHid.u32Limit = pVM->rem.s.Env.segs[R_DS].limit;
2411 pCtx->dsHid.Attr.u = (pVM->rem.s.Env.segs[R_DS].flags >> 8) & 0xF0FF;
2412
2413 pCtx->esHid.u64Base = pVM->rem.s.Env.segs[R_ES].base;
2414 pCtx->esHid.u32Limit = pVM->rem.s.Env.segs[R_ES].limit;
2415 pCtx->esHid.Attr.u = (pVM->rem.s.Env.segs[R_ES].flags >> 8) & 0xF0FF;
2416
2417 pCtx->fsHid.u64Base = pVM->rem.s.Env.segs[R_FS].base;
2418 pCtx->fsHid.u32Limit = pVM->rem.s.Env.segs[R_FS].limit;
2419 pCtx->fsHid.Attr.u = (pVM->rem.s.Env.segs[R_FS].flags >> 8) & 0xF0FF;
2420
2421 pCtx->gsHid.u64Base = pVM->rem.s.Env.segs[R_GS].base;
2422 pCtx->gsHid.u32Limit = pVM->rem.s.Env.segs[R_GS].limit;
2423 pCtx->gsHid.Attr.u = (pVM->rem.s.Env.segs[R_GS].flags >> 8) & 0xF0FF;
2424
2425 pCtx->ssHid.u64Base = pVM->rem.s.Env.segs[R_SS].base;
2426 pCtx->ssHid.u32Limit = pVM->rem.s.Env.segs[R_SS].limit;
2427 pCtx->ssHid.Attr.u = (pVM->rem.s.Env.segs[R_SS].flags >> 8) & 0xF0FF;
2428
2429 /* Sysenter MSR */
2430 pCtx->SysEnter.cs = pVM->rem.s.Env.sysenter_cs;
2431 pCtx->SysEnter.eip = pVM->rem.s.Env.sysenter_eip;
2432 pCtx->SysEnter.esp = pVM->rem.s.Env.sysenter_esp;
2433
2434 /* System MSRs. */
2435 pCtx->msrEFER = pVM->rem.s.Env.efer;
2436 pCtx->msrSTAR = pVM->rem.s.Env.star;
2437 pCtx->msrPAT = pVM->rem.s.Env.pat;
2438#ifdef TARGET_X86_64
2439 pCtx->msrLSTAR = pVM->rem.s.Env.lstar;
2440 pCtx->msrCSTAR = pVM->rem.s.Env.cstar;
2441 pCtx->msrSFMASK = pVM->rem.s.Env.fmask;
2442 pCtx->msrKERNELGSBASE = pVM->rem.s.Env.kernelgsbase;
2443#endif
2444
2445 remR3TrapClear(pVM);
2446
2447 /*
2448 * Check for traps.
2449 */
2450 if ( pVM->rem.s.Env.exception_index >= 0
2451 && pVM->rem.s.Env.exception_index < 256)
2452 {
2453 int rc;
2454
2455 Log(("REMR3StateBack: Pending trap %x %d\n", pVM->rem.s.Env.exception_index, pVM->rem.s.Env.exception_is_int));
2456 rc = TRPMAssertTrap(pVCpu, pVM->rem.s.Env.exception_index, (pVM->rem.s.Env.exception_is_int) ? TRPM_SOFTWARE_INT : TRPM_HARDWARE_INT);
2457 AssertRC(rc);
2458 switch (pVM->rem.s.Env.exception_index)
2459 {
2460 case 0x0e:
2461 TRPMSetFaultAddress(pVCpu, pCtx->cr2);
2462 /* fallthru */
2463 case 0x0a: case 0x0b: case 0x0c: case 0x0d:
2464 case 0x11: case 0x08: /* 0 */
2465 TRPMSetErrorCode(pVCpu, pVM->rem.s.Env.error_code);
2466 break;
2467 }
2468
2469 }
2470
2471 /*
2472 * We're not longer in REM mode.
2473 */
2474 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_REM);
2475 pVM->rem.s.fInREM = false;
2476 pVM->rem.s.pCtx = NULL;
2477 pVM->rem.s.Env.pVCpu = NULL;
2478 STAM_PROFILE_STOP(&pVM->rem.s.StatsStateBack, a);
2479 Log2(("REMR3StateBack: returns VINF_SUCCESS\n"));
2480 return VINF_SUCCESS;
2481}
2482
2483
2484/**
2485 * This is called by the disassembler when it wants to update the cpu state
2486 * before for instance doing a register dump.
2487 */
2488static void remR3StateUpdate(PVM pVM, PVMCPU pVCpu)
2489{
2490 register PCPUMCTX pCtx = pVM->rem.s.pCtx;
2491 unsigned i;
2492
2493 Assert(pVM->rem.s.fInREM);
2494
2495 /*
2496 * Copy back the registers.
2497 * This is done in the order they are declared in the CPUMCTX structure.
2498 */
2499
2500 /** @todo FOP */
2501 /** @todo FPUIP */
2502 /** @todo CS */
2503 /** @todo FPUDP */
2504 /** @todo DS */
2505 /** @todo Fix MXCSR support in QEMU so we don't overwrite MXCSR with 0 when we shouldn't! */
2506 pCtx->fpu.MXCSR = 0;
2507 pCtx->fpu.MXCSR_MASK = 0;
2508
2509 /** @todo check if FPU/XMM was actually used in the recompiler */
2510 restore_raw_fp_state(&pVM->rem.s.Env, (uint8_t *)&pCtx->fpu);
2511//// dprintf2(("FPU state CW=%04X TT=%04X SW=%04X (%04X)\n", env->fpuc, env->fpstt, env->fpus, pVMCtx->fpu.FSW));
2512
2513#ifdef TARGET_X86_64
2514 pCtx->rdi = pVM->rem.s.Env.regs[R_EDI];
2515 pCtx->rsi = pVM->rem.s.Env.regs[R_ESI];
2516 pCtx->rbp = pVM->rem.s.Env.regs[R_EBP];
2517 pCtx->rax = pVM->rem.s.Env.regs[R_EAX];
2518 pCtx->rbx = pVM->rem.s.Env.regs[R_EBX];
2519 pCtx->rdx = pVM->rem.s.Env.regs[R_EDX];
2520 pCtx->rcx = pVM->rem.s.Env.regs[R_ECX];
2521 pCtx->r8 = pVM->rem.s.Env.regs[8];
2522 pCtx->r9 = pVM->rem.s.Env.regs[9];
2523 pCtx->r10 = pVM->rem.s.Env.regs[10];
2524 pCtx->r11 = pVM->rem.s.Env.regs[11];
2525 pCtx->r12 = pVM->rem.s.Env.regs[12];
2526 pCtx->r13 = pVM->rem.s.Env.regs[13];
2527 pCtx->r14 = pVM->rem.s.Env.regs[14];
2528 pCtx->r15 = pVM->rem.s.Env.regs[15];
2529
2530 pCtx->rsp = pVM->rem.s.Env.regs[R_ESP];
2531#else
2532 pCtx->edi = pVM->rem.s.Env.regs[R_EDI];
2533 pCtx->esi = pVM->rem.s.Env.regs[R_ESI];
2534 pCtx->ebp = pVM->rem.s.Env.regs[R_EBP];
2535 pCtx->eax = pVM->rem.s.Env.regs[R_EAX];
2536 pCtx->ebx = pVM->rem.s.Env.regs[R_EBX];
2537 pCtx->edx = pVM->rem.s.Env.regs[R_EDX];
2538 pCtx->ecx = pVM->rem.s.Env.regs[R_ECX];
2539
2540 pCtx->esp = pVM->rem.s.Env.regs[R_ESP];
2541#endif
2542
2543 pCtx->ss = pVM->rem.s.Env.segs[R_SS].selector;
2544
2545 pCtx->gs = pVM->rem.s.Env.segs[R_GS].selector;
2546 pCtx->fs = pVM->rem.s.Env.segs[R_FS].selector;
2547 pCtx->es = pVM->rem.s.Env.segs[R_ES].selector;
2548 pCtx->ds = pVM->rem.s.Env.segs[R_DS].selector;
2549 pCtx->cs = pVM->rem.s.Env.segs[R_CS].selector;
2550
2551#ifdef TARGET_X86_64
2552 pCtx->rip = pVM->rem.s.Env.eip;
2553 pCtx->rflags.u64 = pVM->rem.s.Env.eflags;
2554#else
2555 pCtx->eip = pVM->rem.s.Env.eip;
2556 pCtx->eflags.u32 = pVM->rem.s.Env.eflags;
2557#endif
2558
2559 pCtx->cr0 = pVM->rem.s.Env.cr[0];
2560 pCtx->cr2 = pVM->rem.s.Env.cr[2];
2561 pCtx->cr3 = pVM->rem.s.Env.cr[3];
2562 if ((pVM->rem.s.Env.cr[4] ^ pCtx->cr4) & X86_CR4_VME)
2563 VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_TSS);
2564 pCtx->cr4 = pVM->rem.s.Env.cr[4];
2565
2566 for (i = 0; i < 8; i++)
2567 pCtx->dr[i] = pVM->rem.s.Env.dr[i];
2568
2569 pCtx->gdtr.cbGdt = pVM->rem.s.Env.gdt.limit;
2570 if (pCtx->gdtr.pGdt != (RTGCPTR)pVM->rem.s.Env.gdt.base)
2571 {
2572 pCtx->gdtr.pGdt = (RTGCPTR)pVM->rem.s.Env.gdt.base;
2573 STAM_COUNTER_INC(&gStatREMGDTChange);
2574 VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_GDT);
2575 }
2576
2577 pCtx->idtr.cbIdt = pVM->rem.s.Env.idt.limit;
2578 if (pCtx->idtr.pIdt != (RTGCPTR)pVM->rem.s.Env.idt.base)
2579 {
2580 pCtx->idtr.pIdt = (RTGCPTR)pVM->rem.s.Env.idt.base;
2581 STAM_COUNTER_INC(&gStatREMIDTChange);
2582 VMCPU_FF_SET(pVCpu, VMCPU_FF_TRPM_SYNC_IDT);
2583 }
2584
2585 if ( pCtx->ldtr != pVM->rem.s.Env.ldt.selector
2586 || pCtx->ldtrHid.u64Base != pVM->rem.s.Env.ldt.base
2587 || pCtx->ldtrHid.u32Limit != pVM->rem.s.Env.ldt.limit
2588 || pCtx->ldtrHid.Attr.u != ((pVM->rem.s.Env.ldt.flags >> 8) & 0xF0FF))
2589 {
2590 pCtx->ldtr = pVM->rem.s.Env.ldt.selector;
2591 pCtx->ldtrHid.u64Base = pVM->rem.s.Env.ldt.base;
2592 pCtx->ldtrHid.u32Limit = pVM->rem.s.Env.ldt.limit;
2593 pCtx->ldtrHid.Attr.u = (pVM->rem.s.Env.ldt.flags >> 8) & 0xFFFF;
2594 STAM_COUNTER_INC(&gStatREMLDTRChange);
2595 VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_LDT);
2596 }
2597
2598 if ( pCtx->tr != pVM->rem.s.Env.tr.selector
2599 || pCtx->trHid.u64Base != pVM->rem.s.Env.tr.base
2600 || pCtx->trHid.u32Limit != pVM->rem.s.Env.tr.limit
2601 /* Qemu and AMD/Intel have different ideas about the busy flag ... */
2602 || pCtx->trHid.Attr.u != ( (pVM->rem.s.Env.tr.flags >> 8) & 0xF0FF
2603 ? (pVM->rem.s.Env.tr.flags | DESC_TSS_BUSY_MASK) >> 8
2604 : 0) )
2605 {
2606 Log(("REM: TR changed! %#x{%#llx,%#x,%#x} -> %#x{%llx,%#x,%#x}\n",
2607 pCtx->tr, pCtx->trHid.u64Base, pCtx->trHid.u32Limit, pCtx->trHid.Attr.u,
2608 pVM->rem.s.Env.tr.selector, (uint64_t)pVM->rem.s.Env.tr.base, pVM->rem.s.Env.tr.limit,
2609 (pVM->rem.s.Env.tr.flags >> 8) & 0xF0FF ? (pVM->rem.s.Env.tr.flags | DESC_TSS_BUSY_MASK) >> 8 : 0));
2610 pCtx->tr = pVM->rem.s.Env.tr.selector;
2611 pCtx->trHid.u64Base = pVM->rem.s.Env.tr.base;
2612 pCtx->trHid.u32Limit = pVM->rem.s.Env.tr.limit;
2613 pCtx->trHid.Attr.u = (pVM->rem.s.Env.tr.flags >> 8) & 0xF0FF;
2614 if (pCtx->trHid.Attr.u)
2615 pCtx->trHid.Attr.u |= DESC_TSS_BUSY_MASK >> 8;
2616 STAM_COUNTER_INC(&gStatREMTRChange);
2617 VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_TSS);
2618 }
2619
2620 /** @todo These values could still be out of sync! */
2621 pCtx->csHid.u64Base = pVM->rem.s.Env.segs[R_CS].base;
2622 pCtx->csHid.u32Limit = pVM->rem.s.Env.segs[R_CS].limit;
2623 /** @note QEmu saves the 2nd dword of the descriptor; we should store the attribute word only! */
2624 pCtx->csHid.Attr.u = (pVM->rem.s.Env.segs[R_CS].flags >> 8) & 0xFFFF;
2625
2626 pCtx->dsHid.u64Base = pVM->rem.s.Env.segs[R_DS].base;
2627 pCtx->dsHid.u32Limit = pVM->rem.s.Env.segs[R_DS].limit;
2628 pCtx->dsHid.Attr.u = (pVM->rem.s.Env.segs[R_DS].flags >> 8) & 0xFFFF;
2629
2630 pCtx->esHid.u64Base = pVM->rem.s.Env.segs[R_ES].base;
2631 pCtx->esHid.u32Limit = pVM->rem.s.Env.segs[R_ES].limit;
2632 pCtx->esHid.Attr.u = (pVM->rem.s.Env.segs[R_ES].flags >> 8) & 0xFFFF;
2633
2634 pCtx->fsHid.u64Base = pVM->rem.s.Env.segs[R_FS].base;
2635 pCtx->fsHid.u32Limit = pVM->rem.s.Env.segs[R_FS].limit;
2636 pCtx->fsHid.Attr.u = (pVM->rem.s.Env.segs[R_FS].flags >> 8) & 0xFFFF;
2637
2638 pCtx->gsHid.u64Base = pVM->rem.s.Env.segs[R_GS].base;
2639 pCtx->gsHid.u32Limit = pVM->rem.s.Env.segs[R_GS].limit;
2640 pCtx->gsHid.Attr.u = (pVM->rem.s.Env.segs[R_GS].flags >> 8) & 0xFFFF;
2641
2642 pCtx->ssHid.u64Base = pVM->rem.s.Env.segs[R_SS].base;
2643 pCtx->ssHid.u32Limit = pVM->rem.s.Env.segs[R_SS].limit;
2644 pCtx->ssHid.Attr.u = (pVM->rem.s.Env.segs[R_SS].flags >> 8) & 0xFFFF;
2645
2646 /* Sysenter MSR */
2647 pCtx->SysEnter.cs = pVM->rem.s.Env.sysenter_cs;
2648 pCtx->SysEnter.eip = pVM->rem.s.Env.sysenter_eip;
2649 pCtx->SysEnter.esp = pVM->rem.s.Env.sysenter_esp;
2650
2651 /* System MSRs. */
2652 pCtx->msrEFER = pVM->rem.s.Env.efer;
2653 pCtx->msrSTAR = pVM->rem.s.Env.star;
2654 pCtx->msrPAT = pVM->rem.s.Env.pat;
2655#ifdef TARGET_X86_64
2656 pCtx->msrLSTAR = pVM->rem.s.Env.lstar;
2657 pCtx->msrCSTAR = pVM->rem.s.Env.cstar;
2658 pCtx->msrSFMASK = pVM->rem.s.Env.fmask;
2659 pCtx->msrKERNELGSBASE = pVM->rem.s.Env.kernelgsbase;
2660#endif
2661
2662}
2663
2664
2665/**
2666 * Update the VMM state information if we're currently in REM.
2667 *
2668 * This method is used by the DBGF and PDMDevice when there is any uncertainty of whether
2669 * we're currently executing in REM and the VMM state is invalid. This method will of
2670 * course check that we're executing in REM before syncing any data over to the VMM.
2671 *
2672 * @param pVM The VM handle.
2673 * @param pVCpu The VMCPU handle.
2674 */
2675REMR3DECL(void) REMR3StateUpdate(PVM pVM, PVMCPU pVCpu)
2676{
2677 if (pVM->rem.s.fInREM)
2678 remR3StateUpdate(pVM, pVCpu);
2679}
2680
2681
2682#undef LOG_GROUP
2683#define LOG_GROUP LOG_GROUP_REM
2684
2685
2686/**
2687 * Notify the recompiler about Address Gate 20 state change.
2688 *
2689 * This notification is required since A20 gate changes are
2690 * initialized from a device driver and the VM might just as
2691 * well be in REM mode as in RAW mode.
2692 *
2693 * @param pVM VM handle.
2694 * @param pVCpu VMCPU handle.
2695 * @param fEnable True if the gate should be enabled.
2696 * False if the gate should be disabled.
2697 */
2698REMR3DECL(void) REMR3A20Set(PVM pVM, PVMCPU pVCpu, bool fEnable)
2699{
2700 LogFlow(("REMR3A20Set: fEnable=%d\n", fEnable));
2701 VM_ASSERT_EMT(pVM);
2702
2703 ASMAtomicIncU32(&pVM->rem.s.cIgnoreAll);
2704 cpu_x86_set_a20(&pVM->rem.s.Env, fEnable);
2705 ASMAtomicDecU32(&pVM->rem.s.cIgnoreAll);
2706}
2707
2708
2709/**
2710 * Replays the handler notification changes
2711 * Called in response to VM_FF_REM_HANDLER_NOTIFY from the RAW execution loop.
2712 *
2713 * @param pVM VM handle.
2714 */
2715REMR3DECL(void) REMR3ReplayHandlerNotifications(PVM pVM)
2716{
2717 /*
2718 * Replay the flushes.
2719 */
2720 LogFlow(("REMR3ReplayHandlerNotifications:\n"));
2721 VM_ASSERT_EMT(pVM);
2722
2723 if (VM_FF_TESTANDCLEAR(pVM, VM_FF_REM_HANDLER_NOTIFY_BIT))
2724 {
2725 /* Lockless purging of pending notifications. */
2726 uint32_t idxReqs = ASMAtomicXchgU32(&pVM->rem.s.idxPendingList, -1);
2727 if (idxReqs == -1)
2728 return;
2729
2730 Assert(idxReqs < RT_ELEMENTS(pVM->rem.s.aHandlerNotifications));
2731 PREMHANDLERNOTIFICATION pReqs = &pVM->rem.s.aHandlerNotifications[idxReqs];
2732
2733 /*
2734 * Reverse the list to process it in FIFO order.
2735 */
2736 PREMHANDLERNOTIFICATION pReq = pReqs;
2737 pReqs = NULL;
2738 while (pReq)
2739 {
2740 PREMHANDLERNOTIFICATION pCur = pReq;
2741
2742 if (pReq->idxNext != -1)
2743 {
2744 Assert(pReq->idxNext < RT_ELEMENTS(pVM->rem.s.aHandlerNotifications));
2745 pReq = &pVM->rem.s.aHandlerNotifications[pReq->idxNext];
2746 }
2747 else
2748 pReq = NULL;
2749
2750 pCur->idxNext = (pReqs) ? pReqs->idxSelf : -1;
2751 pReqs = pCur;
2752 }
2753
2754 while (pReqs)
2755 {
2756 PREMHANDLERNOTIFICATION pRec = pReqs;
2757
2758 switch (pRec->enmKind)
2759 {
2760 case REMHANDLERNOTIFICATIONKIND_PHYSICAL_REGISTER:
2761 remR3NotifyHandlerPhysicalRegister(pVM,
2762 pRec->u.PhysicalRegister.enmType,
2763 pRec->u.PhysicalRegister.GCPhys,
2764 pRec->u.PhysicalRegister.cb,
2765 pRec->u.PhysicalRegister.fHasHCHandler);
2766 break;
2767
2768 case REMHANDLERNOTIFICATIONKIND_PHYSICAL_DEREGISTER:
2769 remR3NotifyHandlerPhysicalDeregister(pVM,
2770 pRec->u.PhysicalDeregister.enmType,
2771 pRec->u.PhysicalDeregister.GCPhys,
2772 pRec->u.PhysicalDeregister.cb,
2773 pRec->u.PhysicalDeregister.fHasHCHandler,
2774 pRec->u.PhysicalDeregister.fRestoreAsRAM);
2775 break;
2776
2777 case REMHANDLERNOTIFICATIONKIND_PHYSICAL_MODIFY:
2778 remR3NotifyHandlerPhysicalModify(pVM,
2779 pRec->u.PhysicalModify.enmType,
2780 pRec->u.PhysicalModify.GCPhysOld,
2781 pRec->u.PhysicalModify.GCPhysNew,
2782 pRec->u.PhysicalModify.cb,
2783 pRec->u.PhysicalModify.fHasHCHandler,
2784 pRec->u.PhysicalModify.fRestoreAsRAM);
2785 break;
2786
2787 default:
2788 AssertReleaseMsgFailed(("enmKind=%d\n", pRec->enmKind));
2789 break;
2790 }
2791 if (pReqs->idxNext != -1)
2792 {
2793 AssertMsg(pReqs->idxNext < RT_ELEMENTS(pVM->rem.s.aHandlerNotifications), ("pReqs->idxNext=%d\n", pReqs->idxNext));
2794 pReqs = &pVM->rem.s.aHandlerNotifications[pReqs->idxNext];
2795 }
2796 else
2797 pReqs = NULL;
2798
2799 /* Put the record back into the free list */
2800 uint32_t idxNext;
2801
2802 do
2803 {
2804 idxNext = pVM->rem.s.idxFreeList;
2805 pRec->idxNext = idxNext;
2806 } while (!ASMAtomicCmpXchgU32(&pVM->rem.s.idxFreeList, pRec->idxSelf, idxNext));
2807 }
2808 }
2809}
2810
2811
2812/**
2813 * Notify REM about changed code page.
2814 *
2815 * @returns VBox status code.
2816 * @param pVM VM handle.
2817 * @param pVCpu VMCPU handle.
2818 * @param pvCodePage Code page address
2819 */
2820REMR3DECL(int) REMR3NotifyCodePageChanged(PVM pVM, PVMCPU pVCpu, RTGCPTR pvCodePage)
2821{
2822#ifdef VBOX_REM_PROTECT_PAGES_FROM_SMC
2823 int rc;
2824 RTGCPHYS PhysGC;
2825 uint64_t flags;
2826
2827 VM_ASSERT_EMT(pVM);
2828
2829 /*
2830 * Get the physical page address.
2831 */
2832 rc = PGMGstGetPage(pVM, pvCodePage, &flags, &PhysGC);
2833 if (rc == VINF_SUCCESS)
2834 {
2835 /*
2836 * Sync the required registers and flush the whole page.
2837 * (Easier to do the whole page than notifying it about each physical
2838 * byte that was changed.
2839 */
2840 pVM->rem.s.Env.cr[0] = pVM->rem.s.pCtx->cr0;
2841 pVM->rem.s.Env.cr[2] = pVM->rem.s.pCtx->cr2;
2842 pVM->rem.s.Env.cr[3] = pVM->rem.s.pCtx->cr3;
2843 pVM->rem.s.Env.cr[4] = pVM->rem.s.pCtx->cr4;
2844
2845 tb_invalidate_phys_page_range(PhysGC, PhysGC + PAGE_SIZE - 1, 0);
2846 }
2847#endif
2848 return VINF_SUCCESS;
2849}
2850
2851
2852/**
2853 * Notification about a successful MMR3PhysRegister() call.
2854 *
2855 * @param pVM VM handle.
2856 * @param GCPhys The physical address the RAM.
2857 * @param cb Size of the memory.
2858 * @param fFlags Flags of the REM_NOTIFY_PHYS_RAM_FLAGS_* defines.
2859 */
2860REMR3DECL(void) REMR3NotifyPhysRamRegister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, unsigned fFlags)
2861{
2862 Log(("REMR3NotifyPhysRamRegister: GCPhys=%RGp cb=%RGp fFlags=%#x\n", GCPhys, cb, fFlags));
2863 VM_ASSERT_EMT(pVM);
2864
2865 /*
2866 * Validate input - we trust the caller.
2867 */
2868 Assert(RT_ALIGN_T(GCPhys, PAGE_SIZE, RTGCPHYS) == GCPhys);
2869 Assert(cb);
2870 Assert(RT_ALIGN_Z(cb, PAGE_SIZE) == cb);
2871 AssertMsg(fFlags == REM_NOTIFY_PHYS_RAM_FLAGS_RAM || fFlags == REM_NOTIFY_PHYS_RAM_FLAGS_MMIO2, ("#x\n", fFlags));
2872
2873 /*
2874 * Base ram? Update GCPhysLastRam.
2875 */
2876 if (fFlags & REM_NOTIFY_PHYS_RAM_FLAGS_RAM)
2877 {
2878 if (GCPhys + (cb - 1) > pVM->rem.s.GCPhysLastRam)
2879 {
2880 AssertReleaseMsg(!pVM->rem.s.fGCPhysLastRamFixed, ("GCPhys=%RGp cb=%RGp\n", GCPhys, cb));
2881 pVM->rem.s.GCPhysLastRam = GCPhys + (cb - 1);
2882 }
2883 }
2884
2885 /*
2886 * Register the ram.
2887 */
2888 ASMAtomicIncU32(&pVM->rem.s.cIgnoreAll);
2889
2890 PDMCritSectEnter(&pVM->rem.s.CritSectRegister, VERR_SEM_BUSY);
2891 cpu_register_physical_memory(GCPhys, cb, GCPhys);
2892 PDMCritSectLeave(&pVM->rem.s.CritSectRegister);
2893
2894 ASMAtomicDecU32(&pVM->rem.s.cIgnoreAll);
2895}
2896
2897
2898/**
2899 * Notification about a successful MMR3PhysRomRegister() call.
2900 *
2901 * @param pVM VM handle.
2902 * @param GCPhys The physical address of the ROM.
2903 * @param cb The size of the ROM.
2904 * @param pvCopy Pointer to the ROM copy.
2905 * @param fShadow Whether it's currently writable shadow ROM or normal readonly ROM.
2906 * This function will be called when ever the protection of the
2907 * shadow ROM changes (at reset and end of POST).
2908 */
2909REMR3DECL(void) REMR3NotifyPhysRomRegister(PVM pVM, RTGCPHYS GCPhys, RTUINT cb, void *pvCopy, bool fShadow)
2910{
2911 Log(("REMR3NotifyPhysRomRegister: GCPhys=%RGp cb=%d fShadow=%RTbool\n", GCPhys, cb, fShadow));
2912 VM_ASSERT_EMT(pVM);
2913
2914 /*
2915 * Validate input - we trust the caller.
2916 */
2917 Assert(RT_ALIGN_T(GCPhys, PAGE_SIZE, RTGCPHYS) == GCPhys);
2918 Assert(cb);
2919 Assert(RT_ALIGN_Z(cb, PAGE_SIZE) == cb);
2920
2921 /*
2922 * Register the rom.
2923 */
2924 ASMAtomicIncU32(&pVM->rem.s.cIgnoreAll);
2925
2926 PDMCritSectEnter(&pVM->rem.s.CritSectRegister, VERR_SEM_BUSY);
2927 cpu_register_physical_memory(GCPhys, cb, GCPhys | (fShadow ? 0 : IO_MEM_ROM));
2928 PDMCritSectLeave(&pVM->rem.s.CritSectRegister);
2929
2930 ASMAtomicDecU32(&pVM->rem.s.cIgnoreAll);
2931}
2932
2933
2934/**
2935 * Notification about a successful memory deregistration or reservation.
2936 *
2937 * @param pVM VM Handle.
2938 * @param GCPhys Start physical address.
2939 * @param cb The size of the range.
2940 */
2941REMR3DECL(void) REMR3NotifyPhysRamDeregister(PVM pVM, RTGCPHYS GCPhys, RTUINT cb)
2942{
2943 Log(("REMR3NotifyPhysRamDeregister: GCPhys=%RGp cb=%d\n", GCPhys, cb));
2944 VM_ASSERT_EMT(pVM);
2945
2946 /*
2947 * Validate input - we trust the caller.
2948 */
2949 Assert(RT_ALIGN_T(GCPhys, PAGE_SIZE, RTGCPHYS) == GCPhys);
2950 Assert(cb);
2951 Assert(RT_ALIGN_Z(cb, PAGE_SIZE) == cb);
2952
2953 /*
2954 * Unassigning the memory.
2955 */
2956 ASMAtomicIncU32(&pVM->rem.s.cIgnoreAll);
2957
2958 PDMCritSectEnter(&pVM->rem.s.CritSectRegister, VERR_SEM_BUSY);
2959 cpu_register_physical_memory(GCPhys, cb, IO_MEM_UNASSIGNED);
2960 PDMCritSectLeave(&pVM->rem.s.CritSectRegister);
2961
2962 ASMAtomicDecU32(&pVM->rem.s.cIgnoreAll);
2963}
2964
2965
2966/**
2967 * Notification about a successful PGMR3HandlerPhysicalRegister() call.
2968 *
2969 * @param pVM VM Handle.
2970 * @param enmType Handler type.
2971 * @param GCPhys Handler range address.
2972 * @param cb Size of the handler range.
2973 * @param fHasHCHandler Set if the handler has a HC callback function.
2974 *
2975 * @remark MMR3PhysRomRegister assumes that this function will not apply the
2976 * Handler memory type to memory which has no HC handler.
2977 */
2978static void remR3NotifyHandlerPhysicalRegister(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS cb, bool fHasHCHandler)
2979{
2980 Log(("REMR3NotifyHandlerPhysicalRegister: enmType=%d GCPhys=%RGp cb=%RGp fHasHCHandler=%d\n",
2981 enmType, GCPhys, cb, fHasHCHandler));
2982
2983 VM_ASSERT_EMT(pVM);
2984 Assert(RT_ALIGN_T(GCPhys, PAGE_SIZE, RTGCPHYS) == GCPhys);
2985 Assert(RT_ALIGN_T(cb, PAGE_SIZE, RTGCPHYS) == cb);
2986
2987
2988 ASMAtomicIncU32(&pVM->rem.s.cIgnoreAll);
2989
2990 PDMCritSectEnter(&pVM->rem.s.CritSectRegister, VERR_SEM_BUSY);
2991 if (enmType == PGMPHYSHANDLERTYPE_MMIO)
2992 cpu_register_physical_memory(GCPhys, cb, pVM->rem.s.iMMIOMemType);
2993 else if (fHasHCHandler)
2994 cpu_register_physical_memory(GCPhys, cb, pVM->rem.s.iHandlerMemType);
2995 PDMCritSectLeave(&pVM->rem.s.CritSectRegister);
2996
2997 ASMAtomicDecU32(&pVM->rem.s.cIgnoreAll);
2998}
2999
3000/**
3001 * Notification about a successful PGMR3HandlerPhysicalRegister() call.
3002 *
3003 * @param pVM VM Handle.
3004 * @param enmType Handler type.
3005 * @param GCPhys Handler range address.
3006 * @param cb Size of the handler range.
3007 * @param fHasHCHandler Set if the handler has a HC callback function.
3008 *
3009 * @remark MMR3PhysRomRegister assumes that this function will not apply the
3010 * Handler memory type to memory which has no HC handler.
3011 */
3012REMR3DECL(void) REMR3NotifyHandlerPhysicalRegister(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS cb, bool fHasHCHandler)
3013{
3014 REMR3ReplayHandlerNotifications(pVM);
3015
3016 remR3NotifyHandlerPhysicalRegister(pVM, enmType, GCPhys, cb, fHasHCHandler);
3017}
3018
3019/**
3020 * Notification about a successful PGMR3HandlerPhysicalDeregister() operation.
3021 *
3022 * @param pVM VM Handle.
3023 * @param enmType Handler type.
3024 * @param GCPhys Handler range address.
3025 * @param cb Size of the handler range.
3026 * @param fHasHCHandler Set if the handler has a HC callback function.
3027 * @param fRestoreAsRAM Whether the to restore it as normal RAM or as unassigned memory.
3028 */
3029static void remR3NotifyHandlerPhysicalDeregister(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS cb, bool fHasHCHandler, bool fRestoreAsRAM)
3030{
3031 Log(("REMR3NotifyHandlerPhysicalDeregister: enmType=%d GCPhys=%RGp cb=%RGp fHasHCHandler=%RTbool fRestoreAsRAM=%RTbool RAM=%08x\n",
3032 enmType, GCPhys, cb, fHasHCHandler, fRestoreAsRAM, MMR3PhysGetRamSize(pVM)));
3033 VM_ASSERT_EMT(pVM);
3034
3035
3036 ASMAtomicIncU32(&pVM->rem.s.cIgnoreAll);
3037
3038 PDMCritSectEnter(&pVM->rem.s.CritSectRegister, VERR_SEM_BUSY);
3039 /** @todo this isn't right, MMIO can (in theory) be restored as RAM. */
3040 if (enmType == PGMPHYSHANDLERTYPE_MMIO)
3041 cpu_register_physical_memory(GCPhys, cb, IO_MEM_UNASSIGNED);
3042 else if (fHasHCHandler)
3043 {
3044 if (!fRestoreAsRAM)
3045 {
3046 Assert(GCPhys > MMR3PhysGetRamSize(pVM));
3047 cpu_register_physical_memory(GCPhys, cb, IO_MEM_UNASSIGNED);
3048 }
3049 else
3050 {
3051 Assert(RT_ALIGN_T(GCPhys, PAGE_SIZE, RTGCPHYS) == GCPhys);
3052 Assert(RT_ALIGN_T(cb, PAGE_SIZE, RTGCPHYS) == cb);
3053 cpu_register_physical_memory(GCPhys, cb, GCPhys);
3054 }
3055 }
3056 PDMCritSectLeave(&pVM->rem.s.CritSectRegister);
3057
3058 ASMAtomicDecU32(&pVM->rem.s.cIgnoreAll);
3059}
3060
3061/**
3062 * Notification about a successful PGMR3HandlerPhysicalDeregister() operation.
3063 *
3064 * @param pVM VM Handle.
3065 * @param enmType Handler type.
3066 * @param GCPhys Handler range address.
3067 * @param cb Size of the handler range.
3068 * @param fHasHCHandler Set if the handler has a HC callback function.
3069 * @param fRestoreAsRAM Whether the to restore it as normal RAM or as unassigned memory.
3070 */
3071REMR3DECL(void) REMR3NotifyHandlerPhysicalDeregister(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS cb, bool fHasHCHandler, bool fRestoreAsRAM)
3072{
3073 REMR3ReplayHandlerNotifications(pVM);
3074 remR3NotifyHandlerPhysicalDeregister(pVM, enmType, GCPhys, cb, fHasHCHandler, fRestoreAsRAM);
3075}
3076
3077
3078/**
3079 * Notification about a successful PGMR3HandlerPhysicalModify() call.
3080 *
3081 * @param pVM VM Handle.
3082 * @param enmType Handler type.
3083 * @param GCPhysOld Old handler range address.
3084 * @param GCPhysNew New handler range address.
3085 * @param cb Size of the handler range.
3086 * @param fHasHCHandler Set if the handler has a HC callback function.
3087 * @param fRestoreAsRAM Whether the to restore it as normal RAM or as unassigned memory.
3088 */
3089static void remR3NotifyHandlerPhysicalModify(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhysOld, RTGCPHYS GCPhysNew, RTGCPHYS cb, bool fHasHCHandler, bool fRestoreAsRAM)
3090{
3091 Log(("REMR3NotifyHandlerPhysicalModify: enmType=%d GCPhysOld=%RGp GCPhysNew=%RGp cb=%RGp fHasHCHandler=%RTbool fRestoreAsRAM=%RTbool\n",
3092 enmType, GCPhysOld, GCPhysNew, cb, fHasHCHandler, fRestoreAsRAM));
3093 VM_ASSERT_EMT(pVM);
3094 AssertReleaseMsg(enmType != PGMPHYSHANDLERTYPE_MMIO, ("enmType=%d\n", enmType));
3095
3096 if (fHasHCHandler)
3097 {
3098 ASMAtomicIncU32(&pVM->rem.s.cIgnoreAll);
3099
3100 /*
3101 * Reset the old page.
3102 */
3103 PDMCritSectEnter(&pVM->rem.s.CritSectRegister, VERR_SEM_BUSY);
3104 if (!fRestoreAsRAM)
3105 cpu_register_physical_memory(GCPhysOld, cb, IO_MEM_UNASSIGNED);
3106 else
3107 {
3108 /* This is not perfect, but it'll do for PD monitoring... */
3109 Assert(cb == PAGE_SIZE);
3110 Assert(RT_ALIGN_T(GCPhysOld, PAGE_SIZE, RTGCPHYS) == GCPhysOld);
3111 cpu_register_physical_memory(GCPhysOld, cb, GCPhysOld);
3112 }
3113
3114 /*
3115 * Update the new page.
3116 */
3117 Assert(RT_ALIGN_T(GCPhysNew, PAGE_SIZE, RTGCPHYS) == GCPhysNew);
3118 Assert(RT_ALIGN_T(cb, PAGE_SIZE, RTGCPHYS) == cb);
3119 cpu_register_physical_memory(GCPhysNew, cb, pVM->rem.s.iHandlerMemType);
3120 PDMCritSectLeave(&pVM->rem.s.CritSectRegister);
3121
3122 ASMAtomicDecU32(&pVM->rem.s.cIgnoreAll);
3123 }
3124}
3125
3126/**
3127 * Notification about a successful PGMR3HandlerPhysicalModify() call.
3128 *
3129 * @param pVM VM Handle.
3130 * @param enmType Handler type.
3131 * @param GCPhysOld Old handler range address.
3132 * @param GCPhysNew New handler range address.
3133 * @param cb Size of the handler range.
3134 * @param fHasHCHandler Set if the handler has a HC callback function.
3135 * @param fRestoreAsRAM Whether the to restore it as normal RAM or as unassigned memory.
3136 */
3137REMR3DECL(void) REMR3NotifyHandlerPhysicalModify(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhysOld, RTGCPHYS GCPhysNew, RTGCPHYS cb, bool fHasHCHandler, bool fRestoreAsRAM)
3138{
3139 REMR3ReplayHandlerNotifications(pVM);
3140
3141 remR3NotifyHandlerPhysicalModify(pVM, enmType, GCPhysOld, GCPhysNew, cb, fHasHCHandler, fRestoreAsRAM);
3142}
3143
3144/**
3145 * Checks if we're handling access to this page or not.
3146 *
3147 * @returns true if we're trapping access.
3148 * @returns false if we aren't.
3149 * @param pVM The VM handle.
3150 * @param GCPhys The physical address.
3151 *
3152 * @remark This function will only work correctly in VBOX_STRICT builds!
3153 */
3154REMR3DECL(bool) REMR3IsPageAccessHandled(PVM pVM, RTGCPHYS GCPhys)
3155{
3156#ifdef VBOX_STRICT
3157 unsigned long off;
3158 REMR3ReplayHandlerNotifications(pVM);
3159
3160 off = get_phys_page_offset(GCPhys);
3161 return (off & PAGE_OFFSET_MASK) == pVM->rem.s.iHandlerMemType
3162 || (off & PAGE_OFFSET_MASK) == pVM->rem.s.iMMIOMemType
3163 || (off & PAGE_OFFSET_MASK) == IO_MEM_ROM;
3164#else
3165 return false;
3166#endif
3167}
3168
3169
3170/**
3171 * Deals with a rare case in get_phys_addr_code where the code
3172 * is being monitored.
3173 *
3174 * It could also be an MMIO page, in which case we will raise a fatal error.
3175 *
3176 * @returns The physical address corresponding to addr.
3177 * @param env The cpu environment.
3178 * @param addr The virtual address.
3179 * @param pTLBEntry The TLB entry.
3180 */
3181target_ulong remR3PhysGetPhysicalAddressCode(CPUState* env,
3182 target_ulong addr,
3183 CPUTLBEntry* pTLBEntry,
3184 target_phys_addr_t ioTLBEntry)
3185{
3186 PVM pVM = env->pVM;
3187
3188 if ((ioTLBEntry & ~TARGET_PAGE_MASK) == pVM->rem.s.iHandlerMemType)
3189 {
3190 /* If code memory is being monitored, appropriate IOTLB entry will have
3191 handler IO type, and addend will provide real physical address, no
3192 matter if we store VA in TLB or not, as handlers are always passed PA */
3193 target_ulong ret = (ioTLBEntry & TARGET_PAGE_MASK) + addr;
3194 return ret;
3195 }
3196 LogRel(("\nTrying to execute code with memory type addr_code=%RGv addend=%RGp at %RGv! (iHandlerMemType=%#x iMMIOMemType=%#x IOTLB=%RGp)\n"
3197 "*** handlers\n",
3198 (RTGCPTR)pTLBEntry->addr_code, (RTGCPHYS)pTLBEntry->addend, (RTGCPTR)addr, pVM->rem.s.iHandlerMemType, pVM->rem.s.iMMIOMemType, (RTGCPHYS)ioTLBEntry));
3199 DBGFR3Info(pVM, "handlers", NULL, DBGFR3InfoLogRelHlp());
3200 LogRel(("*** mmio\n"));
3201 DBGFR3Info(pVM, "mmio", NULL, DBGFR3InfoLogRelHlp());
3202 LogRel(("*** phys\n"));
3203 DBGFR3Info(pVM, "phys", NULL, DBGFR3InfoLogRelHlp());
3204 cpu_abort(env, "Trying to execute code with memory type addr_code=%RGv addend=%RGp at %RGv. (iHandlerMemType=%#x iMMIOMemType=%#x)\n",
3205 (RTGCPTR)pTLBEntry->addr_code, (RTGCPHYS)pTLBEntry->addend, (RTGCPTR)addr, pVM->rem.s.iHandlerMemType, pVM->rem.s.iMMIOMemType);
3206 AssertFatalFailed();
3207}
3208
3209/**
3210 * Read guest RAM and ROM.
3211 *
3212 * @param SrcGCPhys The source address (guest physical).
3213 * @param pvDst The destination address.
3214 * @param cb Number of bytes
3215 */
3216void remR3PhysRead(RTGCPHYS SrcGCPhys, void *pvDst, unsigned cb)
3217{
3218 STAM_PROFILE_ADV_START(&gStatMemRead, a);
3219 VBOX_CHECK_ADDR(SrcGCPhys);
3220 PGMPhysRead(cpu_single_env->pVM, SrcGCPhys, pvDst, cb);
3221#ifdef VBOX_DEBUG_PHYS
3222 LogRel(("read(%d): %08x\n", cb, (uint32_t)SrcGCPhys));
3223#endif
3224 STAM_PROFILE_ADV_STOP(&gStatMemRead, a);
3225}
3226
3227
3228/**
3229 * Read guest RAM and ROM, unsigned 8-bit.
3230 *
3231 * @param SrcGCPhys The source address (guest physical).
3232 */
3233RTCCUINTREG remR3PhysReadU8(RTGCPHYS SrcGCPhys)
3234{
3235 uint8_t val;
3236 STAM_PROFILE_ADV_START(&gStatMemRead, a);
3237 VBOX_CHECK_ADDR(SrcGCPhys);
3238 val = PGMR3PhysReadU8(cpu_single_env->pVM, SrcGCPhys);
3239 STAM_PROFILE_ADV_STOP(&gStatMemRead, a);
3240#ifdef VBOX_DEBUG_PHYS
3241 LogRel(("readu8: %x <- %08x\n", val, (uint32_t)SrcGCPhys));
3242#endif
3243 return val;
3244}
3245
3246
3247/**
3248 * Read guest RAM and ROM, signed 8-bit.
3249 *
3250 * @param SrcGCPhys The source address (guest physical).
3251 */
3252RTCCINTREG remR3PhysReadS8(RTGCPHYS SrcGCPhys)
3253{
3254 int8_t val;
3255 STAM_PROFILE_ADV_START(&gStatMemRead, a);
3256 VBOX_CHECK_ADDR(SrcGCPhys);
3257 val = PGMR3PhysReadU8(cpu_single_env->pVM, SrcGCPhys);
3258 STAM_PROFILE_ADV_STOP(&gStatMemRead, a);
3259#ifdef VBOX_DEBUG_PHYS
3260 LogRel(("reads8: %x <- %08x\n", val, (uint32_t)SrcGCPhys));
3261#endif
3262 return val;
3263}
3264
3265
3266/**
3267 * Read guest RAM and ROM, unsigned 16-bit.
3268 *
3269 * @param SrcGCPhys The source address (guest physical).
3270 */
3271RTCCUINTREG remR3PhysReadU16(RTGCPHYS SrcGCPhys)
3272{
3273 uint16_t val;
3274 STAM_PROFILE_ADV_START(&gStatMemRead, a);
3275 VBOX_CHECK_ADDR(SrcGCPhys);
3276 val = PGMR3PhysReadU16(cpu_single_env->pVM, SrcGCPhys);
3277 STAM_PROFILE_ADV_STOP(&gStatMemRead, a);
3278#ifdef VBOX_DEBUG_PHYS
3279 LogRel(("readu16: %x <- %08x\n", val, (uint32_t)SrcGCPhys));
3280#endif
3281 return val;
3282}
3283
3284
3285/**
3286 * Read guest RAM and ROM, signed 16-bit.
3287 *
3288 * @param SrcGCPhys The source address (guest physical).
3289 */
3290RTCCINTREG remR3PhysReadS16(RTGCPHYS SrcGCPhys)
3291{
3292 int16_t val;
3293 STAM_PROFILE_ADV_START(&gStatMemRead, a);
3294 VBOX_CHECK_ADDR(SrcGCPhys);
3295 val = PGMR3PhysReadU16(cpu_single_env->pVM, SrcGCPhys);
3296 STAM_PROFILE_ADV_STOP(&gStatMemRead, a);
3297#ifdef VBOX_DEBUG_PHYS
3298 LogRel(("reads16: %x <- %08x\n", (uint16_t)val, (uint32_t)SrcGCPhys));
3299#endif
3300 return val;
3301}
3302
3303
3304/**
3305 * Read guest RAM and ROM, unsigned 32-bit.
3306 *
3307 * @param SrcGCPhys The source address (guest physical).
3308 */
3309RTCCUINTREG remR3PhysReadU32(RTGCPHYS SrcGCPhys)
3310{
3311 uint32_t val;
3312 STAM_PROFILE_ADV_START(&gStatMemRead, a);
3313 VBOX_CHECK_ADDR(SrcGCPhys);
3314 val = PGMR3PhysReadU32(cpu_single_env->pVM, SrcGCPhys);
3315 STAM_PROFILE_ADV_STOP(&gStatMemRead, a);
3316#ifdef VBOX_DEBUG_PHYS
3317 LogRel(("readu32: %x <- %08x\n", val, (uint32_t)SrcGCPhys));
3318#endif
3319 return val;
3320}
3321
3322
3323/**
3324 * Read guest RAM and ROM, signed 32-bit.
3325 *
3326 * @param SrcGCPhys The source address (guest physical).
3327 */
3328RTCCINTREG remR3PhysReadS32(RTGCPHYS SrcGCPhys)
3329{
3330 int32_t val;
3331 STAM_PROFILE_ADV_START(&gStatMemRead, a);
3332 VBOX_CHECK_ADDR(SrcGCPhys);
3333 val = PGMR3PhysReadU32(cpu_single_env->pVM, SrcGCPhys);
3334 STAM_PROFILE_ADV_STOP(&gStatMemRead, a);
3335#ifdef VBOX_DEBUG_PHYS
3336 LogRel(("reads32: %x <- %08x\n", val, (uint32_t)SrcGCPhys));
3337#endif
3338 return val;
3339}
3340
3341
3342/**
3343 * Read guest RAM and ROM, unsigned 64-bit.
3344 *
3345 * @param SrcGCPhys The source address (guest physical).
3346 */
3347uint64_t remR3PhysReadU64(RTGCPHYS SrcGCPhys)
3348{
3349 uint64_t val;
3350 STAM_PROFILE_ADV_START(&gStatMemRead, a);
3351 VBOX_CHECK_ADDR(SrcGCPhys);
3352 val = PGMR3PhysReadU64(cpu_single_env->pVM, SrcGCPhys);
3353 STAM_PROFILE_ADV_STOP(&gStatMemRead, a);
3354#ifdef VBOX_DEBUG_PHYS
3355 LogRel(("readu64: %llx <- %08x\n", val, (uint32_t)SrcGCPhys));
3356#endif
3357 return val;
3358}
3359
3360
3361/**
3362 * Read guest RAM and ROM, signed 64-bit.
3363 *
3364 * @param SrcGCPhys The source address (guest physical).
3365 */
3366int64_t remR3PhysReadS64(RTGCPHYS SrcGCPhys)
3367{
3368 int64_t val;
3369 STAM_PROFILE_ADV_START(&gStatMemRead, a);
3370 VBOX_CHECK_ADDR(SrcGCPhys);
3371 val = PGMR3PhysReadU64(cpu_single_env->pVM, SrcGCPhys);
3372 STAM_PROFILE_ADV_STOP(&gStatMemRead, a);
3373#ifdef VBOX_DEBUG_PHYS
3374 LogRel(("reads64: %llx <- %08x\n", val, (uint32_t)SrcGCPhys));
3375#endif
3376 return val;
3377}
3378
3379
3380/**
3381 * Write guest RAM.
3382 *
3383 * @param DstGCPhys The destination address (guest physical).
3384 * @param pvSrc The source address.
3385 * @param cb Number of bytes to write
3386 */
3387void remR3PhysWrite(RTGCPHYS DstGCPhys, const void *pvSrc, unsigned cb)
3388{
3389 STAM_PROFILE_ADV_START(&gStatMemWrite, a);
3390 VBOX_CHECK_ADDR(DstGCPhys);
3391 PGMPhysWrite(cpu_single_env->pVM, DstGCPhys, pvSrc, cb);
3392 STAM_PROFILE_ADV_STOP(&gStatMemWrite, a);
3393#ifdef VBOX_DEBUG_PHYS
3394 LogRel(("write(%d): %08x\n", cb, (uint32_t)DstGCPhys));
3395#endif
3396}
3397
3398
3399/**
3400 * Write guest RAM, unsigned 8-bit.
3401 *
3402 * @param DstGCPhys The destination address (guest physical).
3403 * @param val Value
3404 */
3405void remR3PhysWriteU8(RTGCPHYS DstGCPhys, uint8_t val)
3406{
3407 STAM_PROFILE_ADV_START(&gStatMemWrite, a);
3408 VBOX_CHECK_ADDR(DstGCPhys);
3409 PGMR3PhysWriteU8(cpu_single_env->pVM, DstGCPhys, val);
3410 STAM_PROFILE_ADV_STOP(&gStatMemWrite, a);
3411#ifdef VBOX_DEBUG_PHYS
3412 LogRel(("writeu8: %x -> %08x\n", val, (uint32_t)DstGCPhys));
3413#endif
3414}
3415
3416
3417/**
3418 * Write guest RAM, unsigned 8-bit.
3419 *
3420 * @param DstGCPhys The destination address (guest physical).
3421 * @param val Value
3422 */
3423void remR3PhysWriteU16(RTGCPHYS DstGCPhys, uint16_t val)
3424{
3425 STAM_PROFILE_ADV_START(&gStatMemWrite, a);
3426 VBOX_CHECK_ADDR(DstGCPhys);
3427 PGMR3PhysWriteU16(cpu_single_env->pVM, DstGCPhys, val);
3428 STAM_PROFILE_ADV_STOP(&gStatMemWrite, a);
3429#ifdef VBOX_DEBUG_PHYS
3430 LogRel(("writeu16: %x -> %08x\n", val, (uint32_t)DstGCPhys));
3431#endif
3432}
3433
3434
3435/**
3436 * Write guest RAM, unsigned 32-bit.
3437 *
3438 * @param DstGCPhys The destination address (guest physical).
3439 * @param val Value
3440 */
3441void remR3PhysWriteU32(RTGCPHYS DstGCPhys, uint32_t val)
3442{
3443 STAM_PROFILE_ADV_START(&gStatMemWrite, a);
3444 VBOX_CHECK_ADDR(DstGCPhys);
3445 PGMR3PhysWriteU32(cpu_single_env->pVM, DstGCPhys, val);
3446 STAM_PROFILE_ADV_STOP(&gStatMemWrite, a);
3447#ifdef VBOX_DEBUG_PHYS
3448 LogRel(("writeu32: %x -> %08x\n", val, (uint32_t)DstGCPhys));
3449#endif
3450}
3451
3452
3453/**
3454 * Write guest RAM, unsigned 64-bit.
3455 *
3456 * @param DstGCPhys The destination address (guest physical).
3457 * @param val Value
3458 */
3459void remR3PhysWriteU64(RTGCPHYS DstGCPhys, uint64_t val)
3460{
3461 STAM_PROFILE_ADV_START(&gStatMemWrite, a);
3462 VBOX_CHECK_ADDR(DstGCPhys);
3463 PGMR3PhysWriteU64(cpu_single_env->pVM, DstGCPhys, val);
3464 STAM_PROFILE_ADV_STOP(&gStatMemWrite, a);
3465#ifdef VBOX_DEBUG_PHYS
3466 LogRel(("writeu64: %llx -> %08x\n", val, (uint32_t)SrcGCPhys));
3467#endif
3468}
3469
3470#undef LOG_GROUP
3471#define LOG_GROUP LOG_GROUP_REM_MMIO
3472
3473/** Read MMIO memory. */
3474static uint32_t remR3MMIOReadU8(void *pvVM, target_phys_addr_t GCPhys)
3475{
3476 uint32_t u32 = 0;
3477 int rc = IOMMMIORead((PVM)pvVM, GCPhys, &u32, 1);
3478 AssertMsg(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc)); NOREF(rc);
3479 Log2(("remR3MMIOReadU8: GCPhys=%RGp -> %02x\n", GCPhys, u32));
3480 return u32;
3481}
3482
3483/** Read MMIO memory. */
3484static uint32_t remR3MMIOReadU16(void *pvVM, target_phys_addr_t GCPhys)
3485{
3486 uint32_t u32 = 0;
3487 int rc = IOMMMIORead((PVM)pvVM, GCPhys, &u32, 2);
3488 AssertMsg(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc)); NOREF(rc);
3489 Log2(("remR3MMIOReadU16: GCPhys=%RGp -> %04x\n", GCPhys, u32));
3490 return u32;
3491}
3492
3493/** Read MMIO memory. */
3494static uint32_t remR3MMIOReadU32(void *pvVM, target_phys_addr_t GCPhys)
3495{
3496 uint32_t u32 = 0;
3497 int rc = IOMMMIORead((PVM)pvVM, GCPhys, &u32, 4);
3498 AssertMsg(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc)); NOREF(rc);
3499 Log2(("remR3MMIOReadU32: GCPhys=%RGp -> %08x\n", GCPhys, u32));
3500 return u32;
3501}
3502
3503/** Write to MMIO memory. */
3504static void remR3MMIOWriteU8(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32)
3505{
3506 int rc;
3507 Log2(("remR3MMIOWriteU8: GCPhys=%RGp u32=%#x\n", GCPhys, u32));
3508 rc = IOMMMIOWrite((PVM)pvVM, GCPhys, u32, 1);
3509 AssertMsg(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc)); NOREF(rc);
3510}
3511
3512/** Write to MMIO memory. */
3513static void remR3MMIOWriteU16(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32)
3514{
3515 int rc;
3516 Log2(("remR3MMIOWriteU16: GCPhys=%RGp u32=%#x\n", GCPhys, u32));
3517 rc = IOMMMIOWrite((PVM)pvVM, GCPhys, u32, 2);
3518 AssertMsg(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc)); NOREF(rc);
3519}
3520
3521/** Write to MMIO memory. */
3522static void remR3MMIOWriteU32(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32)
3523{
3524 int rc;
3525 Log2(("remR3MMIOWriteU32: GCPhys=%RGp u32=%#x\n", GCPhys, u32));
3526 rc = IOMMMIOWrite((PVM)pvVM, GCPhys, u32, 4);
3527 AssertMsg(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc)); NOREF(rc);
3528}
3529
3530
3531#undef LOG_GROUP
3532#define LOG_GROUP LOG_GROUP_REM_HANDLER
3533
3534/* !!!WARNING!!! This is extremely hackish right now, we assume it's only for LFB access! !!!WARNING!!! */
3535
3536static uint32_t remR3HandlerReadU8(void *pvVM, target_phys_addr_t GCPhys)
3537{
3538 uint8_t u8;
3539 Log2(("remR3HandlerReadU8: GCPhys=%RGp\n", GCPhys));
3540 PGMPhysRead((PVM)pvVM, GCPhys, &u8, sizeof(u8));
3541 return u8;
3542}
3543
3544static uint32_t remR3HandlerReadU16(void *pvVM, target_phys_addr_t GCPhys)
3545{
3546 uint16_t u16;
3547 Log2(("remR3HandlerReadU16: GCPhys=%RGp\n", GCPhys));
3548 PGMPhysRead((PVM)pvVM, GCPhys, &u16, sizeof(u16));
3549 return u16;
3550}
3551
3552static uint32_t remR3HandlerReadU32(void *pvVM, target_phys_addr_t GCPhys)
3553{
3554 uint32_t u32;
3555 Log2(("remR3HandlerReadU32: GCPhys=%RGp\n", GCPhys));
3556 PGMPhysRead((PVM)pvVM, GCPhys, &u32, sizeof(u32));
3557 return u32;
3558}
3559
3560static void remR3HandlerWriteU8(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32)
3561{
3562 Log2(("remR3HandlerWriteU8: GCPhys=%RGp u32=%#x\n", GCPhys, u32));
3563 PGMPhysWrite((PVM)pvVM, GCPhys, &u32, sizeof(uint8_t));
3564}
3565
3566static void remR3HandlerWriteU16(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32)
3567{
3568 Log2(("remR3HandlerWriteU16: GCPhys=%RGp u32=%#x\n", GCPhys, u32));
3569 PGMPhysWrite((PVM)pvVM, GCPhys, &u32, sizeof(uint16_t));
3570}
3571
3572static void remR3HandlerWriteU32(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32)
3573{
3574 Log2(("remR3HandlerWriteU32: GCPhys=%RGp u32=%#x\n", GCPhys, u32));
3575 PGMPhysWrite((PVM)pvVM, GCPhys, &u32, sizeof(uint32_t));
3576}
3577
3578/* -+- disassembly -+- */
3579
3580#undef LOG_GROUP
3581#define LOG_GROUP LOG_GROUP_REM_DISAS
3582
3583
3584/**
3585 * Enables or disables singled stepped disassembly.
3586 *
3587 * @returns VBox status code.
3588 * @param pVM VM handle.
3589 * @param fEnable To enable set this flag, to disable clear it.
3590 */
3591static DECLCALLBACK(int) remR3DisasEnableStepping(PVM pVM, bool fEnable)
3592{
3593 LogFlow(("remR3DisasEnableStepping: fEnable=%d\n", fEnable));
3594 VM_ASSERT_EMT(pVM);
3595
3596 if (fEnable)
3597 pVM->rem.s.Env.state |= CPU_EMULATE_SINGLE_STEP;
3598 else
3599 pVM->rem.s.Env.state &= ~CPU_EMULATE_SINGLE_STEP;
3600 return VINF_SUCCESS;
3601}
3602
3603
3604/**
3605 * Enables or disables singled stepped disassembly.
3606 *
3607 * @returns VBox status code.
3608 * @param pVM VM handle.
3609 * @param fEnable To enable set this flag, to disable clear it.
3610 */
3611REMR3DECL(int) REMR3DisasEnableStepping(PVM pVM, bool fEnable)
3612{
3613 PVMREQ pReq;
3614 int rc;
3615
3616 LogFlow(("REMR3DisasEnableStepping: fEnable=%d\n", fEnable));
3617 if (VM_IS_EMT(pVM))
3618 return remR3DisasEnableStepping(pVM, fEnable);
3619
3620 rc = VMR3ReqCall(pVM, VMCPUID_ANY, &pReq, RT_INDEFINITE_WAIT, (PFNRT)remR3DisasEnableStepping, 2, pVM, fEnable);
3621 AssertRC(rc);
3622 if (RT_SUCCESS(rc))
3623 rc = pReq->iStatus;
3624 VMR3ReqFree(pReq);
3625 return rc;
3626}
3627
3628
3629#if defined(VBOX_WITH_DEBUGGER) && !(defined(RT_OS_WINDOWS) && defined(RT_ARCH_AMD64))
3630/**
3631 * External Debugger Command: .remstep [on|off|1|0]
3632 */
3633static DECLCALLBACK(int) remR3CmdDisasEnableStepping(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
3634{
3635 bool fEnable;
3636 int rc;
3637
3638 /* print status */
3639 if (cArgs == 0)
3640 return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "DisasStepping is %s\n",
3641 pVM->rem.s.Env.state & CPU_EMULATE_SINGLE_STEP ? "enabled" : "disabled");
3642
3643 /* convert the argument and change the mode. */
3644 rc = pCmdHlp->pfnVarToBool(pCmdHlp, &paArgs[0], &fEnable);
3645 if (RT_FAILURE(rc))
3646 return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "boolean conversion failed!\n");
3647 rc = REMR3DisasEnableStepping(pVM, fEnable);
3648 if (RT_FAILURE(rc))
3649 return pCmdHlp->pfnVBoxError(pCmdHlp, rc, "REMR3DisasEnableStepping failed!\n");
3650 return rc;
3651}
3652#endif
3653
3654
3655/**
3656 * Disassembles one instruction and prints it to the log.
3657 *
3658 * @returns Success indicator.
3659 * @param env Pointer to the recompiler CPU structure.
3660 * @param f32BitCode Indicates that whether or not the code should
3661 * be disassembled as 16 or 32 bit. If -1 the CS
3662 * selector will be inspected.
3663 * @param pszPrefix
3664 */
3665bool remR3DisasInstr(CPUState *env, int f32BitCode, char *pszPrefix)
3666{
3667 PVM pVM = env->pVM;
3668 const bool fLog = LogIsEnabled();
3669 const bool fLog2 = LogIs2Enabled();
3670 int rc = VINF_SUCCESS;
3671
3672 /*
3673 * Don't bother if there ain't any log output to do.
3674 */
3675 if (!fLog && !fLog2)
3676 return true;
3677
3678 /*
3679 * Update the state so DBGF reads the correct register values.
3680 */
3681 remR3StateUpdate(pVM, env->pVCpu);
3682
3683 /*
3684 * Log registers if requested.
3685 */
3686 if (!fLog2)
3687 DBGFR3InfoLog(pVM, "cpumguest", pszPrefix);
3688
3689 /*
3690 * Disassemble to log.
3691 */
3692 if (fLog)
3693 rc = DBGFR3DisasInstrCurrentLogInternal(env->pVCpu, pszPrefix);
3694
3695 return RT_SUCCESS(rc);
3696}
3697
3698
3699/**
3700 * Disassemble recompiled code.
3701 *
3702 * @param phFileIgnored Ignored, logfile usually.
3703 * @param pvCode Pointer to the code block.
3704 * @param cb Size of the code block.
3705 */
3706void disas(FILE *phFile, void *pvCode, unsigned long cb)
3707{
3708#ifdef DEBUG_TMP_LOGGING
3709# define DISAS_PRINTF(x...) fprintf(phFile, x)
3710#else
3711# define DISAS_PRINTF(x...) RTLogPrintf(x)
3712 if (LogIs2Enabled())
3713#endif
3714 {
3715 unsigned off = 0;
3716 char szOutput[256];
3717 DISCPUSTATE Cpu;
3718
3719 memset(&Cpu, 0, sizeof(Cpu));
3720#ifdef RT_ARCH_X86
3721 Cpu.mode = CPUMODE_32BIT;
3722#else
3723 Cpu.mode = CPUMODE_64BIT;
3724#endif
3725
3726 DISAS_PRINTF("Recompiled Code: %p %#lx (%ld) bytes\n", pvCode, cb, cb);
3727 while (off < cb)
3728 {
3729 uint32_t cbInstr;
3730 if (RT_SUCCESS(DISInstr(&Cpu, (uintptr_t)pvCode + off, 0, &cbInstr, szOutput)))
3731 DISAS_PRINTF("%s", szOutput);
3732 else
3733 {
3734 DISAS_PRINTF("disas error\n");
3735 cbInstr = 1;
3736#ifdef RT_ARCH_AMD64 /** @todo remove when DISInstr starts supporing 64-bit code. */
3737 break;
3738#endif
3739 }
3740 off += cbInstr;
3741 }
3742 }
3743
3744#undef DISAS_PRINTF
3745}
3746
3747
3748/**
3749 * Disassemble guest code.
3750 *
3751 * @param phFileIgnored Ignored, logfile usually.
3752 * @param uCode The guest address of the code to disassemble. (flat?)
3753 * @param cb Number of bytes to disassemble.
3754 * @param fFlags Flags, probably something which tells if this is 16, 32 or 64 bit code.
3755 */
3756void target_disas(FILE *phFile, target_ulong uCode, target_ulong cb, int fFlags)
3757{
3758#ifdef DEBUG_TMP_LOGGING
3759# define DISAS_PRINTF(x...) fprintf(phFile, x)
3760#else
3761# define DISAS_PRINTF(x...) RTLogPrintf(x)
3762 if (LogIs2Enabled())
3763#endif
3764 {
3765 PVM pVM = cpu_single_env->pVM;
3766 PVMCPU pVCpu = cpu_single_env->pVCpu;
3767 RTSEL cs;
3768 RTGCUINTPTR eip;
3769
3770 Assert(pVCpu);
3771
3772 /*
3773 * Update the state so DBGF reads the correct register values (flags).
3774 */
3775 remR3StateUpdate(pVM, pVCpu);
3776
3777 /*
3778 * Do the disassembling.
3779 */
3780 DISAS_PRINTF("Guest Code: PC=%llx %llx bytes fFlags=%d\n", (uint64_t)uCode, (uint64_t)cb, fFlags);
3781 cs = cpu_single_env->segs[R_CS].selector;
3782 eip = uCode - cpu_single_env->segs[R_CS].base;
3783 for (;;)
3784 {
3785 char szBuf[256];
3786 uint32_t cbInstr;
3787 int rc = DBGFR3DisasInstrEx(pVM,
3788 pVCpu->idCpu,
3789 cs,
3790 eip,
3791 0,
3792 szBuf, sizeof(szBuf),
3793 &cbInstr);
3794 if (RT_SUCCESS(rc))
3795 DISAS_PRINTF("%llx %s\n", (uint64_t)uCode, szBuf);
3796 else
3797 {
3798 DISAS_PRINTF("%llx %04x:%llx: %s\n", (uint64_t)uCode, cs, (uint64_t)eip, szBuf);
3799 cbInstr = 1;
3800 }
3801
3802 /* next */
3803 if (cb <= cbInstr)
3804 break;
3805 cb -= cbInstr;
3806 uCode += cbInstr;
3807 eip += cbInstr;
3808 }
3809 }
3810#undef DISAS_PRINTF
3811}
3812
3813
3814/**
3815 * Looks up a guest symbol.
3816 *
3817 * @returns Pointer to symbol name. This is a static buffer.
3818 * @param orig_addr The address in question.
3819 */
3820const char *lookup_symbol(target_ulong orig_addr)
3821{
3822 RTGCINTPTR off = 0;
3823 DBGFSYMBOL Sym;
3824 PVM pVM = cpu_single_env->pVM;
3825 int rc = DBGFR3SymbolByAddr(pVM, orig_addr, &off, &Sym);
3826 if (RT_SUCCESS(rc))
3827 {
3828 static char szSym[sizeof(Sym.szName) + 48];
3829 if (!off)
3830 RTStrPrintf(szSym, sizeof(szSym), "%s\n", Sym.szName);
3831 else if (off > 0)
3832 RTStrPrintf(szSym, sizeof(szSym), "%s+%x\n", Sym.szName, off);
3833 else
3834 RTStrPrintf(szSym, sizeof(szSym), "%s-%x\n", Sym.szName, -off);
3835 return szSym;
3836 }
3837 return "<N/A>";
3838}
3839
3840
3841#undef LOG_GROUP
3842#define LOG_GROUP LOG_GROUP_REM
3843
3844
3845/* -+- FF notifications -+- */
3846
3847
3848/**
3849 * Notification about a pending interrupt.
3850 *
3851 * @param pVM VM Handle.
3852 * @param pVCpu VMCPU Handle.
3853 * @param u8Interrupt Interrupt
3854 * @thread The emulation thread.
3855 */
3856REMR3DECL(void) REMR3NotifyPendingInterrupt(PVM pVM, PVMCPU pVCpu, uint8_t u8Interrupt)
3857{
3858 Assert(pVM->rem.s.u32PendingInterrupt == REM_NO_PENDING_IRQ);
3859 pVM->rem.s.u32PendingInterrupt = u8Interrupt;
3860}
3861
3862/**
3863 * Notification about a pending interrupt.
3864 *
3865 * @returns Pending interrupt or REM_NO_PENDING_IRQ
3866 * @param pVM VM Handle.
3867 * @param pVCpu VMCPU Handle.
3868 * @thread The emulation thread.
3869 */
3870REMR3DECL(uint32_t) REMR3QueryPendingInterrupt(PVM pVM, PVMCPU pVCpu)
3871{
3872 return pVM->rem.s.u32PendingInterrupt;
3873}
3874
3875/**
3876 * Notification about the interrupt FF being set.
3877 *
3878 * @param pVM VM Handle.
3879 * @param pVCpu VMCPU Handle.
3880 * @thread The emulation thread.
3881 */
3882REMR3DECL(void) REMR3NotifyInterruptSet(PVM pVM, PVMCPU pVCpu)
3883{
3884 LogFlow(("REMR3NotifyInterruptSet: fInRem=%d interrupts %s\n", pVM->rem.s.fInREM,
3885 (pVM->rem.s.Env.eflags & IF_MASK) && !(pVM->rem.s.Env.hflags & HF_INHIBIT_IRQ_MASK) ? "enabled" : "disabled"));
3886 if (pVM->rem.s.fInREM)
3887 {
3888 ASMAtomicOrS32((int32_t volatile *)&cpu_single_env->interrupt_request,
3889 CPU_INTERRUPT_EXTERNAL_HARD);
3890 }
3891}
3892
3893
3894/**
3895 * Notification about the interrupt FF being set.
3896 *
3897 * @param pVM VM Handle.
3898 * @param pVCpu VMCPU Handle.
3899 * @thread Any.
3900 */
3901REMR3DECL(void) REMR3NotifyInterruptClear(PVM pVM, PVMCPU pVCpu)
3902{
3903 LogFlow(("REMR3NotifyInterruptClear:\n"));
3904 if (pVM->rem.s.fInREM)
3905 cpu_reset_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
3906}
3907
3908
3909/**
3910 * Notification about pending timer(s).
3911 *
3912 * @param pVM VM Handle.
3913 * @param pVCpuDst The target cpu for this notification.
3914 * TM will not broadcast pending timer events, but use
3915 * a decidated EMT for them. So, only interrupt REM
3916 * execution if the given CPU is executing in REM.
3917 * @thread Any.
3918 */
3919REMR3DECL(void) REMR3NotifyTimerPending(PVM pVM, PVMCPU pVCpuDst)
3920{
3921#ifndef DEBUG_bird
3922 LogFlow(("REMR3NotifyTimerPending: fInRem=%d\n", pVM->rem.s.fInREM));
3923#endif
3924 if (pVM->rem.s.fInREM)
3925 {
3926 if (pVM->rem.s.Env.pVCpu == pVCpuDst)
3927 {
3928 LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_5, LOG_GROUP_TM, ("REMR3NotifyTimerPending: setting\n"));
3929 ASMAtomicOrS32((int32_t volatile *)&pVM->rem.s.Env.interrupt_request,
3930 CPU_INTERRUPT_EXTERNAL_TIMER);
3931 }
3932 else
3933 LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_5, LOG_GROUP_TM, ("REMR3NotifyTimerPending: pVCpu:%p != pVCpuDst:%p\n", pVM->rem.s.Env.pVCpu, pVCpuDst));
3934 }
3935 else
3936 LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_5, LOG_GROUP_TM, ("REMR3NotifyTimerPending: !fInREM; cpu state=%d\n", VMCPU_GET_STATE(pVCpuDst)));
3937}
3938
3939
3940/**
3941 * Notification about pending DMA transfers.
3942 *
3943 * @param pVM VM Handle.
3944 * @thread Any.
3945 */
3946REMR3DECL(void) REMR3NotifyDmaPending(PVM pVM)
3947{
3948 LogFlow(("REMR3NotifyDmaPending: fInRem=%d\n", pVM->rem.s.fInREM));
3949 if (pVM->rem.s.fInREM)
3950 {
3951 ASMAtomicOrS32((int32_t volatile *)&cpu_single_env->interrupt_request,
3952 CPU_INTERRUPT_EXTERNAL_DMA);
3953 }
3954}
3955
3956
3957/**
3958 * Notification about pending timer(s).
3959 *
3960 * @param pVM VM Handle.
3961 * @thread Any.
3962 */
3963REMR3DECL(void) REMR3NotifyQueuePending(PVM pVM)
3964{
3965 LogFlow(("REMR3NotifyQueuePending: fInRem=%d\n", pVM->rem.s.fInREM));
3966 if (pVM->rem.s.fInREM)
3967 {
3968 ASMAtomicOrS32((int32_t volatile *)&cpu_single_env->interrupt_request,
3969 CPU_INTERRUPT_EXTERNAL_EXIT);
3970 }
3971}
3972
3973
3974/**
3975 * Notification about pending FF set by an external thread.
3976 *
3977 * @param pVM VM handle.
3978 * @thread Any.
3979 */
3980REMR3DECL(void) REMR3NotifyFF(PVM pVM)
3981{
3982 LogFlow(("REMR3NotifyFF: fInRem=%d\n", pVM->rem.s.fInREM));
3983 if (pVM->rem.s.fInREM)
3984 {
3985 ASMAtomicOrS32((int32_t volatile *)&cpu_single_env->interrupt_request,
3986 CPU_INTERRUPT_EXTERNAL_EXIT);
3987 }
3988}
3989
3990
3991#ifdef VBOX_WITH_STATISTICS
3992void remR3ProfileStart(int statcode)
3993{
3994 STAMPROFILEADV *pStat;
3995 switch(statcode)
3996 {
3997 case STATS_EMULATE_SINGLE_INSTR:
3998 pStat = &gStatExecuteSingleInstr;
3999 break;
4000 case STATS_QEMU_COMPILATION:
4001 pStat = &gStatCompilationQEmu;
4002 break;
4003 case STATS_QEMU_RUN_EMULATED_CODE:
4004 pStat = &gStatRunCodeQEmu;
4005 break;
4006 case STATS_QEMU_TOTAL:
4007 pStat = &gStatTotalTimeQEmu;
4008 break;
4009 case STATS_QEMU_RUN_TIMERS:
4010 pStat = &gStatTimers;
4011 break;
4012 case STATS_TLB_LOOKUP:
4013 pStat= &gStatTBLookup;
4014 break;
4015 case STATS_IRQ_HANDLING:
4016 pStat= &gStatIRQ;
4017 break;
4018 case STATS_RAW_CHECK:
4019 pStat = &gStatRawCheck;
4020 break;
4021
4022 default:
4023 AssertMsgFailed(("unknown stat %d\n", statcode));
4024 return;
4025 }
4026 STAM_PROFILE_ADV_START(pStat, a);
4027}
4028
4029
4030void remR3ProfileStop(int statcode)
4031{
4032 STAMPROFILEADV *pStat;
4033 switch(statcode)
4034 {
4035 case STATS_EMULATE_SINGLE_INSTR:
4036 pStat = &gStatExecuteSingleInstr;
4037 break;
4038 case STATS_QEMU_COMPILATION:
4039 pStat = &gStatCompilationQEmu;
4040 break;
4041 case STATS_QEMU_RUN_EMULATED_CODE:
4042 pStat = &gStatRunCodeQEmu;
4043 break;
4044 case STATS_QEMU_TOTAL:
4045 pStat = &gStatTotalTimeQEmu;
4046 break;
4047 case STATS_QEMU_RUN_TIMERS:
4048 pStat = &gStatTimers;
4049 break;
4050 case STATS_TLB_LOOKUP:
4051 pStat= &gStatTBLookup;
4052 break;
4053 case STATS_IRQ_HANDLING:
4054 pStat= &gStatIRQ;
4055 break;
4056 case STATS_RAW_CHECK:
4057 pStat = &gStatRawCheck;
4058 break;
4059 default:
4060 AssertMsgFailed(("unknown stat %d\n", statcode));
4061 return;
4062 }
4063 STAM_PROFILE_ADV_STOP(pStat, a);
4064}
4065#endif
4066
4067/**
4068 * Raise an RC, force rem exit.
4069 *
4070 * @param pVM VM handle.
4071 * @param rc The rc.
4072 */
4073void remR3RaiseRC(PVM pVM, int rc)
4074{
4075 Log(("remR3RaiseRC: rc=%Rrc\n", rc));
4076 Assert(pVM->rem.s.fInREM);
4077 VM_ASSERT_EMT(pVM);
4078 pVM->rem.s.rc = rc;
4079 cpu_interrupt(&pVM->rem.s.Env, CPU_INTERRUPT_RC);
4080}
4081
4082
4083/* -+- timers -+- */
4084
4085uint64_t cpu_get_tsc(CPUX86State *env)
4086{
4087 STAM_COUNTER_INC(&gStatCpuGetTSC);
4088 return TMCpuTickGet(env->pVCpu);
4089}
4090
4091
4092/* -+- interrupts -+- */
4093
4094void cpu_set_ferr(CPUX86State *env)
4095{
4096 int rc = PDMIsaSetIrq(env->pVM, 13, 1);
4097 LogFlow(("cpu_set_ferr: rc=%d\n", rc)); NOREF(rc);
4098}
4099
4100int cpu_get_pic_interrupt(CPUState *env)
4101{
4102 uint8_t u8Interrupt;
4103 int rc;
4104
4105 /* When we fail to forward interrupts directly in raw mode, we fall back to the recompiler.
4106 * In that case we can't call PDMGetInterrupt anymore, because it has already cleared the interrupt
4107 * with the (a)pic.
4108 */
4109 /** @note We assume we will go directly to the recompiler to handle the pending interrupt! */
4110 /** @todo r=bird: In the long run we should just do the interrupt handling in EM/CPUM/TRPM/somewhere and
4111 * if we cannot execute the interrupt handler in raw-mode just reschedule to REM. Once that is done we
4112 * remove this kludge. */
4113 if (env->pVM->rem.s.u32PendingInterrupt != REM_NO_PENDING_IRQ)
4114 {
4115 rc = VINF_SUCCESS;
4116 Assert(env->pVM->rem.s.u32PendingInterrupt <= 255);
4117 u8Interrupt = env->pVM->rem.s.u32PendingInterrupt;
4118 env->pVM->rem.s.u32PendingInterrupt = REM_NO_PENDING_IRQ;
4119 }
4120 else
4121 rc = PDMGetInterrupt(env->pVCpu, &u8Interrupt);
4122
4123 LogFlow(("cpu_get_pic_interrupt: u8Interrupt=%d rc=%Rrc\n", u8Interrupt, rc));
4124 if (RT_SUCCESS(rc))
4125 {
4126 if (VMCPU_FF_ISPENDING(env->pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC))
4127 env->interrupt_request |= CPU_INTERRUPT_HARD;
4128 return u8Interrupt;
4129 }
4130 return -1;
4131}
4132
4133
4134/* -+- local apic -+- */
4135
4136void cpu_set_apic_base(CPUX86State *env, uint64_t val)
4137{
4138 int rc = PDMApicSetBase(env->pVM, val);
4139 LogFlow(("cpu_set_apic_base: val=%#llx rc=%Rrc\n", val, rc)); NOREF(rc);
4140}
4141
4142uint64_t cpu_get_apic_base(CPUX86State *env)
4143{
4144 uint64_t u64;
4145 int rc = PDMApicGetBase(env->pVM, &u64);
4146 if (RT_SUCCESS(rc))
4147 {
4148 LogFlow(("cpu_get_apic_base: returns %#llx \n", u64));
4149 return u64;
4150 }
4151 LogFlow(("cpu_get_apic_base: returns 0 (rc=%Rrc)\n", rc));
4152 return 0;
4153}
4154
4155void cpu_set_apic_tpr(CPUX86State *env, uint8_t val)
4156{
4157 int rc = PDMApicSetTPR(env->pVCpu, val);
4158 LogFlow(("cpu_set_apic_tpr: val=%#x rc=%Rrc\n", val, rc)); NOREF(rc);
4159}
4160
4161uint8_t cpu_get_apic_tpr(CPUX86State *env)
4162{
4163 uint8_t u8;
4164 int rc = PDMApicGetTPR(env->pVCpu, &u8, NULL);
4165 if (RT_SUCCESS(rc))
4166 {
4167 LogFlow(("cpu_get_apic_tpr: returns %#x\n", u8));
4168 return u8;
4169 }
4170 LogFlow(("cpu_get_apic_tpr: returns 0 (rc=%Rrc)\n", rc));
4171 return 0;
4172}
4173
4174
4175uint64_t cpu_apic_rdmsr(CPUX86State *env, uint32_t reg)
4176{
4177 uint64_t value;
4178 int rc = PDMApicReadMSR(env->pVM, 0/* cpu */, reg, &value);
4179 if (RT_SUCCESS(rc))
4180 {
4181 LogFlow(("cpu_apic_rdms returns %#x\n", value));
4182 return value;
4183 }
4184 /** @todo: exception ? */
4185 LogFlow(("cpu_apic_rdms returns 0 (rc=%Rrc)\n", rc));
4186 return value;
4187}
4188
4189void cpu_apic_wrmsr(CPUX86State *env, uint32_t reg, uint64_t value)
4190{
4191 int rc = PDMApicWriteMSR(env->pVM, 0 /* cpu */, reg, value);
4192 /** @todo: exception if error ? */
4193 LogFlow(("cpu_apic_wrmsr: rc=%Rrc\n", rc)); NOREF(rc);
4194}
4195
4196uint64_t cpu_rdmsr(CPUX86State *env, uint32_t msr)
4197{
4198 Assert(env->pVCpu);
4199 return CPUMGetGuestMsr(env->pVCpu, msr);
4200}
4201
4202void cpu_wrmsr(CPUX86State *env, uint32_t msr, uint64_t val)
4203{
4204 Assert(env->pVCpu);
4205 CPUMSetGuestMsr(env->pVCpu, msr, val);
4206}
4207
4208/* -+- I/O Ports -+- */
4209
4210#undef LOG_GROUP
4211#define LOG_GROUP LOG_GROUP_REM_IOPORT
4212
4213void cpu_outb(CPUState *env, int addr, int val)
4214{
4215 int rc;
4216
4217 if (addr != 0x80 && addr != 0x70 && addr != 0x61)
4218 Log2(("cpu_outb: addr=%#06x val=%#x\n", addr, val));
4219
4220 rc = IOMIOPortWrite(env->pVM, (RTIOPORT)addr, val, 1);
4221 if (RT_LIKELY(rc == VINF_SUCCESS))
4222 return;
4223 if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
4224 {
4225 Log(("cpu_outb: addr=%#06x val=%#x -> %Rrc\n", addr, val, rc));
4226 remR3RaiseRC(env->pVM, rc);
4227 return;
4228 }
4229 remAbort(rc, __FUNCTION__);
4230}
4231
4232void cpu_outw(CPUState *env, int addr, int val)
4233{
4234 //Log2(("cpu_outw: addr=%#06x val=%#x\n", addr, val));
4235 int rc = IOMIOPortWrite(env->pVM, (RTIOPORT)addr, val, 2);
4236 if (RT_LIKELY(rc == VINF_SUCCESS))
4237 return;
4238 if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
4239 {
4240 Log(("cpu_outw: addr=%#06x val=%#x -> %Rrc\n", addr, val, rc));
4241 remR3RaiseRC(env->pVM, rc);
4242 return;
4243 }
4244 remAbort(rc, __FUNCTION__);
4245}
4246
4247void cpu_outl(CPUState *env, int addr, int val)
4248{
4249 int rc;
4250 Log2(("cpu_outl: addr=%#06x val=%#x\n", addr, val));
4251 rc = IOMIOPortWrite(env->pVM, (RTIOPORT)addr, val, 4);
4252 if (RT_LIKELY(rc == VINF_SUCCESS))
4253 return;
4254 if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
4255 {
4256 Log(("cpu_outl: addr=%#06x val=%#x -> %Rrc\n", addr, val, rc));
4257 remR3RaiseRC(env->pVM, rc);
4258 return;
4259 }
4260 remAbort(rc, __FUNCTION__);
4261}
4262
4263int cpu_inb(CPUState *env, int addr)
4264{
4265 uint32_t u32 = 0;
4266 int rc = IOMIOPortRead(env->pVM, (RTIOPORT)addr, &u32, 1);
4267 if (RT_LIKELY(rc == VINF_SUCCESS))
4268 {
4269 if (/*addr != 0x61 && */addr != 0x71)
4270 Log2(("cpu_inb: addr=%#06x -> %#x\n", addr, u32));
4271 return (int)u32;
4272 }
4273 if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
4274 {
4275 Log(("cpu_inb: addr=%#06x -> %#x rc=%Rrc\n", addr, u32, rc));
4276 remR3RaiseRC(env->pVM, rc);
4277 return (int)u32;
4278 }
4279 remAbort(rc, __FUNCTION__);
4280 return 0xff;
4281}
4282
4283int cpu_inw(CPUState *env, int addr)
4284{
4285 uint32_t u32 = 0;
4286 int rc = IOMIOPortRead(env->pVM, (RTIOPORT)addr, &u32, 2);
4287 if (RT_LIKELY(rc == VINF_SUCCESS))
4288 {
4289 Log2(("cpu_inw: addr=%#06x -> %#x\n", addr, u32));
4290 return (int)u32;
4291 }
4292 if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
4293 {
4294 Log(("cpu_inw: addr=%#06x -> %#x rc=%Rrc\n", addr, u32, rc));
4295 remR3RaiseRC(env->pVM, rc);
4296 return (int)u32;
4297 }
4298 remAbort(rc, __FUNCTION__);
4299 return 0xffff;
4300}
4301
4302int cpu_inl(CPUState *env, int addr)
4303{
4304 uint32_t u32 = 0;
4305 int rc = IOMIOPortRead(env->pVM, (RTIOPORT)addr, &u32, 4);
4306 if (RT_LIKELY(rc == VINF_SUCCESS))
4307 {
4308//if (addr==0x01f0 && u32 == 0x6b6d)
4309// loglevel = ~0;
4310 Log2(("cpu_inl: addr=%#06x -> %#x\n", addr, u32));
4311 return (int)u32;
4312 }
4313 if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
4314 {
4315 Log(("cpu_inl: addr=%#06x -> %#x rc=%Rrc\n", addr, u32, rc));
4316 remR3RaiseRC(env->pVM, rc);
4317 return (int)u32;
4318 }
4319 remAbort(rc, __FUNCTION__);
4320 return 0xffffffff;
4321}
4322
4323#undef LOG_GROUP
4324#define LOG_GROUP LOG_GROUP_REM
4325
4326
4327/* -+- helpers and misc other interfaces -+- */
4328
4329/**
4330 * Perform the CPUID instruction.
4331 *
4332 * ASMCpuId cannot be invoked from some source files where this is used because of global
4333 * register allocations.
4334 *
4335 * @param env Pointer to the recompiler CPU structure.
4336 * @param uOperator CPUID operation (eax).
4337 * @param pvEAX Where to store eax.
4338 * @param pvEBX Where to store ebx.
4339 * @param pvECX Where to store ecx.
4340 * @param pvEDX Where to store edx.
4341 */
4342void remR3CpuId(CPUState *env, unsigned uOperator, void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX)
4343{
4344 CPUMGetGuestCpuId(env->pVCpu, uOperator, (uint32_t *)pvEAX, (uint32_t *)pvEBX, (uint32_t *)pvECX, (uint32_t *)pvEDX);
4345}
4346
4347
4348#if 0 /* not used */
4349/**
4350 * Interface for qemu hardware to report back fatal errors.
4351 */
4352void hw_error(const char *pszFormat, ...)
4353{
4354 /*
4355 * Bitch about it.
4356 */
4357 /** @todo Add support for nested arg lists in the LogPrintfV routine! I've code for
4358 * this in my Odin32 tree at home! */
4359 va_list args;
4360 va_start(args, pszFormat);
4361 RTLogPrintf("fatal error in virtual hardware:");
4362 RTLogPrintfV(pszFormat, args);
4363 va_end(args);
4364 AssertReleaseMsgFailed(("fatal error in virtual hardware: %s\n", pszFormat));
4365
4366 /*
4367 * If we're in REM context we'll sync back the state before 'jumping' to
4368 * the EMs failure handling.
4369 */
4370 PVM pVM = cpu_single_env->pVM;
4371 if (pVM->rem.s.fInREM)
4372 REMR3StateBack(pVM);
4373 EMR3FatalError(pVM, VERR_REM_VIRTUAL_HARDWARE_ERROR);
4374 AssertMsgFailed(("EMR3FatalError returned!\n"));
4375}
4376#endif
4377
4378/**
4379 * Interface for the qemu cpu to report unhandled situation
4380 * raising a fatal VM error.
4381 */
4382void cpu_abort(CPUState *env, const char *pszFormat, ...)
4383{
4384 va_list va;
4385 PVM pVM;
4386 PVMCPU pVCpu;
4387 char szMsg[256];
4388
4389 /*
4390 * Bitch about it.
4391 */
4392 RTLogFlags(NULL, "nodisabled nobuffered");
4393 RTLogFlush(NULL);
4394
4395 va_start(va, pszFormat);
4396#if defined(RT_OS_WINDOWS) && ARCH_BITS == 64
4397 /* It's a bit complicated when mixing MSC and GCC on AMD64. This is a bit ugly, but it works. */
4398 unsigned cArgs = 0;
4399 uintptr_t auArgs[6] = {0,0,0,0,0,0};
4400 const char *psz = strchr(pszFormat, '%');
4401 while (psz && cArgs < 6)
4402 {
4403 auArgs[cArgs++] = va_arg(va, uintptr_t);
4404 psz = strchr(psz + 1, '%');
4405 }
4406 switch (cArgs)
4407 {
4408 case 1: RTStrPrintf(szMsg, sizeof(szMsg), pszFormat, auArgs[0]); break;
4409 case 2: RTStrPrintf(szMsg, sizeof(szMsg), pszFormat, auArgs[0], auArgs[1]); break;
4410 case 3: RTStrPrintf(szMsg, sizeof(szMsg), pszFormat, auArgs[0], auArgs[1], auArgs[2]); break;
4411 case 4: RTStrPrintf(szMsg, sizeof(szMsg), pszFormat, auArgs[0], auArgs[1], auArgs[2], auArgs[3]); break;
4412 case 5: RTStrPrintf(szMsg, sizeof(szMsg), pszFormat, auArgs[0], auArgs[1], auArgs[2], auArgs[3], auArgs[4]); break;
4413 case 6: RTStrPrintf(szMsg, sizeof(szMsg), pszFormat, auArgs[0], auArgs[1], auArgs[2], auArgs[3], auArgs[4], auArgs[5]); break;
4414 default:
4415 case 0: RTStrPrintf(szMsg, sizeof(szMsg), "%s", pszFormat); break;
4416 }
4417#else
4418 RTStrPrintfV(szMsg, sizeof(szMsg), pszFormat, va);
4419#endif
4420 va_end(va);
4421
4422 RTLogPrintf("fatal error in recompiler cpu: %s\n", szMsg);
4423 RTLogRelPrintf("fatal error in recompiler cpu: %s\n", szMsg);
4424
4425 /*
4426 * If we're in REM context we'll sync back the state before 'jumping' to
4427 * the EMs failure handling.
4428 */
4429 pVM = cpu_single_env->pVM;
4430 pVCpu = cpu_single_env->pVCpu;
4431 Assert(pVCpu);
4432
4433 if (pVM->rem.s.fInREM)
4434 REMR3StateBack(pVM, pVCpu);
4435 EMR3FatalError(pVCpu, VERR_REM_VIRTUAL_CPU_ERROR);
4436 AssertMsgFailed(("EMR3FatalError returned!\n"));
4437}
4438
4439
4440/**
4441 * Aborts the VM.
4442 *
4443 * @param rc VBox error code.
4444 * @param pszTip Hint about why/when this happend.
4445 */
4446void remAbort(int rc, const char *pszTip)
4447{
4448 PVM pVM;
4449 PVMCPU pVCpu;
4450
4451 /*
4452 * Bitch about it.
4453 */
4454 RTLogPrintf("internal REM fatal error: rc=%Rrc %s\n", rc, pszTip);
4455 AssertReleaseMsgFailed(("internal REM fatal error: rc=%Rrc %s\n", rc, pszTip));
4456
4457 /*
4458 * Jump back to where we entered the recompiler.
4459 */
4460 pVM = cpu_single_env->pVM;
4461 pVCpu = cpu_single_env->pVCpu;
4462 Assert(pVCpu);
4463
4464 if (pVM->rem.s.fInREM)
4465 REMR3StateBack(pVM, pVCpu);
4466
4467 EMR3FatalError(pVCpu, rc);
4468 AssertMsgFailed(("EMR3FatalError returned!\n"));
4469}
4470
4471
4472/**
4473 * Dumps a linux system call.
4474 * @param pVCpu VMCPU handle.
4475 */
4476void remR3DumpLnxSyscall(PVMCPU pVCpu)
4477{
4478 static const char *apsz[] =
4479 {
4480 "sys_restart_syscall", /* 0 - old "setup()" system call, used for restarting */
4481 "sys_exit",
4482 "sys_fork",
4483 "sys_read",
4484 "sys_write",
4485 "sys_open", /* 5 */
4486 "sys_close",
4487 "sys_waitpid",
4488 "sys_creat",
4489 "sys_link",
4490 "sys_unlink", /* 10 */
4491 "sys_execve",
4492 "sys_chdir",
4493 "sys_time",
4494 "sys_mknod",
4495 "sys_chmod", /* 15 */
4496 "sys_lchown16",
4497 "sys_ni_syscall", /* old break syscall holder */
4498 "sys_stat",
4499 "sys_lseek",
4500 "sys_getpid", /* 20 */
4501 "sys_mount",
4502 "sys_oldumount",
4503 "sys_setuid16",
4504 "sys_getuid16",
4505 "sys_stime", /* 25 */
4506 "sys_ptrace",
4507 "sys_alarm",
4508 "sys_fstat",
4509 "sys_pause",
4510 "sys_utime", /* 30 */
4511 "sys_ni_syscall", /* old stty syscall holder */
4512 "sys_ni_syscall", /* old gtty syscall holder */
4513 "sys_access",
4514 "sys_nice",
4515 "sys_ni_syscall", /* 35 - old ftime syscall holder */
4516 "sys_sync",
4517 "sys_kill",
4518 "sys_rename",
4519 "sys_mkdir",
4520 "sys_rmdir", /* 40 */
4521 "sys_dup",
4522 "sys_pipe",
4523 "sys_times",
4524 "sys_ni_syscall", /* old prof syscall holder */
4525 "sys_brk", /* 45 */
4526 "sys_setgid16",
4527 "sys_getgid16",
4528 "sys_signal",
4529 "sys_geteuid16",
4530 "sys_getegid16", /* 50 */
4531 "sys_acct",
4532 "sys_umount", /* recycled never used phys() */
4533 "sys_ni_syscall", /* old lock syscall holder */
4534 "sys_ioctl",
4535 "sys_fcntl", /* 55 */
4536 "sys_ni_syscall", /* old mpx syscall holder */
4537 "sys_setpgid",
4538 "sys_ni_syscall", /* old ulimit syscall holder */
4539 "sys_olduname",
4540 "sys_umask", /* 60 */
4541 "sys_chroot",
4542 "sys_ustat",
4543 "sys_dup2",
4544 "sys_getppid",
4545 "sys_getpgrp", /* 65 */
4546 "sys_setsid",
4547 "sys_sigaction",
4548 "sys_sgetmask",
4549 "sys_ssetmask",
4550 "sys_setreuid16", /* 70 */
4551 "sys_setregid16",
4552 "sys_sigsuspend",
4553 "sys_sigpending",
4554 "sys_sethostname",
4555 "sys_setrlimit", /* 75 */
4556 "sys_old_getrlimit",
4557 "sys_getrusage",
4558 "sys_gettimeofday",
4559 "sys_settimeofday",
4560 "sys_getgroups16", /* 80 */
4561 "sys_setgroups16",
4562 "old_select",
4563 "sys_symlink",
4564 "sys_lstat",
4565 "sys_readlink", /* 85 */
4566 "sys_uselib",
4567 "sys_swapon",
4568 "sys_reboot",
4569 "old_readdir",
4570 "old_mmap", /* 90 */
4571 "sys_munmap",
4572 "sys_truncate",
4573 "sys_ftruncate",
4574 "sys_fchmod",
4575 "sys_fchown16", /* 95 */
4576 "sys_getpriority",
4577 "sys_setpriority",
4578 "sys_ni_syscall", /* old profil syscall holder */
4579 "sys_statfs",
4580 "sys_fstatfs", /* 100 */
4581 "sys_ioperm",
4582 "sys_socketcall",
4583 "sys_syslog",
4584 "sys_setitimer",
4585 "sys_getitimer", /* 105 */
4586 "sys_newstat",
4587 "sys_newlstat",
4588 "sys_newfstat",
4589 "sys_uname",
4590 "sys_iopl", /* 110 */
4591 "sys_vhangup",
4592 "sys_ni_syscall", /* old "idle" system call */
4593 "sys_vm86old",
4594 "sys_wait4",
4595 "sys_swapoff", /* 115 */
4596 "sys_sysinfo",
4597 "sys_ipc",
4598 "sys_fsync",
4599 "sys_sigreturn",
4600 "sys_clone", /* 120 */
4601 "sys_setdomainname",
4602 "sys_newuname",
4603 "sys_modify_ldt",
4604 "sys_adjtimex",
4605 "sys_mprotect", /* 125 */
4606 "sys_sigprocmask",
4607 "sys_ni_syscall", /* old "create_module" */
4608 "sys_init_module",
4609 "sys_delete_module",
4610 "sys_ni_syscall", /* 130: old "get_kernel_syms" */
4611 "sys_quotactl",
4612 "sys_getpgid",
4613 "sys_fchdir",
4614 "sys_bdflush",
4615 "sys_sysfs", /* 135 */
4616 "sys_personality",
4617 "sys_ni_syscall", /* reserved for afs_syscall */
4618 "sys_setfsuid16",
4619 "sys_setfsgid16",
4620 "sys_llseek", /* 140 */
4621 "sys_getdents",
4622 "sys_select",
4623 "sys_flock",
4624 "sys_msync",
4625 "sys_readv", /* 145 */
4626 "sys_writev",
4627 "sys_getsid",
4628 "sys_fdatasync",
4629 "sys_sysctl",
4630 "sys_mlock", /* 150 */
4631 "sys_munlock",
4632 "sys_mlockall",
4633 "sys_munlockall",
4634 "sys_sched_setparam",
4635 "sys_sched_getparam", /* 155 */
4636 "sys_sched_setscheduler",
4637 "sys_sched_getscheduler",
4638 "sys_sched_yield",
4639 "sys_sched_get_priority_max",
4640 "sys_sched_get_priority_min", /* 160 */
4641 "sys_sched_rr_get_interval",
4642 "sys_nanosleep",
4643 "sys_mremap",
4644 "sys_setresuid16",
4645 "sys_getresuid16", /* 165 */
4646 "sys_vm86",
4647 "sys_ni_syscall", /* Old sys_query_module */
4648 "sys_poll",
4649 "sys_nfsservctl",
4650 "sys_setresgid16", /* 170 */
4651 "sys_getresgid16",
4652 "sys_prctl",
4653 "sys_rt_sigreturn",
4654 "sys_rt_sigaction",
4655 "sys_rt_sigprocmask", /* 175 */
4656 "sys_rt_sigpending",
4657 "sys_rt_sigtimedwait",
4658 "sys_rt_sigqueueinfo",
4659 "sys_rt_sigsuspend",
4660 "sys_pread64", /* 180 */
4661 "sys_pwrite64",
4662 "sys_chown16",
4663 "sys_getcwd",
4664 "sys_capget",
4665 "sys_capset", /* 185 */
4666 "sys_sigaltstack",
4667 "sys_sendfile",
4668 "sys_ni_syscall", /* reserved for streams1 */
4669 "sys_ni_syscall", /* reserved for streams2 */
4670 "sys_vfork", /* 190 */
4671 "sys_getrlimit",
4672 "sys_mmap2",
4673 "sys_truncate64",
4674 "sys_ftruncate64",
4675 "sys_stat64", /* 195 */
4676 "sys_lstat64",
4677 "sys_fstat64",
4678 "sys_lchown",
4679 "sys_getuid",
4680 "sys_getgid", /* 200 */
4681 "sys_geteuid",
4682 "sys_getegid",
4683 "sys_setreuid",
4684 "sys_setregid",
4685 "sys_getgroups", /* 205 */
4686 "sys_setgroups",
4687 "sys_fchown",
4688 "sys_setresuid",
4689 "sys_getresuid",
4690 "sys_setresgid", /* 210 */
4691 "sys_getresgid",
4692 "sys_chown",
4693 "sys_setuid",
4694 "sys_setgid",
4695 "sys_setfsuid", /* 215 */
4696 "sys_setfsgid",
4697 "sys_pivot_root",
4698 "sys_mincore",
4699 "sys_madvise",
4700 "sys_getdents64", /* 220 */
4701 "sys_fcntl64",
4702 "sys_ni_syscall", /* reserved for TUX */
4703 "sys_ni_syscall",
4704 "sys_gettid",
4705 "sys_readahead", /* 225 */
4706 "sys_setxattr",
4707 "sys_lsetxattr",
4708 "sys_fsetxattr",
4709 "sys_getxattr",
4710 "sys_lgetxattr", /* 230 */
4711 "sys_fgetxattr",
4712 "sys_listxattr",
4713 "sys_llistxattr",
4714 "sys_flistxattr",
4715 "sys_removexattr", /* 235 */
4716 "sys_lremovexattr",
4717 "sys_fremovexattr",
4718 "sys_tkill",
4719 "sys_sendfile64",
4720 "sys_futex", /* 240 */
4721 "sys_sched_setaffinity",
4722 "sys_sched_getaffinity",
4723 "sys_set_thread_area",
4724 "sys_get_thread_area",
4725 "sys_io_setup", /* 245 */
4726 "sys_io_destroy",
4727 "sys_io_getevents",
4728 "sys_io_submit",
4729 "sys_io_cancel",
4730 "sys_fadvise64", /* 250 */
4731 "sys_ni_syscall",
4732 "sys_exit_group",
4733 "sys_lookup_dcookie",
4734 "sys_epoll_create",
4735 "sys_epoll_ctl", /* 255 */
4736 "sys_epoll_wait",
4737 "sys_remap_file_pages",
4738 "sys_set_tid_address",
4739 "sys_timer_create",
4740 "sys_timer_settime", /* 260 */
4741 "sys_timer_gettime",
4742 "sys_timer_getoverrun",
4743 "sys_timer_delete",
4744 "sys_clock_settime",
4745 "sys_clock_gettime", /* 265 */
4746 "sys_clock_getres",
4747 "sys_clock_nanosleep",
4748 "sys_statfs64",
4749 "sys_fstatfs64",
4750 "sys_tgkill", /* 270 */
4751 "sys_utimes",
4752 "sys_fadvise64_64",
4753 "sys_ni_syscall" /* sys_vserver */
4754 };
4755
4756 uint32_t uEAX = CPUMGetGuestEAX(pVCpu);
4757 switch (uEAX)
4758 {
4759 default:
4760 if (uEAX < RT_ELEMENTS(apsz))
4761 Log(("REM: linux syscall %3d: %s (eip=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x ebp=%08x)\n",
4762 uEAX, apsz[uEAX], CPUMGetGuestEIP(pVCpu), CPUMGetGuestEBX(pVCpu), CPUMGetGuestECX(pVCpu),
4763 CPUMGetGuestEDX(pVCpu), CPUMGetGuestESI(pVCpu), CPUMGetGuestEDI(pVCpu), CPUMGetGuestEBP(pVCpu)));
4764 else
4765 Log(("eip=%08x: linux syscall %d (#%x) unknown\n", CPUMGetGuestEIP(pVCpu), uEAX, uEAX));
4766 break;
4767
4768 }
4769}
4770
4771
4772/**
4773 * Dumps an OpenBSD system call.
4774 * @param pVCpu VMCPU handle.
4775 */
4776void remR3DumpOBsdSyscall(PVMCPU pVCpu)
4777{
4778 static const char *apsz[] =
4779 {
4780 "SYS_syscall", //0
4781 "SYS_exit", //1
4782 "SYS_fork", //2
4783 "SYS_read", //3
4784 "SYS_write", //4
4785 "SYS_open", //5
4786 "SYS_close", //6
4787 "SYS_wait4", //7
4788 "SYS_8",
4789 "SYS_link", //9
4790 "SYS_unlink", //10
4791 "SYS_11",
4792 "SYS_chdir", //12
4793 "SYS_fchdir", //13
4794 "SYS_mknod", //14
4795 "SYS_chmod", //15
4796 "SYS_chown", //16
4797 "SYS_break", //17
4798 "SYS_18",
4799 "SYS_19",
4800 "SYS_getpid", //20
4801 "SYS_mount", //21
4802 "SYS_unmount", //22
4803 "SYS_setuid", //23
4804 "SYS_getuid", //24
4805 "SYS_geteuid", //25
4806 "SYS_ptrace", //26
4807 "SYS_recvmsg", //27
4808 "SYS_sendmsg", //28
4809 "SYS_recvfrom", //29
4810 "SYS_accept", //30
4811 "SYS_getpeername", //31
4812 "SYS_getsockname", //32
4813 "SYS_access", //33
4814 "SYS_chflags", //34
4815 "SYS_fchflags", //35
4816 "SYS_sync", //36
4817 "SYS_kill", //37
4818 "SYS_38",
4819 "SYS_getppid", //39
4820 "SYS_40",
4821 "SYS_dup", //41
4822 "SYS_opipe", //42
4823 "SYS_getegid", //43
4824 "SYS_profil", //44
4825 "SYS_ktrace", //45
4826 "SYS_sigaction", //46
4827 "SYS_getgid", //47
4828 "SYS_sigprocmask", //48
4829 "SYS_getlogin", //49
4830 "SYS_setlogin", //50
4831 "SYS_acct", //51
4832 "SYS_sigpending", //52
4833 "SYS_osigaltstack", //53
4834 "SYS_ioctl", //54
4835 "SYS_reboot", //55
4836 "SYS_revoke", //56
4837 "SYS_symlink", //57
4838 "SYS_readlink", //58
4839 "SYS_execve", //59
4840 "SYS_umask", //60
4841 "SYS_chroot", //61
4842 "SYS_62",
4843 "SYS_63",
4844 "SYS_64",
4845 "SYS_65",
4846 "SYS_vfork", //66
4847 "SYS_67",
4848 "SYS_68",
4849 "SYS_sbrk", //69
4850 "SYS_sstk", //70
4851 "SYS_61",
4852 "SYS_vadvise", //72
4853 "SYS_munmap", //73
4854 "SYS_mprotect", //74
4855 "SYS_madvise", //75
4856 "SYS_76",
4857 "SYS_77",
4858 "SYS_mincore", //78
4859 "SYS_getgroups", //79
4860 "SYS_setgroups", //80
4861 "SYS_getpgrp", //81
4862 "SYS_setpgid", //82
4863 "SYS_setitimer", //83
4864 "SYS_84",
4865 "SYS_85",
4866 "SYS_getitimer", //86
4867 "SYS_87",
4868 "SYS_88",
4869 "SYS_89",
4870 "SYS_dup2", //90
4871 "SYS_91",
4872 "SYS_fcntl", //92
4873 "SYS_select", //93
4874 "SYS_94",
4875 "SYS_fsync", //95
4876 "SYS_setpriority", //96
4877 "SYS_socket", //97
4878 "SYS_connect", //98
4879 "SYS_99",
4880 "SYS_getpriority", //100
4881 "SYS_101",
4882 "SYS_102",
4883 "SYS_sigreturn", //103
4884 "SYS_bind", //104
4885 "SYS_setsockopt", //105
4886 "SYS_listen", //106
4887 "SYS_107",
4888 "SYS_108",
4889 "SYS_109",
4890 "SYS_110",
4891 "SYS_sigsuspend", //111
4892 "SYS_112",
4893 "SYS_113",
4894 "SYS_114",
4895 "SYS_115",
4896 "SYS_gettimeofday", //116
4897 "SYS_getrusage", //117
4898 "SYS_getsockopt", //118
4899 "SYS_119",
4900 "SYS_readv", //120
4901 "SYS_writev", //121
4902 "SYS_settimeofday", //122
4903 "SYS_fchown", //123
4904 "SYS_fchmod", //124
4905 "SYS_125",
4906 "SYS_setreuid", //126
4907 "SYS_setregid", //127
4908 "SYS_rename", //128
4909 "SYS_129",
4910 "SYS_130",
4911 "SYS_flock", //131
4912 "SYS_mkfifo", //132
4913 "SYS_sendto", //133
4914 "SYS_shutdown", //134
4915 "SYS_socketpair", //135
4916 "SYS_mkdir", //136
4917 "SYS_rmdir", //137
4918 "SYS_utimes", //138
4919 "SYS_139",
4920 "SYS_adjtime", //140
4921 "SYS_141",
4922 "SYS_142",
4923 "SYS_143",
4924 "SYS_144",
4925 "SYS_145",
4926 "SYS_146",
4927 "SYS_setsid", //147
4928 "SYS_quotactl", //148
4929 "SYS_149",
4930 "SYS_150",
4931 "SYS_151",
4932 "SYS_152",
4933 "SYS_153",
4934 "SYS_154",
4935 "SYS_nfssvc", //155
4936 "SYS_156",
4937 "SYS_157",
4938 "SYS_158",
4939 "SYS_159",
4940 "SYS_160",
4941 "SYS_getfh", //161
4942 "SYS_162",
4943 "SYS_163",
4944 "SYS_164",
4945 "SYS_sysarch", //165
4946 "SYS_166",
4947 "SYS_167",
4948 "SYS_168",
4949 "SYS_169",
4950 "SYS_170",
4951 "SYS_171",
4952 "SYS_172",
4953 "SYS_pread", //173
4954 "SYS_pwrite", //174
4955 "SYS_175",
4956 "SYS_176",
4957 "SYS_177",
4958 "SYS_178",
4959 "SYS_179",
4960 "SYS_180",
4961 "SYS_setgid", //181
4962 "SYS_setegid", //182
4963 "SYS_seteuid", //183
4964 "SYS_lfs_bmapv", //184
4965 "SYS_lfs_markv", //185
4966 "SYS_lfs_segclean", //186
4967 "SYS_lfs_segwait", //187
4968 "SYS_188",
4969 "SYS_189",
4970 "SYS_190",
4971 "SYS_pathconf", //191
4972 "SYS_fpathconf", //192
4973 "SYS_swapctl", //193
4974 "SYS_getrlimit", //194
4975 "SYS_setrlimit", //195
4976 "SYS_getdirentries", //196
4977 "SYS_mmap", //197
4978 "SYS___syscall", //198
4979 "SYS_lseek", //199
4980 "SYS_truncate", //200
4981 "SYS_ftruncate", //201
4982 "SYS___sysctl", //202
4983 "SYS_mlock", //203
4984 "SYS_munlock", //204
4985 "SYS_205",
4986 "SYS_futimes", //206
4987 "SYS_getpgid", //207
4988 "SYS_xfspioctl", //208
4989 "SYS_209",
4990 "SYS_210",
4991 "SYS_211",
4992 "SYS_212",
4993 "SYS_213",
4994 "SYS_214",
4995 "SYS_215",
4996 "SYS_216",
4997 "SYS_217",
4998 "SYS_218",
4999 "SYS_219",
5000 "SYS_220",
5001 "SYS_semget", //221
5002 "SYS_222",
5003 "SYS_223",
5004 "SYS_224",
5005 "SYS_msgget", //225
5006 "SYS_msgsnd", //226
5007 "SYS_msgrcv", //227
5008 "SYS_shmat", //228
5009 "SYS_229",
5010 "SYS_shmdt", //230
5011 "SYS_231",
5012 "SYS_clock_gettime", //232
5013 "SYS_clock_settime", //233
5014 "SYS_clock_getres", //234
5015 "SYS_235",
5016 "SYS_236",
5017 "SYS_237",
5018 "SYS_238",
5019 "SYS_239",
5020 "SYS_nanosleep", //240
5021 "SYS_241",
5022 "SYS_242",
5023 "SYS_243",
5024 "SYS_244",
5025 "SYS_245",
5026 "SYS_246",
5027 "SYS_247",
5028 "SYS_248",
5029 "SYS_249",
5030 "SYS_minherit", //250
5031 "SYS_rfork", //251
5032 "SYS_poll", //252
5033 "SYS_issetugid", //253
5034 "SYS_lchown", //254
5035 "SYS_getsid", //255
5036 "SYS_msync", //256
5037 "SYS_257",
5038 "SYS_258",
5039 "SYS_259",
5040 "SYS_getfsstat", //260
5041 "SYS_statfs", //261
5042 "SYS_fstatfs", //262
5043 "SYS_pipe", //263
5044 "SYS_fhopen", //264
5045 "SYS_265",
5046 "SYS_fhstatfs", //266
5047 "SYS_preadv", //267
5048 "SYS_pwritev", //268
5049 "SYS_kqueue", //269
5050 "SYS_kevent", //270
5051 "SYS_mlockall", //271
5052 "SYS_munlockall", //272
5053 "SYS_getpeereid", //273
5054 "SYS_274",
5055 "SYS_275",
5056 "SYS_276",
5057 "SYS_277",
5058 "SYS_278",
5059 "SYS_279",
5060 "SYS_280",
5061 "SYS_getresuid", //281
5062 "SYS_setresuid", //282
5063 "SYS_getresgid", //283
5064 "SYS_setresgid", //284
5065 "SYS_285",
5066 "SYS_mquery", //286
5067 "SYS_closefrom", //287
5068 "SYS_sigaltstack", //288
5069 "SYS_shmget", //289
5070 "SYS_semop", //290
5071 "SYS_stat", //291
5072 "SYS_fstat", //292
5073 "SYS_lstat", //293
5074 "SYS_fhstat", //294
5075 "SYS___semctl", //295
5076 "SYS_shmctl", //296
5077 "SYS_msgctl", //297
5078 "SYS_MAXSYSCALL", //298
5079 //299
5080 //300
5081 };
5082 uint32_t uEAX;
5083 if (!LogIsEnabled())
5084 return;
5085 uEAX = CPUMGetGuestEAX(pVCpu);
5086 switch (uEAX)
5087 {
5088 default:
5089 if (uEAX < RT_ELEMENTS(apsz))
5090 {
5091 uint32_t au32Args[8] = {0};
5092 PGMPhysSimpleReadGCPtr(pVCpu, au32Args, CPUMGetGuestESP(pVCpu), sizeof(au32Args));
5093 RTLogPrintf("REM: OpenBSD syscall %3d: %s (eip=%08x %08x %08x %08x %08x %08x %08x %08x %08x)\n",
5094 uEAX, apsz[uEAX], CPUMGetGuestEIP(pVCpu), au32Args[0], au32Args[1], au32Args[2], au32Args[3],
5095 au32Args[4], au32Args[5], au32Args[6], au32Args[7]);
5096 }
5097 else
5098 RTLogPrintf("eip=%08x: OpenBSD syscall %d (#%x) unknown!!\n", CPUMGetGuestEIP(pVCpu), uEAX, uEAX);
5099 break;
5100 }
5101}
5102
5103
5104#if defined(IPRT_NO_CRT) && defined(RT_OS_WINDOWS) && defined(RT_ARCH_X86)
5105/**
5106 * The Dll main entry point (stub).
5107 */
5108bool __stdcall _DllMainCRTStartup(void *hModule, uint32_t dwReason, void *pvReserved)
5109{
5110 return true;
5111}
5112
5113void *memcpy(void *dst, const void *src, size_t size)
5114{
5115 uint8_t*pbDst = dst, *pbSrc = src;
5116 while (size-- > 0)
5117 *pbDst++ = *pbSrc++;
5118 return dst;
5119}
5120
5121#endif
5122
5123void cpu_smm_update(CPUState *env)
5124{
5125}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette