VirtualBox

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

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

Prevent an fInRem assertion in the tlb flushing code when A20 is change in VT-x/AMD-V mode. Added a todo in PGMR3PhysSetA20() because we're not doing the right thing for AMD-V (and VT-x).

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