VirtualBox

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

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

Implemented check for monitored page accesses, fixing TSS out of sync problem with VA in TLB. Enabled VA in TLB by default in new REM>

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