VirtualBox

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

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

scm --update-copyright-year

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

© 2023 Oracle
ContactPrivacy policyTerms of Use