VirtualBox

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

Last change on this file since 45751 was 45751, checked in by vboxsync, 12 years ago

Ooops, forgot TRPM related changes.

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

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