VirtualBox

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

Last change on this file since 45513 was 45485, checked in by vboxsync, 12 years ago
  • *: Where possible, drop the #ifdef VBOX_WITH_RAW_RING1 when EMIsRawRing1Enabled is used.
  • SELM: Don't shadow TSS.esp1/ss1 unless ring-1 compression is enabled (also fixed a log statement there).
  • SELM: selmGuestToShadowDesc should not push ring-1 selectors into ring-2 unless EMIsRawRing1Enabled() holds true.
  • REM: Don't set CPU_INTERRUPT_EXTERNAL_EXIT in helper_ltr() for now.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 181.7 KB
Line 
1/* $Id: VBoxRecompiler.c 45485 2013-04-11 14:46:04Z vboxsync $ */
2/** @file
3 * VBox Recompiler - QEMU.
4 */
5
6/*
7 * Copyright (C) 2006-2013 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_REM
23#include <stdio.h> /* FILE */
24#include "osdep.h"
25#include "config.h"
26#include "cpu.h"
27#include "exec-all.h"
28#include "ioport.h"
29
30#include <VBox/vmm/rem.h>
31#include <VBox/vmm/vmapi.h>
32#include <VBox/vmm/tm.h>
33#include <VBox/vmm/ssm.h>
34#include <VBox/vmm/em.h>
35#include <VBox/vmm/trpm.h>
36#include <VBox/vmm/iom.h>
37#include <VBox/vmm/mm.h>
38#include <VBox/vmm/pgm.h>
39#include <VBox/vmm/pdm.h>
40#include <VBox/vmm/dbgf.h>
41#include <VBox/dbg.h>
42#include <VBox/vmm/hm.h>
43#include <VBox/vmm/patm.h>
44#include <VBox/vmm/csam.h>
45#include "REMInternal.h"
46#include <VBox/vmm/vm.h>
47#include <VBox/vmm/uvm.h>
48#include <VBox/param.h>
49#include <VBox/err.h>
50
51#include <VBox/log.h>
52#include <iprt/semaphore.h>
53#include <iprt/asm.h>
54#include <iprt/assert.h>
55#include <iprt/thread.h>
56#include <iprt/string.h>
57
58/* Don't wanna include everything. */
59extern void cpu_exec_init_all(uintptr_t tb_size);
60extern void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3);
61extern void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0);
62extern void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4);
63extern void tlb_flush_page(CPUX86State *env, target_ulong addr);
64extern void tlb_flush(CPUX86State *env, int flush_global);
65extern void sync_seg(CPUX86State *env1, int seg_reg, int selector);
66extern void sync_ldtr(CPUX86State *env1, int selector);
67
68#ifdef VBOX_STRICT
69ram_addr_t get_phys_page_offset(target_ulong addr);
70#endif
71
72
73/*******************************************************************************
74* Defined Constants And Macros *
75*******************************************************************************/
76
77/** Copy 80-bit fpu register at pSrc to pDst.
78 * This is probably faster than *calling* memcpy.
79 */
80#define REM_COPY_FPU_REG(pDst, pSrc) \
81 do { *(PX86FPUMMX)(pDst) = *(const X86FPUMMX *)(pSrc); } while (0)
82
83/** How remR3RunLoggingStep operates. */
84#define REM_USE_QEMU_SINGLE_STEP_FOR_LOGGING
85
86
87/*******************************************************************************
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 *pvEnv, target_phys_addr_t GCPhys);
96static uint32_t remR3MMIOReadU16(void *pvEnv, target_phys_addr_t GCPhys);
97static uint32_t remR3MMIOReadU32(void *pvEnv, target_phys_addr_t GCPhys);
98static void remR3MMIOWriteU8(void *pvEnv, target_phys_addr_t GCPhys, uint32_t u32);
99static void remR3MMIOWriteU16(void *pvEnv, target_phys_addr_t GCPhys, uint32_t u32);
100static void remR3MMIOWriteU32(void *pvEnv, 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->rem.s.Env);
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 pc=%RGv\n", pVM->rem.s.Env.eip));
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 if (EMIsRawRing1Enabled(env->pVM))
1636 {
1637 /* Only ring 0 and 1 supervisor code. */
1638 if (((fFlags >> HF_CPL_SHIFT) & 3) == 2) /* ring 1 code is moved into ring 2, so we can't support ring-2 in that case. */
1639 {
1640 Log2(("raw r0 mode refused: CPL %d\n", (fFlags >> HF_CPL_SHIFT) & 3));
1641 return false;
1642 }
1643 }
1644 /* Only R0. */
1645 else if (((fFlags >> HF_CPL_SHIFT) & 3) != 0)
1646 {
1647 STAM_COUNTER_INC(&gStatRefuseRing1or2);
1648 Log2(("raw r0 mode refused: CPL %d\n", ((fFlags >> HF_CPL_SHIFT) & 3) ));
1649 return false;
1650 }
1651
1652 if (!(u32CR0 & CR0_WP_MASK))
1653 {
1654 STAM_COUNTER_INC(&gStatRefuseWP0);
1655 Log2(("raw r0 mode refused: CR0.WP=0!\n"));
1656 return false;
1657 }
1658
1659 if (PATMIsPatchGCAddr(env->pVM, eip))
1660 {
1661 Log2(("raw r0 mode forced: patch code\n"));
1662 *piException = EXCP_EXECUTE_RAW;
1663 return true;
1664 }
1665
1666#if !defined(VBOX_ALLOW_IF0) && !defined(VBOX_RUN_INTERRUPT_GATE_HANDLERS)
1667 if (!(env->eflags & IF_MASK))
1668 {
1669 STAM_COUNTER_INC(&gStatRefuseIF0);
1670 ////Log2(("R0: IF=0 VIF=%d %08X\n", eip, *env->pVMeflags));
1671 //Log2(("RR0: Interrupts turned off; fall back to emulation\n"));
1672 return false;
1673 }
1674#endif
1675
1676#ifndef VBOX_WITH_RAW_RING1
1677 if (((env->eflags >> IOPL_SHIFT) & 3) != 0)
1678 {
1679 Log2(("raw r0 mode refused: IOPL %d\n", ((env->eflags >> IOPL_SHIFT) & 3)));
1680 return false;
1681 }
1682#endif
1683 env->state |= CPU_RAW_RING0;
1684 }
1685
1686 /*
1687 * Don't reschedule the first time we're called, because there might be
1688 * special reasons why we're here that is not covered by the above checks.
1689 */
1690 if (env->pVM->rem.s.cCanExecuteRaw == 1)
1691 {
1692 Log2(("raw mode refused: first scheduling\n"));
1693 STAM_COUNTER_INC(&gStatRefuseCanExecute);
1694 return false;
1695 }
1696
1697 /*
1698 * Stale hidden selectors means raw-mode is unsafe (being very careful).
1699 */
1700 if (env->segs[R_CS].fVBoxFlags & CPUMSELREG_FLAGS_STALE)
1701 {
1702 Log2(("raw mode refused: stale CS (%#x)\n", env->segs[R_CS].selector));
1703 STAM_COUNTER_INC(&gaStatRefuseStale[R_CS]);
1704 return false;
1705 }
1706 if (env->segs[R_SS].fVBoxFlags & CPUMSELREG_FLAGS_STALE)
1707 {
1708 Log2(("raw mode refused: stale SS (%#x)\n", env->segs[R_SS].selector));
1709 STAM_COUNTER_INC(&gaStatRefuseStale[R_SS]);
1710 return false;
1711 }
1712 if (env->segs[R_DS].fVBoxFlags & CPUMSELREG_FLAGS_STALE)
1713 {
1714 Log2(("raw mode refused: stale DS (%#x)\n", env->segs[R_DS].selector));
1715 STAM_COUNTER_INC(&gaStatRefuseStale[R_DS]);
1716 return false;
1717 }
1718 if (env->segs[R_ES].fVBoxFlags & CPUMSELREG_FLAGS_STALE)
1719 {
1720 Log2(("raw mode refused: stale ES (%#x)\n", env->segs[R_ES].selector));
1721 STAM_COUNTER_INC(&gaStatRefuseStale[R_ES]);
1722 return false;
1723 }
1724 if (env->segs[R_FS].fVBoxFlags & CPUMSELREG_FLAGS_STALE)
1725 {
1726 Log2(("raw mode refused: stale FS (%#x)\n", env->segs[R_FS].selector));
1727 STAM_COUNTER_INC(&gaStatRefuseStale[R_FS]);
1728 return false;
1729 }
1730 if (env->segs[R_GS].fVBoxFlags & CPUMSELREG_FLAGS_STALE)
1731 {
1732 Log2(("raw mode refused: stale GS (%#x)\n", env->segs[R_GS].selector));
1733 STAM_COUNTER_INC(&gaStatRefuseStale[R_GS]);
1734 return false;
1735 }
1736
1737/* Assert(env->pVCpu && PGMPhysIsA20Enabled(env->pVCpu));*/
1738 *piException = EXCP_EXECUTE_RAW;
1739 return true;
1740}
1741
1742
1743/**
1744 * Fetches a code byte.
1745 *
1746 * @returns Success indicator (bool) for ease of use.
1747 * @param env The CPU environment structure.
1748 * @param GCPtrInstr Where to fetch code.
1749 * @param pu8Byte Where to store the byte on success
1750 */
1751bool remR3GetOpcode(CPUX86State *env, RTGCPTR GCPtrInstr, uint8_t *pu8Byte)
1752{
1753 int rc = PATMR3QueryOpcode(env->pVM, GCPtrInstr, pu8Byte);
1754 if (RT_SUCCESS(rc))
1755 return true;
1756 return false;
1757}
1758
1759
1760/**
1761 * Flush (or invalidate if you like) page table/dir entry.
1762 *
1763 * (invlpg instruction; tlb_flush_page)
1764 *
1765 * @param env Pointer to cpu environment.
1766 * @param GCPtr The virtual address which page table/dir entry should be invalidated.
1767 */
1768void remR3FlushPage(CPUX86State *env, RTGCPTR GCPtr)
1769{
1770 PVM pVM = env->pVM;
1771 PCPUMCTX pCtx;
1772 int rc;
1773
1774 Assert(EMRemIsLockOwner(env->pVM));
1775
1776 /*
1777 * When we're replaying invlpg instructions or restoring a saved
1778 * state we disable this path.
1779 */
1780 if (pVM->rem.s.fIgnoreInvlPg || pVM->rem.s.cIgnoreAll)
1781 return;
1782 LogFlow(("remR3FlushPage: GCPtr=%RGv\n", GCPtr));
1783 Assert(pVM->rem.s.fInREM || pVM->rem.s.fInStateSync);
1784
1785 //RAWEx_ProfileStop(env, STATS_QEMU_TOTAL);
1786
1787 /*
1788 * Update the control registers before calling PGMFlushPage.
1789 */
1790 pCtx = (PCPUMCTX)pVM->rem.s.pCtx;
1791 Assert(pCtx);
1792 pCtx->cr0 = env->cr[0];
1793 pCtx->cr3 = env->cr[3];
1794 if ((env->cr[4] ^ pCtx->cr4) & X86_CR4_VME)
1795 VMCPU_FF_SET(env->pVCpu, VMCPU_FF_SELM_SYNC_TSS);
1796 pCtx->cr4 = env->cr[4];
1797
1798 /*
1799 * Let PGM do the rest.
1800 */
1801 Assert(env->pVCpu);
1802 rc = PGMInvalidatePage(env->pVCpu, GCPtr);
1803 if (RT_FAILURE(rc))
1804 {
1805 AssertMsgFailed(("remR3FlushPage %RGv failed with %d!!\n", GCPtr, rc));
1806 VMCPU_FF_SET(env->pVCpu, VMCPU_FF_PGM_SYNC_CR3);
1807 }
1808 //RAWEx_ProfileStart(env, STATS_QEMU_TOTAL);
1809}
1810
1811
1812#ifndef REM_PHYS_ADDR_IN_TLB
1813/** Wrapper for PGMR3PhysTlbGCPhys2Ptr. */
1814void *remR3TlbGCPhys2Ptr(CPUX86State *env1, target_ulong physAddr, int fWritable)
1815{
1816 void *pv;
1817 int rc;
1818
1819
1820 /* Address must be aligned enough to fiddle with lower bits */
1821 Assert((physAddr & 0x3) == 0);
1822 /*AssertMsg((env1->a20_mask & physAddr) == physAddr, ("%llx\n", (uint64_t)physAddr));*/
1823
1824 STAM_PROFILE_START(&gStatGCPhys2HCVirt, a);
1825 rc = PGMR3PhysTlbGCPhys2Ptr(env1->pVM, physAddr, true /*fWritable*/, &pv);
1826 STAM_PROFILE_STOP(&gStatGCPhys2HCVirt, a);
1827 Assert( rc == VINF_SUCCESS
1828 || rc == VINF_PGM_PHYS_TLB_CATCH_WRITE
1829 || rc == VERR_PGM_PHYS_TLB_CATCH_ALL
1830 || rc == VERR_PGM_PHYS_TLB_UNASSIGNED);
1831 if (RT_FAILURE(rc))
1832 return (void *)1;
1833 if (rc == VINF_PGM_PHYS_TLB_CATCH_WRITE)
1834 return (void *)((uintptr_t)pv | 2);
1835 return pv;
1836}
1837#endif /* REM_PHYS_ADDR_IN_TLB */
1838
1839
1840/**
1841 * Called from tlb_protect_code in order to write monitor a code page.
1842 *
1843 * @param env Pointer to the CPU environment.
1844 * @param GCPtr Code page to monitor
1845 */
1846void remR3ProtectCode(CPUX86State *env, RTGCPTR GCPtr)
1847{
1848#ifdef VBOX_REM_PROTECT_PAGES_FROM_SMC
1849 Assert(env->pVM->rem.s.fInREM);
1850 if ( (env->cr[0] & X86_CR0_PG) /* paging must be enabled */
1851 && !(env->state & CPU_EMULATE_SINGLE_INSTR) /* ignore during single instruction execution */
1852 && (((env->hflags >> HF_CPL_SHIFT) & 3) == 0) /* supervisor mode only */
1853 && !(env->eflags & VM_MASK) /* no V86 mode */
1854 && !HMIsEnabled(env->pVM))
1855 CSAMR3MonitorPage(env->pVM, GCPtr, CSAM_TAG_REM);
1856#endif
1857}
1858
1859
1860/**
1861 * Called from tlb_unprotect_code in order to clear write monitoring for a code page.
1862 *
1863 * @param env Pointer to the CPU environment.
1864 * @param GCPtr Code page to monitor
1865 */
1866void remR3UnprotectCode(CPUX86State *env, RTGCPTR GCPtr)
1867{
1868 Assert(env->pVM->rem.s.fInREM);
1869#ifdef VBOX_REM_PROTECT_PAGES_FROM_SMC
1870 if ( (env->cr[0] & X86_CR0_PG) /* paging must be enabled */
1871 && !(env->state & CPU_EMULATE_SINGLE_INSTR) /* ignore during single instruction execution */
1872 && (((env->hflags >> HF_CPL_SHIFT) & 3) == 0) /* supervisor mode only */
1873 && !(env->eflags & VM_MASK) /* no V86 mode */
1874 && !HMIsEnabled(env->pVM))
1875 CSAMR3UnmonitorPage(env->pVM, GCPtr, CSAM_TAG_REM);
1876#endif
1877}
1878
1879
1880/**
1881 * Called when the CPU is initialized, any of the CRx registers are changed or
1882 * when the A20 line is modified.
1883 *
1884 * @param env Pointer to the CPU environment.
1885 * @param fGlobal Set if the flush is global.
1886 */
1887void remR3FlushTLB(CPUX86State *env, bool fGlobal)
1888{
1889 PVM pVM = env->pVM;
1890 PCPUMCTX pCtx;
1891 Assert(EMRemIsLockOwner(pVM));
1892
1893 /*
1894 * When we're replaying invlpg instructions or restoring a saved
1895 * state we disable this path.
1896 */
1897 if (pVM->rem.s.fIgnoreCR3Load || pVM->rem.s.cIgnoreAll)
1898 return;
1899 Assert(pVM->rem.s.fInREM);
1900
1901 /*
1902 * The caller doesn't check cr4, so we have to do that for ourselves.
1903 */
1904 if (!fGlobal && !(env->cr[4] & X86_CR4_PGE))
1905 fGlobal = true;
1906 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" : ""));
1907
1908 /*
1909 * Update the control registers before calling PGMR3FlushTLB.
1910 */
1911 pCtx = (PCPUMCTX)pVM->rem.s.pCtx;
1912 Assert(pCtx);
1913 pCtx->cr0 = env->cr[0];
1914 pCtx->cr3 = env->cr[3];
1915 if ((env->cr[4] ^ pCtx->cr4) & X86_CR4_VME)
1916 VMCPU_FF_SET(env->pVCpu, VMCPU_FF_SELM_SYNC_TSS);
1917 pCtx->cr4 = env->cr[4];
1918
1919 /*
1920 * Let PGM do the rest.
1921 */
1922 Assert(env->pVCpu);
1923 PGMFlushTLB(env->pVCpu, env->cr[3], fGlobal);
1924}
1925
1926
1927/**
1928 * Called when any of the cr0, cr4 or efer registers is updated.
1929 *
1930 * @param env Pointer to the CPU environment.
1931 */
1932void remR3ChangeCpuMode(CPUX86State *env)
1933{
1934 PVM pVM = env->pVM;
1935 uint64_t efer;
1936 PCPUMCTX pCtx;
1937 int rc;
1938
1939 /*
1940 * When we're replaying loads or restoring a saved
1941 * state this path is disabled.
1942 */
1943 if (pVM->rem.s.fIgnoreCpuMode || pVM->rem.s.cIgnoreAll)
1944 return;
1945 Assert(pVM->rem.s.fInREM);
1946
1947 /*
1948 * Update the control registers before calling PGMChangeMode()
1949 * as it may need to map whatever cr3 is pointing to.
1950 */
1951 pCtx = (PCPUMCTX)pVM->rem.s.pCtx;
1952 Assert(pCtx);
1953 pCtx->cr0 = env->cr[0];
1954 pCtx->cr3 = env->cr[3];
1955 if ((env->cr[4] ^ pCtx->cr4) & X86_CR4_VME)
1956 VMCPU_FF_SET(env->pVCpu, VMCPU_FF_SELM_SYNC_TSS);
1957 pCtx->cr4 = env->cr[4];
1958#ifdef TARGET_X86_64
1959 efer = env->efer;
1960 pCtx->msrEFER = efer;
1961#else
1962 efer = 0;
1963#endif
1964 Assert(env->pVCpu);
1965 rc = PGMChangeMode(env->pVCpu, env->cr[0], env->cr[4], efer);
1966 if (rc != VINF_SUCCESS)
1967 {
1968 if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
1969 {
1970 Log(("PGMChangeMode(, %RX64, %RX64, %RX64) -> %Rrc -> remR3RaiseRC\n", env->cr[0], env->cr[4], efer, rc));
1971 remR3RaiseRC(env->pVM, rc);
1972 }
1973 else
1974 cpu_abort(env, "PGMChangeMode(, %RX64, %RX64, %RX64) -> %Rrc\n", env->cr[0], env->cr[4], efer, rc);
1975 }
1976}
1977
1978
1979/**
1980 * Called from compiled code to run dma.
1981 *
1982 * @param env Pointer to the CPU environment.
1983 */
1984void remR3DmaRun(CPUX86State *env)
1985{
1986 remR3ProfileStop(STATS_QEMU_RUN_EMULATED_CODE);
1987 PDMR3DmaRun(env->pVM);
1988 remR3ProfileStart(STATS_QEMU_RUN_EMULATED_CODE);
1989}
1990
1991
1992/**
1993 * Called from compiled code to schedule pending timers in VMM
1994 *
1995 * @param env Pointer to the CPU environment.
1996 */
1997void remR3TimersRun(CPUX86State *env)
1998{
1999 LogFlow(("remR3TimersRun:\n"));
2000 LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_5, LOG_GROUP_TM, ("remR3TimersRun\n"));
2001 remR3ProfileStop(STATS_QEMU_RUN_EMULATED_CODE);
2002 remR3ProfileStart(STATS_QEMU_RUN_TIMERS);
2003 TMR3TimerQueuesDo(env->pVM);
2004 remR3ProfileStop(STATS_QEMU_RUN_TIMERS);
2005 remR3ProfileStart(STATS_QEMU_RUN_EMULATED_CODE);
2006}
2007
2008
2009/**
2010 * Record trap occurrence
2011 *
2012 * @returns VBox status code
2013 * @param env Pointer to the CPU environment.
2014 * @param uTrap Trap nr
2015 * @param uErrorCode Error code
2016 * @param pvNextEIP Next EIP
2017 */
2018int remR3NotifyTrap(CPUX86State *env, uint32_t uTrap, uint32_t uErrorCode, RTGCPTR pvNextEIP)
2019{
2020 PVM pVM = env->pVM;
2021#ifdef VBOX_WITH_STATISTICS
2022 static STAMCOUNTER s_aStatTrap[255];
2023 static bool s_aRegisters[RT_ELEMENTS(s_aStatTrap)];
2024#endif
2025
2026#ifdef VBOX_WITH_STATISTICS
2027 if (uTrap < 255)
2028 {
2029 if (!s_aRegisters[uTrap])
2030 {
2031 char szStatName[64];
2032 s_aRegisters[uTrap] = true;
2033 RTStrPrintf(szStatName, sizeof(szStatName), "/REM/Trap/0x%02X", uTrap);
2034 STAM_REG(env->pVM, &s_aStatTrap[uTrap], STAMTYPE_COUNTER, szStatName, STAMUNIT_OCCURENCES, "Trap stats.");
2035 }
2036 STAM_COUNTER_INC(&s_aStatTrap[uTrap]);
2037 }
2038#endif
2039 Log(("remR3NotifyTrap: uTrap=%x error=%x next_eip=%RGv eip=%RGv cr2=%RGv\n", uTrap, uErrorCode, pvNextEIP, (RTGCPTR)env->eip, (RTGCPTR)env->cr[2]));
2040 if( uTrap < 0x20
2041 && (env->cr[0] & X86_CR0_PE)
2042 && !(env->eflags & X86_EFL_VM))
2043 {
2044#ifdef DEBUG
2045 remR3DisasInstr(env, 1, "remR3NotifyTrap: ");
2046#endif
2047 if(pVM->rem.s.uPendingException == uTrap && ++pVM->rem.s.cPendingExceptions > 512)
2048 {
2049 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]));
2050 remR3RaiseRC(env->pVM, VERR_REM_TOO_MANY_TRAPS);
2051 return VERR_REM_TOO_MANY_TRAPS;
2052 }
2053 if(pVM->rem.s.uPendingException != uTrap || pVM->rem.s.uPendingExcptEIP != env->eip || pVM->rem.s.uPendingExcptCR2 != env->cr[2])
2054 pVM->rem.s.cPendingExceptions = 1;
2055 pVM->rem.s.uPendingException = uTrap;
2056 pVM->rem.s.uPendingExcptEIP = env->eip;
2057 pVM->rem.s.uPendingExcptCR2 = env->cr[2];
2058 }
2059 else
2060 {
2061 pVM->rem.s.cPendingExceptions = 0;
2062 pVM->rem.s.uPendingException = uTrap;
2063 pVM->rem.s.uPendingExcptEIP = env->eip;
2064 pVM->rem.s.uPendingExcptCR2 = env->cr[2];
2065 }
2066 return VINF_SUCCESS;
2067}
2068
2069
2070/*
2071 * Clear current active trap
2072 *
2073 * @param pVM VM Handle.
2074 */
2075void remR3TrapClear(PVM pVM)
2076{
2077 pVM->rem.s.cPendingExceptions = 0;
2078 pVM->rem.s.uPendingException = 0;
2079 pVM->rem.s.uPendingExcptEIP = 0;
2080 pVM->rem.s.uPendingExcptCR2 = 0;
2081}
2082
2083
2084/*
2085 * Record previous call instruction addresses
2086 *
2087 * @param env Pointer to the CPU environment.
2088 */
2089void remR3RecordCall(CPUX86State *env)
2090{
2091 CSAMR3RecordCallAddress(env->pVM, env->eip);
2092}
2093
2094
2095/**
2096 * Syncs the internal REM state with the VM.
2097 *
2098 * This must be called before REMR3Run() is invoked whenever when the REM
2099 * state is not up to date. Calling it several times in a row is not
2100 * permitted.
2101 *
2102 * @returns VBox status code.
2103 *
2104 * @param pVM VM Handle.
2105 * @param pVCpu VMCPU Handle.
2106 *
2107 * @remark The caller has to check for important FFs before calling REMR3Run. REMR3State will
2108 * no do this since the majority of the callers don't want any unnecessary of events
2109 * pending that would immediately interrupt execution.
2110 */
2111REMR3DECL(int) REMR3State(PVM pVM, PVMCPU pVCpu)
2112{
2113 register const CPUMCTX *pCtx;
2114 register unsigned fFlags;
2115 unsigned i;
2116 TRPMEVENT enmType;
2117 uint8_t u8TrapNo;
2118 uint32_t uCpl;
2119 int rc;
2120
2121 STAM_PROFILE_START(&pVM->rem.s.StatsState, a);
2122 Log2(("REMR3State:\n"));
2123
2124 pVM->rem.s.Env.pVCpu = pVCpu;
2125 pCtx = pVM->rem.s.pCtx = CPUMQueryGuestCtxPtr(pVCpu);
2126
2127 Assert(!pVM->rem.s.fInREM);
2128 pVM->rem.s.fInStateSync = true;
2129
2130 /*
2131 * If we have to flush TBs, do that immediately.
2132 */
2133 if (pVM->rem.s.fFlushTBs)
2134 {
2135 STAM_COUNTER_INC(&gStatFlushTBs);
2136 tb_flush(&pVM->rem.s.Env);
2137 pVM->rem.s.fFlushTBs = false;
2138 }
2139
2140 /*
2141 * Copy the registers which require no special handling.
2142 */
2143#ifdef TARGET_X86_64
2144 /* Note that the high dwords of 64 bits registers are undefined in 32 bits mode and are undefined after a mode change. */
2145 Assert(R_EAX == 0);
2146 pVM->rem.s.Env.regs[R_EAX] = pCtx->rax;
2147 Assert(R_ECX == 1);
2148 pVM->rem.s.Env.regs[R_ECX] = pCtx->rcx;
2149 Assert(R_EDX == 2);
2150 pVM->rem.s.Env.regs[R_EDX] = pCtx->rdx;
2151 Assert(R_EBX == 3);
2152 pVM->rem.s.Env.regs[R_EBX] = pCtx->rbx;
2153 Assert(R_ESP == 4);
2154 pVM->rem.s.Env.regs[R_ESP] = pCtx->rsp;
2155 Assert(R_EBP == 5);
2156 pVM->rem.s.Env.regs[R_EBP] = pCtx->rbp;
2157 Assert(R_ESI == 6);
2158 pVM->rem.s.Env.regs[R_ESI] = pCtx->rsi;
2159 Assert(R_EDI == 7);
2160 pVM->rem.s.Env.regs[R_EDI] = pCtx->rdi;
2161 pVM->rem.s.Env.regs[8] = pCtx->r8;
2162 pVM->rem.s.Env.regs[9] = pCtx->r9;
2163 pVM->rem.s.Env.regs[10] = pCtx->r10;
2164 pVM->rem.s.Env.regs[11] = pCtx->r11;
2165 pVM->rem.s.Env.regs[12] = pCtx->r12;
2166 pVM->rem.s.Env.regs[13] = pCtx->r13;
2167 pVM->rem.s.Env.regs[14] = pCtx->r14;
2168 pVM->rem.s.Env.regs[15] = pCtx->r15;
2169
2170 pVM->rem.s.Env.eip = pCtx->rip;
2171
2172 pVM->rem.s.Env.eflags = pCtx->rflags.u64;
2173#else
2174 Assert(R_EAX == 0);
2175 pVM->rem.s.Env.regs[R_EAX] = pCtx->eax;
2176 Assert(R_ECX == 1);
2177 pVM->rem.s.Env.regs[R_ECX] = pCtx->ecx;
2178 Assert(R_EDX == 2);
2179 pVM->rem.s.Env.regs[R_EDX] = pCtx->edx;
2180 Assert(R_EBX == 3);
2181 pVM->rem.s.Env.regs[R_EBX] = pCtx->ebx;
2182 Assert(R_ESP == 4);
2183 pVM->rem.s.Env.regs[R_ESP] = pCtx->esp;
2184 Assert(R_EBP == 5);
2185 pVM->rem.s.Env.regs[R_EBP] = pCtx->ebp;
2186 Assert(R_ESI == 6);
2187 pVM->rem.s.Env.regs[R_ESI] = pCtx->esi;
2188 Assert(R_EDI == 7);
2189 pVM->rem.s.Env.regs[R_EDI] = pCtx->edi;
2190 pVM->rem.s.Env.eip = pCtx->eip;
2191
2192 pVM->rem.s.Env.eflags = pCtx->eflags.u32;
2193#endif
2194
2195 pVM->rem.s.Env.cr[2] = pCtx->cr2;
2196
2197 /** @todo we could probably benefit from using a CPUM_CHANGED_DRx flag too! */
2198 for (i=0;i<8;i++)
2199 pVM->rem.s.Env.dr[i] = pCtx->dr[i];
2200
2201#ifdef HF_HALTED_MASK /** @todo remove me when we're up to date again. */
2202 /*
2203 * Clear the halted hidden flag (the interrupt waking up the CPU can
2204 * have been dispatched in raw mode).
2205 */
2206 pVM->rem.s.Env.hflags &= ~HF_HALTED_MASK;
2207#endif
2208
2209 /*
2210 * Replay invlpg? Only if we're not flushing the TLB.
2211 */
2212 fFlags = CPUMR3RemEnter(pVCpu, &uCpl);
2213 LogFlow(("CPUMR3RemEnter %x %x\n", fFlags, uCpl));
2214 if (pVM->rem.s.cInvalidatedPages)
2215 {
2216 if (!(fFlags & CPUM_CHANGED_GLOBAL_TLB_FLUSH))
2217 {
2218 RTUINT i;
2219
2220 pVM->rem.s.fIgnoreCR3Load = true;
2221 pVM->rem.s.fIgnoreInvlPg = true;
2222 for (i = 0; i < pVM->rem.s.cInvalidatedPages; i++)
2223 {
2224 Log2(("REMR3State: invlpg %RGv\n", pVM->rem.s.aGCPtrInvalidatedPages[i]));
2225 tlb_flush_page(&pVM->rem.s.Env, pVM->rem.s.aGCPtrInvalidatedPages[i]);
2226 }
2227 pVM->rem.s.fIgnoreInvlPg = false;
2228 pVM->rem.s.fIgnoreCR3Load = false;
2229 }
2230 pVM->rem.s.cInvalidatedPages = 0;
2231 }
2232
2233 /* Replay notification changes. */
2234 REMR3ReplayHandlerNotifications(pVM);
2235
2236 /* Update MSRs; before CRx registers! */
2237 pVM->rem.s.Env.efer = pCtx->msrEFER;
2238 pVM->rem.s.Env.star = pCtx->msrSTAR;
2239 pVM->rem.s.Env.pat = pCtx->msrPAT;
2240#ifdef TARGET_X86_64
2241 pVM->rem.s.Env.lstar = pCtx->msrLSTAR;
2242 pVM->rem.s.Env.cstar = pCtx->msrCSTAR;
2243 pVM->rem.s.Env.fmask = pCtx->msrSFMASK;
2244 pVM->rem.s.Env.kernelgsbase = pCtx->msrKERNELGSBASE;
2245
2246 /* Update the internal long mode activate flag according to the new EFER value. */
2247 if (pCtx->msrEFER & MSR_K6_EFER_LMA)
2248 pVM->rem.s.Env.hflags |= HF_LMA_MASK;
2249 else
2250 pVM->rem.s.Env.hflags &= ~(HF_LMA_MASK | HF_CS64_MASK);
2251#endif
2252
2253 /* Update the inhibit IRQ mask. */
2254 pVM->rem.s.Env.hflags &= ~HF_INHIBIT_IRQ_MASK;
2255 if (VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
2256 {
2257 RTGCPTR InhibitPC = EMGetInhibitInterruptsPC(pVCpu);
2258 if (InhibitPC == pCtx->rip)
2259 pVM->rem.s.Env.hflags |= HF_INHIBIT_IRQ_MASK;
2260 else
2261 {
2262 Log(("Clearing VMCPU_FF_INHIBIT_INTERRUPTS at %RGv - successor %RGv (REM#1)\n", (RTGCPTR)pCtx->rip, InhibitPC));
2263 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
2264 }
2265 }
2266
2267 /*
2268 * Sync the A20 gate.
2269 */
2270 bool fA20State = PGMPhysIsA20Enabled(pVCpu);
2271 if (fA20State != RT_BOOL(pVM->rem.s.Env.a20_mask & RT_BIT(20)))
2272 {
2273 ASMAtomicIncU32(&pVM->rem.s.cIgnoreAll);
2274 cpu_x86_set_a20(&pVM->rem.s.Env, fA20State);
2275 ASMAtomicDecU32(&pVM->rem.s.cIgnoreAll);
2276 }
2277
2278 /*
2279 * Registers which are rarely changed and require special handling / order when changed.
2280 */
2281 if (fFlags & ( CPUM_CHANGED_GLOBAL_TLB_FLUSH
2282 | CPUM_CHANGED_CR4
2283 | CPUM_CHANGED_CR0
2284 | CPUM_CHANGED_CR3
2285 | CPUM_CHANGED_GDTR
2286 | CPUM_CHANGED_IDTR
2287 | CPUM_CHANGED_SYSENTER_MSR
2288 | CPUM_CHANGED_LDTR
2289 | CPUM_CHANGED_CPUID
2290 | CPUM_CHANGED_FPU_REM
2291 )
2292 )
2293 {
2294 if (fFlags & CPUM_CHANGED_GLOBAL_TLB_FLUSH)
2295 {
2296 pVM->rem.s.fIgnoreCR3Load = true;
2297 tlb_flush(&pVM->rem.s.Env, true);
2298 pVM->rem.s.fIgnoreCR3Load = false;
2299 }
2300
2301 /* CR4 before CR0! */
2302 if (fFlags & CPUM_CHANGED_CR4)
2303 {
2304 pVM->rem.s.fIgnoreCR3Load = true;
2305 pVM->rem.s.fIgnoreCpuMode = true;
2306 cpu_x86_update_cr4(&pVM->rem.s.Env, pCtx->cr4);
2307 pVM->rem.s.fIgnoreCpuMode = false;
2308 pVM->rem.s.fIgnoreCR3Load = false;
2309 }
2310
2311 if (fFlags & CPUM_CHANGED_CR0)
2312 {
2313 pVM->rem.s.fIgnoreCR3Load = true;
2314 pVM->rem.s.fIgnoreCpuMode = true;
2315 cpu_x86_update_cr0(&pVM->rem.s.Env, pCtx->cr0);
2316 pVM->rem.s.fIgnoreCpuMode = false;
2317 pVM->rem.s.fIgnoreCR3Load = false;
2318 }
2319
2320 if (fFlags & CPUM_CHANGED_CR3)
2321 {
2322 pVM->rem.s.fIgnoreCR3Load = true;
2323 cpu_x86_update_cr3(&pVM->rem.s.Env, pCtx->cr3);
2324 pVM->rem.s.fIgnoreCR3Load = false;
2325 }
2326
2327 if (fFlags & CPUM_CHANGED_GDTR)
2328 {
2329 pVM->rem.s.Env.gdt.base = pCtx->gdtr.pGdt;
2330 pVM->rem.s.Env.gdt.limit = pCtx->gdtr.cbGdt;
2331 }
2332
2333 if (fFlags & CPUM_CHANGED_IDTR)
2334 {
2335 pVM->rem.s.Env.idt.base = pCtx->idtr.pIdt;
2336 pVM->rem.s.Env.idt.limit = pCtx->idtr.cbIdt;
2337 }
2338
2339 if (fFlags & CPUM_CHANGED_SYSENTER_MSR)
2340 {
2341 pVM->rem.s.Env.sysenter_cs = pCtx->SysEnter.cs;
2342 pVM->rem.s.Env.sysenter_eip = pCtx->SysEnter.eip;
2343 pVM->rem.s.Env.sysenter_esp = pCtx->SysEnter.esp;
2344 }
2345
2346 if (fFlags & CPUM_CHANGED_LDTR)
2347 {
2348 if (pCtx->ldtr.fFlags & CPUMSELREG_FLAGS_VALID)
2349 {
2350 pVM->rem.s.Env.ldt.selector = pCtx->ldtr.Sel;
2351 pVM->rem.s.Env.ldt.newselector = 0;
2352 pVM->rem.s.Env.ldt.fVBoxFlags = pCtx->ldtr.fFlags;
2353 pVM->rem.s.Env.ldt.base = pCtx->ldtr.u64Base;
2354 pVM->rem.s.Env.ldt.limit = pCtx->ldtr.u32Limit;
2355 pVM->rem.s.Env.ldt.flags = (pCtx->ldtr.Attr.u << 8) & 0xFFFFFF;
2356 }
2357 else
2358 {
2359 AssertFailed(); /* Shouldn't happen, see cpumR3LoadExec. */
2360 sync_ldtr(&pVM->rem.s.Env, pCtx->ldtr.Sel);
2361 }
2362 }
2363
2364 if (fFlags & CPUM_CHANGED_CPUID)
2365 {
2366 uint32_t u32Dummy;
2367
2368 /*
2369 * Get the CPUID features.
2370 */
2371 CPUMGetGuestCpuId(pVCpu, 1, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext_features, &pVM->rem.s.Env.cpuid_features);
2372 CPUMGetGuestCpuId(pVCpu, 0x80000001, &u32Dummy, &u32Dummy, &u32Dummy, &pVM->rem.s.Env.cpuid_ext2_features);
2373 }
2374
2375 /* Sync FPU state after CR4, CPUID and EFER (!). */
2376 if (fFlags & CPUM_CHANGED_FPU_REM)
2377 save_raw_fp_state(&pVM->rem.s.Env, (uint8_t *)&pCtx->fpu); /* 'save' is an excellent name. */
2378 }
2379
2380 /*
2381 * Sync TR unconditionally to make life simpler.
2382 */
2383 pVM->rem.s.Env.tr.selector = pCtx->tr.Sel;
2384 pVM->rem.s.Env.tr.newselector = 0;
2385 pVM->rem.s.Env.tr.fVBoxFlags = pCtx->tr.fFlags;
2386 pVM->rem.s.Env.tr.base = pCtx->tr.u64Base;
2387 pVM->rem.s.Env.tr.limit = pCtx->tr.u32Limit;
2388 pVM->rem.s.Env.tr.flags = (pCtx->tr.Attr.u << 8) & 0xFFFFFF;
2389 /* Note! do_interrupt will fault if the busy flag is still set... */
2390 pVM->rem.s.Env.tr.flags &= ~DESC_TSS_BUSY_MASK;
2391
2392 /*
2393 * Update selector registers.
2394 *
2395 * This must be done *after* we've synced gdt, ldt and crX registers
2396 * since we're reading the GDT/LDT om sync_seg. This will happen with
2397 * saved state which takes a quick dip into rawmode for instance.
2398 *
2399 * CPL/Stack; Note first check this one as the CPL might have changed.
2400 * The wrong CPL can cause QEmu to raise an exception in sync_seg!!
2401 */
2402 cpu_x86_set_cpl(&pVM->rem.s.Env, uCpl);
2403 /* Note! QEmu saves the 2nd dword of the descriptor; we should convert the attribute word back! */
2404#define SYNC_IN_SREG(a_pEnv, a_SReg, a_pRemSReg, a_pVBoxSReg) \
2405 do \
2406 { \
2407 if (CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, a_pVBoxSReg)) \
2408 { \
2409 cpu_x86_load_seg_cache(a_pEnv, R_##a_SReg, \
2410 (a_pVBoxSReg)->Sel, \
2411 (a_pVBoxSReg)->u64Base, \
2412 (a_pVBoxSReg)->u32Limit, \
2413 ((a_pVBoxSReg)->Attr.u << 8) & 0xFFFFFF); \
2414 (a_pRemSReg)->fVBoxFlags = (a_pVBoxSReg)->fFlags; \
2415 } \
2416 /* This only-reload-if-changed stuff is the old approach, we should ditch it. */ \
2417 else if ((a_pRemSReg)->selector != (a_pVBoxSReg)->Sel) \
2418 { \
2419 Log2(("REMR3State: " #a_SReg " changed from %04x to %04x!\n", \
2420 (a_pRemSReg)->selector, (a_pVBoxSReg)->Sel)); \
2421 sync_seg(a_pEnv, R_##a_SReg, (a_pVBoxSReg)->Sel); \
2422 if ((a_pRemSReg)->newselector) \
2423 STAM_COUNTER_INC(&gStatSelOutOfSync[R_##a_SReg]); \
2424 } \
2425 else \
2426 (a_pRemSReg)->newselector = 0; \
2427 } while (0)
2428
2429 SYNC_IN_SREG(&pVM->rem.s.Env, CS, &pVM->rem.s.Env.segs[R_CS], &pCtx->cs);
2430 SYNC_IN_SREG(&pVM->rem.s.Env, SS, &pVM->rem.s.Env.segs[R_SS], &pCtx->ss);
2431 SYNC_IN_SREG(&pVM->rem.s.Env, DS, &pVM->rem.s.Env.segs[R_DS], &pCtx->ds);
2432 SYNC_IN_SREG(&pVM->rem.s.Env, ES, &pVM->rem.s.Env.segs[R_ES], &pCtx->es);
2433 SYNC_IN_SREG(&pVM->rem.s.Env, FS, &pVM->rem.s.Env.segs[R_FS], &pCtx->fs);
2434 SYNC_IN_SREG(&pVM->rem.s.Env, GS, &pVM->rem.s.Env.segs[R_GS], &pCtx->gs);
2435 /** @todo need to find a way to communicate potential GDT/LDT changes and thread switches. The selector might
2436 * be the same but not the base/limit. */
2437
2438 /*
2439 * Check for traps.
2440 */
2441 pVM->rem.s.Env.exception_index = -1; /** @todo this won't work :/ */
2442 rc = TRPMQueryTrap(pVCpu, &u8TrapNo, &enmType);
2443 if (RT_SUCCESS(rc))
2444 {
2445#ifdef DEBUG
2446 if (u8TrapNo == 0x80)
2447 {
2448 remR3DumpLnxSyscall(pVCpu);
2449 remR3DumpOBsdSyscall(pVCpu);
2450 }
2451#endif
2452
2453 pVM->rem.s.Env.exception_index = u8TrapNo;
2454 if (enmType != TRPM_SOFTWARE_INT)
2455 {
2456 pVM->rem.s.Env.exception_is_int = 0;
2457 pVM->rem.s.Env.exception_next_eip = pVM->rem.s.Env.eip;
2458 }
2459 else
2460 {
2461 /*
2462 * The there are two 1 byte opcodes and one 2 byte opcode for software interrupts.
2463 * We ASSUME that there are no prefixes and sets the default to 2 byte, and checks
2464 * for int03 and into.
2465 */
2466 pVM->rem.s.Env.exception_is_int = 1;
2467 pVM->rem.s.Env.exception_next_eip = pCtx->rip + 2;
2468 /* int 3 may be generated by one-byte 0xcc */
2469 if (u8TrapNo == 3)
2470 {
2471 if (read_byte(&pVM->rem.s.Env, pVM->rem.s.Env.segs[R_CS].base + pCtx->rip) == 0xcc)
2472 pVM->rem.s.Env.exception_next_eip = pCtx->rip + 1;
2473 }
2474 /* int 4 may be generated by one-byte 0xce */
2475 else if (u8TrapNo == 4)
2476 {
2477 if (read_byte(&pVM->rem.s.Env, pVM->rem.s.Env.segs[R_CS].base + pCtx->rip) == 0xce)
2478 pVM->rem.s.Env.exception_next_eip = pCtx->rip + 1;
2479 }
2480 }
2481
2482 /* get error code and cr2 if needed. */
2483 if (enmType == TRPM_TRAP)
2484 {
2485 switch (u8TrapNo)
2486 {
2487 case 0x0e:
2488 pVM->rem.s.Env.cr[2] = TRPMGetFaultAddress(pVCpu);
2489 /* fallthru */
2490 case 0x0a: case 0x0b: case 0x0c: case 0x0d:
2491 pVM->rem.s.Env.error_code = TRPMGetErrorCode(pVCpu);
2492 break;
2493
2494 case 0x11: case 0x08:
2495 default:
2496 pVM->rem.s.Env.error_code = 0;
2497 break;
2498 }
2499 }
2500 else
2501 pVM->rem.s.Env.error_code = 0;
2502
2503 /*
2504 * We can now reset the active trap since the recompiler is gonna have a go at it.
2505 */
2506 rc = TRPMResetTrap(pVCpu);
2507 AssertRC(rc);
2508 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,
2509 (RTGCPTR)pVM->rem.s.Env.cr[2], (RTGCPTR)pVM->rem.s.Env.exception_next_eip, pVM->rem.s.Env.exception_is_int ? " software" : ""));
2510 }
2511
2512 /*
2513 * Clear old interrupt request flags; Check for pending hardware interrupts.
2514 * (See @remark for why we don't check for other FFs.)
2515 */
2516 pVM->rem.s.Env.interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB | CPU_INTERRUPT_TIMER);
2517 if ( pVM->rem.s.u32PendingInterrupt != REM_NO_PENDING_IRQ
2518 || VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC))
2519 pVM->rem.s.Env.interrupt_request |= CPU_INTERRUPT_HARD;
2520
2521 /*
2522 * We're now in REM mode.
2523 */
2524 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_REM);
2525 pVM->rem.s.fInREM = true;
2526 pVM->rem.s.fInStateSync = false;
2527 pVM->rem.s.cCanExecuteRaw = 0;
2528 STAM_PROFILE_STOP(&pVM->rem.s.StatsState, a);
2529 Log2(("REMR3State: returns VINF_SUCCESS\n"));
2530 return VINF_SUCCESS;
2531}
2532
2533
2534/**
2535 * Syncs back changes in the REM state to the the VM state.
2536 *
2537 * This must be called after invoking REMR3Run().
2538 * Calling it several times in a row is not permitted.
2539 *
2540 * @returns VBox status code.
2541 *
2542 * @param pVM VM Handle.
2543 * @param pVCpu VMCPU Handle.
2544 */
2545REMR3DECL(int) REMR3StateBack(PVM pVM, PVMCPU pVCpu)
2546{
2547 register PCPUMCTX pCtx = pVM->rem.s.pCtx;
2548 Assert(pCtx);
2549 unsigned i;
2550
2551 STAM_PROFILE_START(&pVM->rem.s.StatsStateBack, a);
2552 Log2(("REMR3StateBack:\n"));
2553 Assert(pVM->rem.s.fInREM);
2554
2555 /*
2556 * Copy back the registers.
2557 * This is done in the order they are declared in the CPUMCTX structure.
2558 */
2559
2560 /** @todo FOP */
2561 /** @todo FPUIP */
2562 /** @todo CS */
2563 /** @todo FPUDP */
2564 /** @todo DS */
2565
2566 /** @todo check if FPU/XMM was actually used in the recompiler */
2567 restore_raw_fp_state(&pVM->rem.s.Env, (uint8_t *)&pCtx->fpu);
2568//// dprintf2(("FPU state CW=%04X TT=%04X SW=%04X (%04X)\n", env->fpuc, env->fpstt, env->fpus, pVMCtx->fpu.FSW));
2569
2570#ifdef TARGET_X86_64
2571 /* Note that the high dwords of 64 bits registers are undefined in 32 bits mode and are undefined after a mode change. */
2572 pCtx->rdi = pVM->rem.s.Env.regs[R_EDI];
2573 pCtx->rsi = pVM->rem.s.Env.regs[R_ESI];
2574 pCtx->rbp = pVM->rem.s.Env.regs[R_EBP];
2575 pCtx->rax = pVM->rem.s.Env.regs[R_EAX];
2576 pCtx->rbx = pVM->rem.s.Env.regs[R_EBX];
2577 pCtx->rdx = pVM->rem.s.Env.regs[R_EDX];
2578 pCtx->rcx = pVM->rem.s.Env.regs[R_ECX];
2579 pCtx->r8 = pVM->rem.s.Env.regs[8];
2580 pCtx->r9 = pVM->rem.s.Env.regs[9];
2581 pCtx->r10 = pVM->rem.s.Env.regs[10];
2582 pCtx->r11 = pVM->rem.s.Env.regs[11];
2583 pCtx->r12 = pVM->rem.s.Env.regs[12];
2584 pCtx->r13 = pVM->rem.s.Env.regs[13];
2585 pCtx->r14 = pVM->rem.s.Env.regs[14];
2586 pCtx->r15 = pVM->rem.s.Env.regs[15];
2587
2588 pCtx->rsp = pVM->rem.s.Env.regs[R_ESP];
2589
2590#else
2591 pCtx->edi = pVM->rem.s.Env.regs[R_EDI];
2592 pCtx->esi = pVM->rem.s.Env.regs[R_ESI];
2593 pCtx->ebp = pVM->rem.s.Env.regs[R_EBP];
2594 pCtx->eax = pVM->rem.s.Env.regs[R_EAX];
2595 pCtx->ebx = pVM->rem.s.Env.regs[R_EBX];
2596 pCtx->edx = pVM->rem.s.Env.regs[R_EDX];
2597 pCtx->ecx = pVM->rem.s.Env.regs[R_ECX];
2598
2599 pCtx->esp = pVM->rem.s.Env.regs[R_ESP];
2600#endif
2601
2602#define SYNC_BACK_SREG(a_sreg, a_SREG) \
2603 do \
2604 { \
2605 pCtx->a_sreg.Sel = pVM->rem.s.Env.segs[R_##a_SREG].selector; \
2606 if (!pVM->rem.s.Env.segs[R_SS].newselector) \
2607 { \
2608 pCtx->a_sreg.ValidSel = pVM->rem.s.Env.segs[R_##a_SREG].selector; \
2609 pCtx->a_sreg.fFlags = CPUMSELREG_FLAGS_VALID; \
2610 pCtx->a_sreg.u64Base = pVM->rem.s.Env.segs[R_##a_SREG].base; \
2611 pCtx->a_sreg.u32Limit = pVM->rem.s.Env.segs[R_##a_SREG].limit; \
2612 /* Note! QEmu saves the 2nd dword of the descriptor; we should store the attribute word only! */ \
2613 pCtx->a_sreg.Attr.u = (pVM->rem.s.Env.segs[R_##a_SREG].flags >> 8) & 0xF0FF; \
2614 } \
2615 else \
2616 { \
2617 pCtx->a_sreg.fFlags = 0; \
2618 STAM_COUNTER_INC(&gStatSelOutOfSyncStateBack[R_##a_SREG]); \
2619 } \
2620 } while (0)
2621
2622 SYNC_BACK_SREG(es, ES);
2623 SYNC_BACK_SREG(cs, CS);
2624 SYNC_BACK_SREG(ss, SS);
2625 SYNC_BACK_SREG(ds, DS);
2626 SYNC_BACK_SREG(fs, FS);
2627 SYNC_BACK_SREG(gs, GS);
2628
2629#ifdef TARGET_X86_64
2630 pCtx->rip = pVM->rem.s.Env.eip;
2631 pCtx->rflags.u64 = pVM->rem.s.Env.eflags;
2632#else
2633 pCtx->eip = pVM->rem.s.Env.eip;
2634 pCtx->eflags.u32 = pVM->rem.s.Env.eflags;
2635#endif
2636
2637 pCtx->cr0 = pVM->rem.s.Env.cr[0];
2638 pCtx->cr2 = pVM->rem.s.Env.cr[2];
2639 pCtx->cr3 = pVM->rem.s.Env.cr[3];
2640 if ((pVM->rem.s.Env.cr[4] ^ pCtx->cr4) & X86_CR4_VME)
2641 VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_TSS);
2642 pCtx->cr4 = pVM->rem.s.Env.cr[4];
2643
2644 for (i = 0; i < 8; i++)
2645 pCtx->dr[i] = pVM->rem.s.Env.dr[i];
2646
2647 pCtx->gdtr.cbGdt = pVM->rem.s.Env.gdt.limit;
2648 if (pCtx->gdtr.pGdt != pVM->rem.s.Env.gdt.base)
2649 {
2650 pCtx->gdtr.pGdt = pVM->rem.s.Env.gdt.base;
2651 STAM_COUNTER_INC(&gStatREMGDTChange);
2652 VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_GDT);
2653 }
2654
2655 pCtx->idtr.cbIdt = pVM->rem.s.Env.idt.limit;
2656 if (pCtx->idtr.pIdt != pVM->rem.s.Env.idt.base)
2657 {
2658 pCtx->idtr.pIdt = pVM->rem.s.Env.idt.base;
2659 STAM_COUNTER_INC(&gStatREMIDTChange);
2660 VMCPU_FF_SET(pVCpu, VMCPU_FF_TRPM_SYNC_IDT);
2661 }
2662
2663 if ( pCtx->ldtr.Sel != pVM->rem.s.Env.ldt.selector
2664 || pCtx->ldtr.ValidSel != pVM->rem.s.Env.ldt.selector
2665 || pCtx->ldtr.u64Base != pVM->rem.s.Env.ldt.base
2666 || pCtx->ldtr.u32Limit != pVM->rem.s.Env.ldt.limit
2667 || pCtx->ldtr.Attr.u != ((pVM->rem.s.Env.ldt.flags >> 8) & 0xF0FF)
2668 || !(pCtx->ldtr.fFlags & CPUMSELREG_FLAGS_VALID)
2669 )
2670 {
2671 pCtx->ldtr.Sel = pVM->rem.s.Env.ldt.selector;
2672 pCtx->ldtr.ValidSel = pVM->rem.s.Env.ldt.selector;
2673 pCtx->ldtr.fFlags = CPUMSELREG_FLAGS_VALID;
2674 pCtx->ldtr.u64Base = pVM->rem.s.Env.ldt.base;
2675 pCtx->ldtr.u32Limit = pVM->rem.s.Env.ldt.limit;
2676 pCtx->ldtr.Attr.u = (pVM->rem.s.Env.ldt.flags >> 8) & 0xF0FF;
2677 STAM_COUNTER_INC(&gStatREMLDTRChange);
2678 VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_LDT);
2679 }
2680
2681 if ( pCtx->tr.Sel != pVM->rem.s.Env.tr.selector
2682 || pCtx->tr.ValidSel != pVM->rem.s.Env.tr.selector
2683 || pCtx->tr.u64Base != pVM->rem.s.Env.tr.base
2684 || pCtx->tr.u32Limit != pVM->rem.s.Env.tr.limit
2685 /* Qemu and AMD/Intel have different ideas about the busy flag ... */
2686 || pCtx->tr.Attr.u != ( (pVM->rem.s.Env.tr.flags >> 8) & 0xF0FF
2687 ? (pVM->rem.s.Env.tr.flags | DESC_TSS_BUSY_MASK) >> 8
2688 : 0)
2689 || !(pCtx->tr.fFlags & CPUMSELREG_FLAGS_VALID)
2690 )
2691 {
2692 Log(("REM: TR changed! %#x{%#llx,%#x,%#x} -> %#x{%llx,%#x,%#x}\n",
2693 pCtx->tr.Sel, pCtx->tr.u64Base, pCtx->tr.u32Limit, pCtx->tr.Attr.u,
2694 pVM->rem.s.Env.tr.selector, (uint64_t)pVM->rem.s.Env.tr.base, pVM->rem.s.Env.tr.limit,
2695 (pVM->rem.s.Env.tr.flags >> 8) & 0xF0FF ? (pVM->rem.s.Env.tr.flags | DESC_TSS_BUSY_MASK) >> 8 : 0));
2696 pCtx->tr.Sel = pVM->rem.s.Env.tr.selector;
2697 pCtx->tr.ValidSel = pVM->rem.s.Env.tr.selector;
2698 pCtx->tr.fFlags = CPUMSELREG_FLAGS_VALID;
2699 pCtx->tr.u64Base = pVM->rem.s.Env.tr.base;
2700 pCtx->tr.u32Limit = pVM->rem.s.Env.tr.limit;
2701 pCtx->tr.Attr.u = (pVM->rem.s.Env.tr.flags >> 8) & 0xF0FF;
2702 if (pCtx->tr.Attr.u)
2703 pCtx->tr.Attr.u |= DESC_TSS_BUSY_MASK >> 8;
2704 STAM_COUNTER_INC(&gStatREMTRChange);
2705 VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_TSS);
2706 }
2707
2708 /* Sysenter MSR */
2709 pCtx->SysEnter.cs = pVM->rem.s.Env.sysenter_cs;
2710 pCtx->SysEnter.eip = pVM->rem.s.Env.sysenter_eip;
2711 pCtx->SysEnter.esp = pVM->rem.s.Env.sysenter_esp;
2712
2713 /* System MSRs. */
2714 pCtx->msrEFER = pVM->rem.s.Env.efer;
2715 pCtx->msrSTAR = pVM->rem.s.Env.star;
2716 pCtx->msrPAT = pVM->rem.s.Env.pat;
2717#ifdef TARGET_X86_64
2718 pCtx->msrLSTAR = pVM->rem.s.Env.lstar;
2719 pCtx->msrCSTAR = pVM->rem.s.Env.cstar;
2720 pCtx->msrSFMASK = pVM->rem.s.Env.fmask;
2721 pCtx->msrKERNELGSBASE = pVM->rem.s.Env.kernelgsbase;
2722#endif
2723
2724 /* Inhibit interrupt flag. */
2725 if (pVM->rem.s.Env.hflags & HF_INHIBIT_IRQ_MASK)
2726 {
2727 Log(("Settings VMCPU_FF_INHIBIT_INTERRUPTS at %RGv (REM)\n", (RTGCPTR)pCtx->rip));
2728 EMSetInhibitInterruptsPC(pVCpu, pCtx->rip);
2729 VMCPU_FF_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
2730 }
2731 else if (VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
2732 {
2733 Log(("Clearing VMCPU_FF_INHIBIT_INTERRUPTS at %RGv - successor %RGv (REM#2)\n", (RTGCPTR)pCtx->rip, EMGetInhibitInterruptsPC(pVCpu)));
2734 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
2735 }
2736
2737 remR3TrapClear(pVM);
2738
2739 /*
2740 * Check for traps.
2741 */
2742 if ( pVM->rem.s.Env.exception_index >= 0
2743 && pVM->rem.s.Env.exception_index < 256)
2744 {
2745 int rc;
2746
2747 Log(("REMR3StateBack: Pending trap %x %d\n", pVM->rem.s.Env.exception_index, pVM->rem.s.Env.exception_is_int));
2748 rc = TRPMAssertTrap(pVCpu, pVM->rem.s.Env.exception_index, (pVM->rem.s.Env.exception_is_int) ? TRPM_SOFTWARE_INT : TRPM_HARDWARE_INT);
2749 AssertRC(rc);
2750 switch (pVM->rem.s.Env.exception_index)
2751 {
2752 case 0x0e:
2753 TRPMSetFaultAddress(pVCpu, pCtx->cr2);
2754 /* fallthru */
2755 case 0x0a: case 0x0b: case 0x0c: case 0x0d:
2756 case 0x11: case 0x08: /* 0 */
2757 TRPMSetErrorCode(pVCpu, pVM->rem.s.Env.error_code);
2758 break;
2759 }
2760
2761 }
2762
2763 /*
2764 * We're not longer in REM mode.
2765 */
2766 CPUMR3RemLeave(pVCpu,
2767 HMIsEnabled(pVM)
2768 || ( pVM->rem.s.Env.segs[R_SS].newselector
2769 | pVM->rem.s.Env.segs[R_GS].newselector
2770 | pVM->rem.s.Env.segs[R_FS].newselector
2771 | pVM->rem.s.Env.segs[R_ES].newselector
2772 | pVM->rem.s.Env.segs[R_DS].newselector
2773 | pVM->rem.s.Env.segs[R_CS].newselector) == 0
2774 );
2775 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_REM);
2776 pVM->rem.s.fInREM = false;
2777 pVM->rem.s.pCtx = NULL;
2778 pVM->rem.s.Env.pVCpu = NULL;
2779 STAM_PROFILE_STOP(&pVM->rem.s.StatsStateBack, a);
2780 Log2(("REMR3StateBack: returns VINF_SUCCESS\n"));
2781 return VINF_SUCCESS;
2782}
2783
2784
2785/**
2786 * This is called by the disassembler when it wants to update the cpu state
2787 * before for instance doing a register dump.
2788 */
2789static void remR3StateUpdate(PVM pVM, PVMCPU pVCpu)
2790{
2791 register PCPUMCTX pCtx = pVM->rem.s.pCtx;
2792 unsigned i;
2793
2794 Assert(pVM->rem.s.fInREM);
2795
2796 /*
2797 * Copy back the registers.
2798 * This is done in the order they are declared in the CPUMCTX structure.
2799 */
2800
2801 /** @todo FOP */
2802 /** @todo FPUIP */
2803 /** @todo CS */
2804 /** @todo FPUDP */
2805 /** @todo DS */
2806 /** @todo Fix MXCSR support in QEMU so we don't overwrite MXCSR with 0 when we shouldn't! */
2807 pCtx->fpu.MXCSR = 0;
2808 pCtx->fpu.MXCSR_MASK = 0;
2809
2810 /** @todo check if FPU/XMM was actually used in the recompiler */
2811 restore_raw_fp_state(&pVM->rem.s.Env, (uint8_t *)&pCtx->fpu);
2812//// dprintf2(("FPU state CW=%04X TT=%04X SW=%04X (%04X)\n", env->fpuc, env->fpstt, env->fpus, pVMCtx->fpu.FSW));
2813
2814#ifdef TARGET_X86_64
2815 pCtx->rdi = pVM->rem.s.Env.regs[R_EDI];
2816 pCtx->rsi = pVM->rem.s.Env.regs[R_ESI];
2817 pCtx->rbp = pVM->rem.s.Env.regs[R_EBP];
2818 pCtx->rax = pVM->rem.s.Env.regs[R_EAX];
2819 pCtx->rbx = pVM->rem.s.Env.regs[R_EBX];
2820 pCtx->rdx = pVM->rem.s.Env.regs[R_EDX];
2821 pCtx->rcx = pVM->rem.s.Env.regs[R_ECX];
2822 pCtx->r8 = pVM->rem.s.Env.regs[8];
2823 pCtx->r9 = pVM->rem.s.Env.regs[9];
2824 pCtx->r10 = pVM->rem.s.Env.regs[10];
2825 pCtx->r11 = pVM->rem.s.Env.regs[11];
2826 pCtx->r12 = pVM->rem.s.Env.regs[12];
2827 pCtx->r13 = pVM->rem.s.Env.regs[13];
2828 pCtx->r14 = pVM->rem.s.Env.regs[14];
2829 pCtx->r15 = pVM->rem.s.Env.regs[15];
2830
2831 pCtx->rsp = pVM->rem.s.Env.regs[R_ESP];
2832#else
2833 pCtx->edi = pVM->rem.s.Env.regs[R_EDI];
2834 pCtx->esi = pVM->rem.s.Env.regs[R_ESI];
2835 pCtx->ebp = pVM->rem.s.Env.regs[R_EBP];
2836 pCtx->eax = pVM->rem.s.Env.regs[R_EAX];
2837 pCtx->ebx = pVM->rem.s.Env.regs[R_EBX];
2838 pCtx->edx = pVM->rem.s.Env.regs[R_EDX];
2839 pCtx->ecx = pVM->rem.s.Env.regs[R_ECX];
2840
2841 pCtx->esp = pVM->rem.s.Env.regs[R_ESP];
2842#endif
2843
2844 SYNC_BACK_SREG(es, ES);
2845 SYNC_BACK_SREG(cs, CS);
2846 SYNC_BACK_SREG(ss, SS);
2847 SYNC_BACK_SREG(ds, DS);
2848 SYNC_BACK_SREG(fs, FS);
2849 SYNC_BACK_SREG(gs, GS);
2850
2851#ifdef TARGET_X86_64
2852 pCtx->rip = pVM->rem.s.Env.eip;
2853 pCtx->rflags.u64 = pVM->rem.s.Env.eflags;
2854#else
2855 pCtx->eip = pVM->rem.s.Env.eip;
2856 pCtx->eflags.u32 = pVM->rem.s.Env.eflags;
2857#endif
2858
2859 pCtx->cr0 = pVM->rem.s.Env.cr[0];
2860 pCtx->cr2 = pVM->rem.s.Env.cr[2];
2861 pCtx->cr3 = pVM->rem.s.Env.cr[3];
2862 if ((pVM->rem.s.Env.cr[4] ^ pCtx->cr4) & X86_CR4_VME)
2863 VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_TSS);
2864 pCtx->cr4 = pVM->rem.s.Env.cr[4];
2865
2866 for (i = 0; i < 8; i++)
2867 pCtx->dr[i] = pVM->rem.s.Env.dr[i];
2868
2869 pCtx->gdtr.cbGdt = pVM->rem.s.Env.gdt.limit;
2870 if (pCtx->gdtr.pGdt != (RTGCPTR)pVM->rem.s.Env.gdt.base)
2871 {
2872 pCtx->gdtr.pGdt = (RTGCPTR)pVM->rem.s.Env.gdt.base;
2873 STAM_COUNTER_INC(&gStatREMGDTChange);
2874 VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_GDT);
2875 }
2876
2877 pCtx->idtr.cbIdt = pVM->rem.s.Env.idt.limit;
2878 if (pCtx->idtr.pIdt != (RTGCPTR)pVM->rem.s.Env.idt.base)
2879 {
2880 pCtx->idtr.pIdt = (RTGCPTR)pVM->rem.s.Env.idt.base;
2881 STAM_COUNTER_INC(&gStatREMIDTChange);
2882 VMCPU_FF_SET(pVCpu, VMCPU_FF_TRPM_SYNC_IDT);
2883 }
2884
2885 if ( pCtx->ldtr.Sel != pVM->rem.s.Env.ldt.selector
2886 || pCtx->ldtr.ValidSel != pVM->rem.s.Env.ldt.selector
2887 || pCtx->ldtr.u64Base != pVM->rem.s.Env.ldt.base
2888 || pCtx->ldtr.u32Limit != pVM->rem.s.Env.ldt.limit
2889 || pCtx->ldtr.Attr.u != ((pVM->rem.s.Env.ldt.flags >> 8) & 0xF0FF)
2890 || !(pCtx->ldtr.fFlags & CPUMSELREG_FLAGS_VALID)
2891 )
2892 {
2893 pCtx->ldtr.Sel = pVM->rem.s.Env.ldt.selector;
2894 pCtx->ldtr.ValidSel = pVM->rem.s.Env.ldt.selector;
2895 pCtx->ldtr.fFlags = CPUMSELREG_FLAGS_VALID;
2896 pCtx->ldtr.u64Base = pVM->rem.s.Env.ldt.base;
2897 pCtx->ldtr.u32Limit = pVM->rem.s.Env.ldt.limit;
2898 pCtx->ldtr.Attr.u = (pVM->rem.s.Env.ldt.flags >> 8) & 0xF0FF;
2899 STAM_COUNTER_INC(&gStatREMLDTRChange);
2900 VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_LDT);
2901 }
2902
2903 if ( pCtx->tr.Sel != pVM->rem.s.Env.tr.selector
2904 || pCtx->tr.ValidSel != pVM->rem.s.Env.tr.selector
2905 || pCtx->tr.u64Base != pVM->rem.s.Env.tr.base
2906 || pCtx->tr.u32Limit != pVM->rem.s.Env.tr.limit
2907 /* Qemu and AMD/Intel have different ideas about the busy flag ... */
2908 || pCtx->tr.Attr.u != ( (pVM->rem.s.Env.tr.flags >> 8) & 0xF0FF
2909 ? (pVM->rem.s.Env.tr.flags | DESC_TSS_BUSY_MASK) >> 8
2910 : 0)
2911 || !(pCtx->tr.fFlags & CPUMSELREG_FLAGS_VALID)
2912 )
2913 {
2914 Log(("REM: TR changed! %#x{%#llx,%#x,%#x} -> %#x{%llx,%#x,%#x}\n",
2915 pCtx->tr.Sel, pCtx->tr.u64Base, pCtx->tr.u32Limit, pCtx->tr.Attr.u,
2916 pVM->rem.s.Env.tr.selector, (uint64_t)pVM->rem.s.Env.tr.base, pVM->rem.s.Env.tr.limit,
2917 (pVM->rem.s.Env.tr.flags >> 8) & 0xF0FF ? (pVM->rem.s.Env.tr.flags | DESC_TSS_BUSY_MASK) >> 8 : 0));
2918 pCtx->tr.Sel = pVM->rem.s.Env.tr.selector;
2919 pCtx->tr.ValidSel = pVM->rem.s.Env.tr.selector;
2920 pCtx->tr.fFlags = CPUMSELREG_FLAGS_VALID;
2921 pCtx->tr.u64Base = pVM->rem.s.Env.tr.base;
2922 pCtx->tr.u32Limit = pVM->rem.s.Env.tr.limit;
2923 pCtx->tr.Attr.u = (pVM->rem.s.Env.tr.flags >> 8) & 0xF0FF;
2924 if (pCtx->tr.Attr.u)
2925 pCtx->tr.Attr.u |= DESC_TSS_BUSY_MASK >> 8;
2926 STAM_COUNTER_INC(&gStatREMTRChange);
2927 VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_TSS);
2928 }
2929
2930 /* Sysenter MSR */
2931 pCtx->SysEnter.cs = pVM->rem.s.Env.sysenter_cs;
2932 pCtx->SysEnter.eip = pVM->rem.s.Env.sysenter_eip;
2933 pCtx->SysEnter.esp = pVM->rem.s.Env.sysenter_esp;
2934
2935 /* System MSRs. */
2936 pCtx->msrEFER = pVM->rem.s.Env.efer;
2937 pCtx->msrSTAR = pVM->rem.s.Env.star;
2938 pCtx->msrPAT = pVM->rem.s.Env.pat;
2939#ifdef TARGET_X86_64
2940 pCtx->msrLSTAR = pVM->rem.s.Env.lstar;
2941 pCtx->msrCSTAR = pVM->rem.s.Env.cstar;
2942 pCtx->msrSFMASK = pVM->rem.s.Env.fmask;
2943 pCtx->msrKERNELGSBASE = pVM->rem.s.Env.kernelgsbase;
2944#endif
2945
2946}
2947
2948
2949/**
2950 * Update the VMM state information if we're currently in REM.
2951 *
2952 * This method is used by the DBGF and PDMDevice when there is any uncertainty of whether
2953 * we're currently executing in REM and the VMM state is invalid. This method will of
2954 * course check that we're executing in REM before syncing any data over to the VMM.
2955 *
2956 * @param pVM The VM handle.
2957 * @param pVCpu The VMCPU handle.
2958 */
2959REMR3DECL(void) REMR3StateUpdate(PVM pVM, PVMCPU pVCpu)
2960{
2961 if (pVM->rem.s.fInREM)
2962 remR3StateUpdate(pVM, pVCpu);
2963}
2964
2965
2966#undef LOG_GROUP
2967#define LOG_GROUP LOG_GROUP_REM
2968
2969
2970/**
2971 * Notify the recompiler about Address Gate 20 state change.
2972 *
2973 * This notification is required since A20 gate changes are
2974 * initialized from a device driver and the VM might just as
2975 * well be in REM mode as in RAW mode.
2976 *
2977 * @param pVM VM handle.
2978 * @param pVCpu VMCPU handle.
2979 * @param fEnable True if the gate should be enabled.
2980 * False if the gate should be disabled.
2981 */
2982REMR3DECL(void) REMR3A20Set(PVM pVM, PVMCPU pVCpu, bool fEnable)
2983{
2984 LogFlow(("REMR3A20Set: fEnable=%d\n", fEnable));
2985 VM_ASSERT_EMT(pVM);
2986
2987 /** @todo SMP and the A20 gate... */
2988 if (pVM->rem.s.Env.pVCpu == pVCpu)
2989 {
2990 ASMAtomicIncU32(&pVM->rem.s.cIgnoreAll);
2991 cpu_x86_set_a20(&pVM->rem.s.Env, fEnable);
2992 ASMAtomicDecU32(&pVM->rem.s.cIgnoreAll);
2993 }
2994}
2995
2996
2997/**
2998 * Replays the handler notification changes
2999 * Called in response to VM_FF_REM_HANDLER_NOTIFY from the RAW execution loop.
3000 *
3001 * @param pVM VM handle.
3002 */
3003REMR3DECL(void) REMR3ReplayHandlerNotifications(PVM pVM)
3004{
3005 /*
3006 * Replay the flushes.
3007 */
3008 LogFlow(("REMR3ReplayHandlerNotifications:\n"));
3009 VM_ASSERT_EMT(pVM);
3010
3011 /** @todo this isn't ensuring correct replay order. */
3012 if (VM_FF_TESTANDCLEAR(pVM, VM_FF_REM_HANDLER_NOTIFY))
3013 {
3014 uint32_t idxNext;
3015 uint32_t idxRevHead;
3016 uint32_t idxHead;
3017#ifdef VBOX_STRICT
3018 int32_t c = 0;
3019#endif
3020
3021 /* Lockless purging of pending notifications. */
3022 idxHead = ASMAtomicXchgU32(&pVM->rem.s.idxPendingList, UINT32_MAX);
3023 if (idxHead == UINT32_MAX)
3024 return;
3025 Assert(idxHead < RT_ELEMENTS(pVM->rem.s.aHandlerNotifications));
3026
3027 /*
3028 * Reverse the list to process it in FIFO order.
3029 */
3030 idxRevHead = UINT32_MAX;
3031 do
3032 {
3033 /* Save the index of the next rec. */
3034 idxNext = pVM->rem.s.aHandlerNotifications[idxHead].idxNext;
3035 Assert(idxNext < RT_ELEMENTS(pVM->rem.s.aHandlerNotifications) || idxNext == UINT32_MAX);
3036 /* Push the record onto the reversed list. */
3037 pVM->rem.s.aHandlerNotifications[idxHead].idxNext = idxRevHead;
3038 idxRevHead = idxHead;
3039 Assert(++c <= RT_ELEMENTS(pVM->rem.s.aHandlerNotifications));
3040 /* Advance. */
3041 idxHead = idxNext;
3042 } while (idxHead != UINT32_MAX);
3043
3044 /*
3045 * Loop thru the list, reinserting the record into the free list as they are
3046 * processed to avoid having other EMTs running out of entries while we're flushing.
3047 */
3048 idxHead = idxRevHead;
3049 do
3050 {
3051 PREMHANDLERNOTIFICATION pCur = &pVM->rem.s.aHandlerNotifications[idxHead];
3052 uint32_t idxCur;
3053 Assert(--c >= 0);
3054
3055 switch (pCur->enmKind)
3056 {
3057 case REMHANDLERNOTIFICATIONKIND_PHYSICAL_REGISTER:
3058 remR3NotifyHandlerPhysicalRegister(pVM,
3059 pCur->u.PhysicalRegister.enmType,
3060 pCur->u.PhysicalRegister.GCPhys,
3061 pCur->u.PhysicalRegister.cb,
3062 pCur->u.PhysicalRegister.fHasHCHandler);
3063 break;
3064
3065 case REMHANDLERNOTIFICATIONKIND_PHYSICAL_DEREGISTER:
3066 remR3NotifyHandlerPhysicalDeregister(pVM,
3067 pCur->u.PhysicalDeregister.enmType,
3068 pCur->u.PhysicalDeregister.GCPhys,
3069 pCur->u.PhysicalDeregister.cb,
3070 pCur->u.PhysicalDeregister.fHasHCHandler,
3071 pCur->u.PhysicalDeregister.fRestoreAsRAM);
3072 break;
3073
3074 case REMHANDLERNOTIFICATIONKIND_PHYSICAL_MODIFY:
3075 remR3NotifyHandlerPhysicalModify(pVM,
3076 pCur->u.PhysicalModify.enmType,
3077 pCur->u.PhysicalModify.GCPhysOld,
3078 pCur->u.PhysicalModify.GCPhysNew,
3079 pCur->u.PhysicalModify.cb,
3080 pCur->u.PhysicalModify.fHasHCHandler,
3081 pCur->u.PhysicalModify.fRestoreAsRAM);
3082 break;
3083
3084 default:
3085 AssertReleaseMsgFailed(("enmKind=%d\n", pCur->enmKind));
3086 break;
3087 }
3088
3089 /*
3090 * Advance idxHead.
3091 */
3092 idxCur = idxHead;
3093 idxHead = pCur->idxNext;
3094 Assert(idxHead < RT_ELEMENTS(pVM->rem.s.aHandlerNotifications) || (idxHead == UINT32_MAX && c == 0));
3095
3096 /*
3097 * Put the record back into the free list.
3098 */
3099 do
3100 {
3101 idxNext = ASMAtomicUoReadU32(&pVM->rem.s.idxFreeList);
3102 ASMAtomicWriteU32(&pCur->idxNext, idxNext);
3103 ASMCompilerBarrier();
3104 } while (!ASMAtomicCmpXchgU32(&pVM->rem.s.idxFreeList, idxCur, idxNext));
3105 } while (idxHead != UINT32_MAX);
3106
3107#ifdef VBOX_STRICT
3108 if (pVM->cCpus == 1)
3109 {
3110 unsigned c;
3111 /* Check that all records are now on the free list. */
3112 for (c = 0, idxNext = pVM->rem.s.idxFreeList; idxNext != UINT32_MAX;
3113 idxNext = pVM->rem.s.aHandlerNotifications[idxNext].idxNext)
3114 c++;
3115 AssertReleaseMsg(c == RT_ELEMENTS(pVM->rem.s.aHandlerNotifications), ("%#x != %#x, idxFreeList=%#x\n", c, RT_ELEMENTS(pVM->rem.s.aHandlerNotifications), pVM->rem.s.idxFreeList));
3116 }
3117#endif
3118 }
3119}
3120
3121
3122/**
3123 * Notify REM about changed code page.
3124 *
3125 * @returns VBox status code.
3126 * @param pVM VM handle.
3127 * @param pVCpu VMCPU handle.
3128 * @param pvCodePage Code page address
3129 */
3130REMR3DECL(int) REMR3NotifyCodePageChanged(PVM pVM, PVMCPU pVCpu, RTGCPTR pvCodePage)
3131{
3132#ifdef VBOX_REM_PROTECT_PAGES_FROM_SMC
3133 int rc;
3134 RTGCPHYS PhysGC;
3135 uint64_t flags;
3136
3137 VM_ASSERT_EMT(pVM);
3138
3139 /*
3140 * Get the physical page address.
3141 */
3142 rc = PGMGstGetPage(pVM, pvCodePage, &flags, &PhysGC);
3143 if (rc == VINF_SUCCESS)
3144 {
3145 /*
3146 * Sync the required registers and flush the whole page.
3147 * (Easier to do the whole page than notifying it about each physical
3148 * byte that was changed.
3149 */
3150 pVM->rem.s.Env.cr[0] = pVM->rem.s.pCtx->cr0;
3151 pVM->rem.s.Env.cr[2] = pVM->rem.s.pCtx->cr2;
3152 pVM->rem.s.Env.cr[3] = pVM->rem.s.pCtx->cr3;
3153 pVM->rem.s.Env.cr[4] = pVM->rem.s.pCtx->cr4;
3154
3155 tb_invalidate_phys_page_range(PhysGC, PhysGC + PAGE_SIZE - 1, 0);
3156 }
3157#endif
3158 return VINF_SUCCESS;
3159}
3160
3161
3162/**
3163 * Notification about a successful MMR3PhysRegister() call.
3164 *
3165 * @param pVM VM handle.
3166 * @param GCPhys The physical address the RAM.
3167 * @param cb Size of the memory.
3168 * @param fFlags Flags of the REM_NOTIFY_PHYS_RAM_FLAGS_* defines.
3169 */
3170REMR3DECL(void) REMR3NotifyPhysRamRegister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, unsigned fFlags)
3171{
3172 Log(("REMR3NotifyPhysRamRegister: GCPhys=%RGp cb=%RGp fFlags=%#x\n", GCPhys, cb, fFlags));
3173 VM_ASSERT_EMT(pVM);
3174
3175 /*
3176 * Validate input - we trust the caller.
3177 */
3178 Assert(RT_ALIGN_T(GCPhys, PAGE_SIZE, RTGCPHYS) == GCPhys);
3179 Assert(cb);
3180 Assert(RT_ALIGN_Z(cb, PAGE_SIZE) == cb);
3181 AssertMsg(fFlags == REM_NOTIFY_PHYS_RAM_FLAGS_RAM || fFlags == REM_NOTIFY_PHYS_RAM_FLAGS_MMIO2, ("#x\n", fFlags));
3182
3183 /*
3184 * Base ram? Update GCPhysLastRam.
3185 */
3186 if (fFlags & REM_NOTIFY_PHYS_RAM_FLAGS_RAM)
3187 {
3188 if (GCPhys + (cb - 1) > pVM->rem.s.GCPhysLastRam)
3189 {
3190 AssertReleaseMsg(!pVM->rem.s.fGCPhysLastRamFixed, ("GCPhys=%RGp cb=%RGp\n", GCPhys, cb));
3191 pVM->rem.s.GCPhysLastRam = GCPhys + (cb - 1);
3192 }
3193 }
3194
3195 /*
3196 * Register the ram.
3197 */
3198 ASMAtomicIncU32(&pVM->rem.s.cIgnoreAll);
3199
3200 PDMCritSectEnter(&pVM->rem.s.CritSectRegister, VERR_SEM_BUSY);
3201 cpu_register_physical_memory_offset(GCPhys, cb, GCPhys, GCPhys);
3202 PDMCritSectLeave(&pVM->rem.s.CritSectRegister);
3203
3204 ASMAtomicDecU32(&pVM->rem.s.cIgnoreAll);
3205}
3206
3207
3208/**
3209 * Notification about a successful MMR3PhysRomRegister() call.
3210 *
3211 * @param pVM VM handle.
3212 * @param GCPhys The physical address of the ROM.
3213 * @param cb The size of the ROM.
3214 * @param pvCopy Pointer to the ROM copy.
3215 * @param fShadow Whether it's currently writable shadow ROM or normal readonly ROM.
3216 * This function will be called when ever the protection of the
3217 * shadow ROM changes (at reset and end of POST).
3218 */
3219REMR3DECL(void) REMR3NotifyPhysRomRegister(PVM pVM, RTGCPHYS GCPhys, RTUINT cb, void *pvCopy, bool fShadow)
3220{
3221 Log(("REMR3NotifyPhysRomRegister: GCPhys=%RGp cb=%d fShadow=%RTbool\n", GCPhys, cb, fShadow));
3222 VM_ASSERT_EMT(pVM);
3223
3224 /*
3225 * Validate input - we trust the caller.
3226 */
3227 Assert(RT_ALIGN_T(GCPhys, PAGE_SIZE, RTGCPHYS) == GCPhys);
3228 Assert(cb);
3229 Assert(RT_ALIGN_Z(cb, PAGE_SIZE) == cb);
3230
3231 /*
3232 * Register the rom.
3233 */
3234 ASMAtomicIncU32(&pVM->rem.s.cIgnoreAll);
3235
3236 PDMCritSectEnter(&pVM->rem.s.CritSectRegister, VERR_SEM_BUSY);
3237 cpu_register_physical_memory_offset(GCPhys, cb, GCPhys | (fShadow ? 0 : IO_MEM_ROM), GCPhys);
3238 PDMCritSectLeave(&pVM->rem.s.CritSectRegister);
3239
3240 ASMAtomicDecU32(&pVM->rem.s.cIgnoreAll);
3241}
3242
3243
3244/**
3245 * Notification about a successful memory deregistration or reservation.
3246 *
3247 * @param pVM VM Handle.
3248 * @param GCPhys Start physical address.
3249 * @param cb The size of the range.
3250 */
3251REMR3DECL(void) REMR3NotifyPhysRamDeregister(PVM pVM, RTGCPHYS GCPhys, RTUINT cb)
3252{
3253 Log(("REMR3NotifyPhysRamDeregister: GCPhys=%RGp cb=%d\n", GCPhys, cb));
3254 VM_ASSERT_EMT(pVM);
3255
3256 /*
3257 * Validate input - we trust the caller.
3258 */
3259 Assert(RT_ALIGN_T(GCPhys, PAGE_SIZE, RTGCPHYS) == GCPhys);
3260 Assert(cb);
3261 Assert(RT_ALIGN_Z(cb, PAGE_SIZE) == cb);
3262
3263 /*
3264 * Unassigning the memory.
3265 */
3266 ASMAtomicIncU32(&pVM->rem.s.cIgnoreAll);
3267
3268 PDMCritSectEnter(&pVM->rem.s.CritSectRegister, VERR_SEM_BUSY);
3269 cpu_register_physical_memory_offset(GCPhys, cb, IO_MEM_UNASSIGNED, GCPhys);
3270 PDMCritSectLeave(&pVM->rem.s.CritSectRegister);
3271
3272 ASMAtomicDecU32(&pVM->rem.s.cIgnoreAll);
3273}
3274
3275
3276/**
3277 * Notification about a successful PGMR3HandlerPhysicalRegister() call.
3278 *
3279 * @param pVM VM Handle.
3280 * @param enmType Handler type.
3281 * @param GCPhys Handler range address.
3282 * @param cb Size of the handler range.
3283 * @param fHasHCHandler Set if the handler has a HC callback function.
3284 *
3285 * @remark MMR3PhysRomRegister assumes that this function will not apply the
3286 * Handler memory type to memory which has no HC handler.
3287 */
3288static void remR3NotifyHandlerPhysicalRegister(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS cb, bool fHasHCHandler)
3289{
3290 Log(("REMR3NotifyHandlerPhysicalRegister: enmType=%d GCPhys=%RGp cb=%RGp fHasHCHandler=%d\n",
3291 enmType, GCPhys, cb, fHasHCHandler));
3292
3293 VM_ASSERT_EMT(pVM);
3294 Assert(RT_ALIGN_T(GCPhys, PAGE_SIZE, RTGCPHYS) == GCPhys);
3295 Assert(RT_ALIGN_T(cb, PAGE_SIZE, RTGCPHYS) == cb);
3296
3297
3298 ASMAtomicIncU32(&pVM->rem.s.cIgnoreAll);
3299
3300 PDMCritSectEnter(&pVM->rem.s.CritSectRegister, VERR_SEM_BUSY);
3301 if (enmType == PGMPHYSHANDLERTYPE_MMIO)
3302 cpu_register_physical_memory_offset(GCPhys, cb, pVM->rem.s.iMMIOMemType, GCPhys);
3303 else if (fHasHCHandler)
3304 cpu_register_physical_memory_offset(GCPhys, cb, pVM->rem.s.iHandlerMemType, GCPhys);
3305 PDMCritSectLeave(&pVM->rem.s.CritSectRegister);
3306
3307 ASMAtomicDecU32(&pVM->rem.s.cIgnoreAll);
3308}
3309
3310/**
3311 * Notification about a successful PGMR3HandlerPhysicalRegister() call.
3312 *
3313 * @param pVM VM Handle.
3314 * @param enmType Handler type.
3315 * @param GCPhys Handler range address.
3316 * @param cb Size of the handler range.
3317 * @param fHasHCHandler Set if the handler has a HC callback function.
3318 *
3319 * @remark MMR3PhysRomRegister assumes that this function will not apply the
3320 * Handler memory type to memory which has no HC handler.
3321 */
3322REMR3DECL(void) REMR3NotifyHandlerPhysicalRegister(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS cb, bool fHasHCHandler)
3323{
3324 REMR3ReplayHandlerNotifications(pVM);
3325
3326 remR3NotifyHandlerPhysicalRegister(pVM, enmType, GCPhys, cb, fHasHCHandler);
3327}
3328
3329/**
3330 * Notification about a successful PGMR3HandlerPhysicalDeregister() operation.
3331 *
3332 * @param pVM VM Handle.
3333 * @param enmType Handler type.
3334 * @param GCPhys Handler range address.
3335 * @param cb Size of the handler range.
3336 * @param fHasHCHandler Set if the handler has a HC callback function.
3337 * @param fRestoreAsRAM Whether the to restore it as normal RAM or as unassigned memory.
3338 */
3339static void remR3NotifyHandlerPhysicalDeregister(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS cb, bool fHasHCHandler, bool fRestoreAsRAM)
3340{
3341 Log(("REMR3NotifyHandlerPhysicalDeregister: enmType=%d GCPhys=%RGp cb=%RGp fHasHCHandler=%RTbool fRestoreAsRAM=%RTbool RAM=%08x\n",
3342 enmType, GCPhys, cb, fHasHCHandler, fRestoreAsRAM, MMR3PhysGetRamSize(pVM)));
3343 VM_ASSERT_EMT(pVM);
3344
3345
3346 ASMAtomicIncU32(&pVM->rem.s.cIgnoreAll);
3347
3348 PDMCritSectEnter(&pVM->rem.s.CritSectRegister, VERR_SEM_BUSY);
3349 /** @todo this isn't right, MMIO can (in theory) be restored as RAM. */
3350 if (enmType == PGMPHYSHANDLERTYPE_MMIO)
3351 cpu_register_physical_memory_offset(GCPhys, cb, IO_MEM_UNASSIGNED, GCPhys);
3352 else if (fHasHCHandler)
3353 {
3354 if (!fRestoreAsRAM)
3355 {
3356 Assert(GCPhys > MMR3PhysGetRamSize(pVM));
3357 cpu_register_physical_memory_offset(GCPhys, cb, IO_MEM_UNASSIGNED, GCPhys);
3358 }
3359 else
3360 {
3361 Assert(RT_ALIGN_T(GCPhys, PAGE_SIZE, RTGCPHYS) == GCPhys);
3362 Assert(RT_ALIGN_T(cb, PAGE_SIZE, RTGCPHYS) == cb);
3363 cpu_register_physical_memory_offset(GCPhys, cb, GCPhys, GCPhys);
3364 }
3365 }
3366 PDMCritSectLeave(&pVM->rem.s.CritSectRegister);
3367
3368 ASMAtomicDecU32(&pVM->rem.s.cIgnoreAll);
3369}
3370
3371/**
3372 * Notification about a successful PGMR3HandlerPhysicalDeregister() operation.
3373 *
3374 * @param pVM VM Handle.
3375 * @param enmType Handler type.
3376 * @param GCPhys Handler range address.
3377 * @param cb Size of the handler range.
3378 * @param fHasHCHandler Set if the handler has a HC callback function.
3379 * @param fRestoreAsRAM Whether the to restore it as normal RAM or as unassigned memory.
3380 */
3381REMR3DECL(void) REMR3NotifyHandlerPhysicalDeregister(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS cb, bool fHasHCHandler, bool fRestoreAsRAM)
3382{
3383 REMR3ReplayHandlerNotifications(pVM);
3384 remR3NotifyHandlerPhysicalDeregister(pVM, enmType, GCPhys, cb, fHasHCHandler, fRestoreAsRAM);
3385}
3386
3387
3388/**
3389 * Notification about a successful PGMR3HandlerPhysicalModify() call.
3390 *
3391 * @param pVM VM Handle.
3392 * @param enmType Handler type.
3393 * @param GCPhysOld Old handler range address.
3394 * @param GCPhysNew New handler range address.
3395 * @param cb Size of the handler range.
3396 * @param fHasHCHandler Set if the handler has a HC callback function.
3397 * @param fRestoreAsRAM Whether the to restore it as normal RAM or as unassigned memory.
3398 */
3399static void remR3NotifyHandlerPhysicalModify(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhysOld, RTGCPHYS GCPhysNew, RTGCPHYS cb, bool fHasHCHandler, bool fRestoreAsRAM)
3400{
3401 Log(("REMR3NotifyHandlerPhysicalModify: enmType=%d GCPhysOld=%RGp GCPhysNew=%RGp cb=%RGp fHasHCHandler=%RTbool fRestoreAsRAM=%RTbool\n",
3402 enmType, GCPhysOld, GCPhysNew, cb, fHasHCHandler, fRestoreAsRAM));
3403 VM_ASSERT_EMT(pVM);
3404 AssertReleaseMsg(enmType != PGMPHYSHANDLERTYPE_MMIO, ("enmType=%d\n", enmType));
3405
3406 if (fHasHCHandler)
3407 {
3408 ASMAtomicIncU32(&pVM->rem.s.cIgnoreAll);
3409
3410 /*
3411 * Reset the old page.
3412 */
3413 PDMCritSectEnter(&pVM->rem.s.CritSectRegister, VERR_SEM_BUSY);
3414 if (!fRestoreAsRAM)
3415 cpu_register_physical_memory_offset(GCPhysOld, cb, IO_MEM_UNASSIGNED, GCPhysOld);
3416 else
3417 {
3418 /* This is not perfect, but it'll do for PD monitoring... */
3419 Assert(cb == PAGE_SIZE);
3420 Assert(RT_ALIGN_T(GCPhysOld, PAGE_SIZE, RTGCPHYS) == GCPhysOld);
3421 cpu_register_physical_memory_offset(GCPhysOld, cb, GCPhysOld, GCPhysOld);
3422 }
3423
3424 /*
3425 * Update the new page.
3426 */
3427 Assert(RT_ALIGN_T(GCPhysNew, PAGE_SIZE, RTGCPHYS) == GCPhysNew);
3428 Assert(RT_ALIGN_T(cb, PAGE_SIZE, RTGCPHYS) == cb);
3429 cpu_register_physical_memory_offset(GCPhysNew, cb, pVM->rem.s.iHandlerMemType, GCPhysNew);
3430 PDMCritSectLeave(&pVM->rem.s.CritSectRegister);
3431
3432 ASMAtomicDecU32(&pVM->rem.s.cIgnoreAll);
3433 }
3434}
3435
3436/**
3437 * Notification about a successful PGMR3HandlerPhysicalModify() call.
3438 *
3439 * @param pVM VM Handle.
3440 * @param enmType Handler type.
3441 * @param GCPhysOld Old handler range address.
3442 * @param GCPhysNew New handler range address.
3443 * @param cb Size of the handler range.
3444 * @param fHasHCHandler Set if the handler has a HC callback function.
3445 * @param fRestoreAsRAM Whether the to restore it as normal RAM or as unassigned memory.
3446 */
3447REMR3DECL(void) REMR3NotifyHandlerPhysicalModify(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhysOld, RTGCPHYS GCPhysNew, RTGCPHYS cb, bool fHasHCHandler, bool fRestoreAsRAM)
3448{
3449 REMR3ReplayHandlerNotifications(pVM);
3450
3451 remR3NotifyHandlerPhysicalModify(pVM, enmType, GCPhysOld, GCPhysNew, cb, fHasHCHandler, fRestoreAsRAM);
3452}
3453
3454/**
3455 * Checks if we're handling access to this page or not.
3456 *
3457 * @returns true if we're trapping access.
3458 * @returns false if we aren't.
3459 * @param pVM The VM handle.
3460 * @param GCPhys The physical address.
3461 *
3462 * @remark This function will only work correctly in VBOX_STRICT builds!
3463 */
3464REMR3DECL(bool) REMR3IsPageAccessHandled(PVM pVM, RTGCPHYS GCPhys)
3465{
3466#ifdef VBOX_STRICT
3467 ram_addr_t off;
3468 REMR3ReplayHandlerNotifications(pVM);
3469
3470 off = get_phys_page_offset(GCPhys);
3471 return (off & PAGE_OFFSET_MASK) == pVM->rem.s.iHandlerMemType
3472 || (off & PAGE_OFFSET_MASK) == pVM->rem.s.iMMIOMemType
3473 || (off & PAGE_OFFSET_MASK) == IO_MEM_ROM;
3474#else
3475 return false;
3476#endif
3477}
3478
3479
3480/**
3481 * Deals with a rare case in get_phys_addr_code where the code
3482 * is being monitored.
3483 *
3484 * It could also be an MMIO page, in which case we will raise a fatal error.
3485 *
3486 * @returns The physical address corresponding to addr.
3487 * @param env The cpu environment.
3488 * @param addr The virtual address.
3489 * @param pTLBEntry The TLB entry.
3490 */
3491target_ulong remR3PhysGetPhysicalAddressCode(CPUX86State *env,
3492 target_ulong addr,
3493 CPUTLBEntry *pTLBEntry,
3494 target_phys_addr_t ioTLBEntry)
3495{
3496 PVM pVM = env->pVM;
3497
3498 if ((ioTLBEntry & ~TARGET_PAGE_MASK) == pVM->rem.s.iHandlerMemType)
3499 {
3500 /* If code memory is being monitored, appropriate IOTLB entry will have
3501 handler IO type, and addend will provide real physical address, no
3502 matter if we store VA in TLB or not, as handlers are always passed PA */
3503 target_ulong ret = (ioTLBEntry & TARGET_PAGE_MASK) + addr;
3504 return ret;
3505 }
3506 LogRel(("\nTrying to execute code with memory type addr_code=%RGv addend=%RGp at %RGv! (iHandlerMemType=%#x iMMIOMemType=%#x IOTLB=%RGp)\n"
3507 "*** handlers\n",
3508 (RTGCPTR)pTLBEntry->addr_code, (RTGCPHYS)pTLBEntry->addend, (RTGCPTR)addr, pVM->rem.s.iHandlerMemType, pVM->rem.s.iMMIOMemType, (RTGCPHYS)ioTLBEntry));
3509 DBGFR3Info(pVM->pUVM, "handlers", NULL, DBGFR3InfoLogRelHlp());
3510 LogRel(("*** mmio\n"));
3511 DBGFR3Info(pVM->pUVM, "mmio", NULL, DBGFR3InfoLogRelHlp());
3512 LogRel(("*** phys\n"));
3513 DBGFR3Info(pVM->pUVM, "phys", NULL, DBGFR3InfoLogRelHlp());
3514 cpu_abort(env, "Trying to execute code with memory type addr_code=%RGv addend=%RGp at %RGv. (iHandlerMemType=%#x iMMIOMemType=%#x)\n",
3515 (RTGCPTR)pTLBEntry->addr_code, (RTGCPHYS)pTLBEntry->addend, (RTGCPTR)addr, pVM->rem.s.iHandlerMemType, pVM->rem.s.iMMIOMemType);
3516 AssertFatalFailed();
3517}
3518
3519/**
3520 * Read guest RAM and ROM.
3521 *
3522 * @param SrcGCPhys The source address (guest physical).
3523 * @param pvDst The destination address.
3524 * @param cb Number of bytes
3525 */
3526void remR3PhysRead(RTGCPHYS SrcGCPhys, void *pvDst, unsigned cb)
3527{
3528 STAM_PROFILE_ADV_START(&gStatMemRead, a);
3529 VBOX_CHECK_ADDR(SrcGCPhys);
3530 PGMPhysRead(cpu_single_env->pVM, SrcGCPhys, pvDst, cb);
3531#ifdef VBOX_DEBUG_PHYS
3532 LogRel(("read(%d): %08x\n", cb, (uint32_t)SrcGCPhys));
3533#endif
3534 STAM_PROFILE_ADV_STOP(&gStatMemRead, a);
3535}
3536
3537
3538/**
3539 * Read guest RAM and ROM, unsigned 8-bit.
3540 *
3541 * @param SrcGCPhys The source address (guest physical).
3542 */
3543RTCCUINTREG remR3PhysReadU8(RTGCPHYS SrcGCPhys)
3544{
3545 uint8_t val;
3546 STAM_PROFILE_ADV_START(&gStatMemRead, a);
3547 VBOX_CHECK_ADDR(SrcGCPhys);
3548 val = PGMR3PhysReadU8(cpu_single_env->pVM, SrcGCPhys);
3549 STAM_PROFILE_ADV_STOP(&gStatMemRead, a);
3550#ifdef VBOX_DEBUG_PHYS
3551 LogRel(("readu8: %x <- %08x\n", val, (uint32_t)SrcGCPhys));
3552#endif
3553 return val;
3554}
3555
3556
3557/**
3558 * Read guest RAM and ROM, signed 8-bit.
3559 *
3560 * @param SrcGCPhys The source address (guest physical).
3561 */
3562RTCCINTREG remR3PhysReadS8(RTGCPHYS SrcGCPhys)
3563{
3564 int8_t val;
3565 STAM_PROFILE_ADV_START(&gStatMemRead, a);
3566 VBOX_CHECK_ADDR(SrcGCPhys);
3567 val = PGMR3PhysReadU8(cpu_single_env->pVM, SrcGCPhys);
3568 STAM_PROFILE_ADV_STOP(&gStatMemRead, a);
3569#ifdef VBOX_DEBUG_PHYS
3570 LogRel(("reads8: %x <- %08x\n", val, (uint32_t)SrcGCPhys));
3571#endif
3572 return val;
3573}
3574
3575
3576/**
3577 * Read guest RAM and ROM, unsigned 16-bit.
3578 *
3579 * @param SrcGCPhys The source address (guest physical).
3580 */
3581RTCCUINTREG remR3PhysReadU16(RTGCPHYS SrcGCPhys)
3582{
3583 uint16_t val;
3584 STAM_PROFILE_ADV_START(&gStatMemRead, a);
3585 VBOX_CHECK_ADDR(SrcGCPhys);
3586 val = PGMR3PhysReadU16(cpu_single_env->pVM, SrcGCPhys);
3587 STAM_PROFILE_ADV_STOP(&gStatMemRead, a);
3588#ifdef VBOX_DEBUG_PHYS
3589 LogRel(("readu16: %x <- %08x\n", val, (uint32_t)SrcGCPhys));
3590#endif
3591 return val;
3592}
3593
3594
3595/**
3596 * Read guest RAM and ROM, signed 16-bit.
3597 *
3598 * @param SrcGCPhys The source address (guest physical).
3599 */
3600RTCCINTREG remR3PhysReadS16(RTGCPHYS SrcGCPhys)
3601{
3602 int16_t val;
3603 STAM_PROFILE_ADV_START(&gStatMemRead, a);
3604 VBOX_CHECK_ADDR(SrcGCPhys);
3605 val = PGMR3PhysReadU16(cpu_single_env->pVM, SrcGCPhys);
3606 STAM_PROFILE_ADV_STOP(&gStatMemRead, a);
3607#ifdef VBOX_DEBUG_PHYS
3608 LogRel(("reads16: %x <- %08x\n", (uint16_t)val, (uint32_t)SrcGCPhys));
3609#endif
3610 return val;
3611}
3612
3613
3614/**
3615 * Read guest RAM and ROM, unsigned 32-bit.
3616 *
3617 * @param SrcGCPhys The source address (guest physical).
3618 */
3619RTCCUINTREG remR3PhysReadU32(RTGCPHYS SrcGCPhys)
3620{
3621 uint32_t val;
3622 STAM_PROFILE_ADV_START(&gStatMemRead, a);
3623 VBOX_CHECK_ADDR(SrcGCPhys);
3624 val = PGMR3PhysReadU32(cpu_single_env->pVM, SrcGCPhys);
3625 STAM_PROFILE_ADV_STOP(&gStatMemRead, a);
3626#ifdef VBOX_DEBUG_PHYS
3627 LogRel(("readu32: %x <- %08x\n", val, (uint32_t)SrcGCPhys));
3628#endif
3629 return val;
3630}
3631
3632
3633/**
3634 * Read guest RAM and ROM, signed 32-bit.
3635 *
3636 * @param SrcGCPhys The source address (guest physical).
3637 */
3638RTCCINTREG remR3PhysReadS32(RTGCPHYS SrcGCPhys)
3639{
3640 int32_t val;
3641 STAM_PROFILE_ADV_START(&gStatMemRead, a);
3642 VBOX_CHECK_ADDR(SrcGCPhys);
3643 val = PGMR3PhysReadU32(cpu_single_env->pVM, SrcGCPhys);
3644 STAM_PROFILE_ADV_STOP(&gStatMemRead, a);
3645#ifdef VBOX_DEBUG_PHYS
3646 LogRel(("reads32: %x <- %08x\n", val, (uint32_t)SrcGCPhys));
3647#endif
3648 return val;
3649}
3650
3651
3652/**
3653 * Read guest RAM and ROM, unsigned 64-bit.
3654 *
3655 * @param SrcGCPhys The source address (guest physical).
3656 */
3657uint64_t remR3PhysReadU64(RTGCPHYS SrcGCPhys)
3658{
3659 uint64_t val;
3660 STAM_PROFILE_ADV_START(&gStatMemRead, a);
3661 VBOX_CHECK_ADDR(SrcGCPhys);
3662 val = PGMR3PhysReadU64(cpu_single_env->pVM, SrcGCPhys);
3663 STAM_PROFILE_ADV_STOP(&gStatMemRead, a);
3664#ifdef VBOX_DEBUG_PHYS
3665 LogRel(("readu64: %llx <- %08x\n", val, (uint32_t)SrcGCPhys));
3666#endif
3667 return val;
3668}
3669
3670
3671/**
3672 * Read guest RAM and ROM, signed 64-bit.
3673 *
3674 * @param SrcGCPhys The source address (guest physical).
3675 */
3676int64_t remR3PhysReadS64(RTGCPHYS SrcGCPhys)
3677{
3678 int64_t val;
3679 STAM_PROFILE_ADV_START(&gStatMemRead, a);
3680 VBOX_CHECK_ADDR(SrcGCPhys);
3681 val = PGMR3PhysReadU64(cpu_single_env->pVM, SrcGCPhys);
3682 STAM_PROFILE_ADV_STOP(&gStatMemRead, a);
3683#ifdef VBOX_DEBUG_PHYS
3684 LogRel(("reads64: %llx <- %08x\n", val, (uint32_t)SrcGCPhys));
3685#endif
3686 return val;
3687}
3688
3689
3690/**
3691 * Write guest RAM.
3692 *
3693 * @param DstGCPhys The destination address (guest physical).
3694 * @param pvSrc The source address.
3695 * @param cb Number of bytes to write
3696 */
3697void remR3PhysWrite(RTGCPHYS DstGCPhys, const void *pvSrc, unsigned cb)
3698{
3699 STAM_PROFILE_ADV_START(&gStatMemWrite, a);
3700 VBOX_CHECK_ADDR(DstGCPhys);
3701 PGMPhysWrite(cpu_single_env->pVM, DstGCPhys, pvSrc, cb);
3702 STAM_PROFILE_ADV_STOP(&gStatMemWrite, a);
3703#ifdef VBOX_DEBUG_PHYS
3704 LogRel(("write(%d): %08x\n", cb, (uint32_t)DstGCPhys));
3705#endif
3706}
3707
3708
3709/**
3710 * Write guest RAM, unsigned 8-bit.
3711 *
3712 * @param DstGCPhys The destination address (guest physical).
3713 * @param val Value
3714 */
3715void remR3PhysWriteU8(RTGCPHYS DstGCPhys, uint8_t val)
3716{
3717 STAM_PROFILE_ADV_START(&gStatMemWrite, a);
3718 VBOX_CHECK_ADDR(DstGCPhys);
3719 PGMR3PhysWriteU8(cpu_single_env->pVM, DstGCPhys, val);
3720 STAM_PROFILE_ADV_STOP(&gStatMemWrite, a);
3721#ifdef VBOX_DEBUG_PHYS
3722 LogRel(("writeu8: %x -> %08x\n", val, (uint32_t)DstGCPhys));
3723#endif
3724}
3725
3726
3727/**
3728 * Write guest RAM, unsigned 8-bit.
3729 *
3730 * @param DstGCPhys The destination address (guest physical).
3731 * @param val Value
3732 */
3733void remR3PhysWriteU16(RTGCPHYS DstGCPhys, uint16_t val)
3734{
3735 STAM_PROFILE_ADV_START(&gStatMemWrite, a);
3736 VBOX_CHECK_ADDR(DstGCPhys);
3737 PGMR3PhysWriteU16(cpu_single_env->pVM, DstGCPhys, val);
3738 STAM_PROFILE_ADV_STOP(&gStatMemWrite, a);
3739#ifdef VBOX_DEBUG_PHYS
3740 LogRel(("writeu16: %x -> %08x\n", val, (uint32_t)DstGCPhys));
3741#endif
3742}
3743
3744
3745/**
3746 * Write guest RAM, unsigned 32-bit.
3747 *
3748 * @param DstGCPhys The destination address (guest physical).
3749 * @param val Value
3750 */
3751void remR3PhysWriteU32(RTGCPHYS DstGCPhys, uint32_t val)
3752{
3753 STAM_PROFILE_ADV_START(&gStatMemWrite, a);
3754 VBOX_CHECK_ADDR(DstGCPhys);
3755 PGMR3PhysWriteU32(cpu_single_env->pVM, DstGCPhys, val);
3756 STAM_PROFILE_ADV_STOP(&gStatMemWrite, a);
3757#ifdef VBOX_DEBUG_PHYS
3758 LogRel(("writeu32: %x -> %08x\n", val, (uint32_t)DstGCPhys));
3759#endif
3760}
3761
3762
3763/**
3764 * Write guest RAM, unsigned 64-bit.
3765 *
3766 * @param DstGCPhys The destination address (guest physical).
3767 * @param val Value
3768 */
3769void remR3PhysWriteU64(RTGCPHYS DstGCPhys, uint64_t val)
3770{
3771 STAM_PROFILE_ADV_START(&gStatMemWrite, a);
3772 VBOX_CHECK_ADDR(DstGCPhys);
3773 PGMR3PhysWriteU64(cpu_single_env->pVM, DstGCPhys, val);
3774 STAM_PROFILE_ADV_STOP(&gStatMemWrite, a);
3775#ifdef VBOX_DEBUG_PHYS
3776 LogRel(("writeu64: %llx -> %08x\n", val, (uint32_t)DstGCPhys));
3777#endif
3778}
3779
3780#undef LOG_GROUP
3781#define LOG_GROUP LOG_GROUP_REM_MMIO
3782
3783/** Read MMIO memory. */
3784static uint32_t remR3MMIOReadU8(void *pvEnv, target_phys_addr_t GCPhys)
3785{
3786 CPUX86State *env = (CPUX86State *)pvEnv;
3787 uint32_t u32 = 0;
3788 int rc = IOMMMIORead(env->pVM, env->pVCpu, GCPhys, &u32, 1);
3789 AssertMsg(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc)); NOREF(rc);
3790 Log2(("remR3MMIOReadU8: GCPhys=%RGp -> %02x\n", (RTGCPHYS)GCPhys, u32));
3791 return u32;
3792}
3793
3794/** Read MMIO memory. */
3795static uint32_t remR3MMIOReadU16(void *pvEnv, target_phys_addr_t GCPhys)
3796{
3797 CPUX86State *env = (CPUX86State *)pvEnv;
3798 uint32_t u32 = 0;
3799 int rc = IOMMMIORead(env->pVM, env->pVCpu, GCPhys, &u32, 2);
3800 AssertMsg(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc)); NOREF(rc);
3801 Log2(("remR3MMIOReadU16: GCPhys=%RGp -> %04x\n", (RTGCPHYS)GCPhys, u32));
3802 return u32;
3803}
3804
3805/** Read MMIO memory. */
3806static uint32_t remR3MMIOReadU32(void *pvEnv, target_phys_addr_t GCPhys)
3807{
3808 CPUX86State *env = (CPUX86State *)pvEnv;
3809 uint32_t u32 = 0;
3810 int rc = IOMMMIORead(env->pVM, env->pVCpu, GCPhys, &u32, 4);
3811 AssertMsg(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc)); NOREF(rc);
3812 Log2(("remR3MMIOReadU32: GCPhys=%RGp -> %08x\n", (RTGCPHYS)GCPhys, u32));
3813 return u32;
3814}
3815
3816/** Write to MMIO memory. */
3817static void remR3MMIOWriteU8(void *pvEnv, target_phys_addr_t GCPhys, uint32_t u32)
3818{
3819 CPUX86State *env = (CPUX86State *)pvEnv;
3820 int rc;
3821 Log2(("remR3MMIOWriteU8: GCPhys=%RGp u32=%#x\n", (RTGCPHYS)GCPhys, u32));
3822 rc = IOMMMIOWrite(env->pVM, env->pVCpu, GCPhys, u32, 1);
3823 AssertMsg(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc)); NOREF(rc);
3824}
3825
3826/** Write to MMIO memory. */
3827static void remR3MMIOWriteU16(void *pvEnv, target_phys_addr_t GCPhys, uint32_t u32)
3828{
3829 CPUX86State *env = (CPUX86State *)pvEnv;
3830 int rc;
3831 Log2(("remR3MMIOWriteU16: GCPhys=%RGp u32=%#x\n", (RTGCPHYS)GCPhys, u32));
3832 rc = IOMMMIOWrite(env->pVM, env->pVCpu, GCPhys, u32, 2);
3833 AssertMsg(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc)); NOREF(rc);
3834}
3835
3836/** Write to MMIO memory. */
3837static void remR3MMIOWriteU32(void *pvEnv, target_phys_addr_t GCPhys, uint32_t u32)
3838{
3839 CPUX86State *env = (CPUX86State *)pvEnv;
3840 int rc;
3841 Log2(("remR3MMIOWriteU32: GCPhys=%RGp u32=%#x\n", (RTGCPHYS)GCPhys, u32));
3842 rc = IOMMMIOWrite(env->pVM, env->pVCpu, GCPhys, u32, 4);
3843 AssertMsg(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc)); NOREF(rc);
3844}
3845
3846
3847#undef LOG_GROUP
3848#define LOG_GROUP LOG_GROUP_REM_HANDLER
3849
3850/* !!!WARNING!!! This is extremely hackish right now, we assume it's only for LFB access! !!!WARNING!!! */
3851
3852static uint32_t remR3HandlerReadU8(void *pvVM, target_phys_addr_t GCPhys)
3853{
3854 uint8_t u8;
3855 Log2(("remR3HandlerReadU8: GCPhys=%RGp\n", (RTGCPHYS)GCPhys));
3856 PGMPhysRead((PVM)pvVM, GCPhys, &u8, sizeof(u8));
3857 return u8;
3858}
3859
3860static uint32_t remR3HandlerReadU16(void *pvVM, target_phys_addr_t GCPhys)
3861{
3862 uint16_t u16;
3863 Log2(("remR3HandlerReadU16: GCPhys=%RGp\n", (RTGCPHYS)GCPhys));
3864 PGMPhysRead((PVM)pvVM, GCPhys, &u16, sizeof(u16));
3865 return u16;
3866}
3867
3868static uint32_t remR3HandlerReadU32(void *pvVM, target_phys_addr_t GCPhys)
3869{
3870 uint32_t u32;
3871 Log2(("remR3HandlerReadU32: GCPhys=%RGp\n", (RTGCPHYS)GCPhys));
3872 PGMPhysRead((PVM)pvVM, GCPhys, &u32, sizeof(u32));
3873 return u32;
3874}
3875
3876static void remR3HandlerWriteU8(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32)
3877{
3878 Log2(("remR3HandlerWriteU8: GCPhys=%RGp u32=%#x\n", (RTGCPHYS)GCPhys, u32));
3879 PGMPhysWrite((PVM)pvVM, GCPhys, &u32, sizeof(uint8_t));
3880}
3881
3882static void remR3HandlerWriteU16(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32)
3883{
3884 Log2(("remR3HandlerWriteU16: GCPhys=%RGp u32=%#x\n", (RTGCPHYS)GCPhys, u32));
3885 PGMPhysWrite((PVM)pvVM, GCPhys, &u32, sizeof(uint16_t));
3886}
3887
3888static void remR3HandlerWriteU32(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32)
3889{
3890 Log2(("remR3HandlerWriteU32: GCPhys=%RGp u32=%#x\n", (RTGCPHYS)GCPhys, u32));
3891 PGMPhysWrite((PVM)pvVM, GCPhys, &u32, sizeof(uint32_t));
3892}
3893
3894/* -+- disassembly -+- */
3895
3896#undef LOG_GROUP
3897#define LOG_GROUP LOG_GROUP_REM_DISAS
3898
3899
3900/**
3901 * Enables or disables singled stepped disassembly.
3902 *
3903 * @returns VBox status code.
3904 * @param pVM VM handle.
3905 * @param fEnable To enable set this flag, to disable clear it.
3906 */
3907static DECLCALLBACK(int) remR3DisasEnableStepping(PVM pVM, bool fEnable)
3908{
3909 LogFlow(("remR3DisasEnableStepping: fEnable=%d\n", fEnable));
3910 VM_ASSERT_EMT(pVM);
3911
3912 if (fEnable)
3913 pVM->rem.s.Env.state |= CPU_EMULATE_SINGLE_STEP;
3914 else
3915 pVM->rem.s.Env.state &= ~CPU_EMULATE_SINGLE_STEP;
3916#ifdef REM_USE_QEMU_SINGLE_STEP_FOR_LOGGING
3917 cpu_single_step(&pVM->rem.s.Env, fEnable);
3918#endif
3919 return VINF_SUCCESS;
3920}
3921
3922
3923/**
3924 * Enables or disables singled stepped disassembly.
3925 *
3926 * @returns VBox status code.
3927 * @param pVM VM handle.
3928 * @param fEnable To enable set this flag, to disable clear it.
3929 */
3930REMR3DECL(int) REMR3DisasEnableStepping(PVM pVM, bool fEnable)
3931{
3932 int rc;
3933
3934 LogFlow(("REMR3DisasEnableStepping: fEnable=%d\n", fEnable));
3935 if (VM_IS_EMT(pVM))
3936 return remR3DisasEnableStepping(pVM, fEnable);
3937
3938 rc = VMR3ReqPriorityCallWait(pVM, VMCPUID_ANY, (PFNRT)remR3DisasEnableStepping, 2, pVM, fEnable);
3939 AssertRC(rc);
3940 return rc;
3941}
3942
3943
3944#if defined(VBOX_WITH_DEBUGGER) && !(defined(RT_OS_WINDOWS) && defined(RT_ARCH_AMD64))
3945/**
3946 * External Debugger Command: .remstep [on|off|1|0]
3947 */
3948static DECLCALLBACK(int) remR3CmdDisasEnableStepping(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
3949{
3950 int rc;
3951 PVM pVM = pUVM->pVM;
3952
3953 if (cArgs == 0)
3954 /*
3955 * Print the current status.
3956 */
3957 rc = DBGCCmdHlpPrintf(pCmdHlp, "DisasStepping is %s\n",
3958 pVM->rem.s.Env.state & CPU_EMULATE_SINGLE_STEP ? "enabled" : "disabled");
3959 else
3960 {
3961 /*
3962 * Convert the argument and change the mode.
3963 */
3964 bool fEnable;
3965 rc = DBGCCmdHlpVarToBool(pCmdHlp, &paArgs[0], &fEnable);
3966 if (RT_SUCCESS(rc))
3967 {
3968 rc = REMR3DisasEnableStepping(pVM, fEnable);
3969 if (RT_SUCCESS(rc))
3970 rc = DBGCCmdHlpPrintf(pCmdHlp, "DisasStepping was %s\n", fEnable ? "enabled" : "disabled");
3971 else
3972 rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "REMR3DisasEnableStepping");
3973 }
3974 else
3975 rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "DBGCCmdHlpVarToBool");
3976 }
3977 return rc;
3978}
3979#endif /* VBOX_WITH_DEBUGGER && !win.amd64 */
3980
3981
3982/**
3983 * Disassembles one instruction and prints it to the log.
3984 *
3985 * @returns Success indicator.
3986 * @param env Pointer to the recompiler CPU structure.
3987 * @param f32BitCode Indicates that whether or not the code should
3988 * be disassembled as 16 or 32 bit. If -1 the CS
3989 * selector will be inspected.
3990 * @param pszPrefix
3991 */
3992bool remR3DisasInstr(CPUX86State *env, int f32BitCode, char *pszPrefix)
3993{
3994 PVM pVM = env->pVM;
3995 const bool fLog = LogIsEnabled();
3996 const bool fLog2 = LogIs2Enabled();
3997 int rc = VINF_SUCCESS;
3998
3999 /*
4000 * Don't bother if there ain't any log output to do.
4001 */
4002 if (!fLog && !fLog2)
4003 return true;
4004
4005 /*
4006 * Update the state so DBGF reads the correct register values.
4007 */
4008 remR3StateUpdate(pVM, env->pVCpu);
4009
4010 /*
4011 * Log registers if requested.
4012 */
4013 if (fLog2)
4014 DBGFR3_INFO_LOG(pVM, "cpumguest", pszPrefix);
4015
4016 /*
4017 * Disassemble to log.
4018 */
4019 if (fLog)
4020 {
4021 PVMCPU pVCpu = VMMGetCpu(pVM);
4022 char szBuf[256];
4023 szBuf[0] = '\0';
4024 int rc = DBGFR3DisasInstrEx(pVCpu->pVMR3->pUVM,
4025 pVCpu->idCpu,
4026 0, /* Sel */
4027 0, /* GCPtr */
4028 DBGF_DISAS_FLAGS_CURRENT_GUEST
4029 | DBGF_DISAS_FLAGS_DEFAULT_MODE,
4030 szBuf,
4031 sizeof(szBuf),
4032 NULL);
4033 if (RT_FAILURE(rc))
4034 RTStrPrintf(szBuf, sizeof(szBuf), "DBGFR3DisasInstrEx failed with rc=%Rrc\n", rc);
4035 if (pszPrefix && *pszPrefix)
4036 RTLogPrintf("%s-CPU%d: %s\n", pszPrefix, pVCpu->idCpu, szBuf);
4037 else
4038 RTLogPrintf("CPU%d: %s\n", pVCpu->idCpu, szBuf);
4039 }
4040
4041 return RT_SUCCESS(rc);
4042}
4043
4044
4045/**
4046 * Disassemble recompiled code.
4047 *
4048 * @param phFileIgnored Ignored, logfile usually.
4049 * @param pvCode Pointer to the code block.
4050 * @param cb Size of the code block.
4051 */
4052void disas(FILE *phFile, void *pvCode, unsigned long cb)
4053{
4054 if (LogIs2Enabled())
4055 {
4056 unsigned off = 0;
4057 char szOutput[256];
4058 DISCPUSTATE Cpu;
4059#ifdef RT_ARCH_X86
4060 DISCPUMODE enmCpuMode = DISCPUMODE_32BIT;
4061#else
4062 DISCPUMODE enmCpuMode = DISCPUMODE_64BIT;
4063#endif
4064
4065 RTLogPrintf("Recompiled Code: %p %#lx (%ld) bytes\n", pvCode, cb, cb);
4066 while (off < cb)
4067 {
4068 uint32_t cbInstr;
4069 int rc = DISInstrToStr((uint8_t const *)pvCode + off, enmCpuMode,
4070 &Cpu, &cbInstr, szOutput, sizeof(szOutput));
4071 if (RT_SUCCESS(rc))
4072 RTLogPrintf("%s", szOutput);
4073 else
4074 {
4075 RTLogPrintf("disas error %Rrc\n", rc);
4076 cbInstr = 1;
4077 }
4078 off += cbInstr;
4079 }
4080 }
4081}
4082
4083
4084/**
4085 * Disassemble guest code.
4086 *
4087 * @param phFileIgnored Ignored, logfile usually.
4088 * @param uCode The guest address of the code to disassemble. (flat?)
4089 * @param cb Number of bytes to disassemble.
4090 * @param fFlags Flags, probably something which tells if this is 16, 32 or 64 bit code.
4091 */
4092void target_disas(FILE *phFile, target_ulong uCode, target_ulong cb, int fFlags)
4093{
4094 if (LogIs2Enabled())
4095 {
4096 PVM pVM = cpu_single_env->pVM;
4097 PVMCPU pVCpu = cpu_single_env->pVCpu;
4098 RTSEL cs;
4099 RTGCUINTPTR eip;
4100
4101 Assert(pVCpu);
4102
4103 /*
4104 * Update the state so DBGF reads the correct register values (flags).
4105 */
4106 remR3StateUpdate(pVM, pVCpu);
4107
4108 /*
4109 * Do the disassembling.
4110 */
4111 RTLogPrintf("Guest Code: PC=%llx %llx bytes fFlags=%d\n", (uint64_t)uCode, (uint64_t)cb, fFlags);
4112 cs = cpu_single_env->segs[R_CS].selector;
4113 eip = uCode - cpu_single_env->segs[R_CS].base;
4114 for (;;)
4115 {
4116 char szBuf[256];
4117 uint32_t cbInstr;
4118 int rc = DBGFR3DisasInstrEx(pVM->pUVM,
4119 pVCpu->idCpu,
4120 cs,
4121 eip,
4122 DBGF_DISAS_FLAGS_DEFAULT_MODE,
4123 szBuf, sizeof(szBuf),
4124 &cbInstr);
4125 if (RT_SUCCESS(rc))
4126 RTLogPrintf("%llx %s\n", (uint64_t)uCode, szBuf);
4127 else
4128 {
4129 RTLogPrintf("%llx %04x:%llx: %s\n", (uint64_t)uCode, cs, (uint64_t)eip, szBuf);
4130 cbInstr = 1;
4131 }
4132
4133 /* next */
4134 if (cb <= cbInstr)
4135 break;
4136 cb -= cbInstr;
4137 uCode += cbInstr;
4138 eip += cbInstr;
4139 }
4140 }
4141}
4142
4143
4144/**
4145 * Looks up a guest symbol.
4146 *
4147 * @returns Pointer to symbol name. This is a static buffer.
4148 * @param orig_addr The address in question.
4149 */
4150const char *lookup_symbol(target_ulong orig_addr)
4151{
4152 PVM pVM = cpu_single_env->pVM;
4153 RTGCINTPTR off = 0;
4154 RTDBGSYMBOL Sym;
4155 DBGFADDRESS Addr;
4156
4157 int rc = DBGFR3AsSymbolByAddr(pVM->pUVM, DBGF_AS_GLOBAL, DBGFR3AddrFromFlat(pVM->pUVM, &Addr, orig_addr),
4158 &off, &Sym, NULL /*phMod*/);
4159 if (RT_SUCCESS(rc))
4160 {
4161 static char szSym[sizeof(Sym.szName) + 48];
4162 if (!off)
4163 RTStrPrintf(szSym, sizeof(szSym), "%s\n", Sym.szName);
4164 else if (off > 0)
4165 RTStrPrintf(szSym, sizeof(szSym), "%s+%x\n", Sym.szName, off);
4166 else
4167 RTStrPrintf(szSym, sizeof(szSym), "%s-%x\n", Sym.szName, -off);
4168 return szSym;
4169 }
4170 return "<N/A>";
4171}
4172
4173
4174#undef LOG_GROUP
4175#define LOG_GROUP LOG_GROUP_REM
4176
4177
4178/* -+- FF notifications -+- */
4179
4180
4181/**
4182 * Notification about a pending interrupt.
4183 *
4184 * @param pVM VM Handle.
4185 * @param pVCpu VMCPU Handle.
4186 * @param u8Interrupt Interrupt
4187 * @thread The emulation thread.
4188 */
4189REMR3DECL(void) REMR3NotifyPendingInterrupt(PVM pVM, PVMCPU pVCpu, uint8_t u8Interrupt)
4190{
4191 Assert(pVM->rem.s.u32PendingInterrupt == REM_NO_PENDING_IRQ);
4192 pVM->rem.s.u32PendingInterrupt = u8Interrupt;
4193}
4194
4195/**
4196 * Notification about a pending interrupt.
4197 *
4198 * @returns Pending interrupt or REM_NO_PENDING_IRQ
4199 * @param pVM VM Handle.
4200 * @param pVCpu VMCPU Handle.
4201 * @thread The emulation thread.
4202 */
4203REMR3DECL(uint32_t) REMR3QueryPendingInterrupt(PVM pVM, PVMCPU pVCpu)
4204{
4205 return pVM->rem.s.u32PendingInterrupt;
4206}
4207
4208/**
4209 * Notification about the interrupt FF being set.
4210 *
4211 * @param pVM VM Handle.
4212 * @param pVCpu VMCPU Handle.
4213 * @thread The emulation thread.
4214 */
4215REMR3DECL(void) REMR3NotifyInterruptSet(PVM pVM, PVMCPU pVCpu)
4216{
4217#ifndef IEM_VERIFICATION_MODE
4218 LogFlow(("REMR3NotifyInterruptSet: fInRem=%d interrupts %s\n", pVM->rem.s.fInREM,
4219 (pVM->rem.s.Env.eflags & IF_MASK) && !(pVM->rem.s.Env.hflags & HF_INHIBIT_IRQ_MASK) ? "enabled" : "disabled"));
4220 if (pVM->rem.s.fInREM)
4221 {
4222 ASMAtomicOrS32((int32_t volatile *)&cpu_single_env->interrupt_request,
4223 CPU_INTERRUPT_EXTERNAL_HARD);
4224 }
4225#endif
4226}
4227
4228
4229/**
4230 * Notification about the interrupt FF being set.
4231 *
4232 * @param pVM VM Handle.
4233 * @param pVCpu VMCPU Handle.
4234 * @thread Any.
4235 */
4236REMR3DECL(void) REMR3NotifyInterruptClear(PVM pVM, PVMCPU pVCpu)
4237{
4238 LogFlow(("REMR3NotifyInterruptClear:\n"));
4239 if (pVM->rem.s.fInREM)
4240 cpu_reset_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
4241}
4242
4243
4244/**
4245 * Notification about pending timer(s).
4246 *
4247 * @param pVM VM Handle.
4248 * @param pVCpuDst The target cpu for this notification.
4249 * TM will not broadcast pending timer events, but use
4250 * a dedicated EMT for them. So, only interrupt REM
4251 * execution if the given CPU is executing in REM.
4252 * @thread Any.
4253 */
4254REMR3DECL(void) REMR3NotifyTimerPending(PVM pVM, PVMCPU pVCpuDst)
4255{
4256#ifndef IEM_VERIFICATION_MODE
4257#ifndef DEBUG_bird
4258 LogFlow(("REMR3NotifyTimerPending: fInRem=%d\n", pVM->rem.s.fInREM));
4259#endif
4260 if (pVM->rem.s.fInREM)
4261 {
4262 if (pVM->rem.s.Env.pVCpu == pVCpuDst)
4263 {
4264 LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_5, LOG_GROUP_TM, ("REMR3NotifyTimerPending: setting\n"));
4265 ASMAtomicOrS32((int32_t volatile *)&pVM->rem.s.Env.interrupt_request,
4266 CPU_INTERRUPT_EXTERNAL_TIMER);
4267 }
4268 else
4269 LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_5, LOG_GROUP_TM, ("REMR3NotifyTimerPending: pVCpu:%p != pVCpuDst:%p\n", pVM->rem.s.Env.pVCpu, pVCpuDst));
4270 }
4271 else
4272 LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_5, LOG_GROUP_TM, ("REMR3NotifyTimerPending: !fInREM; cpu state=%d\n", VMCPU_GET_STATE(pVCpuDst)));
4273#endif
4274}
4275
4276
4277/**
4278 * Notification about pending DMA transfers.
4279 *
4280 * @param pVM VM Handle.
4281 * @thread Any.
4282 */
4283REMR3DECL(void) REMR3NotifyDmaPending(PVM pVM)
4284{
4285#ifndef IEM_VERIFICATION_MODE
4286 LogFlow(("REMR3NotifyDmaPending: fInRem=%d\n", pVM->rem.s.fInREM));
4287 if (pVM->rem.s.fInREM)
4288 {
4289 ASMAtomicOrS32((int32_t volatile *)&cpu_single_env->interrupt_request,
4290 CPU_INTERRUPT_EXTERNAL_DMA);
4291 }
4292#endif
4293}
4294
4295
4296/**
4297 * Notification about pending timer(s).
4298 *
4299 * @param pVM VM Handle.
4300 * @thread Any.
4301 */
4302REMR3DECL(void) REMR3NotifyQueuePending(PVM pVM)
4303{
4304#ifndef IEM_VERIFICATION_MODE
4305 LogFlow(("REMR3NotifyQueuePending: fInRem=%d\n", pVM->rem.s.fInREM));
4306 if (pVM->rem.s.fInREM)
4307 {
4308 ASMAtomicOrS32((int32_t volatile *)&cpu_single_env->interrupt_request,
4309 CPU_INTERRUPT_EXTERNAL_EXIT);
4310 }
4311#endif
4312}
4313
4314
4315/**
4316 * Notification about pending FF set by an external thread.
4317 *
4318 * @param pVM VM handle.
4319 * @thread Any.
4320 */
4321REMR3DECL(void) REMR3NotifyFF(PVM pVM)
4322{
4323#ifndef IEM_VERIFICATION_MODE
4324 LogFlow(("REMR3NotifyFF: fInRem=%d\n", pVM->rem.s.fInREM));
4325 if (pVM->rem.s.fInREM)
4326 {
4327 ASMAtomicOrS32((int32_t volatile *)&cpu_single_env->interrupt_request,
4328 CPU_INTERRUPT_EXTERNAL_EXIT);
4329 }
4330#endif
4331}
4332
4333
4334#ifdef VBOX_WITH_STATISTICS
4335void remR3ProfileStart(int statcode)
4336{
4337 STAMPROFILEADV *pStat;
4338 switch(statcode)
4339 {
4340 case STATS_EMULATE_SINGLE_INSTR:
4341 pStat = &gStatExecuteSingleInstr;
4342 break;
4343 case STATS_QEMU_COMPILATION:
4344 pStat = &gStatCompilationQEmu;
4345 break;
4346 case STATS_QEMU_RUN_EMULATED_CODE:
4347 pStat = &gStatRunCodeQEmu;
4348 break;
4349 case STATS_QEMU_TOTAL:
4350 pStat = &gStatTotalTimeQEmu;
4351 break;
4352 case STATS_QEMU_RUN_TIMERS:
4353 pStat = &gStatTimers;
4354 break;
4355 case STATS_TLB_LOOKUP:
4356 pStat= &gStatTBLookup;
4357 break;
4358 case STATS_IRQ_HANDLING:
4359 pStat= &gStatIRQ;
4360 break;
4361 case STATS_RAW_CHECK:
4362 pStat = &gStatRawCheck;
4363 break;
4364
4365 default:
4366 AssertMsgFailed(("unknown stat %d\n", statcode));
4367 return;
4368 }
4369 STAM_PROFILE_ADV_START(pStat, a);
4370}
4371
4372
4373void remR3ProfileStop(int statcode)
4374{
4375 STAMPROFILEADV *pStat;
4376 switch(statcode)
4377 {
4378 case STATS_EMULATE_SINGLE_INSTR:
4379 pStat = &gStatExecuteSingleInstr;
4380 break;
4381 case STATS_QEMU_COMPILATION:
4382 pStat = &gStatCompilationQEmu;
4383 break;
4384 case STATS_QEMU_RUN_EMULATED_CODE:
4385 pStat = &gStatRunCodeQEmu;
4386 break;
4387 case STATS_QEMU_TOTAL:
4388 pStat = &gStatTotalTimeQEmu;
4389 break;
4390 case STATS_QEMU_RUN_TIMERS:
4391 pStat = &gStatTimers;
4392 break;
4393 case STATS_TLB_LOOKUP:
4394 pStat= &gStatTBLookup;
4395 break;
4396 case STATS_IRQ_HANDLING:
4397 pStat= &gStatIRQ;
4398 break;
4399 case STATS_RAW_CHECK:
4400 pStat = &gStatRawCheck;
4401 break;
4402 default:
4403 AssertMsgFailed(("unknown stat %d\n", statcode));
4404 return;
4405 }
4406 STAM_PROFILE_ADV_STOP(pStat, a);
4407}
4408#endif
4409
4410/**
4411 * Raise an RC, force rem exit.
4412 *
4413 * @param pVM VM handle.
4414 * @param rc The rc.
4415 */
4416void remR3RaiseRC(PVM pVM, int rc)
4417{
4418 Log(("remR3RaiseRC: rc=%Rrc\n", rc));
4419 Assert(pVM->rem.s.fInREM);
4420 VM_ASSERT_EMT(pVM);
4421 pVM->rem.s.rc = rc;
4422 cpu_interrupt(&pVM->rem.s.Env, CPU_INTERRUPT_RC);
4423}
4424
4425
4426/* -+- timers -+- */
4427
4428uint64_t cpu_get_tsc(CPUX86State *env)
4429{
4430 STAM_COUNTER_INC(&gStatCpuGetTSC);
4431 return TMCpuTickGet(env->pVCpu);
4432}
4433
4434
4435/* -+- interrupts -+- */
4436
4437void cpu_set_ferr(CPUX86State *env)
4438{
4439 int rc = PDMIsaSetIrq(env->pVM, 13, 1, 0 /*uTagSrc*/);
4440 LogFlow(("cpu_set_ferr: rc=%d\n", rc)); NOREF(rc);
4441}
4442
4443int cpu_get_pic_interrupt(CPUX86State *env)
4444{
4445 uint8_t u8Interrupt;
4446 int rc;
4447
4448 /* When we fail to forward interrupts directly in raw mode, we fall back to the recompiler.
4449 * In that case we can't call PDMGetInterrupt anymore, because it has already cleared the interrupt
4450 * with the (a)pic.
4451 */
4452 /* Note! We assume we will go directly to the recompiler to handle the pending interrupt! */
4453 /** @todo r=bird: In the long run we should just do the interrupt handling in EM/CPUM/TRPM/somewhere and
4454 * if we cannot execute the interrupt handler in raw-mode just reschedule to REM. Once that is done we
4455 * remove this kludge. */
4456 if (env->pVM->rem.s.u32PendingInterrupt != REM_NO_PENDING_IRQ)
4457 {
4458 rc = VINF_SUCCESS;
4459 Assert(env->pVM->rem.s.u32PendingInterrupt <= 255);
4460 u8Interrupt = env->pVM->rem.s.u32PendingInterrupt;
4461 env->pVM->rem.s.u32PendingInterrupt = REM_NO_PENDING_IRQ;
4462 }
4463 else
4464 rc = PDMGetInterrupt(env->pVCpu, &u8Interrupt);
4465
4466 LogFlow(("cpu_get_pic_interrupt: u8Interrupt=%d rc=%Rrc pc=%04x:%08llx ~flags=%08llx\n",
4467 u8Interrupt, rc, env->segs[R_CS].selector, (uint64_t)env->eip, (uint64_t)env->eflags));
4468 if (RT_SUCCESS(rc))
4469 {
4470 if (VMCPU_FF_ISPENDING(env->pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC))
4471 env->interrupt_request |= CPU_INTERRUPT_HARD;
4472 return u8Interrupt;
4473 }
4474 return -1;
4475}
4476
4477
4478/* -+- local apic -+- */
4479
4480#if 0 /* CPUMSetGuestMsr does this now. */
4481void cpu_set_apic_base(CPUX86State *env, uint64_t val)
4482{
4483 int rc = PDMApicSetBase(env->pVM, val);
4484 LogFlow(("cpu_set_apic_base: val=%#llx rc=%Rrc\n", val, rc)); NOREF(rc);
4485}
4486#endif
4487
4488uint64_t cpu_get_apic_base(CPUX86State *env)
4489{
4490 uint64_t u64;
4491 int rc = CPUMQueryGuestMsr(env->pVCpu, MSR_IA32_APICBASE, &u64);
4492 if (RT_SUCCESS(rc))
4493 {
4494 LogFlow(("cpu_get_apic_base: returns %#llx \n", u64));
4495 return u64;
4496 }
4497 LogFlow(("cpu_get_apic_base: returns 0 (rc=%Rrc)\n", rc));
4498 return 0;
4499}
4500
4501void cpu_set_apic_tpr(CPUX86State *env, uint8_t val)
4502{
4503 int rc = PDMApicSetTPR(env->pVCpu, val << 4); /* cr8 bits 3-0 correspond to bits 7-4 of the task priority mmio register. */
4504 LogFlow(("cpu_set_apic_tpr: val=%#x rc=%Rrc\n", val, rc)); NOREF(rc);
4505}
4506
4507uint8_t cpu_get_apic_tpr(CPUX86State *env)
4508{
4509 uint8_t u8;
4510 int rc = PDMApicGetTPR(env->pVCpu, &u8, NULL);
4511 if (RT_SUCCESS(rc))
4512 {
4513 LogFlow(("cpu_get_apic_tpr: returns %#x\n", u8));
4514 return u8 >> 4; /* cr8 bits 3-0 correspond to bits 7-4 of the task priority mmio register. */
4515 }
4516 LogFlow(("cpu_get_apic_tpr: returns 0 (rc=%Rrc)\n", rc));
4517 return 0;
4518}
4519
4520/**
4521 * Read an MSR.
4522 *
4523 * @retval 0 success.
4524 * @retval -1 failure, raise \#GP(0).
4525 * @param env The cpu state.
4526 * @param idMsr The MSR to read.
4527 * @param puValue Where to return the value.
4528 */
4529int cpu_rdmsr(CPUX86State *env, uint32_t idMsr, uint64_t *puValue)
4530{
4531 Assert(env->pVCpu);
4532 return CPUMQueryGuestMsr(env->pVCpu, idMsr, puValue) == VINF_SUCCESS ? 0 : -1;
4533}
4534
4535/**
4536 * Write to an MSR.
4537 *
4538 * @retval 0 success.
4539 * @retval -1 failure, raise \#GP(0).
4540 * @param env The cpu state.
4541 * @param idMsr The MSR to read.
4542 * @param puValue Where to return the value.
4543 */
4544int cpu_wrmsr(CPUX86State *env, uint32_t idMsr, uint64_t uValue)
4545{
4546 Assert(env->pVCpu);
4547 return CPUMSetGuestMsr(env->pVCpu, idMsr, uValue) == VINF_SUCCESS ? 0 : -1;
4548}
4549
4550/* -+- I/O Ports -+- */
4551
4552#undef LOG_GROUP
4553#define LOG_GROUP LOG_GROUP_REM_IOPORT
4554
4555void cpu_outb(CPUX86State *env, pio_addr_t addr, uint8_t val)
4556{
4557 int rc;
4558
4559 if (addr != 0x80 && addr != 0x70 && addr != 0x61)
4560 Log2(("cpu_outb: addr=%#06x val=%#x\n", addr, val));
4561
4562 rc = IOMIOPortWrite(env->pVM, env->pVCpu, (RTIOPORT)addr, val, 1);
4563 if (RT_LIKELY(rc == VINF_SUCCESS))
4564 return;
4565 if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
4566 {
4567 Log(("cpu_outb: addr=%#06x val=%#x -> %Rrc\n", addr, val, rc));
4568 remR3RaiseRC(env->pVM, rc);
4569 return;
4570 }
4571 remAbort(rc, __FUNCTION__);
4572}
4573
4574void cpu_outw(CPUX86State *env, pio_addr_t addr, uint16_t val)
4575{
4576 //Log2(("cpu_outw: addr=%#06x val=%#x\n", addr, val));
4577 int rc = IOMIOPortWrite(env->pVM, env->pVCpu, (RTIOPORT)addr, val, 2);
4578 if (RT_LIKELY(rc == VINF_SUCCESS))
4579 return;
4580 if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
4581 {
4582 Log(("cpu_outw: addr=%#06x val=%#x -> %Rrc\n", addr, val, rc));
4583 remR3RaiseRC(env->pVM, rc);
4584 return;
4585 }
4586 remAbort(rc, __FUNCTION__);
4587}
4588
4589void cpu_outl(CPUX86State *env, pio_addr_t addr, uint32_t val)
4590{
4591 int rc;
4592 Log2(("cpu_outl: addr=%#06x val=%#x\n", addr, val));
4593 rc = IOMIOPortWrite(env->pVM, env->pVCpu, (RTIOPORT)addr, val, 4);
4594 if (RT_LIKELY(rc == VINF_SUCCESS))
4595 return;
4596 if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
4597 {
4598 Log(("cpu_outl: addr=%#06x val=%#x -> %Rrc\n", addr, val, rc));
4599 remR3RaiseRC(env->pVM, rc);
4600 return;
4601 }
4602 remAbort(rc, __FUNCTION__);
4603}
4604
4605uint8_t cpu_inb(CPUX86State *env, pio_addr_t addr)
4606{
4607 uint32_t u32 = 0;
4608 int rc = IOMIOPortRead(env->pVM, env->pVCpu, (RTIOPORT)addr, &u32, 1);
4609 if (RT_LIKELY(rc == VINF_SUCCESS))
4610 {
4611 if (/*addr != 0x61 && */addr != 0x71)
4612 Log2(("cpu_inb: addr=%#06x -> %#x\n", addr, u32));
4613 return (uint8_t)u32;
4614 }
4615 if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
4616 {
4617 Log(("cpu_inb: addr=%#06x -> %#x rc=%Rrc\n", addr, u32, rc));
4618 remR3RaiseRC(env->pVM, rc);
4619 return (uint8_t)u32;
4620 }
4621 remAbort(rc, __FUNCTION__);
4622 return UINT8_C(0xff);
4623}
4624
4625uint16_t cpu_inw(CPUX86State *env, pio_addr_t addr)
4626{
4627 uint32_t u32 = 0;
4628 int rc = IOMIOPortRead(env->pVM, env->pVCpu, (RTIOPORT)addr, &u32, 2);
4629 if (RT_LIKELY(rc == VINF_SUCCESS))
4630 {
4631 Log2(("cpu_inw: addr=%#06x -> %#x\n", addr, u32));
4632 return (uint16_t)u32;
4633 }
4634 if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
4635 {
4636 Log(("cpu_inw: addr=%#06x -> %#x rc=%Rrc\n", addr, u32, rc));
4637 remR3RaiseRC(env->pVM, rc);
4638 return (uint16_t)u32;
4639 }
4640 remAbort(rc, __FUNCTION__);
4641 return UINT16_C(0xffff);
4642}
4643
4644uint32_t cpu_inl(CPUX86State *env, pio_addr_t addr)
4645{
4646 uint32_t u32 = 0;
4647 int rc = IOMIOPortRead(env->pVM, env->pVCpu, (RTIOPORT)addr, &u32, 4);
4648 if (RT_LIKELY(rc == VINF_SUCCESS))
4649 {
4650//if (addr==0x01f0 && u32 == 0x6b6d)
4651// loglevel = ~0;
4652 Log2(("cpu_inl: addr=%#06x -> %#x\n", addr, u32));
4653 return u32;
4654 }
4655 if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
4656 {
4657 Log(("cpu_inl: addr=%#06x -> %#x rc=%Rrc\n", addr, u32, rc));
4658 remR3RaiseRC(env->pVM, rc);
4659 return u32;
4660 }
4661 remAbort(rc, __FUNCTION__);
4662 return UINT32_C(0xffffffff);
4663}
4664
4665#undef LOG_GROUP
4666#define LOG_GROUP LOG_GROUP_REM
4667
4668
4669/* -+- helpers and misc other interfaces -+- */
4670
4671/**
4672 * Perform the CPUID instruction.
4673 *
4674 * @param env Pointer to the recompiler CPU structure.
4675 * @param idx The CPUID leaf (eax).
4676 * @param idxSub The CPUID sub-leaf (ecx) where applicable.
4677 * @param pvEAX Where to store eax.
4678 * @param pvEBX Where to store ebx.
4679 * @param pvECX Where to store ecx.
4680 * @param pvEDX Where to store edx.
4681 */
4682void cpu_x86_cpuid(CPUX86State *env, uint32_t idx, uint32_t idxSub,
4683 uint32_t *pEAX, uint32_t *pEBX, uint32_t *pECX, uint32_t *pEDX)
4684{
4685 NOREF(idxSub);
4686 CPUMGetGuestCpuId(env->pVCpu, idx, pEAX, pEBX, pECX, pEDX);
4687}
4688
4689
4690#if 0 /* not used */
4691/**
4692 * Interface for qemu hardware to report back fatal errors.
4693 */
4694void hw_error(const char *pszFormat, ...)
4695{
4696 /*
4697 * Bitch about it.
4698 */
4699 /** @todo Add support for nested arg lists in the LogPrintfV routine! I've code for
4700 * this in my Odin32 tree at home! */
4701 va_list args;
4702 va_start(args, pszFormat);
4703 RTLogPrintf("fatal error in virtual hardware:");
4704 RTLogPrintfV(pszFormat, args);
4705 va_end(args);
4706 AssertReleaseMsgFailed(("fatal error in virtual hardware: %s\n", pszFormat));
4707
4708 /*
4709 * If we're in REM context we'll sync back the state before 'jumping' to
4710 * the EMs failure handling.
4711 */
4712 PVM pVM = cpu_single_env->pVM;
4713 if (pVM->rem.s.fInREM)
4714 REMR3StateBack(pVM);
4715 EMR3FatalError(pVM, VERR_REM_VIRTUAL_HARDWARE_ERROR);
4716 AssertMsgFailed(("EMR3FatalError returned!\n"));
4717}
4718#endif
4719
4720/**
4721 * Interface for the qemu cpu to report unhandled situation
4722 * raising a fatal VM error.
4723 */
4724void cpu_abort(CPUX86State *env, const char *pszFormat, ...)
4725{
4726 va_list va;
4727 PVM pVM;
4728 PVMCPU pVCpu;
4729 char szMsg[256];
4730
4731 /*
4732 * Bitch about it.
4733 */
4734 RTLogFlags(NULL, "nodisabled nobuffered");
4735 RTLogFlush(NULL);
4736
4737 va_start(va, pszFormat);
4738#if defined(RT_OS_WINDOWS) && ARCH_BITS == 64
4739 /* It's a bit complicated when mixing MSC and GCC on AMD64. This is a bit ugly, but it works. */
4740 unsigned cArgs = 0;
4741 uintptr_t auArgs[6] = {0,0,0,0,0,0};
4742 const char *psz = strchr(pszFormat, '%');
4743 while (psz && cArgs < 6)
4744 {
4745 auArgs[cArgs++] = va_arg(va, uintptr_t);
4746 psz = strchr(psz + 1, '%');
4747 }
4748 switch (cArgs)
4749 {
4750 case 1: RTStrPrintf(szMsg, sizeof(szMsg), pszFormat, auArgs[0]); break;
4751 case 2: RTStrPrintf(szMsg, sizeof(szMsg), pszFormat, auArgs[0], auArgs[1]); break;
4752 case 3: RTStrPrintf(szMsg, sizeof(szMsg), pszFormat, auArgs[0], auArgs[1], auArgs[2]); break;
4753 case 4: RTStrPrintf(szMsg, sizeof(szMsg), pszFormat, auArgs[0], auArgs[1], auArgs[2], auArgs[3]); break;
4754 case 5: RTStrPrintf(szMsg, sizeof(szMsg), pszFormat, auArgs[0], auArgs[1], auArgs[2], auArgs[3], auArgs[4]); break;
4755 case 6: RTStrPrintf(szMsg, sizeof(szMsg), pszFormat, auArgs[0], auArgs[1], auArgs[2], auArgs[3], auArgs[4], auArgs[5]); break;
4756 default:
4757 case 0: RTStrPrintf(szMsg, sizeof(szMsg), "%s", pszFormat); break;
4758 }
4759#else
4760 RTStrPrintfV(szMsg, sizeof(szMsg), pszFormat, va);
4761#endif
4762 va_end(va);
4763
4764 RTLogPrintf("fatal error in recompiler cpu: %s\n", szMsg);
4765 RTLogRelPrintf("fatal error in recompiler cpu: %s\n", szMsg);
4766
4767 /*
4768 * If we're in REM context we'll sync back the state before 'jumping' to
4769 * the EMs failure handling.
4770 */
4771 pVM = cpu_single_env->pVM;
4772 pVCpu = cpu_single_env->pVCpu;
4773 Assert(pVCpu);
4774
4775 if (pVM->rem.s.fInREM)
4776 REMR3StateBack(pVM, pVCpu);
4777 EMR3FatalError(pVCpu, VERR_REM_VIRTUAL_CPU_ERROR);
4778 AssertMsgFailed(("EMR3FatalError returned!\n"));
4779}
4780
4781
4782/**
4783 * Aborts the VM.
4784 *
4785 * @param rc VBox error code.
4786 * @param pszTip Hint about why/when this happened.
4787 */
4788void remAbort(int rc, const char *pszTip)
4789{
4790 PVM pVM;
4791 PVMCPU pVCpu;
4792
4793 /*
4794 * Bitch about it.
4795 */
4796 RTLogPrintf("internal REM fatal error: rc=%Rrc %s\n", rc, pszTip);
4797 AssertReleaseMsgFailed(("internal REM fatal error: rc=%Rrc %s\n", rc, pszTip));
4798
4799 /*
4800 * Jump back to where we entered the recompiler.
4801 */
4802 pVM = cpu_single_env->pVM;
4803 pVCpu = cpu_single_env->pVCpu;
4804 Assert(pVCpu);
4805
4806 if (pVM->rem.s.fInREM)
4807 REMR3StateBack(pVM, pVCpu);
4808
4809 EMR3FatalError(pVCpu, rc);
4810 AssertMsgFailed(("EMR3FatalError returned!\n"));
4811}
4812
4813
4814/**
4815 * Dumps a linux system call.
4816 * @param pVCpu VMCPU handle.
4817 */
4818void remR3DumpLnxSyscall(PVMCPU pVCpu)
4819{
4820 static const char *apsz[] =
4821 {
4822 "sys_restart_syscall", /* 0 - old "setup()" system call, used for restarting */
4823 "sys_exit",
4824 "sys_fork",
4825 "sys_read",
4826 "sys_write",
4827 "sys_open", /* 5 */
4828 "sys_close",
4829 "sys_waitpid",
4830 "sys_creat",
4831 "sys_link",
4832 "sys_unlink", /* 10 */
4833 "sys_execve",
4834 "sys_chdir",
4835 "sys_time",
4836 "sys_mknod",
4837 "sys_chmod", /* 15 */
4838 "sys_lchown16",
4839 "sys_ni_syscall", /* old break syscall holder */
4840 "sys_stat",
4841 "sys_lseek",
4842 "sys_getpid", /* 20 */
4843 "sys_mount",
4844 "sys_oldumount",
4845 "sys_setuid16",
4846 "sys_getuid16",
4847 "sys_stime", /* 25 */
4848 "sys_ptrace",
4849 "sys_alarm",
4850 "sys_fstat",
4851 "sys_pause",
4852 "sys_utime", /* 30 */
4853 "sys_ni_syscall", /* old stty syscall holder */
4854 "sys_ni_syscall", /* old gtty syscall holder */
4855 "sys_access",
4856 "sys_nice",
4857 "sys_ni_syscall", /* 35 - old ftime syscall holder */
4858 "sys_sync",
4859 "sys_kill",
4860 "sys_rename",
4861 "sys_mkdir",
4862 "sys_rmdir", /* 40 */
4863 "sys_dup",
4864 "sys_pipe",
4865 "sys_times",
4866 "sys_ni_syscall", /* old prof syscall holder */
4867 "sys_brk", /* 45 */
4868 "sys_setgid16",
4869 "sys_getgid16",
4870 "sys_signal",
4871 "sys_geteuid16",
4872 "sys_getegid16", /* 50 */
4873 "sys_acct",
4874 "sys_umount", /* recycled never used phys() */
4875 "sys_ni_syscall", /* old lock syscall holder */
4876 "sys_ioctl",
4877 "sys_fcntl", /* 55 */
4878 "sys_ni_syscall", /* old mpx syscall holder */
4879 "sys_setpgid",
4880 "sys_ni_syscall", /* old ulimit syscall holder */
4881 "sys_olduname",
4882 "sys_umask", /* 60 */
4883 "sys_chroot",
4884 "sys_ustat",
4885 "sys_dup2",
4886 "sys_getppid",
4887 "sys_getpgrp", /* 65 */
4888 "sys_setsid",
4889 "sys_sigaction",
4890 "sys_sgetmask",
4891 "sys_ssetmask",
4892 "sys_setreuid16", /* 70 */
4893 "sys_setregid16",
4894 "sys_sigsuspend",
4895 "sys_sigpending",
4896 "sys_sethostname",
4897 "sys_setrlimit", /* 75 */
4898 "sys_old_getrlimit",
4899 "sys_getrusage",
4900 "sys_gettimeofday",
4901 "sys_settimeofday",
4902 "sys_getgroups16", /* 80 */
4903 "sys_setgroups16",
4904 "old_select",
4905 "sys_symlink",
4906 "sys_lstat",
4907 "sys_readlink", /* 85 */
4908 "sys_uselib",
4909 "sys_swapon",
4910 "sys_reboot",
4911 "old_readdir",
4912 "old_mmap", /* 90 */
4913 "sys_munmap",
4914 "sys_truncate",
4915 "sys_ftruncate",
4916 "sys_fchmod",
4917 "sys_fchown16", /* 95 */
4918 "sys_getpriority",
4919 "sys_setpriority",
4920 "sys_ni_syscall", /* old profil syscall holder */
4921 "sys_statfs",
4922 "sys_fstatfs", /* 100 */
4923 "sys_ioperm",
4924 "sys_socketcall",
4925 "sys_syslog",
4926 "sys_setitimer",
4927 "sys_getitimer", /* 105 */
4928 "sys_newstat",
4929 "sys_newlstat",
4930 "sys_newfstat",
4931 "sys_uname",
4932 "sys_iopl", /* 110 */
4933 "sys_vhangup",
4934 "sys_ni_syscall", /* old "idle" system call */
4935 "sys_vm86old",
4936 "sys_wait4",
4937 "sys_swapoff", /* 115 */
4938 "sys_sysinfo",
4939 "sys_ipc",
4940 "sys_fsync",
4941 "sys_sigreturn",
4942 "sys_clone", /* 120 */
4943 "sys_setdomainname",
4944 "sys_newuname",
4945 "sys_modify_ldt",
4946 "sys_adjtimex",
4947 "sys_mprotect", /* 125 */
4948 "sys_sigprocmask",
4949 "sys_ni_syscall", /* old "create_module" */
4950 "sys_init_module",
4951 "sys_delete_module",
4952 "sys_ni_syscall", /* 130: old "get_kernel_syms" */
4953 "sys_quotactl",
4954 "sys_getpgid",
4955 "sys_fchdir",
4956 "sys_bdflush",
4957 "sys_sysfs", /* 135 */
4958 "sys_personality",
4959 "sys_ni_syscall", /* reserved for afs_syscall */
4960 "sys_setfsuid16",
4961 "sys_setfsgid16",
4962 "sys_llseek", /* 140 */
4963 "sys_getdents",
4964 "sys_select",
4965 "sys_flock",
4966 "sys_msync",
4967 "sys_readv", /* 145 */
4968 "sys_writev",
4969 "sys_getsid",
4970 "sys_fdatasync",
4971 "sys_sysctl",
4972 "sys_mlock", /* 150 */
4973 "sys_munlock",
4974 "sys_mlockall",
4975 "sys_munlockall",
4976 "sys_sched_setparam",
4977 "sys_sched_getparam", /* 155 */
4978 "sys_sched_setscheduler",
4979 "sys_sched_getscheduler",
4980 "sys_sched_yield",
4981 "sys_sched_get_priority_max",
4982 "sys_sched_get_priority_min", /* 160 */
4983 "sys_sched_rr_get_interval",
4984 "sys_nanosleep",
4985 "sys_mremap",
4986 "sys_setresuid16",
4987 "sys_getresuid16", /* 165 */
4988 "sys_vm86",
4989 "sys_ni_syscall", /* Old sys_query_module */
4990 "sys_poll",
4991 "sys_nfsservctl",
4992 "sys_setresgid16", /* 170 */
4993 "sys_getresgid16",
4994 "sys_prctl",
4995 "sys_rt_sigreturn",
4996 "sys_rt_sigaction",
4997 "sys_rt_sigprocmask", /* 175 */
4998 "sys_rt_sigpending",
4999 "sys_rt_sigtimedwait",
5000 "sys_rt_sigqueueinfo",
5001 "sys_rt_sigsuspend",
5002 "sys_pread64", /* 180 */
5003 "sys_pwrite64",
5004 "sys_chown16",
5005 "sys_getcwd",
5006 "sys_capget",
5007 "sys_capset", /* 185 */
5008 "sys_sigaltstack",
5009 "sys_sendfile",
5010 "sys_ni_syscall", /* reserved for streams1 */
5011 "sys_ni_syscall", /* reserved for streams2 */
5012 "sys_vfork", /* 190 */
5013 "sys_getrlimit",
5014 "sys_mmap2",
5015 "sys_truncate64",
5016 "sys_ftruncate64",
5017 "sys_stat64", /* 195 */
5018 "sys_lstat64",
5019 "sys_fstat64",
5020 "sys_lchown",
5021 "sys_getuid",
5022 "sys_getgid", /* 200 */
5023 "sys_geteuid",
5024 "sys_getegid",
5025 "sys_setreuid",
5026 "sys_setregid",
5027 "sys_getgroups", /* 205 */
5028 "sys_setgroups",
5029 "sys_fchown",
5030 "sys_setresuid",
5031 "sys_getresuid",
5032 "sys_setresgid", /* 210 */
5033 "sys_getresgid",
5034 "sys_chown",
5035 "sys_setuid",
5036 "sys_setgid",
5037 "sys_setfsuid", /* 215 */
5038 "sys_setfsgid",
5039 "sys_pivot_root",
5040 "sys_mincore",
5041 "sys_madvise",
5042 "sys_getdents64", /* 220 */
5043 "sys_fcntl64",
5044 "sys_ni_syscall", /* reserved for TUX */
5045 "sys_ni_syscall",
5046 "sys_gettid",
5047 "sys_readahead", /* 225 */
5048 "sys_setxattr",
5049 "sys_lsetxattr",
5050 "sys_fsetxattr",
5051 "sys_getxattr",
5052 "sys_lgetxattr", /* 230 */
5053 "sys_fgetxattr",
5054 "sys_listxattr",
5055 "sys_llistxattr",
5056 "sys_flistxattr",
5057 "sys_removexattr", /* 235 */
5058 "sys_lremovexattr",
5059 "sys_fremovexattr",
5060 "sys_tkill",
5061 "sys_sendfile64",
5062 "sys_futex", /* 240 */
5063 "sys_sched_setaffinity",
5064 "sys_sched_getaffinity",
5065 "sys_set_thread_area",
5066 "sys_get_thread_area",
5067 "sys_io_setup", /* 245 */
5068 "sys_io_destroy",
5069 "sys_io_getevents",
5070 "sys_io_submit",
5071 "sys_io_cancel",
5072 "sys_fadvise64", /* 250 */
5073 "sys_ni_syscall",
5074 "sys_exit_group",
5075 "sys_lookup_dcookie",
5076 "sys_epoll_create",
5077 "sys_epoll_ctl", /* 255 */
5078 "sys_epoll_wait",
5079 "sys_remap_file_pages",
5080 "sys_set_tid_address",
5081 "sys_timer_create",
5082 "sys_timer_settime", /* 260 */
5083 "sys_timer_gettime",
5084 "sys_timer_getoverrun",
5085 "sys_timer_delete",
5086 "sys_clock_settime",
5087 "sys_clock_gettime", /* 265 */
5088 "sys_clock_getres",
5089 "sys_clock_nanosleep",
5090 "sys_statfs64",
5091 "sys_fstatfs64",
5092 "sys_tgkill", /* 270 */
5093 "sys_utimes",
5094 "sys_fadvise64_64",
5095 "sys_ni_syscall" /* sys_vserver */
5096 };
5097
5098 uint32_t uEAX = CPUMGetGuestEAX(pVCpu);
5099 switch (uEAX)
5100 {
5101 default:
5102 if (uEAX < RT_ELEMENTS(apsz))
5103 Log(("REM: linux syscall %3d: %s (eip=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x ebp=%08x)\n",
5104 uEAX, apsz[uEAX], CPUMGetGuestEIP(pVCpu), CPUMGetGuestEBX(pVCpu), CPUMGetGuestECX(pVCpu),
5105 CPUMGetGuestEDX(pVCpu), CPUMGetGuestESI(pVCpu), CPUMGetGuestEDI(pVCpu), CPUMGetGuestEBP(pVCpu)));
5106 else
5107 Log(("eip=%08x: linux syscall %d (#%x) unknown\n", CPUMGetGuestEIP(pVCpu), uEAX, uEAX));
5108 break;
5109
5110 }
5111}
5112
5113
5114/**
5115 * Dumps an OpenBSD system call.
5116 * @param pVCpu VMCPU handle.
5117 */
5118void remR3DumpOBsdSyscall(PVMCPU pVCpu)
5119{
5120 static const char *apsz[] =
5121 {
5122 "SYS_syscall", //0
5123 "SYS_exit", //1
5124 "SYS_fork", //2
5125 "SYS_read", //3
5126 "SYS_write", //4
5127 "SYS_open", //5
5128 "SYS_close", //6
5129 "SYS_wait4", //7
5130 "SYS_8",
5131 "SYS_link", //9
5132 "SYS_unlink", //10
5133 "SYS_11",
5134 "SYS_chdir", //12
5135 "SYS_fchdir", //13
5136 "SYS_mknod", //14
5137 "SYS_chmod", //15
5138 "SYS_chown", //16
5139 "SYS_break", //17
5140 "SYS_18",
5141 "SYS_19",
5142 "SYS_getpid", //20
5143 "SYS_mount", //21
5144 "SYS_unmount", //22
5145 "SYS_setuid", //23
5146 "SYS_getuid", //24
5147 "SYS_geteuid", //25
5148 "SYS_ptrace", //26
5149 "SYS_recvmsg", //27
5150 "SYS_sendmsg", //28
5151 "SYS_recvfrom", //29
5152 "SYS_accept", //30
5153 "SYS_getpeername", //31
5154 "SYS_getsockname", //32
5155 "SYS_access", //33
5156 "SYS_chflags", //34
5157 "SYS_fchflags", //35
5158 "SYS_sync", //36
5159 "SYS_kill", //37
5160 "SYS_38",
5161 "SYS_getppid", //39
5162 "SYS_40",
5163 "SYS_dup", //41
5164 "SYS_opipe", //42
5165 "SYS_getegid", //43
5166 "SYS_profil", //44
5167 "SYS_ktrace", //45
5168 "SYS_sigaction", //46
5169 "SYS_getgid", //47
5170 "SYS_sigprocmask", //48
5171 "SYS_getlogin", //49
5172 "SYS_setlogin", //50
5173 "SYS_acct", //51
5174 "SYS_sigpending", //52
5175 "SYS_osigaltstack", //53
5176 "SYS_ioctl", //54
5177 "SYS_reboot", //55
5178 "SYS_revoke", //56
5179 "SYS_symlink", //57
5180 "SYS_readlink", //58
5181 "SYS_execve", //59
5182 "SYS_umask", //60
5183 "SYS_chroot", //61
5184 "SYS_62",
5185 "SYS_63",
5186 "SYS_64",
5187 "SYS_65",
5188 "SYS_vfork", //66
5189 "SYS_67",
5190 "SYS_68",
5191 "SYS_sbrk", //69
5192 "SYS_sstk", //70
5193 "SYS_61",
5194 "SYS_vadvise", //72
5195 "SYS_munmap", //73
5196 "SYS_mprotect", //74
5197 "SYS_madvise", //75
5198 "SYS_76",
5199 "SYS_77",
5200 "SYS_mincore", //78
5201 "SYS_getgroups", //79
5202 "SYS_setgroups", //80
5203 "SYS_getpgrp", //81
5204 "SYS_setpgid", //82
5205 "SYS_setitimer", //83
5206 "SYS_84",
5207 "SYS_85",
5208 "SYS_getitimer", //86
5209 "SYS_87",
5210 "SYS_88",
5211 "SYS_89",
5212 "SYS_dup2", //90
5213 "SYS_91",
5214 "SYS_fcntl", //92
5215 "SYS_select", //93
5216 "SYS_94",
5217 "SYS_fsync", //95
5218 "SYS_setpriority", //96
5219 "SYS_socket", //97
5220 "SYS_connect", //98
5221 "SYS_99",
5222 "SYS_getpriority", //100
5223 "SYS_101",
5224 "SYS_102",
5225 "SYS_sigreturn", //103
5226 "SYS_bind", //104
5227 "SYS_setsockopt", //105
5228 "SYS_listen", //106
5229 "SYS_107",
5230 "SYS_108",
5231 "SYS_109",
5232 "SYS_110",
5233 "SYS_sigsuspend", //111
5234 "SYS_112",
5235 "SYS_113",
5236 "SYS_114",
5237 "SYS_115",
5238 "SYS_gettimeofday", //116
5239 "SYS_getrusage", //117
5240 "SYS_getsockopt", //118
5241 "SYS_119",
5242 "SYS_readv", //120
5243 "SYS_writev", //121
5244 "SYS_settimeofday", //122
5245 "SYS_fchown", //123
5246 "SYS_fchmod", //124
5247 "SYS_125",
5248 "SYS_setreuid", //126
5249 "SYS_setregid", //127
5250 "SYS_rename", //128
5251 "SYS_129",
5252 "SYS_130",
5253 "SYS_flock", //131
5254 "SYS_mkfifo", //132
5255 "SYS_sendto", //133
5256 "SYS_shutdown", //134
5257 "SYS_socketpair", //135
5258 "SYS_mkdir", //136
5259 "SYS_rmdir", //137
5260 "SYS_utimes", //138
5261 "SYS_139",
5262 "SYS_adjtime", //140
5263 "SYS_141",
5264 "SYS_142",
5265 "SYS_143",
5266 "SYS_144",
5267 "SYS_145",
5268 "SYS_146",
5269 "SYS_setsid", //147
5270 "SYS_quotactl", //148
5271 "SYS_149",
5272 "SYS_150",
5273 "SYS_151",
5274 "SYS_152",
5275 "SYS_153",
5276 "SYS_154",
5277 "SYS_nfssvc", //155
5278 "SYS_156",
5279 "SYS_157",
5280 "SYS_158",
5281 "SYS_159",
5282 "SYS_160",
5283 "SYS_getfh", //161
5284 "SYS_162",
5285 "SYS_163",
5286 "SYS_164",
5287 "SYS_sysarch", //165
5288 "SYS_166",
5289 "SYS_167",
5290 "SYS_168",
5291 "SYS_169",
5292 "SYS_170",
5293 "SYS_171",
5294 "SYS_172",
5295 "SYS_pread", //173
5296 "SYS_pwrite", //174
5297 "SYS_175",
5298 "SYS_176",
5299 "SYS_177",
5300 "SYS_178",
5301 "SYS_179",
5302 "SYS_180",
5303 "SYS_setgid", //181
5304 "SYS_setegid", //182
5305 "SYS_seteuid", //183
5306 "SYS_lfs_bmapv", //184
5307 "SYS_lfs_markv", //185
5308 "SYS_lfs_segclean", //186
5309 "SYS_lfs_segwait", //187
5310 "SYS_188",
5311 "SYS_189",
5312 "SYS_190",
5313 "SYS_pathconf", //191
5314 "SYS_fpathconf", //192
5315 "SYS_swapctl", //193
5316 "SYS_getrlimit", //194
5317 "SYS_setrlimit", //195
5318 "SYS_getdirentries", //196
5319 "SYS_mmap", //197
5320 "SYS___syscall", //198
5321 "SYS_lseek", //199
5322 "SYS_truncate", //200
5323 "SYS_ftruncate", //201
5324 "SYS___sysctl", //202
5325 "SYS_mlock", //203
5326 "SYS_munlock", //204
5327 "SYS_205",
5328 "SYS_futimes", //206
5329 "SYS_getpgid", //207
5330 "SYS_xfspioctl", //208
5331 "SYS_209",
5332 "SYS_210",
5333 "SYS_211",
5334 "SYS_212",
5335 "SYS_213",
5336 "SYS_214",
5337 "SYS_215",
5338 "SYS_216",
5339 "SYS_217",
5340 "SYS_218",
5341 "SYS_219",
5342 "SYS_220",
5343 "SYS_semget", //221
5344 "SYS_222",
5345 "SYS_223",
5346 "SYS_224",
5347 "SYS_msgget", //225
5348 "SYS_msgsnd", //226
5349 "SYS_msgrcv", //227
5350 "SYS_shmat", //228
5351 "SYS_229",
5352 "SYS_shmdt", //230
5353 "SYS_231",
5354 "SYS_clock_gettime", //232
5355 "SYS_clock_settime", //233
5356 "SYS_clock_getres", //234
5357 "SYS_235",
5358 "SYS_236",
5359 "SYS_237",
5360 "SYS_238",
5361 "SYS_239",
5362 "SYS_nanosleep", //240
5363 "SYS_241",
5364 "SYS_242",
5365 "SYS_243",
5366 "SYS_244",
5367 "SYS_245",
5368 "SYS_246",
5369 "SYS_247",
5370 "SYS_248",
5371 "SYS_249",
5372 "SYS_minherit", //250
5373 "SYS_rfork", //251
5374 "SYS_poll", //252
5375 "SYS_issetugid", //253
5376 "SYS_lchown", //254
5377 "SYS_getsid", //255
5378 "SYS_msync", //256
5379 "SYS_257",
5380 "SYS_258",
5381 "SYS_259",
5382 "SYS_getfsstat", //260
5383 "SYS_statfs", //261
5384 "SYS_fstatfs", //262
5385 "SYS_pipe", //263
5386 "SYS_fhopen", //264
5387 "SYS_265",
5388 "SYS_fhstatfs", //266
5389 "SYS_preadv", //267
5390 "SYS_pwritev", //268
5391 "SYS_kqueue", //269
5392 "SYS_kevent", //270
5393 "SYS_mlockall", //271
5394 "SYS_munlockall", //272
5395 "SYS_getpeereid", //273
5396 "SYS_274",
5397 "SYS_275",
5398 "SYS_276",
5399 "SYS_277",
5400 "SYS_278",
5401 "SYS_279",
5402 "SYS_280",
5403 "SYS_getresuid", //281
5404 "SYS_setresuid", //282
5405 "SYS_getresgid", //283
5406 "SYS_setresgid", //284
5407 "SYS_285",
5408 "SYS_mquery", //286
5409 "SYS_closefrom", //287
5410 "SYS_sigaltstack", //288
5411 "SYS_shmget", //289
5412 "SYS_semop", //290
5413 "SYS_stat", //291
5414 "SYS_fstat", //292
5415 "SYS_lstat", //293
5416 "SYS_fhstat", //294
5417 "SYS___semctl", //295
5418 "SYS_shmctl", //296
5419 "SYS_msgctl", //297
5420 "SYS_MAXSYSCALL", //298
5421 //299
5422 //300
5423 };
5424 uint32_t uEAX;
5425 if (!LogIsEnabled())
5426 return;
5427 uEAX = CPUMGetGuestEAX(pVCpu);
5428 switch (uEAX)
5429 {
5430 default:
5431 if (uEAX < RT_ELEMENTS(apsz))
5432 {
5433 uint32_t au32Args[8] = {0};
5434 PGMPhysSimpleReadGCPtr(pVCpu, au32Args, CPUMGetGuestESP(pVCpu), sizeof(au32Args));
5435 RTLogPrintf("REM: OpenBSD syscall %3d: %s (eip=%08x %08x %08x %08x %08x %08x %08x %08x %08x)\n",
5436 uEAX, apsz[uEAX], CPUMGetGuestEIP(pVCpu), au32Args[0], au32Args[1], au32Args[2], au32Args[3],
5437 au32Args[4], au32Args[5], au32Args[6], au32Args[7]);
5438 }
5439 else
5440 RTLogPrintf("eip=%08x: OpenBSD syscall %d (#%x) unknown!!\n", CPUMGetGuestEIP(pVCpu), uEAX, uEAX);
5441 break;
5442 }
5443}
5444
5445
5446#if defined(IPRT_NO_CRT) && defined(RT_OS_WINDOWS) && defined(RT_ARCH_X86)
5447/**
5448 * The Dll main entry point (stub).
5449 */
5450bool __stdcall _DllMainCRTStartup(void *hModule, uint32_t dwReason, void *pvReserved)
5451{
5452 return true;
5453}
5454
5455void *memcpy(void *dst, const void *src, size_t size)
5456{
5457 uint8_t*pbDst = dst, *pbSrc = src;
5458 while (size-- > 0)
5459 *pbDst++ = *pbSrc++;
5460 return dst;
5461}
5462
5463#endif
5464
5465void cpu_smm_update(CPUX86State *env)
5466{
5467}
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