VirtualBox

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

Last change on this file since 20399 was 20399, checked in by vboxsync, 16 years ago

Minor updates

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