VirtualBox

source: vbox/trunk/src/VBox/VMM/EMHwaccm.cpp@ 26146

Last change on this file since 26146 was 26146, checked in by vboxsync, 15 years ago

Make sure we fall back to the recompiler if the VMM device heap is inactive (VT-x real mode or VT-x+EPT protected mode without paging)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.6 KB
Line 
1/* $Id: EMHwaccm.cpp 26146 2010-02-02 13:51:26Z vboxsync $ */
2/** @file
3 * EM - Execution Monitor / Manager - hardware virtualization
4 */
5
6/*
7 * Copyright (C) 2006-2009 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/** @page pg_em EM - The Execution Monitor / Manager
23 *
24 * The Execution Monitor/Manager is responsible for running the VM, scheduling
25 * the right kind of execution (Raw-mode, Hardware Assisted, Recompiled or
26 * Interpreted), and keeping the CPU states in sync. The function
27 * EMR3ExecuteVM() is the 'main-loop' of the VM, while each of the execution
28 * modes has different inner loops (emR3RawExecute, emR3HwAccExecute, and
29 * emR3RemExecute).
30 *
31 * The interpreted execution is only used to avoid switching between
32 * raw-mode/hwaccm and the recompiler when fielding virtualization traps/faults.
33 * The interpretation is thus implemented as part of EM.
34 *
35 * @see grp_em
36 */
37
38/*******************************************************************************
39* Header Files *
40*******************************************************************************/
41#define LOG_GROUP LOG_GROUP_EM
42#include <VBox/em.h>
43#include <VBox/vmm.h>
44#ifdef VBOX_WITH_VMI
45# include <VBox/parav.h>
46#endif
47#include <VBox/csam.h>
48#include <VBox/selm.h>
49#include <VBox/trpm.h>
50#include <VBox/iom.h>
51#include <VBox/dbgf.h>
52#include <VBox/pgm.h>
53#include <VBox/rem.h>
54#include <VBox/tm.h>
55#include <VBox/mm.h>
56#include <VBox/ssm.h>
57#include <VBox/pdmapi.h>
58#include <VBox/pdmcritsect.h>
59#include <VBox/pdmqueue.h>
60#include <VBox/hwaccm.h>
61#include "EMInternal.h"
62#include <VBox/vm.h>
63#include <VBox/cpumdis.h>
64#include <VBox/dis.h>
65#include <VBox/disopcode.h>
66#include <VBox/dbgf.h>
67
68
69/*******************************************************************************
70* Defined Constants And Macros *
71*******************************************************************************/
72#if 0 /* Disabled till after 2.1.0 when we've time to test it. */
73#define EM_NOTIFY_HWACCM
74#endif
75
76
77/*******************************************************************************
78* Internal Functions *
79*******************************************************************************/
80DECLINLINE(int) emR3ExecuteInstruction(PVM pVM, PVMCPU pVCpu, const char *pszPrefix, int rcGC = VINF_SUCCESS);
81static int emR3ExecuteIOInstruction(PVM pVM, PVMCPU pVCpu);
82static int emR3HwaccmForcedActions(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
83
84#define EMHANDLERC_WITH_HWACCM
85#include "EMHandleRCTmpl.h"
86
87
88#ifdef DEBUG
89
90/**
91 * Steps hardware accelerated mode.
92 *
93 * @returns VBox status code.
94 * @param pVM The VM handle.
95 * @param pVCpu The VMCPU handle.
96 */
97static int emR3HwAccStep(PVM pVM, PVMCPU pVCpu)
98{
99 Assert(pVCpu->em.s.enmState == EMSTATE_DEBUG_GUEST_HWACC);
100
101 int rc;
102 PCPUMCTX pCtx = pVCpu->em.s.pCtx;
103 VMCPU_FF_CLEAR(pVCpu, (VMCPU_FF_SELM_SYNC_GDT | VMCPU_FF_SELM_SYNC_LDT | VMCPU_FF_TRPM_SYNC_IDT | VMCPU_FF_SELM_SYNC_TSS));
104
105 /*
106 * Check vital forced actions, but ignore pending interrupts and timers.
107 */
108 if ( VM_FF_ISPENDING(pVM, VM_FF_HIGH_PRIORITY_PRE_RAW_MASK)
109 || VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_HIGH_PRIORITY_PRE_RAW_MASK))
110 {
111 rc = emR3HwaccmForcedActions(pVM, pVCpu, pCtx);
112 if (rc != VINF_SUCCESS)
113 return rc;
114 }
115 /*
116 * Set flags for single stepping.
117 */
118 CPUMSetGuestEFlags(pVCpu, CPUMGetGuestEFlags(pVCpu) | X86_EFL_TF | X86_EFL_RF);
119
120 /*
121 * Single step.
122 * We do not start time or anything, if anything we should just do a few nanoseconds.
123 */
124 do
125 {
126 rc = VMMR3HwAccRunGC(pVM, pVCpu);
127 } while ( rc == VINF_SUCCESS
128 || rc == VINF_EM_RAW_INTERRUPT);
129 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_RESUME_GUEST_MASK);
130
131 /*
132 * Make sure the trap flag is cleared.
133 * (Too bad if the guest is trying to single step too.)
134 */
135 CPUMSetGuestEFlags(pVCpu, CPUMGetGuestEFlags(pVCpu) & ~X86_EFL_TF);
136
137 /*
138 * Deal with the return codes.
139 */
140 rc = emR3HighPriorityPostForcedActions(pVM, pVCpu, rc);
141 rc = emR3HwaccmHandleRC(pVM, pVCpu, pCtx, rc);
142 return rc;
143}
144
145
146static int emR3SingleStepExecHwAcc(PVM pVM, PVMCPU pVCpu, uint32_t cIterations)
147{
148 int rc = VINF_SUCCESS;
149 EMSTATE enmOldState = pVCpu->em.s.enmState;
150 pVCpu->em.s.enmState = EMSTATE_DEBUG_GUEST_HWACC;
151
152 Log(("Single step BEGIN:\n"));
153 for (uint32_t i = 0; i < cIterations; i++)
154 {
155 DBGFR3PrgStep(pVCpu);
156 DBGFR3DisasInstrCurrentLog(pVCpu, "RSS: ");
157 rc = emR3HwAccStep(pVM, pVCpu);
158 if ( rc != VINF_SUCCESS
159 || !HWACCMR3CanExecuteGuest(pVM, pVCpu->em.s.pCtx))
160 break;
161 }
162 Log(("Single step END: rc=%Rrc\n", rc));
163 CPUMSetGuestEFlags(pVCpu, CPUMGetGuestEFlags(pVCpu) & ~X86_EFL_TF);
164 pVCpu->em.s.enmState = enmOldState;
165 return rc == VINF_SUCCESS ? VINF_EM_RESCHEDULE_REM : rc;
166}
167
168#endif /* DEBUG */
169
170
171/**
172 * Executes one (or perhaps a few more) instruction(s).
173 *
174 * @returns VBox status code suitable for EM.
175 *
176 * @param pVM VM handle.
177 * @param pVCpu VMCPU handle
178 * @param rcGC GC return code
179 * @param pszPrefix Disassembly prefix. If not NULL we'll disassemble the
180 * instruction and prefix the log output with this text.
181 */
182#ifdef LOG_ENABLED
183static int emR3ExecuteInstructionWorker(PVM pVM, PVMCPU pVCpu, int rcGC, const char *pszPrefix)
184#else
185static int emR3ExecuteInstructionWorker(PVM pVM, PVMCPU pVCpu, int rcGC)
186#endif
187{
188 PCPUMCTX pCtx = pVCpu->em.s.pCtx;
189 int rc;
190
191 /*
192 *
193 * The simple solution is to use the recompiler.
194 * The better solution is to disassemble the current instruction and
195 * try handle as many as possible without using REM.
196 *
197 */
198
199#ifdef LOG_ENABLED
200 /*
201 * Disassemble the instruction if requested.
202 */
203 if (pszPrefix)
204 {
205 DBGFR3InfoLog(pVM, "cpumguest", pszPrefix);
206 DBGFR3DisasInstrCurrentLog(pVCpu, pszPrefix);
207 }
208#endif /* LOG_ENABLED */
209
210#if 0
211 /* Try our own instruction emulator before falling back to the recompiler. */
212 DISCPUSTATE Cpu;
213 rc = CPUMR3DisasmInstrCPU(pVM, pVCpu, pCtx, pCtx->rip, &Cpu, "GEN EMU");
214 if (RT_SUCCESS(rc))
215 {
216 uint32_t size;
217
218 switch (Cpu.pCurInstr->opcode)
219 {
220 /* @todo we can do more now */
221 case OP_MOV:
222 case OP_AND:
223 case OP_OR:
224 case OP_XOR:
225 case OP_POP:
226 case OP_INC:
227 case OP_DEC:
228 case OP_XCHG:
229 STAM_PROFILE_START(&pVCpu->em.s.StatMiscEmu, a);
230 rc = EMInterpretInstructionCPU(pVM, pVCpu, &Cpu, CPUMCTX2CORE(pCtx), 0, &size);
231 if (RT_SUCCESS(rc))
232 {
233 pCtx->rip += Cpu.opsize;
234#ifdef EM_NOTIFY_HWACCM
235 if (pVCpu->em.s.enmState == EMSTATE_DEBUG_GUEST_HWACC)
236 HWACCMR3NotifyEmulated(pVCpu);
237#endif
238 STAM_PROFILE_STOP(&pVCpu->em.s.StatMiscEmu, a);
239 return rc;
240 }
241 if (rc != VERR_EM_INTERPRETER)
242 AssertMsgFailedReturn(("rc=%Rrc\n", rc), rc);
243 STAM_PROFILE_STOP(&pVCpu->em.s.StatMiscEmu, a);
244 break;
245 }
246 }
247#endif /* 0 */
248 STAM_PROFILE_START(&pVCpu->em.s.StatREMEmu, a);
249 Log(("EMINS: %04x:%RGv RSP=%RGv\n", pCtx->cs, (RTGCPTR)pCtx->rip, (RTGCPTR)pCtx->rsp));
250 EMRemLock(pVM);
251 /* Flush the recompiler TLB if the VCPU has changed. */
252 if (pVM->em.s.idLastRemCpu != pVCpu->idCpu)
253 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_ALL);
254 pVM->em.s.idLastRemCpu = pVCpu->idCpu;
255
256 rc = REMR3EmulateInstruction(pVM, pVCpu);
257 EMRemUnlock(pVM);
258 STAM_PROFILE_STOP(&pVCpu->em.s.StatREMEmu, a);
259
260#ifdef EM_NOTIFY_HWACCM
261 if (pVCpu->em.s.enmState == EMSTATE_DEBUG_GUEST_HWACC)
262 HWACCMR3NotifyEmulated(pVCpu);
263#endif
264 return rc;
265}
266
267
268/**
269 * Executes one (or perhaps a few more) instruction(s).
270 * This is just a wrapper for discarding pszPrefix in non-logging builds.
271 *
272 * @returns VBox status code suitable for EM.
273 * @param pVM VM handle.
274 * @param pVCpu VMCPU handle.
275 * @param pszPrefix Disassembly prefix. If not NULL we'll disassemble the
276 * instruction and prefix the log output with this text.
277 * @param rcGC GC return code
278 */
279DECLINLINE(int) emR3ExecuteInstruction(PVM pVM, PVMCPU pVCpu, const char *pszPrefix, int rcGC)
280{
281#ifdef LOG_ENABLED
282 return emR3ExecuteInstructionWorker(pVM, pVCpu, rcGC, pszPrefix);
283#else
284 return emR3ExecuteInstructionWorker(pVM, pVCpu, rcGC);
285#endif
286}
287
288/**
289 * Executes one (or perhaps a few more) IO instruction(s).
290 *
291 * @returns VBox status code suitable for EM.
292 * @param pVM VM handle.
293 * @param pVCpu VMCPU handle.
294 */
295static int emR3ExecuteIOInstruction(PVM pVM, PVMCPU pVCpu)
296{
297 PCPUMCTX pCtx = pVCpu->em.s.pCtx;
298
299 STAM_PROFILE_START(&pVCpu->em.s.StatIOEmu, a);
300
301 /* Try to restart the io instruction that was refused in ring-0. */
302 VBOXSTRICTRC rcStrict = HWACCMR3RestartPendingIOInstr(pVM, pVCpu, pCtx);
303 if (IOM_SUCCESS(rcStrict))
304 {
305 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->StatIoRestarted);
306 STAM_PROFILE_STOP(&pVCpu->em.s.StatIOEmu, a);
307 return VBOXSTRICTRC_TODO(rcStrict); /* rip already updated. */
308 }
309 AssertMsgReturn(rcStrict == VERR_NOT_FOUND, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)),
310 RT_SUCCESS_NP(rcStrict) ? VERR_INTERNAL_ERROR_5 : VBOXSTRICTRC_TODO(rcStrict));
311
312 /** @todo probably we should fall back to the recompiler; otherwise we'll go back and forth between HC & GC
313 * as io instructions tend to come in packages of more than one
314 */
315 DISCPUSTATE Cpu;
316 int rc2 = CPUMR3DisasmInstrCPU(pVM, pVCpu, pCtx, pCtx->rip, &Cpu, "IO EMU");
317 if (RT_SUCCESS(rc2))
318 {
319 rcStrict = VINF_EM_RAW_EMULATE_INSTR;
320
321 if (!(Cpu.prefix & (PREFIX_REP | PREFIX_REPNE)))
322 {
323 switch (Cpu.pCurInstr->opcode)
324 {
325 case OP_IN:
326 {
327 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->StatIn);
328 rcStrict = IOMInterpretIN(pVM, CPUMCTX2CORE(pCtx), &Cpu);
329 break;
330 }
331
332 case OP_OUT:
333 {
334 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->StatOut);
335 rcStrict = IOMInterpretOUT(pVM, CPUMCTX2CORE(pCtx), &Cpu);
336 break;
337 }
338 }
339 }
340 else if (Cpu.prefix & PREFIX_REP)
341 {
342 switch (Cpu.pCurInstr->opcode)
343 {
344 case OP_INSB:
345 case OP_INSWD:
346 {
347 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->StatIn);
348 rcStrict = IOMInterpretINS(pVM, CPUMCTX2CORE(pCtx), &Cpu);
349 break;
350 }
351
352 case OP_OUTSB:
353 case OP_OUTSWD:
354 {
355 STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->StatOut);
356 rcStrict = IOMInterpretOUTS(pVM, CPUMCTX2CORE(pCtx), &Cpu);
357 break;
358 }
359 }
360 }
361
362 /*
363 * Handled the I/O return codes.
364 * (The unhandled cases end up with rcStrict == VINF_EM_RAW_EMULATE_INSTR.)
365 */
366 if (IOM_SUCCESS(rcStrict))
367 {
368 pCtx->rip += Cpu.opsize;
369 STAM_PROFILE_STOP(&pVCpu->em.s.StatIOEmu, a);
370 return VBOXSTRICTRC_TODO(rcStrict);
371 }
372
373 if (rcStrict == VINF_EM_RAW_GUEST_TRAP)
374 {
375 /* The active trap will be dispatched. */
376 Assert(TRPMHasTrap(pVCpu));
377 STAM_PROFILE_STOP(&pVCpu->em.s.StatIOEmu, a);
378 return VINF_SUCCESS;
379 }
380 AssertMsg(rcStrict != VINF_TRPM_XCPT_DISPATCHED, ("Handle VINF_TRPM_XCPT_DISPATCHED\n"));
381
382 if (RT_FAILURE(rcStrict))
383 {
384 STAM_PROFILE_STOP(&pVCpu->em.s.StatIOEmu, a);
385 return VBOXSTRICTRC_TODO(rcStrict);
386 }
387 AssertMsg(rcStrict == VINF_EM_RAW_EMULATE_INSTR || rcStrict == VINF_EM_RESCHEDULE_REM, ("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
388 }
389
390 STAM_PROFILE_STOP(&pVCpu->em.s.StatIOEmu, a);
391 return emR3ExecuteInstruction(pVM, pVCpu, "IO: ");
392}
393
394
395/**
396 * Process raw-mode specific forced actions.
397 *
398 * This function is called when any FFs in the VM_FF_HIGH_PRIORITY_PRE_RAW_MASK is pending.
399 *
400 * @returns VBox status code. May return VINF_EM_NO_MEMORY but none of the other
401 * EM statuses.
402 * @param pVM The VM handle.
403 * @param pVCpu The VMCPU handle.
404 * @param pCtx The guest CPUM register context.
405 */
406static int emR3HwaccmForcedActions(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
407{
408 /*
409 * Sync page directory.
410 */
411 if (VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL))
412 {
413 Assert(pVCpu->em.s.enmState != EMSTATE_WAIT_SIPI);
414 int rc = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
415 if (RT_FAILURE(rc))
416 return rc;
417
418 Assert(!VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_SELM_SYNC_GDT | VMCPU_FF_SELM_SYNC_LDT));
419
420 /* Prefetch pages for EIP and ESP. */
421 /** @todo This is rather expensive. Should investigate if it really helps at all. */
422 rc = PGMPrefetchPage(pVCpu, SELMToFlat(pVM, DIS_SELREG_CS, CPUMCTX2CORE(pCtx), pCtx->rip));
423 if (rc == VINF_SUCCESS)
424 rc = PGMPrefetchPage(pVCpu, SELMToFlat(pVM, DIS_SELREG_SS, CPUMCTX2CORE(pCtx), pCtx->rsp));
425 if (rc != VINF_SUCCESS)
426 {
427 if (rc != VINF_PGM_SYNC_CR3)
428 {
429 AssertLogRelMsgReturn(RT_FAILURE(rc), ("%Rrc\n", rc), VERR_IPE_UNEXPECTED_INFO_STATUS);
430 return rc;
431 }
432 rc = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4, VMCPU_FF_ISSET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
433 if (RT_FAILURE(rc))
434 return rc;
435 }
436 /** @todo maybe prefetch the supervisor stack page as well */
437 Assert(!VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_SELM_SYNC_GDT | VMCPU_FF_SELM_SYNC_LDT));
438 }
439
440 /*
441 * Allocate handy pages (just in case the above actions have consumed some pages).
442 */
443 if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_PGM_NEED_HANDY_PAGES, VM_FF_PGM_NO_MEMORY))
444 {
445 int rc = PGMR3PhysAllocateHandyPages(pVM);
446 if (RT_FAILURE(rc))
447 return rc;
448 }
449
450 /*
451 * Check whether we're out of memory now.
452 *
453 * This may stem from some of the above actions or operations that has been executed
454 * since we ran FFs. The allocate handy pages must for instance always be followed by
455 * this check.
456 */
457 if (VM_FF_ISPENDING(pVM, VM_FF_PGM_NO_MEMORY))
458 return VINF_EM_NO_MEMORY;
459
460 return VINF_SUCCESS;
461}
462
463
464/**
465 * Executes hardware accelerated raw code. (Intel VT-x & AMD-V)
466 *
467 * This function contains the raw-mode version of the inner
468 * execution loop (the outer loop being in EMR3ExecuteVM()).
469 *
470 * @returns VBox status code. The most important ones are: VINF_EM_RESCHEDULE, VINF_EM_RESCHEDULE_RAW,
471 * VINF_EM_RESCHEDULE_REM, VINF_EM_SUSPEND, VINF_EM_RESET and VINF_EM_TERMINATE.
472 *
473 * @param pVM VM handle.
474 * @param pVCpu VMCPU handle.
475 * @param pfFFDone Where to store an indicator telling whether or not
476 * FFs were done before returning.
477 */
478int emR3HwAccExecute(PVM pVM, PVMCPU pVCpu, bool *pfFFDone)
479{
480 int rc = VERR_INTERNAL_ERROR;
481 PCPUMCTX pCtx = pVCpu->em.s.pCtx;
482
483 LogFlow(("emR3HwAccExecute%d: (cs:eip=%04x:%RGv)\n", pVCpu->idCpu, pCtx->cs, (RTGCPTR)pCtx->rip));
484 *pfFFDone = false;
485
486 STAM_COUNTER_INC(&pVCpu->em.s.StatHwAccExecuteEntry);
487
488#ifdef EM_NOTIFY_HWACCM
489 HWACCMR3NotifyScheduled(pVCpu);
490#endif
491
492 /*
493 * Spin till we get a forced action which returns anything but VINF_SUCCESS.
494 */
495 for (;;)
496 {
497 STAM_PROFILE_ADV_START(&pVCpu->em.s.StatHwAccEntry, a);
498
499 /* Check if a forced reschedule is pending. */
500 if (HWACCMR3IsRescheduleRequired(pVM, pCtx))
501 {
502 rc = VINF_EM_RESCHEDULE;
503 break;
504 }
505
506 /*
507 * Process high priority pre-execution raw-mode FFs.
508 */
509 VMCPU_FF_CLEAR(pVCpu, (VMCPU_FF_SELM_SYNC_GDT | VMCPU_FF_SELM_SYNC_LDT | VMCPU_FF_TRPM_SYNC_IDT | VMCPU_FF_SELM_SYNC_TSS)); /* not relevant in HWACCM mode; shouldn't be set really. */
510 if ( VM_FF_ISPENDING(pVM, VM_FF_HIGH_PRIORITY_PRE_RAW_MASK)
511 || VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_HIGH_PRIORITY_PRE_RAW_MASK))
512 {
513 rc = emR3HwaccmForcedActions(pVM, pVCpu, pCtx);
514 if (rc != VINF_SUCCESS)
515 break;
516 }
517
518#ifdef LOG_ENABLED
519 /*
520 * Log important stuff before entering GC.
521 */
522 if (TRPMHasTrap(pVCpu))
523 Log(("CPU%d: Pending hardware interrupt=0x%x cs:rip=%04X:%RGv\n", pVCpu->idCpu, TRPMGetTrapNo(pVCpu), pCtx->cs, (RTGCPTR)pCtx->rip));
524
525 uint32_t cpl = CPUMGetGuestCPL(pVCpu, CPUMCTX2CORE(pCtx));
526
527 if (pVM->cCpus == 1)
528 {
529 if (pCtx->eflags.Bits.u1VM)
530 Log(("HWV86: %08X IF=%d\n", pCtx->eip, pCtx->eflags.Bits.u1IF));
531 else if (CPUMIsGuestIn64BitCodeEx(pCtx))
532 Log(("HWR%d: %04X:%RGv ESP=%RGv IF=%d IOPL=%d CR0=%x CR4=%x EFER=%x\n", cpl, pCtx->cs, (RTGCPTR)pCtx->rip, pCtx->rsp, pCtx->eflags.Bits.u1IF, pCtx->eflags.Bits.u2IOPL, (uint32_t)pCtx->cr0, (uint32_t)pCtx->cr4, (uint32_t)pCtx->msrEFER));
533 else
534 Log(("HWR%d: %04X:%08X ESP=%08X IF=%d IOPL=%d CR0=%x CR4=%x EFER=%x\n", cpl, pCtx->cs, pCtx->eip, pCtx->esp, pCtx->eflags.Bits.u1IF, pCtx->eflags.Bits.u2IOPL, (uint32_t)pCtx->cr0, (uint32_t)pCtx->cr4, (uint32_t)pCtx->msrEFER));
535 }
536 else
537 {
538 if (pCtx->eflags.Bits.u1VM)
539 Log(("HWV86-CPU%d: %08X IF=%d\n", pVCpu->idCpu, pCtx->eip, pCtx->eflags.Bits.u1IF));
540 else if (CPUMIsGuestIn64BitCodeEx(pCtx))
541 Log(("HWR%d-CPU%d: %04X:%RGv ESP=%RGv IF=%d IOPL=%d CR0=%x CR4=%x EFER=%x\n", cpl, pVCpu->idCpu, pCtx->cs, (RTGCPTR)pCtx->rip, pCtx->rsp, pCtx->eflags.Bits.u1IF, pCtx->eflags.Bits.u2IOPL, (uint32_t)pCtx->cr0, (uint32_t)pCtx->cr4, (uint32_t)pCtx->msrEFER));
542 else
543 Log(("HWR%d-CPU%d: %04X:%08X ESP=%08X IF=%d IOPL=%d CR0=%x CR4=%x EFER=%x\n", cpl, pVCpu->idCpu, pCtx->cs, pCtx->eip, pCtx->esp, pCtx->eflags.Bits.u1IF, pCtx->eflags.Bits.u2IOPL, (uint32_t)pCtx->cr0, (uint32_t)pCtx->cr4, (uint32_t)pCtx->msrEFER));
544 }
545#endif /* LOG_ENABLED */
546
547 /*
548 * Execute the code.
549 */
550 STAM_PROFILE_ADV_STOP(&pVCpu->em.s.StatHwAccEntry, a);
551 STAM_PROFILE_START(&pVCpu->em.s.StatHwAccExec, x);
552 rc = VMMR3HwAccRunGC(pVM, pVCpu);
553 STAM_PROFILE_STOP(&pVCpu->em.s.StatHwAccExec, x);
554
555 /*
556 * Deal with high priority post execution FFs before doing anything else.
557 */
558 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_RESUME_GUEST_MASK);
559 if ( VM_FF_ISPENDING(pVM, VM_FF_HIGH_PRIORITY_POST_MASK)
560 || VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_HIGH_PRIORITY_POST_MASK))
561 rc = emR3HighPriorityPostForcedActions(pVM, pVCpu, rc);
562
563 /*
564 * Process the returned status code.
565 */
566 if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
567 break;
568
569 rc = emR3HwaccmHandleRC(pVM, pVCpu, pCtx, rc);
570 if (rc != VINF_SUCCESS)
571 break;
572
573 /*
574 * Check and execute forced actions.
575 */
576#ifdef VBOX_HIGH_RES_TIMERS_HACK
577 TMTimerPollVoid(pVM, pVCpu);
578#endif
579 if ( VM_FF_ISPENDING(pVM, VM_FF_ALL_MASK)
580 || VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_ALL_MASK))
581 {
582 rc = emR3ForcedActions(pVM, pVCpu, rc);
583 if ( rc != VINF_SUCCESS
584 && rc != VINF_EM_RESCHEDULE_HWACC)
585 {
586 *pfFFDone = true;
587 break;
588 }
589 }
590 }
591
592 /*
593 * Return to outer loop.
594 */
595#if defined(LOG_ENABLED) && defined(DEBUG)
596 RTLogFlush(NULL);
597#endif
598 return rc;
599}
600
601
Note: See TracBrowser for help on using the repository browser.

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