VirtualBox

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

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

List near, unassemble, hyper register and more tiny debugger fixes.

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

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