VirtualBox

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

Last change on this file since 30453 was 30453, checked in by vboxsync, 14 years ago

DBGFR3DisasInstrEx: Flags for overriding the instruction set, adding u64, u32, u16 and uv86 to the debugger.

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