VirtualBox

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

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

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

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette