VirtualBox

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

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

REM: Don't set cr2 and error_code when TRPM reports a pending software or hardware interrupt, only do that for traps. (hardware int 0eh causes trouble otherwise)

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