VirtualBox

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

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

VMM: HM cleanup.

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