VirtualBox

source: vbox/trunk/src/recompiler_new/VBoxRecompiler.c@ 14742

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

finally fixed timner starvation for real, also REM improvments
by putting external events check into right places and reverted
PIT DRAM refresh rate frequency code to correct one

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

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