VirtualBox

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

Last change on this file since 52041 was 52041, checked in by vboxsync, 10 years ago

VMM: Fix NMI handling.

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