VirtualBox

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

Last change on this file since 80012 was 80007, checked in by vboxsync, 5 years ago

VMM: Kicking out raw-mode (work in progress). bugref:9517

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

© 2023 Oracle
ContactPrivacy policyTerms of Use