VirtualBox

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

Last change on this file since 3668 was 3615, checked in by vboxsync, 17 years ago

Callback wrapping using custom assembly templates (too lazy to generate code). Disabled the problematic DBGC stuff on 64-bit windows.

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