VirtualBox

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

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

DBGF,DBGC,++: PVM -> PUVM. Some refactoring and cleanup as well.

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