VirtualBox

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

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

REM: Initialize hardware virtualization state in the partially constructed guest-CPU context that will be used by HMCanExecuteGuest().

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

© 2023 Oracle
ContactPrivacy policyTerms of Use