VirtualBox

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

Last change on this file since 72331 was 70948, checked in by vboxsync, 7 years ago

VMM: Added a bMainExecutionEngine member to the VM structure for use instead of fHMEnabled and fNEMEnabled. Changed a lot of HMIsEnabled invocations to use the new macros VM_IS_RAW_MODE_ENABLED and VM_IS_HM_OR_NEM_ENABLED. Eliminated fHMEnabledFixed. Fixed inverted test for raw-mode debug register sanity checking. Some other minor cleanups.

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

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