VirtualBox

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

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

Ring-1 compression patches, courtesy of trivirt AG:

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