VirtualBox

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

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

The new MMIO2 code.
WARNING! This changes the pci mapping protocol for MMIO2 so it's working the same way as I/O ports and normal MMIO memory. External users of the interface will have to update their mapping routines.

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

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