VirtualBox

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

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

More nitpicking from side-by-side diff with old version.

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

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