VirtualBox

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

Last change on this file since 47309 was 47309, checked in by vboxsync, 12 years ago

REM: Try set DESC_INTEL_UNUSED where applicable. Fixed values in DR6, mapped DR5 to DR7 and DR4 to DR6.

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