VirtualBox

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

Last change on this file since 72493 was 72493, checked in by vboxsync, 6 years ago

IEM,REM,++: Removed code related IEM_VERIFICATION_MODE and friends because it (1) adds aditional complexity and mess, (2) suffers bit rot as it's infrequently used, and (3) prevents using pVCpu->cpum.GstCtx directly.

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