VirtualBox

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

Last change on this file since 66259 was 64655, checked in by vboxsync, 8 years ago

VMM,recompiler: Get rid of PDM APIC interfaces reducing one level of indirection, cleaned up some unused stuff in recompiler.

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