VirtualBox

source: vbox/trunk/src/VBox/VMM/EM.cpp@ 2738

Last change on this file since 2738 was 2716, checked in by vboxsync, 18 years ago

One other case where we should check if any forced actions are pending before forwarding a trap or interrupt.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 139.1 KB
Line 
1/* $Id: EM.cpp 2716 2007-05-18 14:33:00Z vboxsync $ */
2/** @file
3 * EM - Execution Monitor/Manager.
4 */
5
6/*
7 * Copyright (C) 2006 InnoTek Systemberatung GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22
23/** @page pg_em EM - The Execution Monitor/Manager
24 *
25 * The Execution Monitor/Manager is responsible for running the VM, scheduling
26 * the right kind of execution (Raw, Recompiled, Interpreted,..), and keeping
27 * the CPU states in sync. The function RMR3ExecuteVM() is the 'main-loop' of
28 * the VM.
29 *
30 */
31
32/*******************************************************************************
33* Header Files *
34*******************************************************************************/
35#define LOG_GROUP LOG_GROUP_EM
36#include <VBox/em.h>
37#include <VBox/vmm.h>
38#include <VBox/patm.h>
39#include <VBox/csam.h>
40#include <VBox/selm.h>
41#include <VBox/trpm.h>
42#include <VBox/iom.h>
43#include <VBox/dbgf.h>
44#include <VBox/pgm.h>
45#include <VBox/rem.h>
46#include <VBox/tm.h>
47#include <VBox/mm.h>
48#include <VBox/pdm.h>
49#include <VBox/hwaccm.h>
50#include <VBox/patm.h>
51#include "EMInternal.h"
52#include <VBox/vm.h>
53#include <VBox/cpumdis.h>
54#include <VBox/dis.h>
55#include <VBox/disopcode.h>
56#include <VBox/dbgf.h>
57
58#include <VBox/log.h>
59#include <iprt/thread.h>
60#include <iprt/assert.h>
61#include <iprt/asm.h>
62#include <iprt/semaphore.h>
63#include <iprt/string.h>
64#include <iprt/avl.h>
65#include <iprt/stream.h>
66#include <VBox/param.h>
67#include <VBox/err.h>
68
69
70/*******************************************************************************
71* Internal Functions *
72*******************************************************************************/
73static DECLCALLBACK(int) emR3Save(PVM pVM, PSSMHANDLE pSSM);
74static DECLCALLBACK(int) emR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version);
75static int emR3Debug(PVM pVM, int rc);
76static int emR3RemStep(PVM pVM);
77static int emR3RemExecute(PVM pVM, bool *pfFFDone);
78static int emR3RawResumeHyper(PVM pVM);
79static int emR3RawStep(PVM pVM);
80DECLINLINE(int) emR3RawHandleRC(PVM pVM, PCPUMCTX pCtx, int rc);
81DECLINLINE(int) emR3RawUpdateForceFlag(PVM pVM, PCPUMCTX pCtx, int rc);
82static int emR3RawForcedActions(PVM pVM, PCPUMCTX pCtx);
83static int emR3RawExecute(PVM pVM, bool *pfFFDone);
84DECLINLINE(int) emR3RawExecuteInstruction(PVM pVM, const char *pszPrefix, int rcGC = VINF_SUCCESS);
85static int emR3HighPriorityPostForcedActions(PVM pVM, int rc);
86static int emR3ForcedActions(PVM pVM, int rc);
87static int emR3RawGuestTrap(PVM pVM);
88
89
90/**
91 * Initializes the EM.
92 *
93 * @returns VBox status code.
94 * @param pVM The VM to operate on.
95 */
96EMR3DECL(int) EMR3Init(PVM pVM)
97{
98 LogFlow(("EMR3Init\n"));
99 /*
100 * Assert alignment and sizes.
101 */
102 AssertRelease(!(RT_OFFSETOF(VM, em.s) & 31));
103 AssertRelease(sizeof(pVM->em.s) <= sizeof(pVM->em.padding));
104 AssertReleaseMsg(sizeof(pVM->em.s.u.FatalLongJump) <= sizeof(pVM->em.s.u.achPaddingFatalLongJump),
105 ("%d bytes, padding %d\n", sizeof(pVM->em.s.u.FatalLongJump), sizeof(pVM->em.s.u.achPaddingFatalLongJump)));
106
107 /*
108 * Init the structure.
109 */
110 pVM->em.s.offVM = RT_OFFSETOF(VM, em.s);
111 int rc = CFGMR3QueryBool(CFGMR3GetRoot(pVM), "RawR3Enabled", &pVM->fRawR3Enabled);
112 if (VBOX_FAILURE(rc))
113 pVM->fRawR3Enabled = true;
114 rc = CFGMR3QueryBool(CFGMR3GetRoot(pVM), "RawR0Enabled", &pVM->fRawR0Enabled);
115 if (VBOX_FAILURE(rc))
116 pVM->fRawR0Enabled = true;
117 Log(("EMR3Init: fRawR3Enabled=%d fRawR0Enabled=%d\n", pVM->fRawR3Enabled, pVM->fRawR0Enabled));
118 pVM->em.s.enmState = EMSTATE_NONE;
119 pVM->em.s.fForceRAW = false;
120
121 rc = CPUMQueryGuestCtxPtr(pVM, &pVM->em.s.pCtx);
122 AssertMsgRC(rc, ("CPUMQueryGuestCtxPtr -> %Vrc\n", rc));
123 pVM->em.s.pPatmGCState = PATMR3QueryGCStateHC(pVM);
124 AssertMsg(pVM->em.s.pPatmGCState, ("PATMR3QueryGCStateHC failed!\n"));
125
126 /*
127 * Saved state.
128 */
129 rc = SSMR3RegisterInternal(pVM, "em", 0, EM_SAVED_STATE_VERSION, 16,
130 NULL, emR3Save, NULL,
131 NULL, emR3Load, NULL);
132 if (VBOX_FAILURE(rc))
133 return rc;
134
135 /*
136 * Statistics.
137 */
138#ifdef VBOX_WITH_STATISTICS
139 PEMSTATS pStats;
140 rc = MMHyperAlloc(pVM, sizeof(*pStats), 0, MM_TAG_EM, (void **)&pStats);
141 if (VBOX_FAILURE(rc))
142 return rc;
143 pVM->em.s.pStatsHC = pStats;
144 pVM->em.s.pStatsGC = MMHyperHC2GC(pVM, pStats);
145
146 STAM_REG(pVM, &pStats->StatGCEmulate, STAMTYPE_PROFILE, "/EM/GC/Interpret", STAMUNIT_TICKS_PER_CALL, "Profiling of EMInterpretInstruction.");
147 STAM_REG(pVM, &pStats->StatHCEmulate, STAMTYPE_PROFILE, "/EM/HC/Interpret", STAMUNIT_TICKS_PER_CALL, "Profiling of EMInterpretInstruction.");
148
149 STAM_REG(pVM, &pStats->StatGCInterpretSucceeded, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success", STAMUNIT_OCCURENCES, "The number of times an instruction was successfully interpreted.");
150 STAM_REG(pVM, &pStats->StatHCInterpretSucceeded, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success", STAMUNIT_OCCURENCES, "The number of times an instruction was successfully interpreted.");
151
152 STAM_REG_USED(pVM, &pStats->StatGCAnd, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/And", STAMUNIT_OCCURENCES, "The number of times AND was successfully interpreted.");
153 STAM_REG_USED(pVM, &pStats->StatHCAnd, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/And", STAMUNIT_OCCURENCES, "The number of times AND was successfully interpreted.");
154 STAM_REG_USED(pVM, &pStats->StatGCAdd, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/Add", STAMUNIT_OCCURENCES, "The number of times ADD was successfully interpreted.");
155 STAM_REG_USED(pVM, &pStats->StatHCAdd, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/Add", STAMUNIT_OCCURENCES, "The number of times ADD was successfully interpreted.");
156 STAM_REG_USED(pVM, &pStats->StatGCAdc, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/Adc", STAMUNIT_OCCURENCES, "The number of times ADC was successfully interpreted.");
157 STAM_REG_USED(pVM, &pStats->StatHCAdc, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/Adc", STAMUNIT_OCCURENCES, "The number of times ADC was successfully interpreted.");
158 STAM_REG_USED(pVM, &pStats->StatGCSub, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/Sub", STAMUNIT_OCCURENCES, "The number of times SUB was successfully interpreted.");
159 STAM_REG_USED(pVM, &pStats->StatHCSub, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/Sub", STAMUNIT_OCCURENCES, "The number of times SUB was successfully interpreted.");
160 STAM_REG_USED(pVM, &pStats->StatGCCpuId, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/CpuId", STAMUNIT_OCCURENCES, "The number of times CPUID was successfully interpreted.");
161 STAM_REG_USED(pVM, &pStats->StatHCCpuId, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/CpuId", STAMUNIT_OCCURENCES, "The number of times CPUID was successfully interpreted.");
162 STAM_REG_USED(pVM, &pStats->StatGCDec, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/Dec", STAMUNIT_OCCURENCES, "The number of times DEC was successfully interpreted.");
163 STAM_REG_USED(pVM, &pStats->StatHCDec, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/Dec", STAMUNIT_OCCURENCES, "The number of times DEC was successfully interpreted.");
164 STAM_REG_USED(pVM, &pStats->StatGCHlt, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/Hlt", STAMUNIT_OCCURENCES, "The number of times HLT was successfully interpreted.");
165 STAM_REG_USED(pVM, &pStats->StatHCHlt, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/Hlt", STAMUNIT_OCCURENCES, "The number of times HLT was successfully interpreted.");
166 STAM_REG_USED(pVM, &pStats->StatGCInc, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/Inc", STAMUNIT_OCCURENCES, "The number of times INC was successfully interpreted.");
167 STAM_REG_USED(pVM, &pStats->StatHCInc, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/Inc", STAMUNIT_OCCURENCES, "The number of times INC was successfully interpreted.");
168 STAM_REG_USED(pVM, &pStats->StatGCInvlPg, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/Invlpg", STAMUNIT_OCCURENCES, "The number of times INVLPG was successfully interpreted.");
169 STAM_REG_USED(pVM, &pStats->StatHCInvlPg, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/Invlpg", STAMUNIT_OCCURENCES, "The number of times INVLPG was successfully interpreted.");
170 STAM_REG_USED(pVM, &pStats->StatGCIret, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/Iret", STAMUNIT_OCCURENCES, "The number of times IRET was successfully interpreted.");
171 STAM_REG_USED(pVM, &pStats->StatHCIret, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/Iret", STAMUNIT_OCCURENCES, "The number of times IRET was successfully interpreted.");
172 STAM_REG_USED(pVM, &pStats->StatGCLLdt, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/LLdt", STAMUNIT_OCCURENCES, "The number of times LLDT was successfully interpreted.");
173 STAM_REG_USED(pVM, &pStats->StatHCLLdt, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/LLdt", STAMUNIT_OCCURENCES, "The number of times LLDT was successfully interpreted.");
174 STAM_REG_USED(pVM, &pStats->StatGCMov, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/Mov", STAMUNIT_OCCURENCES, "The number of times MOV was successfully interpreted.");
175 STAM_REG_USED(pVM, &pStats->StatHCMov, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/Mov", STAMUNIT_OCCURENCES, "The number of times MOV was successfully interpreted.");
176 STAM_REG_USED(pVM, &pStats->StatGCMovCRx, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/MovCRx", STAMUNIT_OCCURENCES, "The number of times MOV CRx was successfully interpreted.");
177 STAM_REG_USED(pVM, &pStats->StatHCMovCRx, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/MovCRx", STAMUNIT_OCCURENCES, "The number of times MOV CRx was successfully interpreted.");
178 STAM_REG_USED(pVM, &pStats->StatGCMovDRx, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/MovDRx", STAMUNIT_OCCURENCES, "The number of times MOV DRx was successfully interpreted.");
179 STAM_REG_USED(pVM, &pStats->StatHCMovDRx, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/MovDRx", STAMUNIT_OCCURENCES, "The number of times MOV DRx was successfully interpreted.");
180 STAM_REG_USED(pVM, &pStats->StatGCOr, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/Or", STAMUNIT_OCCURENCES, "The number of times OR was successfully interpreted.");
181 STAM_REG_USED(pVM, &pStats->StatHCOr, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/Or", STAMUNIT_OCCURENCES, "The number of times OR was successfully interpreted.");
182 STAM_REG_USED(pVM, &pStats->StatGCPop, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/Pop", STAMUNIT_OCCURENCES, "The number of times POP was successfully interpreted.");
183 STAM_REG_USED(pVM, &pStats->StatHCPop, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/Pop", STAMUNIT_OCCURENCES, "The number of times POP was successfully interpreted.");
184 STAM_REG_USED(pVM, &pStats->StatGCRdtsc, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/Rdtsc", STAMUNIT_OCCURENCES, "The number of times RDTSC was successfully interpreted.");
185 STAM_REG_USED(pVM, &pStats->StatHCRdtsc, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/Rdtsc", STAMUNIT_OCCURENCES, "The number of times RDTSC was successfully interpreted.");
186 STAM_REG_USED(pVM, &pStats->StatGCSti, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/Sti", STAMUNIT_OCCURENCES, "The number of times STI was successfully interpreted.");
187 STAM_REG_USED(pVM, &pStats->StatHCSti, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/Sti", STAMUNIT_OCCURENCES, "The number of times STI was successfully interpreted.");
188 STAM_REG_USED(pVM, &pStats->StatGCXchg, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/Xchg", STAMUNIT_OCCURENCES, "The number of times XCHG was successfully interpreted.");
189 STAM_REG_USED(pVM, &pStats->StatHCXchg, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/Xchg", STAMUNIT_OCCURENCES, "The number of times XCHG was successfully interpreted.");
190 STAM_REG_USED(pVM, &pStats->StatGCXor, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/Xor", STAMUNIT_OCCURENCES, "The number of times XOR was successfully interpreted.");
191 STAM_REG_USED(pVM, &pStats->StatHCXor, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/Xor", STAMUNIT_OCCURENCES, "The number of times XOR was successfully interpreted.");
192 STAM_REG_USED(pVM, &pStats->StatGCMonitor, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/Monitor", STAMUNIT_OCCURENCES, "The number of times MONITOR was successfully interpreted.");
193 STAM_REG_USED(pVM, &pStats->StatHCMonitor, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/Monitor", STAMUNIT_OCCURENCES, "The number of times MONITOR was successfully interpreted.");
194 STAM_REG_USED(pVM, &pStats->StatGCMWait, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/MWait", STAMUNIT_OCCURENCES, "The number of times MWAIT was successfully interpreted.");
195 STAM_REG_USED(pVM, &pStats->StatHCMWait, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/MWait", STAMUNIT_OCCURENCES, "The number of times MWAIT was successfully interpreted.");
196 STAM_REG_USED(pVM, &pStats->StatGCBtr, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/Btr", STAMUNIT_OCCURENCES, "The number of times BTR was successfully interpreted.");
197 STAM_REG_USED(pVM, &pStats->StatHCBtr, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/Btr", STAMUNIT_OCCURENCES, "The number of times BTR was successfully interpreted.");
198 STAM_REG_USED(pVM, &pStats->StatGCBts, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/Bts", STAMUNIT_OCCURENCES, "The number of times BTS was successfully interpreted.");
199 STAM_REG_USED(pVM, &pStats->StatHCBts, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/Bts", STAMUNIT_OCCURENCES, "The number of times BTS was successfully interpreted.");
200 STAM_REG_USED(pVM, &pStats->StatGCBtc, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/Btc", STAMUNIT_OCCURENCES, "The number of times BTC was successfully interpreted.");
201 STAM_REG_USED(pVM, &pStats->StatHCBtc, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/Btc", STAMUNIT_OCCURENCES, "The number of times BTC was successfully interpreted.");
202 STAM_REG_USED(pVM, &pStats->StatGCCmpXchg, STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/CmpXchg", STAMUNIT_OCCURENCES, "The number of times CMPXCHG was successfully interpreted.");
203 STAM_REG_USED(pVM, &pStats->StatHCCmpXchg, STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/CmpXchg", STAMUNIT_OCCURENCES, "The number of times CMPXCHG was successfully interpreted.");
204
205 STAM_REG(pVM, &pStats->StatGCInterpretFailed, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed", STAMUNIT_OCCURENCES, "The number of times an instruction was not interpreted.");
206 STAM_REG(pVM, &pStats->StatHCInterpretFailed, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed", STAMUNIT_OCCURENCES, "The number of times an instruction was not interpreted.");
207
208 STAM_REG_USED(pVM, &pStats->StatGCFailedAnd, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/And", STAMUNIT_OCCURENCES, "The number of times AND was not interpreted.");
209 STAM_REG_USED(pVM, &pStats->StatHCFailedAnd, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/And", STAMUNIT_OCCURENCES, "The number of times AND was not interpreted.");
210 STAM_REG_USED(pVM, &pStats->StatGCFailedCpuId, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/CpuId", STAMUNIT_OCCURENCES, "The number of times CPUID was not interpreted.");
211 STAM_REG_USED(pVM, &pStats->StatHCFailedCpuId, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/CpuId", STAMUNIT_OCCURENCES, "The number of times CPUID was not interpreted.");
212 STAM_REG_USED(pVM, &pStats->StatGCFailedDec, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Dec", STAMUNIT_OCCURENCES, "The number of times DEC was not interpreted.");
213 STAM_REG_USED(pVM, &pStats->StatHCFailedDec, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/Dec", STAMUNIT_OCCURENCES, "The number of times DEC was not interpreted.");
214 STAM_REG_USED(pVM, &pStats->StatGCFailedHlt, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Hlt", STAMUNIT_OCCURENCES, "The number of times HLT was not interpreted.");
215 STAM_REG_USED(pVM, &pStats->StatHCFailedHlt, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/Hlt", STAMUNIT_OCCURENCES, "The number of times HLT was not interpreted.");
216 STAM_REG_USED(pVM, &pStats->StatGCFailedInc, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Inc", STAMUNIT_OCCURENCES, "The number of times INC was not interpreted.");
217 STAM_REG_USED(pVM, &pStats->StatHCFailedInc, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/Inc", STAMUNIT_OCCURENCES, "The number of times INC was not interpreted.");
218 STAM_REG_USED(pVM, &pStats->StatGCFailedInvlPg, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/InvlPg", STAMUNIT_OCCURENCES, "The number of times INVLPG was not interpreted.");
219 STAM_REG_USED(pVM, &pStats->StatHCFailedInvlPg, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/InvlPg", STAMUNIT_OCCURENCES, "The number of times INVLPG was not interpreted.");
220 STAM_REG_USED(pVM, &pStats->StatGCFailedIret, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Iret", STAMUNIT_OCCURENCES, "The number of times IRET was not interpreted.");
221 STAM_REG_USED(pVM, &pStats->StatHCFailedIret, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/Iret", STAMUNIT_OCCURENCES, "The number of times IRET was not interpreted.");
222 STAM_REG_USED(pVM, &pStats->StatGCFailedLLdt, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/LLdt", STAMUNIT_OCCURENCES, "The number of times LLDT was not interpreted.");
223 STAM_REG_USED(pVM, &pStats->StatHCFailedLLdt, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/LLdt", STAMUNIT_OCCURENCES, "The number of times LLDT was not interpreted.");
224 STAM_REG_USED(pVM, &pStats->StatGCFailedMov, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Mov", STAMUNIT_OCCURENCES, "The number of times MOV was not interpreted.");
225 STAM_REG_USED(pVM, &pStats->StatHCFailedMov, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/Mov", STAMUNIT_OCCURENCES, "The number of times MOV was not interpreted.");
226 STAM_REG_USED(pVM, &pStats->StatGCFailedMovCRx, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/MovCRx", STAMUNIT_OCCURENCES, "The number of times MOV CRx was not interpreted.");
227 STAM_REG_USED(pVM, &pStats->StatHCFailedMovCRx, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/MovCRx", STAMUNIT_OCCURENCES, "The number of times MOV CRx was not interpreted.");
228 STAM_REG_USED(pVM, &pStats->StatGCFailedMovDRx, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/MovDRx", STAMUNIT_OCCURENCES, "The number of times MOV DRx was not interpreted.");
229 STAM_REG_USED(pVM, &pStats->StatHCFailedMovDRx, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/MovDRx", STAMUNIT_OCCURENCES, "The number of times MOV DRx was not interpreted.");
230 STAM_REG_USED(pVM, &pStats->StatGCFailedOr, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Or", STAMUNIT_OCCURENCES, "The number of times OR was not interpreted.");
231 STAM_REG_USED(pVM, &pStats->StatHCFailedOr, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/Or", STAMUNIT_OCCURENCES, "The number of times OR was not interpreted.");
232 STAM_REG_USED(pVM, &pStats->StatGCFailedPop, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Pop", STAMUNIT_OCCURENCES, "The number of times POP was not interpreted.");
233 STAM_REG_USED(pVM, &pStats->StatHCFailedPop, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/Pop", STAMUNIT_OCCURENCES, "The number of times POP was not interpreted.");
234 STAM_REG_USED(pVM, &pStats->StatGCFailedSti, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Sti", STAMUNIT_OCCURENCES, "The number of times STI was not interpreted.");
235 STAM_REG_USED(pVM, &pStats->StatHCFailedSti, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/Sti", STAMUNIT_OCCURENCES, "The number of times STI was not interpreted.");
236 STAM_REG_USED(pVM, &pStats->StatGCFailedXchg, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Xchg", STAMUNIT_OCCURENCES, "The number of times XCHG was not interpreted.");
237 STAM_REG_USED(pVM, &pStats->StatHCFailedXchg, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/Xchg", STAMUNIT_OCCURENCES, "The number of times XCHG was not interpreted.");
238 STAM_REG_USED(pVM, &pStats->StatGCFailedXor, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Xor", STAMUNIT_OCCURENCES, "The number of times XOR was not interpreted.");
239 STAM_REG_USED(pVM, &pStats->StatHCFailedXor, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/Xor", STAMUNIT_OCCURENCES, "The number of times XOR was not interpreted.");
240 STAM_REG_USED(pVM, &pStats->StatGCFailedMonitor, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Monitor", STAMUNIT_OCCURENCES, "The number of times MONITOR was not interpreted.");
241 STAM_REG_USED(pVM, &pStats->StatHCFailedMonitor, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/Monitor", STAMUNIT_OCCURENCES, "The number of times MONITOR was not interpreted.");
242 STAM_REG_USED(pVM, &pStats->StatGCFailedMWait, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/MWait", STAMUNIT_OCCURENCES, "The number of times MONITOR was not interpreted.");
243 STAM_REG_USED(pVM, &pStats->StatHCFailedMWait, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/MWait", STAMUNIT_OCCURENCES, "The number of times MONITOR was not interpreted.");
244 STAM_REG_USED(pVM, &pStats->StatGCFailedRdtsc, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Rdtsc", STAMUNIT_OCCURENCES, "The number of times RDTSC was not interpreted.");
245 STAM_REG_USED(pVM, &pStats->StatHCFailedRdtsc, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/Rdtsc", STAMUNIT_OCCURENCES, "The number of times RDTSC was not interpreted.");
246
247 STAM_REG_USED(pVM, &pStats->StatGCFailedMisc, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Misc", STAMUNIT_OCCURENCES, "The number of times some misc instruction was encountered.");
248 STAM_REG_USED(pVM, &pStats->StatHCFailedMisc, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/Misc", STAMUNIT_OCCURENCES, "The number of times some misc instruction was encountered.");
249 STAM_REG_USED(pVM, &pStats->StatGCFailedAdd, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Add", STAMUNIT_OCCURENCES, "The number of times ADD was not interpreted.");
250 STAM_REG_USED(pVM, &pStats->StatHCFailedAdd, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/Add", STAMUNIT_OCCURENCES, "The number of times ADD was not interpreted.");
251 STAM_REG_USED(pVM, &pStats->StatGCFailedAdc, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Adc", STAMUNIT_OCCURENCES, "The number of times ADC was not interpreted.");
252 STAM_REG_USED(pVM, &pStats->StatHCFailedAdc, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/Adc", STAMUNIT_OCCURENCES, "The number of times ADC was not interpreted.");
253 STAM_REG_USED(pVM, &pStats->StatGCFailedBtr, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Btr", STAMUNIT_OCCURENCES, "The number of times BTR was not interpreted.");
254 STAM_REG_USED(pVM, &pStats->StatHCFailedBtr, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/Btr", STAMUNIT_OCCURENCES, "The number of times BTR was not interpreted.");
255 STAM_REG_USED(pVM, &pStats->StatGCFailedBts, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Bts", STAMUNIT_OCCURENCES, "The number of times BTS was not interpreted.");
256 STAM_REG_USED(pVM, &pStats->StatHCFailedBts, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/Bts", STAMUNIT_OCCURENCES, "The number of times BTS was not interpreted.");
257 STAM_REG_USED(pVM, &pStats->StatGCFailedBtc, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Btc", STAMUNIT_OCCURENCES, "The number of times BTC was not interpreted.");
258 STAM_REG_USED(pVM, &pStats->StatHCFailedBtc, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/Btc", STAMUNIT_OCCURENCES, "The number of times BTC was not interpreted.");
259 STAM_REG_USED(pVM, &pStats->StatGCFailedCli, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Cli", STAMUNIT_OCCURENCES, "The number of times CLI was not interpreted.");
260 STAM_REG_USED(pVM, &pStats->StatHCFailedCli, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/Cli", STAMUNIT_OCCURENCES, "The number of times CLI was not interpreted.");
261 STAM_REG_USED(pVM, &pStats->StatGCFailedCmpXchg, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/CmpXchg", STAMUNIT_OCCURENCES, "The number of times CMPXCHG was not interpreted.");
262 STAM_REG_USED(pVM, &pStats->StatHCFailedCmpXchg, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/CmpXchg", STAMUNIT_OCCURENCES, "The number of times CMPXCHG was not interpreted.");
263 STAM_REG_USED(pVM, &pStats->StatGCFailedMovNTPS, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/MovNTPS", STAMUNIT_OCCURENCES, "The number of times MOVNTPS was not interpreted.");
264 STAM_REG_USED(pVM, &pStats->StatHCFailedMovNTPS, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/MovNTPS", STAMUNIT_OCCURENCES, "The number of times MOVNTPS was not interpreted.");
265 STAM_REG_USED(pVM, &pStats->StatGCFailedStosWD, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/StosWD", STAMUNIT_OCCURENCES, "The number of times STOSWD was not interpreted.");
266 STAM_REG_USED(pVM, &pStats->StatHCFailedStosWD, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/StosWD", STAMUNIT_OCCURENCES, "The number of times STOSWD was not interpreted.");
267 STAM_REG_USED(pVM, &pStats->StatGCFailedSub, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Sub", STAMUNIT_OCCURENCES, "The number of times SUB was not interpreted.");
268 STAM_REG_USED(pVM, &pStats->StatHCFailedSub, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/Sub", STAMUNIT_OCCURENCES, "The number of times SUB was not interpreted.");
269 STAM_REG_USED(pVM, &pStats->StatGCFailedWbInvd, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/WbInvd", STAMUNIT_OCCURENCES, "The number of times WBINVD was not interpreted.");
270 STAM_REG_USED(pVM, &pStats->StatHCFailedWbInvd, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/WbInvd", STAMUNIT_OCCURENCES, "The number of times WBINVD was not interpreted.");
271
272 STAM_REG_USED(pVM, &pStats->StatGCFailedUserMode, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/UserMode", STAMUNIT_OCCURENCES, "The number of rejections because of CPL.");
273 STAM_REG_USED(pVM, &pStats->StatHCFailedUserMode, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/UserMode", STAMUNIT_OCCURENCES, "The number of rejections because of CPL.");
274 STAM_REG_USED(pVM, &pStats->StatGCFailedPrefix, STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/Prefix", STAMUNIT_OCCURENCES, "The number of rejections because of prefix .");
275 STAM_REG_USED(pVM, &pStats->StatHCFailedPrefix, STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/Prefix", STAMUNIT_OCCURENCES, "The number of rejections because of prefix .");
276
277 STAM_REG_USED(pVM, &pStats->StatCli, STAMTYPE_COUNTER, "/EM/HC/PrivInst/Cli", STAMUNIT_OCCURENCES, "Number of cli instructions.");
278 STAM_REG_USED(pVM, &pStats->StatSti, STAMTYPE_COUNTER, "/EM/HC/PrivInst/Sti", STAMUNIT_OCCURENCES, "Number of sli instructions.");
279 STAM_REG_USED(pVM, &pStats->StatIn, STAMTYPE_COUNTER, "/EM/HC/PrivInst/In", STAMUNIT_OCCURENCES, "Number of in instructions.");
280 STAM_REG_USED(pVM, &pStats->StatOut, STAMTYPE_COUNTER, "/EM/HC/PrivInst/Out", STAMUNIT_OCCURENCES, "Number of out instructions.");
281 STAM_REG_USED(pVM, &pStats->StatHlt, STAMTYPE_COUNTER, "/EM/HC/PrivInst/Hlt", STAMUNIT_OCCURENCES, "Number of hlt instructions not handled in GC because of PATM.");
282 STAM_REG_USED(pVM, &pStats->StatInvlpg, STAMTYPE_COUNTER, "/EM/HC/PrivInst/Invlpg", STAMUNIT_OCCURENCES, "Number of invlpg instructions.");
283 STAM_REG_USED(pVM, &pStats->StatMisc, STAMTYPE_COUNTER, "/EM/HC/PrivInst/Misc", STAMUNIT_OCCURENCES, "Number of misc. instructions.");
284 STAM_REG_USED(pVM, &pStats->StatMovWriteCR[0], STAMTYPE_COUNTER, "/EM/HC/PrivInst/Mov CR0, X", STAMUNIT_OCCURENCES, "Number of mov CR0 read instructions.");
285 STAM_REG_USED(pVM, &pStats->StatMovWriteCR[1], STAMTYPE_COUNTER, "/EM/HC/PrivInst/Mov CR1, X", STAMUNIT_OCCURENCES, "Number of mov CR1 read instructions.");
286 STAM_REG_USED(pVM, &pStats->StatMovWriteCR[2], STAMTYPE_COUNTER, "/EM/HC/PrivInst/Mov CR2, X", STAMUNIT_OCCURENCES, "Number of mov CR2 read instructions.");
287 STAM_REG_USED(pVM, &pStats->StatMovWriteCR[3], STAMTYPE_COUNTER, "/EM/HC/PrivInst/Mov CR3, X", STAMUNIT_OCCURENCES, "Number of mov CR3 read instructions.");
288 STAM_REG_USED(pVM, &pStats->StatMovWriteCR[4], STAMTYPE_COUNTER, "/EM/HC/PrivInst/Mov CR4, X", STAMUNIT_OCCURENCES, "Number of mov CR4 read instructions.");
289 STAM_REG_USED(pVM, &pStats->StatMovReadCR[0], STAMTYPE_COUNTER, "/EM/HC/PrivInst/Mov X, CR0", STAMUNIT_OCCURENCES, "Number of mov CR0 write instructions.");
290 STAM_REG_USED(pVM, &pStats->StatMovReadCR[1], STAMTYPE_COUNTER, "/EM/HC/PrivInst/Mov X, CR1", STAMUNIT_OCCURENCES, "Number of mov CR1 write instructions.");
291 STAM_REG_USED(pVM, &pStats->StatMovReadCR[2], STAMTYPE_COUNTER, "/EM/HC/PrivInst/Mov X, CR2", STAMUNIT_OCCURENCES, "Number of mov CR2 write instructions.");
292 STAM_REG_USED(pVM, &pStats->StatMovReadCR[3], STAMTYPE_COUNTER, "/EM/HC/PrivInst/Mov X, CR3", STAMUNIT_OCCURENCES, "Number of mov CR3 write instructions.");
293 STAM_REG_USED(pVM, &pStats->StatMovReadCR[4], STAMTYPE_COUNTER, "/EM/HC/PrivInst/Mov X, CR4", STAMUNIT_OCCURENCES, "Number of mov CR4 write instructions.");
294 STAM_REG_USED(pVM, &pStats->StatMovDRx, STAMTYPE_COUNTER, "/EM/HC/PrivInst/MovDRx", STAMUNIT_OCCURENCES, "Number of mov DRx instructions.");
295 STAM_REG_USED(pVM, &pStats->StatIret, STAMTYPE_COUNTER, "/EM/HC/PrivInst/Iret", STAMUNIT_OCCURENCES, "Number of iret instructions.");
296 STAM_REG_USED(pVM, &pStats->StatMovLgdt, STAMTYPE_COUNTER, "/EM/HC/PrivInst/Lgdt", STAMUNIT_OCCURENCES, "Number of lgdt instructions.");
297 STAM_REG_USED(pVM, &pStats->StatMovLidt, STAMTYPE_COUNTER, "/EM/HC/PrivInst/Lidt", STAMUNIT_OCCURENCES, "Number of lidt instructions.");
298 STAM_REG_USED(pVM, &pStats->StatMovLldt, STAMTYPE_COUNTER, "/EM/HC/PrivInst/Lldt", STAMUNIT_OCCURENCES, "Number of lldt instructions.");
299 STAM_REG_USED(pVM, &pStats->StatSysEnter, STAMTYPE_COUNTER, "/EM/HC/PrivInst/Sysenter", STAMUNIT_OCCURENCES, "Number of sysenter instructions.");
300 STAM_REG_USED(pVM, &pStats->StatSysExit, STAMTYPE_COUNTER, "/EM/HC/PrivInst/Sysexit", STAMUNIT_OCCURENCES, "Number of sysexit instructions.");
301 STAM_REG_USED(pVM, &pStats->StatSysCall, STAMTYPE_COUNTER, "/EM/HC/PrivInst/Syscall", STAMUNIT_OCCURENCES, "Number of syscall instructions.");
302 STAM_REG_USED(pVM, &pStats->StatSysRet, STAMTYPE_COUNTER, "/EM/HC/PrivInst/Sysret", STAMUNIT_OCCURENCES, "Number of sysret instructions.");
303
304 STAM_REG(pVM, &pVM->em.s.StatTotalClis, STAMTYPE_COUNTER, "/EM/Cli/Total", STAMUNIT_OCCURENCES, "Total number of cli instructions executed.");
305 pVM->em.s.pCliStatTree = 0;
306#endif /* VBOX_WITH_STATISTICS */
307
308/* these should be considered for release statistics. */
309 STAM_REG(pVM, &pVM->em.s.StatForcedActions, STAMTYPE_PROFILE, "/PROF/EM/ForcedActions", STAMUNIT_TICKS_PER_CALL, "Profiling forced action execution.");
310 STAM_REG(pVM, &pVM->em.s.StatHalted, STAMTYPE_PROFILE, "/PROF/EM/Halted", STAMUNIT_TICKS_PER_CALL, "Profiling halted state (VMR3WaitHalted).");
311 STAM_REG(pVM, &pVM->em.s.StatHwAccEntry, STAMTYPE_PROFILE, "/PROF/EM/HwAccEnter", STAMUNIT_TICKS_PER_CALL, "Profiling Hardware Accelerated Mode entry overhead.");
312 STAM_REG(pVM, &pVM->em.s.StatHwAccExec, STAMTYPE_PROFILE, "/PROF/EM/HwAccExec", STAMUNIT_TICKS_PER_CALL, "Profiling Hardware Accelerated Mode execution.");
313 STAM_REG(pVM, &pVM->em.s.StatIOEmu, STAMTYPE_PROFILE, "/PROF/EM/Emulation/IO", STAMUNIT_TICKS_PER_CALL, "Profiling of emR3RawExecuteIOInstruction.");
314 STAM_REG(pVM, &pVM->em.s.StatPrivEmu, STAMTYPE_PROFILE, "/PROF/EM/Emulation/Priv", STAMUNIT_TICKS_PER_CALL, "Profiling of emR3RawPrivileged.");
315 STAM_REG(pVM, &pVM->em.s.StatMiscEmu, STAMTYPE_PROFILE, "/PROF/EM/Emulation/Misc", STAMUNIT_TICKS_PER_CALL, "Profiling of emR3RawExecuteInstruction.");
316 STAM_REG(pVM, &pVM->em.s.StatREMEmu, STAMTYPE_PROFILE, "/PROF/EM/REMEmuSingle", STAMUNIT_TICKS_PER_CALL, "Profiling single instruction REM execution.");
317 STAM_REG(pVM, &pVM->em.s.StatREMExec, STAMTYPE_PROFILE, "/PROF/EM/REMExec", STAMUNIT_TICKS_PER_CALL, "Profiling REM execution.");
318 STAM_REG(pVM, &pVM->em.s.StatREMSync, STAMTYPE_PROFILE, "/PROF/EM/REMSync", STAMUNIT_TICKS_PER_CALL, "Profiling REM context syncing.");
319 STAM_REG(pVM, &pVM->em.s.StatREMTotal, STAMTYPE_PROFILE, "/PROF/EM/REMTotal", STAMUNIT_TICKS_PER_CALL, "Profiling emR3RemExecute (excluding FFs).");
320 STAM_REG(pVM, &pVM->em.s.StatRAWEntry, STAMTYPE_PROFILE, "/PROF/EM/RAWEnter", STAMUNIT_TICKS_PER_CALL, "Profiling Raw Mode entry overhead.");
321 STAM_REG(pVM, &pVM->em.s.StatRAWExec, STAMTYPE_PROFILE, "/PROF/EM/RAWExec", STAMUNIT_TICKS_PER_CALL, "Profiling Raw Mode execution.");
322 STAM_REG(pVM, &pVM->em.s.StatRAWTail, STAMTYPE_PROFILE, "/PROF/EM/RAWTail", STAMUNIT_TICKS_PER_CALL, "Profiling Raw Mode tail overhead.");
323 STAM_REG(pVM, &pVM->em.s.StatRAWTotal, STAMTYPE_PROFILE, "/PROF/EM/RAWTotal", STAMUNIT_TICKS_PER_CALL, "Profiling emR3RawExecute (excluding FFs).");
324 STAM_REG(pVM, &pVM->em.s.StatTotal, STAMTYPE_PROFILE, "/PROF/EM/Total", STAMUNIT_TICKS_PER_CALL, "Profiling EMR3ExecuteVM.");
325
326
327 return VINF_SUCCESS;
328}
329
330
331
332/**
333 * Applies relocations to data and code managed by this
334 * component. This function will be called at init and
335 * whenever the VMM need to relocate it self inside the GC.
336 *
337 * @param pVM The VM.
338 */
339EMR3DECL(void) EMR3Relocate(PVM pVM)
340{
341 LogFlow(("EMR3Relocate\n"));
342 if (pVM->em.s.pStatsHC)
343 pVM->em.s.pStatsGC = MMHyperHC2GC(pVM, pVM->em.s.pStatsHC);
344}
345
346
347/**
348 * Reset notification.
349 *
350 * @param pVM
351 */
352EMR3DECL(void) EMR3Reset(PVM pVM)
353{
354 LogFlow(("EMR3Reset: \n"));
355 pVM->em.s.fForceRAW = false;
356}
357
358
359/**
360 * Terminates the EM.
361 *
362 * Termination means cleaning up and freeing all resources,
363 * the VM it self is at this point powered off or suspended.
364 *
365 * @returns VBox status code.
366 * @param pVM The VM to operate on.
367 */
368EMR3DECL(int) EMR3Term(PVM pVM)
369{
370 AssertMsg(pVM->em.s.offVM, ("bad init order!\n"));
371
372 return VINF_SUCCESS;
373}
374
375
376/**
377 * Execute state save operation.
378 *
379 * @returns VBox status code.
380 * @param pVM VM Handle.
381 * @param pSSM SSM operation handle.
382 */
383static DECLCALLBACK(int) emR3Save(PVM pVM, PSSMHANDLE pSSM)
384{
385 return SSMR3PutBool(pSSM, pVM->em.s.fForceRAW);
386}
387
388
389/**
390 * Execute state load operation.
391 *
392 * @returns VBox status code.
393 * @param pVM VM Handle.
394 * @param pSSM SSM operation handle.
395 * @param u32Version Data layout version.
396 */
397static DECLCALLBACK(int) emR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version)
398{
399 /*
400 * Validate version.
401 */
402 if (u32Version != EM_SAVED_STATE_VERSION)
403 {
404 Log(("emR3Load: Invalid version u32Version=%d (current %d)!\n", u32Version, EM_SAVED_STATE_VERSION));
405 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
406 }
407
408 /*
409 * Load the saved state.
410 */
411 int rc = SSMR3GetBool(pSSM, &pVM->em.s.fForceRAW);
412 if (VBOX_FAILURE(rc))
413 pVM->em.s.fForceRAW = false;
414
415 Assert(pVM->em.s.pCliStatTree == 0);
416 return rc;
417}
418
419
420/**
421 * Enables or disables a set of raw-mode execution modes.
422 *
423 * @returns VINF_SUCCESS on success.
424 * @returns VINF_RESCHEDULE if a rescheduling might be required.
425 * @returns VERR_INVALID_PARAMETER on an invalid enmMode value.
426 *
427 * @param pVM The VM to operate on.
428 * @param enmMode The execution mode change.
429 * @thread The emulation thread.
430 */
431EMR3DECL(int) EMR3RawSetMode(PVM pVM, EMRAWMODE enmMode)
432{
433 switch (enmMode)
434 {
435 case EMRAW_NONE:
436 pVM->fRawR3Enabled = false;
437 pVM->fRawR0Enabled = false;
438 break;
439 case EMRAW_RING3_ENABLE:
440 pVM->fRawR3Enabled = true;
441 break;
442 case EMRAW_RING3_DISABLE:
443 pVM->fRawR3Enabled = false;
444 break;
445 case EMRAW_RING0_ENABLE:
446 pVM->fRawR0Enabled = true;
447 break;
448 case EMRAW_RING0_DISABLE:
449 pVM->fRawR0Enabled = false;
450 break;
451 default:
452 AssertMsgFailed(("Invalid enmMode=%d\n", enmMode));
453 return VERR_INVALID_PARAMETER;
454 }
455 Log(("EMR3SetRawMode: fRawR3Enabled=%RTbool fRawR0Enabled=%RTbool pVM->fRawR3Enabled=%RTbool\n",
456 pVM->fRawR3Enabled, pVM->fRawR0Enabled, pVM->fRawR3Enabled));
457 return pVM->em.s.enmState == EMSTATE_RAW ? VINF_EM_RESCHEDULE : VINF_SUCCESS;
458}
459
460
461/**
462 * Raise a fatal error.
463 *
464 * Safely terminate the VM with full state report and stuff. This function
465 * will naturally never return.
466 *
467 * @param pVM VM handle.
468 * @param rc VBox status code.
469 */
470EMR3DECL(void) EMR3FatalError(PVM pVM, int rc)
471{
472 longjmp(pVM->em.s.u.FatalLongJump, rc);
473 AssertReleaseMsgFailed(("longjmp returned!\n"));
474}
475
476
477/**
478 * Gets the EM state name.
479 *
480 * @returns pointer to read only state name,
481 * @param enmState The state.
482 */
483EMR3DECL(const char *) EMR3GetStateName(EMSTATE enmState)
484{
485 switch (enmState)
486 {
487 case EMSTATE_RAW: return "EMSTATE_RAW";
488 case EMSTATE_HWACC: return "EMSTATE_HWACC";
489 case EMSTATE_REM: return "EMSTATE_REM";
490 case EMSTATE_HALTED: return "EMSTATE_HALTED";
491 case EMSTATE_SUSPENDED: return "EMSTATE_SUSPENDED";
492 case EMSTATE_TERMINATING: return "EMSTATE_TERMINATING";
493 case EMSTATE_DEBUG_GUEST_RAW: return "EMSTATE_DEBUG_GUEST_RAW";
494 case EMSTATE_DEBUG_GUEST_REM: return "EMSTATE_DEBUG_GUEST_REM";
495 case EMSTATE_DEBUG_HYPER: return "EMSTATE_DEBUG_HYPER";
496 case EMSTATE_GURU_MEDITATION: return "EMSTATE_GURU_MEDITATION";
497 default: return "Unknown!";
498 }
499}
500
501
502#ifdef VBOX_WITH_STATISTICS
503/**
504 * Just a braindead function to keep track of cli addresses.
505 * @param pVM VM handle.
506 * @param pInstrGC The EIP of the cli instruction.
507 */
508static void emR3RecordCli(PVM pVM, RTGCPTR pInstrGC)
509{
510 PCLISTAT pRec;
511
512 pRec = (PCLISTAT)RTAvlPVGet(&pVM->em.s.pCliStatTree, (AVLPVKEY)pInstrGC);
513 if (!pRec)
514 {
515 /* New cli instruction; insert into the tree. */
516 pRec = (PCLISTAT)MMR3HeapAllocZ(pVM, MM_TAG_EM, sizeof(*pRec));
517 Assert(pRec);
518 if (!pRec)
519 return;
520 pRec->Core.Key = (AVLPVKEY)pInstrGC;
521
522 char szCliStatName[32];
523 RTStrPrintf(szCliStatName, sizeof(szCliStatName), "/EM/Cli/0x%VGv", pInstrGC);
524 STAM_REG(pVM, &pRec->Counter, STAMTYPE_COUNTER, szCliStatName, STAMUNIT_OCCURENCES, "Number of times cli was executed.");
525
526 bool fRc = RTAvlPVInsert(&pVM->em.s.pCliStatTree, &pRec->Core);
527 Assert(fRc); NOREF(fRc);
528 }
529 STAM_COUNTER_INC(&pRec->Counter);
530 STAM_COUNTER_INC(&pVM->em.s.StatTotalClis);
531}
532#endif /* VBOX_WITH_STATISTICS */
533
534
535/**
536 * Debug loop.
537 *
538 * @returns VBox status code for EM.
539 * @param pVM VM handle.
540 * @param rc Current EM VBox status code..
541 */
542static int emR3Debug(PVM pVM, int rc)
543{
544 for (;;)
545 {
546 Log(("emR3Debug: rc=%Vrc\n", rc));
547 const int rcLast = rc;
548
549 /*
550 * Debug related RC.
551 */
552 switch (rc)
553 {
554 /*
555 * Single step an instruction.
556 */
557 case VINF_EM_DBG_STEP:
558 if ( pVM->em.s.enmState == EMSTATE_DEBUG_GUEST_RAW
559 || pVM->em.s.enmState == EMSTATE_DEBUG_HYPER
560 || pVM->em.s.fForceRAW /* paranoia */)
561 rc = emR3RawStep(pVM);
562 else
563 {
564 Assert(pVM->em.s.enmState == EMSTATE_DEBUG_GUEST_REM);
565 rc = emR3RemStep(pVM);
566 }
567 break;
568
569 /*
570 * Simple events: stepped, breakpoint, stop/assertion.
571 */
572 case VINF_EM_DBG_STEPPED:
573 rc = DBGFR3Event(pVM, DBGFEVENT_STEPPED);
574 break;
575
576 case VINF_EM_DBG_BREAKPOINT:
577 rc = DBGFR3EventBreakpoint(pVM, DBGFEVENT_BREAKPOINT);
578 break;
579
580 case VINF_EM_DBG_STOP:
581 rc = DBGFR3EventSrc(pVM, DBGFEVENT_DEV_STOP, NULL, 0, NULL, NULL);
582 break;
583
584 case VINF_EM_DBG_HYPER_STEPPED:
585 rc = DBGFR3Event(pVM, DBGFEVENT_STEPPED_HYPER);
586 break;
587
588 case VINF_EM_DBG_HYPER_BREAKPOINT:
589 rc = DBGFR3EventBreakpoint(pVM, DBGFEVENT_BREAKPOINT_HYPER);
590 break;
591
592 case VINF_EM_DBG_HYPER_ASSERTION:
593 RTPrintf("\nVINF_EM_DBG_HYPER_ASSERTION:\n%s%s\n", VMMR3GetGCAssertMsg1(pVM), VMMR3GetGCAssertMsg2(pVM));
594 rc = DBGFR3EventAssertion(pVM, DBGFEVENT_ASSERTION_HYPER, VMMR3GetGCAssertMsg1(pVM), VMMR3GetGCAssertMsg2(pVM));
595 break;
596
597 /*
598 * Guru meditation.
599 */
600 default: /** @todo don't use default for guru, but make special errors code! */
601 rc = DBGFR3Event(pVM, DBGFEVENT_FATAL_ERROR);
602 break;
603 }
604
605 /*
606 * Process the result.
607 */
608 do
609 {
610 switch (rc)
611 {
612 /*
613 * Continue the debugging loop.
614 */
615 case VINF_EM_DBG_STEP:
616 case VINF_EM_DBG_STOP:
617 case VINF_EM_DBG_STEPPED:
618 case VINF_EM_DBG_BREAKPOINT:
619 case VINF_EM_DBG_HYPER_STEPPED:
620 case VINF_EM_DBG_HYPER_BREAKPOINT:
621 case VINF_EM_DBG_HYPER_ASSERTION:
622 break;
623
624 /*
625 * Resuming execution (in some form) has to be done here if we got
626 * a hypervisor debug event.
627 */
628 case VINF_SUCCESS:
629 case VINF_EM_RESUME:
630 case VINF_EM_SUSPEND:
631 case VINF_EM_RESCHEDULE:
632 case VINF_EM_RESCHEDULE_RAW:
633 case VINF_EM_RESCHEDULE_REM:
634 case VINF_EM_HALT:
635 if (pVM->em.s.enmState == EMSTATE_DEBUG_HYPER)
636 {
637 rc = emR3RawResumeHyper(pVM);
638 if (rc != VINF_SUCCESS && VBOX_SUCCESS(rc))
639 continue;
640 }
641 if (rc == VINF_SUCCESS)
642 rc = VINF_EM_RESCHEDULE;
643 return rc;
644
645 /*
646 * The debugger isn't attached.
647 * We'll simply turn the thing off since that's the easiest thing to do.
648 */
649 case VERR_DBGF_NOT_ATTACHED:
650 switch (rcLast)
651 {
652 case VINF_EM_DBG_HYPER_ASSERTION:
653 case VINF_EM_DBG_HYPER_STEPPED:
654 case VINF_EM_DBG_HYPER_BREAKPOINT:
655 return rcLast;
656 }
657 return VINF_EM_OFF;
658
659 /*
660 * Status codes terminating the VM in one or another sense.
661 */
662 case VINF_EM_TERMINATE:
663 case VINF_EM_OFF:
664 case VINF_EM_RESET:
665 case VINF_EM_RAW_STALE_SELECTOR:
666 case VINF_EM_RAW_IRET_TRAP:
667 case VERR_TRPM_PANIC:
668 case VERR_TRPM_DONT_PANIC:
669 case VERR_INTERNAL_ERROR:
670 return rc;
671
672 /*
673 * The rest is unexpected, and will keep us here.
674 */
675 default:
676 AssertMsgFailed(("Unxpected rc %Vrc!\n", rc));
677 break;
678 }
679 } while (false);
680 } /* debug for ever */
681}
682
683
684/**
685 * Steps recompiled code.
686 *
687 * @returns VBox status code. The most important ones are: VINF_EM_STEP_EVENT,
688 * VINF_EM_RESCHEDULE, VINF_EM_SUSPEND, VINF_EM_RESET and VINF_EM_TERMINATE.
689 *
690 * @param pVM VM handle.
691 */
692static int emR3RemStep(PVM pVM)
693{
694 LogFlow(("emR3RemStep: cs:eip=%04x:%08x\n", CPUMGetGuestCS(pVM), CPUMGetGuestEIP(pVM)));
695
696 /*
697 * Switch to REM, step instruction, switch back.
698 */
699 int rc = REMR3State(pVM);
700 if (VBOX_SUCCESS(rc))
701 {
702 rc = REMR3Step(pVM);
703 REMR3StateBack(pVM);
704 }
705 LogFlow(("emR3RemStep: returns %Vrc cs:eip=%04x:%08x\n", rc, CPUMGetGuestCS(pVM), CPUMGetGuestEIP(pVM)));
706 return rc;
707}
708
709/**
710 * Executes recompiled code.
711 *
712 * This function contains the recompiler version of the inner
713 * execution loop (the outer loop being in EMR3ExecuteVM()).
714 *
715 * @returns VBox status code. The most important ones are: VINF_EM_RESCHEDULE,
716 * VINF_EM_SUSPEND, VINF_EM_RESET and VINF_EM_TERMINATE.
717 *
718 * @param pVM VM handle.
719 * @param pfFFDone Where to store an indicator telling wheter or not
720 * FFs were done before returning.
721 *
722 */
723static int emR3RemExecute(PVM pVM, bool *pfFFDone)
724{
725#ifdef LOG_ENABLED
726 PCPUMCTX pCtx = pVM->em.s.pCtx;
727 if (pCtx->eflags.Bits.u1VM)
728 Log(("EMV86: %04X:%08X IF=%d\n", pCtx->cs, pCtx->eip, pCtx->eflags.Bits.u1IF));
729 else if ((pCtx->ss & X86_SEL_RPL) == 0)
730 Log(("EMR0: %08X ESP=%08X IF=%d CPL=%d\n", pCtx->eip, pCtx->esp, pCtx->eflags.Bits.u1IF, (pCtx->ss & X86_SEL_RPL)));
731 else if ((pCtx->ss & X86_SEL_RPL) == 3)
732 Log(("EMR3: %08X ESP=%08X IF=%d\n", pCtx->eip, pCtx->esp, pCtx->eflags.Bits.u1IF));
733#endif
734 STAM_PROFILE_ADV_START(&pVM->em.s.StatREMTotal, a);
735
736#if defined(VBOX_STRICT) && defined(DEBUG_bird)
737 AssertMsg( VM_FF_ISPENDING(pVM, VM_FF_PGM_SYNC_CR3|VM_FF_PGM_SYNC_CR3_NON_GLOBAL)
738 || !MMHyperIsInsideArea(pVM, CPUMGetGuestEIP(pVM)), /** @todo #1419 - get flat address. */
739 ("cs:eip=%RX16:%RX32\n", CPUMGetGuestCS(pVM), CPUMGetGuestEIP(pVM)));
740#endif
741
742 /*
743 * Spin till we get a forced action which returns anything but VINF_SUCCESS
744 * or the REM suggests raw-mode execution.
745 */
746 *pfFFDone = false;
747 bool fInREMState = false;
748 int rc = VINF_SUCCESS;
749 for (;;)
750 {
751 /*
752 * Update REM state if not already in sync.
753 */
754 if (!fInREMState)
755 {
756 STAM_PROFILE_START(&pVM->em.s.StatREMSync, b);
757 rc = REMR3State(pVM);
758 STAM_PROFILE_STOP(&pVM->em.s.StatREMSync, b);
759 if (VBOX_FAILURE(rc))
760 break;
761 fInREMState = true;
762
763 /*
764 * We might have missed the raising of VMREQ, TIMER and some other
765 * imporant FFs while we were busy switching the state. So, check again.
766 */
767 if (VM_FF_ISPENDING(pVM, VM_FF_REQUEST | VM_FF_TIMER | VM_FF_PDM_QUEUES | VM_FF_DBGF | VM_FF_TERMINATE | VM_FF_RESET))
768 {
769 LogFlow(("emR3RemExecute: Skipping run, because FF is set. %#x\n", pVM->fForcedActions));
770 goto l_REMDoForcedActions;
771 }
772 }
773
774
775 /*
776 * Execute REM.
777 */
778 STAM_PROFILE_START(&pVM->em.s.StatREMExec, c);
779 rc = REMR3Run(pVM);
780 STAM_PROFILE_STOP(&pVM->em.s.StatREMExec, c);
781
782
783 /*
784 * Deal with high priority post execution FFs before doing anything else.
785 */
786 if (VM_FF_ISPENDING(pVM, VM_FF_HIGH_PRIORITY_POST_MASK))
787 rc = emR3HighPriorityPostForcedActions(pVM, rc);
788
789 /*
790 * Process the returned status code.
791 * (Try keep this short! Call functions!)
792 */
793 if (rc != VINF_SUCCESS)
794 {
795 if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
796 break;
797 if (rc != VINF_REM_INTERRUPED_FF)
798 {
799 /*
800 * Anything which is not known to us means an internal error
801 * and the termination of the VM!
802 */
803 AssertMsgFailed(("Unknown GC return code: %Vra\n", rc));
804 break;
805 }
806 }
807
808
809 /*
810 * Check and execute forced actions.
811 * Sync back the VM state before calling any of these.
812 */
813#ifdef VBOX_HIGH_RES_TIMERS_HACK
814 TMTimerPoll(pVM);
815#endif
816 if (VM_FF_ISPENDING(pVM, VM_FF_ALL_BUT_RAW_MASK & ~(VM_FF_CSAM_PENDING_ACTION | VM_FF_CSAM_SCAN_PAGE)))
817 {
818l_REMDoForcedActions:
819 if (fInREMState)
820 {
821 STAM_PROFILE_START(&pVM->em.s.StatREMSync, d);
822 REMR3StateBack(pVM);
823 STAM_PROFILE_STOP(&pVM->em.s.StatREMSync, d);
824 fInREMState = false;
825 }
826 STAM_PROFILE_ADV_SUSPEND(&pVM->em.s.StatREMTotal, a);
827 rc = emR3ForcedActions(pVM, rc);
828 STAM_PROFILE_ADV_RESUME(&pVM->em.s.StatREMTotal, a);
829 if ( rc != VINF_SUCCESS
830 && rc != VINF_EM_RESCHEDULE_REM)
831 {
832 *pfFFDone = true;
833 break;
834 }
835 }
836
837 } /* The Inner Loop, recompiled execution mode version. */
838
839
840 /*
841 * Returning. Sync back the VM state if required.
842 */
843 if (fInREMState)
844 {
845 STAM_PROFILE_START(&pVM->em.s.StatREMSync, e);
846 REMR3StateBack(pVM);
847 STAM_PROFILE_STOP(&pVM->em.s.StatREMSync, e);
848 }
849
850 STAM_PROFILE_ADV_STOP(&pVM->em.s.StatREMTotal, a);
851 return rc;
852}
853
854
855/**
856 * Resumes executing hypervisor after a debug event.
857 *
858 * This is kind of special since our current guest state is
859 * potentially out of sync.
860 *
861 * @returns VBox status code.
862 * @param pVM The VM handle.
863 */
864static int emR3RawResumeHyper(PVM pVM)
865{
866 int rc;
867 PCPUMCTX pCtx = pVM->em.s.pCtx;
868 Assert(pVM->em.s.enmState == EMSTATE_DEBUG_HYPER);
869 Log(("emR3RawResumeHyper: cs:eip=%RTsel:%RGr efl=%RGr\n", pCtx->cs, pCtx->eip, pCtx->eflags));
870
871 /*
872 * Resume execution.
873 */
874 CPUMRawEnter(pVM, NULL);
875 CPUMSetHyperEFlags(pVM, CPUMGetHyperEFlags(pVM) | X86_EFL_RF);
876 rc = VMMR3ResumeHyper(pVM);
877 Log(("emR3RawStep: cs:eip=%RTsel:%RGr efl=%RGr - returned from GC with rc=%Vrc\n", pCtx->cs, pCtx->eip, pCtx->eflags, rc));
878 rc = CPUMRawLeave(pVM, NULL, rc);
879 VM_FF_CLEAR(pVM, VM_FF_RESUME_GUEST_MASK);
880
881 /*
882 * Deal with the return code.
883 */
884 rc = emR3HighPriorityPostForcedActions(pVM, rc);
885 rc = emR3RawHandleRC(pVM, pCtx, rc);
886 rc = emR3RawUpdateForceFlag(pVM, pCtx, rc);
887 return rc;
888}
889
890
891/**
892 * Steps rawmode.
893 *
894 * @returns VBox status code.
895 * @param pVM The VM handle.
896 */
897static int emR3RawStep(PVM pVM)
898{
899 Assert( pVM->em.s.enmState == EMSTATE_DEBUG_HYPER
900 || pVM->em.s.enmState == EMSTATE_DEBUG_GUEST_RAW
901 || pVM->em.s.enmState == EMSTATE_DEBUG_GUEST_REM);
902 int rc;
903 PCPUMCTX pCtx = pVM->em.s.pCtx;
904 bool fGuest = pVM->em.s.enmState != EMSTATE_DEBUG_HYPER;
905#ifndef DEBUG_sandervl
906 Log(("emR3RawStep: cs:eip=%RTsel:%RGr efl=%RGr\n", fGuest ? CPUMGetGuestCS(pVM) : CPUMGetHyperCS(pVM),
907 fGuest ? CPUMGetGuestEIP(pVM) : CPUMGetHyperEIP(pVM), fGuest ? CPUMGetGuestEFlags(pVM) : CPUMGetHyperEFlags(pVM)));
908#endif
909 if (fGuest)
910 {
911 /*
912 * Check vital forced actions, but ignore pending interrupts and timers.
913 */
914 if (VM_FF_ISPENDING(pVM, VM_FF_HIGH_PRIORITY_PRE_RAW_MASK))
915 {
916 rc = emR3RawForcedActions(pVM, pCtx);
917 if (VBOX_FAILURE(rc))
918 return rc;
919 }
920
921 /*
922 * Set flags for single stepping.
923 */
924 CPUMSetGuestEFlags(pVM, CPUMGetGuestEFlags(pVM) | X86_EFL_TF | X86_EFL_RF);
925 }
926 else
927 CPUMSetHyperEFlags(pVM, CPUMGetHyperEFlags(pVM) | X86_EFL_TF | X86_EFL_RF);
928
929 /*
930 * Single step.
931 * We do not start time or anything, if anything we should just do a few nanoseconds.
932 */
933 CPUMRawEnter(pVM, NULL);
934 do
935 {
936 if (pVM->em.s.enmState == EMSTATE_DEBUG_HYPER)
937 rc = VMMR3ResumeHyper(pVM);
938 else
939 rc = VMMR3RawRunGC(pVM);
940#ifndef DEBUG_sandervl
941 Log(("emR3RawStep: cs:eip=%RTsel:%RGr efl=%RGr - GC rc %Vrc\n", fGuest ? CPUMGetGuestCS(pVM) : CPUMGetHyperCS(pVM),
942 fGuest ? CPUMGetGuestEIP(pVM) : CPUMGetHyperEIP(pVM), fGuest ? CPUMGetGuestEFlags(pVM) : CPUMGetHyperEFlags(pVM), rc));
943#endif
944 } while ( rc == VINF_SUCCESS
945 || rc == VINF_EM_RAW_INTERRUPT);
946 rc = CPUMRawLeave(pVM, NULL, rc);
947 VM_FF_CLEAR(pVM, VM_FF_RESUME_GUEST_MASK);
948
949 /*
950 * Make sure the trap flag is cleared.
951 * (Too bad if the guest is trying to single step too.)
952 */
953 if (fGuest)
954 CPUMSetGuestEFlags(pVM, CPUMGetGuestEFlags(pVM) & ~X86_EFL_TF);
955 else
956 CPUMSetHyperEFlags(pVM, CPUMGetHyperEFlags(pVM) & ~X86_EFL_TF);
957
958 /*
959 * Deal with the return codes.
960 */
961 rc = emR3HighPriorityPostForcedActions(pVM, rc);
962 rc = emR3RawHandleRC(pVM, pCtx, rc);
963 rc = emR3RawUpdateForceFlag(pVM, pCtx, rc);
964 return rc;
965}
966
967
968#ifdef DEBUG
969
970/**
971 * Steps hardware accelerated mode.
972 *
973 * @returns VBox status code.
974 * @param pVM The VM handle.
975 */
976static int emR3HwAccStep(PVM pVM)
977{
978 Assert(pVM->em.s.enmState == EMSTATE_DEBUG_GUEST_HWACC);
979
980 int rc;
981 PCPUMCTX pCtx = pVM->em.s.pCtx;
982 VM_FF_CLEAR(pVM, (VM_FF_SELM_SYNC_GDT | VM_FF_SELM_SYNC_LDT | VM_FF_TRPM_SYNC_IDT | VM_FF_SELM_SYNC_TSS));
983
984 /*
985 * Check vital forced actions, but ignore pending interrupts and timers.
986 */
987 if (VM_FF_ISPENDING(pVM, VM_FF_HIGH_PRIORITY_PRE_RAW_MASK))
988 {
989 rc = emR3RawForcedActions(pVM, pCtx);
990 if (VBOX_FAILURE(rc))
991 return rc;
992 }
993 /*
994 * Set flags for single stepping.
995 */
996 CPUMSetGuestEFlags(pVM, CPUMGetGuestEFlags(pVM) | X86_EFL_TF | X86_EFL_RF);
997
998 /*
999 * Single step.
1000 * We do not start time or anything, if anything we should just do a few nanoseconds.
1001 */
1002 do
1003 {
1004 rc = VMMR3HwAccRunGC(pVM);
1005 } while ( rc == VINF_SUCCESS
1006 || rc == VINF_EM_RAW_INTERRUPT);
1007 VM_FF_CLEAR(pVM, VM_FF_RESUME_GUEST_MASK);
1008
1009 /*
1010 * Make sure the trap flag is cleared.
1011 * (Too bad if the guest is trying to single step too.)
1012 */
1013 CPUMSetGuestEFlags(pVM, CPUMGetGuestEFlags(pVM) & ~X86_EFL_TF);
1014
1015 /*
1016 * Deal with the return codes.
1017 */
1018 rc = emR3HighPriorityPostForcedActions(pVM, rc);
1019 rc = emR3RawHandleRC(pVM, pCtx, rc);
1020 rc = emR3RawUpdateForceFlag(pVM, pCtx, rc);
1021 return rc;
1022}
1023
1024
1025void emR3SingleStepExecRaw(PVM pVM, uint32_t cIterations)
1026{
1027 EMSTATE enmOldState = pVM->em.s.enmState;
1028
1029 pVM->em.s.enmState = EMSTATE_DEBUG_GUEST_RAW;
1030
1031 Log(("Single step BEGIN:\n"));
1032 for(uint32_t i=0;i<cIterations;i++)
1033 {
1034 DBGFR3PrgStep(pVM);
1035 DBGFR3DisasInstrCurrentLog(pVM, "RSS: ");
1036 emR3RawStep(pVM);
1037 }
1038 Log(("Single step END:\n"));
1039 CPUMSetGuestEFlags(pVM, CPUMGetGuestEFlags(pVM) & ~X86_EFL_TF);
1040 pVM->em.s.enmState = enmOldState;
1041}
1042
1043
1044void emR3SingleStepExecHwAcc(PVM pVM, uint32_t cIterations)
1045{
1046 EMSTATE enmOldState = pVM->em.s.enmState;
1047
1048 pVM->em.s.enmState = EMSTATE_DEBUG_GUEST_HWACC;
1049
1050 Log(("Single step BEGIN:\n"));
1051 for(uint32_t i=0;i<cIterations;i++)
1052 {
1053 DBGFR3PrgStep(pVM);
1054 DBGFR3DisasInstrCurrentLog(pVM, "RSS: ");
1055 emR3HwAccStep(pVM);
1056 }
1057 Log(("Single step END:\n"));
1058 CPUMSetGuestEFlags(pVM, CPUMGetGuestEFlags(pVM) & ~X86_EFL_TF);
1059 pVM->em.s.enmState = enmOldState;
1060}
1061
1062
1063void emR3SingleStepExecRem(PVM pVM, uint32_t cIterations)
1064{
1065 EMSTATE enmOldState = pVM->em.s.enmState;
1066
1067 pVM->em.s.enmState = EMSTATE_DEBUG_GUEST_REM;
1068
1069 Log(("Single step BEGIN:\n"));
1070 for(uint32_t i=0;i<cIterations;i++)
1071 {
1072 DBGFR3PrgStep(pVM);
1073 DBGFR3DisasInstrCurrentLog(pVM, "RSS: ");
1074 emR3RemStep(pVM);
1075 }
1076 Log(("Single step END:\n"));
1077 CPUMSetGuestEFlags(pVM, CPUMGetGuestEFlags(pVM) & ~X86_EFL_TF);
1078 pVM->em.s.enmState = enmOldState;
1079}
1080
1081#endif /* DEBUG */
1082
1083
1084/**
1085 * Executes one (or perhaps a few more) instruction(s).
1086 *
1087 * @returns VBox status code suitable for EM.
1088 *
1089 * @param pVM VM handle.
1090 * @param rcGC GC return code
1091 * @param pszPrefix Disassembly prefix. If not NULL we'll disassemble the
1092 * instruction and prefix the log output with this text.
1093 */
1094#ifdef LOG_ENABLED
1095static int emR3RawExecuteInstructionWorker(PVM pVM, int rcGC, const char *pszPrefix)
1096#else
1097static int emR3RawExecuteInstructionWorker(PVM pVM, int rcGC)
1098#endif
1099{
1100 PCPUMCTX pCtx = pVM->em.s.pCtx;
1101 int rc;
1102
1103 /*
1104 *
1105 * The simple solution is to use the recompiler.
1106 * The better solution is to disassemble the current instruction and
1107 * try handle as many as possible without using REM.
1108 *
1109 */
1110
1111#ifdef LOG_ENABLED
1112 /*
1113 * Disassemble the instruction if requested.
1114 */
1115 if (pszPrefix)
1116 {
1117 DBGFR3InfoLog(pVM, "cpumguest", pszPrefix);
1118 DBGFR3DisasInstrCurrentLog(pVM, pszPrefix);
1119 }
1120#endif /* LOG_ENABLED */
1121
1122 /*
1123 * PATM is making life more interesting.
1124 * We cannot hand anything to REM which has an EIP inside patch code. So, we'll
1125 * tell PATM there is a trap in this code and have it take the appropriate actions
1126 * to allow us execute the code in REM.
1127 */
1128 if (PATMIsPatchGCAddr(pVM, pCtx->eip))
1129 {
1130 Log(("emR3RawExecuteInstruction: In patch block. eip=%VGv\n", pCtx->eip));
1131
1132 RTGCPTR pNewEip;
1133 rc = PATMR3HandleTrap(pVM, pCtx, pCtx->eip, &pNewEip);
1134 switch (rc)
1135 {
1136 /*
1137 * It's not very useful to emulate a single instruction and then go back to raw
1138 * mode; just execute the whole block until IF is set again.
1139 */
1140 case VINF_SUCCESS:
1141 Log(("emR3RawExecuteInstruction: Executing instruction starting at new address %VGv IF=%d VMIF=%x\n",
1142 pNewEip, pCtx->eflags.Bits.u1IF, pVM->em.s.pPatmGCState->uVMFlags));
1143 pCtx->eip = pNewEip;
1144 Assert(pCtx->eip);
1145
1146 if (pCtx->eflags.Bits.u1IF)
1147 {
1148 /*
1149 * The last instruction in the patch block needs to be executed!! (sti/sysexit for example)
1150 */
1151 Log(("PATCH: IF=1 -> emulate last instruction as it can't be interrupted!!\n"));
1152 return emR3RawExecuteInstruction(pVM, "PATCHIR");
1153 }
1154 else if (rcGC == VINF_PATM_PENDING_IRQ_AFTER_IRET)
1155 {
1156 /* special case: iret, that sets IF, detected a pending irq/event */
1157 return emR3RawExecuteInstruction(pVM, "PATCHIRET");
1158 }
1159 return VINF_EM_RESCHEDULE_REM;
1160
1161 /*
1162 * One instruction.
1163 */
1164 case VINF_PATCH_EMULATE_INSTR:
1165 Log(("emR3RawExecuteInstruction: Emulate patched instruction at %VGv IF=%d VMIF=%x\n",
1166 pNewEip, pCtx->eflags.Bits.u1IF, pVM->em.s.pPatmGCState->uVMFlags));
1167 pCtx->eip = pNewEip;
1168 return emR3RawExecuteInstruction(pVM, "PATCHIR");
1169
1170 /*
1171 * The patch was disabled, hand it to the REM.
1172 */
1173 case VERR_PATCH_DISABLED:
1174 Log(("emR3RawExecuteInstruction: Disabled patch -> new eip %VGv IF=%d VMIF=%x\n",
1175 pNewEip, pCtx->eflags.Bits.u1IF, pVM->em.s.pPatmGCState->uVMFlags));
1176 pCtx->eip = pNewEip;
1177 if (pCtx->eflags.Bits.u1IF)
1178 {
1179 /*
1180 * The last instruction in the patch block needs to be executed!! (sti/sysexit for example)
1181 */
1182 Log(("PATCH: IF=1 -> emulate last instruction as it can't be interrupted!!\n"));
1183 return emR3RawExecuteInstruction(pVM, "PATCHIR");
1184 }
1185 return VINF_EM_RESCHEDULE_REM;
1186
1187 /* Force continued patch exection; usually due to write monitored stack. */
1188 case VINF_PATCH_CONTINUE:
1189 return VINF_SUCCESS;
1190
1191 default:
1192 AssertReleaseMsgFailed(("Unknown return code %Vrc from PATMR3HandleTrap\n", rc));
1193 return VERR_INTERNAL_ERROR;
1194 }
1195 }
1196
1197#if 0 /// @todo Sander, this breaks the linux image (panics). So, I'm disabling it for now. (OP_MOV triggers it btw.)
1198 DISCPUSTATE Cpu;
1199 rc = CPUMR3DisasmInstrCPU(pVM, pCtx, pCtx->eip, &Cpu, "GEN EMU");
1200 if (VBOX_SUCCESS(rc))
1201 {
1202 uint32_t size;
1203
1204 switch (Cpu.pCurInstr->opcode)
1205 {
1206 case OP_MOV:
1207 case OP_AND:
1208 case OP_OR:
1209 case OP_XOR:
1210 case OP_POP:
1211 case OP_INC:
1212 case OP_DEC:
1213 case OP_XCHG:
1214 STAM_PROFILE_START(&pVM->em.s.StatMiscEmu, a);
1215 rc = EMInterpretInstructionCPU(pVM, &Cpu, CPUMCTX2CORE(pCtx), 0, &size);
1216 if (VBOX_SUCCESS(rc))
1217 {
1218 pCtx->eip += Cpu.opsize;
1219 STAM_PROFILE_STOP(&pVM->em.s.StatMiscEmu, a);
1220 return rc;
1221 }
1222 if (rc != VERR_EM_INTERPRETER)
1223 AssertMsgFailedReturn(("rc=%Vrc\n", rc), rc);
1224 STAM_PROFILE_STOP(&pVM->em.s.StatMiscEmu, a);
1225 break;
1226 }
1227 }
1228#endif
1229 STAM_PROFILE_START(&pVM->em.s.StatREMEmu, a);
1230 rc = REMR3EmulateInstruction(pVM);
1231 STAM_PROFILE_STOP(&pVM->em.s.StatREMEmu, a);
1232
1233 return rc;
1234}
1235
1236
1237/**
1238 * Executes one (or perhaps a few more) instruction(s).
1239 * This is just a wrapper for discarding pszPrefix in non-logging builds.
1240 *
1241 * @returns VBox status code suitable for EM.
1242 * @param pVM VM handle.
1243 * @param pszPrefix Disassembly prefix. If not NULL we'll disassemble the
1244 * instruction and prefix the log output with this text.
1245 * @param rcGC GC return code
1246 */
1247DECLINLINE(int) emR3RawExecuteInstruction(PVM pVM, const char *pszPrefix, int rcGC)
1248{
1249#ifdef LOG_ENABLED
1250 return emR3RawExecuteInstructionWorker(pVM, rcGC, pszPrefix);
1251#else
1252 return emR3RawExecuteInstructionWorker(pVM, rcGC);
1253#endif
1254}
1255
1256/**
1257 * Executes one (or perhaps a few more) IO instruction(s).
1258 *
1259 * @returns VBox status code suitable for EM.
1260 * @param pVM VM handle.
1261 */
1262int emR3RawExecuteIOInstruction(PVM pVM)
1263{
1264 int rc;
1265 PCPUMCTX pCtx = pVM->em.s.pCtx;
1266
1267 STAM_PROFILE_START(&pVM->em.s.StatIOEmu, a);
1268
1269 /** @todo probably we should fall back to the recompiler; otherwise we'll go back and forth between HC & GC
1270 * as io instructions tend to come in packages of more than one
1271 */
1272 DISCPUSTATE Cpu;
1273 rc = CPUMR3DisasmInstrCPU(pVM, pCtx, pCtx->eip, &Cpu, "IO EMU");
1274 if (VBOX_SUCCESS(rc))
1275 {
1276 rc = VINF_EM_RESCHEDULE_REM;
1277
1278 if (!(Cpu.prefix & (PREFIX_REP | PREFIX_REPNE)))
1279 {
1280 switch (Cpu.pCurInstr->opcode)
1281 {
1282 case OP_IN:
1283 {
1284 STAM_COUNTER_INC(&pVM->em.s.CTXSUFF(pStats)->StatIn);
1285 rc = IOMInterpretIN(pVM, CPUMCTX2CORE(pCtx), &Cpu);
1286 break;
1287 }
1288
1289 case OP_OUT:
1290 {
1291 STAM_COUNTER_INC(&pVM->em.s.CTXSUFF(pStats)->StatOut);
1292 rc = IOMInterpretOUT(pVM, CPUMCTX2CORE(pCtx), &Cpu);
1293 break;
1294 }
1295 }
1296 }
1297 else if (Cpu.prefix & PREFIX_REP)
1298 {
1299 switch (Cpu.pCurInstr->opcode)
1300 {
1301 case OP_INSB:
1302 case OP_INSWD:
1303 {
1304 STAM_COUNTER_INC(&pVM->em.s.CTXSUFF(pStats)->StatIn);
1305 rc = IOMInterpretINS(pVM, CPUMCTX2CORE(pCtx), &Cpu);
1306 break;
1307 }
1308
1309 case OP_OUTSB:
1310 case OP_OUTSWD:
1311 {
1312 STAM_COUNTER_INC(&pVM->em.s.CTXSUFF(pStats)->StatOut);
1313 rc = IOMInterpretOUTS(pVM, CPUMCTX2CORE(pCtx), &Cpu);
1314 break;
1315 }
1316 }
1317 }
1318
1319 /*
1320 * Handled the I/O return codes.
1321 * (The unhandled cases ends up with rc == VINF_EM_RESCHEDULE_REM.)
1322 */
1323 if ( rc == VINF_SUCCESS
1324 || (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST))
1325 {
1326 pCtx->eip += Cpu.opsize;
1327 STAM_PROFILE_STOP(&pVM->em.s.StatIOEmu, a);
1328 return rc;
1329 }
1330 if (rc == VINF_EM_RAW_GUEST_TRAP)
1331 {
1332 STAM_PROFILE_STOP(&pVM->em.s.StatIOEmu, a);
1333 rc = emR3RawGuestTrap(pVM);
1334 return rc;
1335 }
1336 AssertMsg(rc != VINF_TRPM_XCPT_DISPATCHED, ("Handle VINF_TRPM_XCPT_DISPATCHED\n"));
1337 if (VBOX_FAILURE(rc))
1338 {
1339 STAM_PROFILE_STOP(&pVM->em.s.StatIOEmu, a);
1340 return rc;
1341 }
1342 AssertMsg(rc == VINF_EM_RESCHEDULE_REM, ("rc=%Vrc\n", rc));
1343 }
1344
1345 STAM_PROFILE_STOP(&pVM->em.s.StatIOEmu, a);
1346 return emR3RawExecuteInstruction(pVM, "IO: ");
1347}
1348
1349
1350/**
1351 * Handle a guest context trap.
1352 *
1353 * @returns VBox status code suitable for EM.
1354 * @param pVM VM handle.
1355 */
1356static int emR3RawGuestTrap(PVM pVM)
1357{
1358 PCPUMCTX pCtx = pVM->em.s.pCtx;
1359
1360 /*
1361 * Get the trap info.
1362 */
1363 uint8_t u8TrapNo;
1364 TRPMEVENT enmType;;
1365 RTGCUINT uErrorCode;
1366 RTGCUINTPTR uCR2;
1367 int rc = TRPMQueryTrapAll(pVM, &u8TrapNo, &enmType, &uErrorCode, &uCR2);
1368 if (VBOX_FAILURE(rc))
1369 {
1370 AssertReleaseMsgFailed(("No trap! (rc=%Vrc)\n", rc));
1371 return rc;
1372 }
1373
1374 /* Traps can be directly forwarded in hardware accelerated mode. */
1375 if (HWACCMR3IsActive(pVM))
1376 {
1377#ifdef LOGGING_ENABLED
1378 DBGFR3InfoLog(pVM, "cpumguest", "Guest trap");
1379 DBGFR3DisasInstrCurrentLog(pVM, "Guest trap");
1380#endif
1381 return VINF_EM_RESCHEDULE_HWACC;
1382 }
1383
1384 /** Scan kernel code that traps; we might not get another chance. */
1385 if ( (pCtx->ss & X86_SEL_RPL) <= 1
1386 && !pCtx->eflags.Bits.u1VM)
1387 {
1388 Assert(!PATMIsPatchGCAddr(pVM, pCtx->eip));
1389 CSAMR3CheckCodeEx(pVM, pCtx->cs, &pCtx->csHid, pCtx->eip);
1390 }
1391
1392 if (u8TrapNo == 6) /* (#UD) Invalid opcode. */
1393 {
1394 DISCPUSTATE cpu;
1395
1396 /* If MONITOR & MWAIT are supported, then interpret them here. */
1397 rc = CPUMR3DisasmInstrCPU(pVM, pCtx, pCtx->eip, &cpu, "Guest Trap (#UD): ");
1398 if ( VBOX_SUCCESS(rc)
1399 && (cpu.pCurInstr->opcode == OP_MONITOR || cpu.pCurInstr->opcode == OP_MWAIT))
1400 {
1401 uint32_t u32Dummy, u32Features, u32ExtFeatures, size;
1402
1403 CPUMGetGuestCpuId(pVM, 1, &u32Dummy, &u32Dummy, &u32ExtFeatures, &u32Features);
1404
1405 if (u32ExtFeatures & X86_CPUID_FEATURE_ECX_MONITOR)
1406 {
1407 rc = TRPMResetTrap(pVM);
1408 AssertRC(rc);
1409
1410 rc = EMInterpretInstructionCPU(pVM, &cpu, CPUMCTX2CORE(pCtx), 0, &size);
1411 if (VBOX_SUCCESS(rc))
1412 {
1413 pCtx->eip += cpu.opsize;
1414 return rc;
1415 }
1416 return emR3RawExecuteInstruction(pVM, "Monitor: ");
1417 }
1418 }
1419 }
1420 else if (u8TrapNo == 13) /* (#GP) Privileged exception */
1421 {
1422 DISCPUSTATE cpu;
1423
1424 rc = CPUMR3DisasmInstrCPU(pVM, pCtx, pCtx->eip, &cpu, "Guest Trap: ");
1425 if (VBOX_SUCCESS(rc) && (cpu.pCurInstr->optype & OPTYPE_PORTIO))
1426 {
1427 /*
1428 * We should really check the TSS for the IO bitmap, but it's not like this
1429 * lazy approach really makes things worse.
1430 */
1431 rc = TRPMResetTrap(pVM);
1432 AssertRC(rc);
1433 return emR3RawExecuteInstruction(pVM, "IO Guest Trap: ");
1434 }
1435 }
1436
1437#ifdef LOG_ENABLED
1438 DBGFR3InfoLog(pVM, "cpumguest", "Guest trap");
1439 DBGFR3DisasInstrCurrentLog(pVM, "Guest trap");
1440
1441 /* Get guest page information. */
1442 uint64_t fFlags = 0;
1443 RTGCPHYS GCPhys = 0;
1444 int rc2 = PGMGstGetPage(pVM, uCR2, &fFlags, &GCPhys);
1445 Log(("emR3RawGuestTrap: cs:eip=%04x:%08x: trap=%02x err=%08x cr2=%08x cr0=%08x%s: Phys=%VGp fFlags=%08llx %s %s %s%s rc2=%d\n",
1446 pCtx->cs, pCtx->eip, u8TrapNo, uErrorCode, uCR2, pCtx->cr0, (enmType == TRPM_SOFTWARE_INT) ? " software" : "", GCPhys, fFlags,
1447 fFlags & X86_PTE_P ? "P " : "NP", fFlags & X86_PTE_US ? "U" : "S",
1448 fFlags & X86_PTE_RW ? "RW" : "R0", fFlags & X86_PTE_G ? " G" : "", rc2));
1449#endif
1450
1451 /*
1452 * #PG has CR2.
1453 * (Because of stuff like above we must set CR2 in a delayed fashion.)
1454 */
1455 if (u8TrapNo == 14 /* #PG */)
1456 pCtx->cr2 = uCR2;
1457
1458 return VINF_EM_RESCHEDULE_REM;
1459}
1460
1461
1462/**
1463 * Handle a ring switch trap.
1464 * Need to do statistics and to install patches. The result is going to REM.
1465 *
1466 * @returns VBox status code suitable for EM.
1467 * @param pVM VM handle.
1468 */
1469int emR3RawRingSwitch(PVM pVM)
1470{
1471 int rc;
1472 DISCPUSTATE Cpu;
1473 PCPUMCTX pCtx = pVM->em.s.pCtx;
1474
1475 /*
1476 * sysenter, syscall & callgate
1477 */
1478 rc = CPUMR3DisasmInstrCPU(pVM, pCtx, pCtx->eip, &Cpu, "RSWITCH: ");
1479 if (VBOX_SUCCESS(rc))
1480 {
1481 if (Cpu.pCurInstr->opcode == OP_SYSENTER)
1482 {
1483 if (pCtx->SysEnter.cs != 0)
1484 {
1485 rc = PATMR3InstallPatch(pVM, SELMToFlat(pVM, pCtx->eflags, pCtx->cs, &pCtx->csHid, pCtx->eip),
1486 SELMIsSelector32Bit(pVM, pCtx->eflags, pCtx->cs, &pCtx->csHid) ? PATMFL_CODE32 : 0);
1487 if (VBOX_SUCCESS(rc))
1488 {
1489 DBGFR3DisasInstrCurrentLog(pVM, "Patched sysenter instruction");
1490 return VINF_EM_RESCHEDULE_RAW;
1491 }
1492 }
1493 }
1494
1495#ifdef VBOX_WITH_STATISTICS
1496 switch (Cpu.pCurInstr->opcode)
1497 {
1498 case OP_SYSENTER:
1499 STAM_COUNTER_INC(&pVM->em.s.CTXSUFF(pStats)->StatSysEnter);
1500 break;
1501 case OP_SYSEXIT:
1502 STAM_COUNTER_INC(&pVM->em.s.CTXSUFF(pStats)->StatSysExit);
1503 break;
1504 case OP_SYSCALL:
1505 STAM_COUNTER_INC(&pVM->em.s.CTXSUFF(pStats)->StatSysCall);
1506 break;
1507 case OP_SYSRET:
1508 STAM_COUNTER_INC(&pVM->em.s.CTXSUFF(pStats)->StatSysRet);
1509 break;
1510 }
1511#endif
1512 }
1513 else
1514 AssertRC(rc);
1515
1516 /* go to the REM to emulate a single instruction */
1517 return emR3RawExecuteInstruction(pVM, "RSWITCH: ");
1518}
1519
1520/**
1521 * Handle a trap (#PF or #GP) in patch code
1522 *
1523 * @returns VBox status code suitable for EM.
1524 * @param pVM VM handle.
1525 * @param pCtx CPU context
1526 * @param gcret GC return code
1527 */
1528int emR3PatchTrap(PVM pVM, PCPUMCTX pCtx, int gcret)
1529{
1530 uint8_t u8TrapNo;
1531 int rc;
1532 TRPMEVENT enmType;
1533 RTGCUINT uErrorCode;
1534 RTGCUINTPTR uCR2;
1535
1536 Assert(PATMIsPatchGCAddr(pVM, pCtx->eip));
1537
1538 if (gcret == VINF_PATM_PATCH_INT3)
1539 {
1540 u8TrapNo = 3;
1541 uCR2 = 0;
1542 uErrorCode = 0;
1543 }
1544 else
1545 if (gcret == VINF_PATM_PATCH_TRAP_GP)
1546 {
1547 /* No active trap in this case. Kind of ugly. */
1548 u8TrapNo = X86_XCPT_GP;
1549 uCR2 = 0;
1550 uErrorCode = 0;
1551 }
1552 else
1553 {
1554 rc = TRPMQueryTrapAll(pVM, &u8TrapNo, &enmType, &uErrorCode, &uCR2);
1555 if (VBOX_FAILURE(rc))
1556 {
1557 AssertReleaseMsgFailed(("emR3PatchTrap: no trap! (rc=%Vrc) gcret=%Vrc\n", rc, gcret));
1558 return rc;
1559 }
1560 /* Reset the trap as we'll execute the original instruction again. */
1561 TRPMResetTrap(pVM);
1562 }
1563
1564 /*
1565 * Deal with traps inside patch code.
1566 * (This code won't run outside GC.)
1567 */
1568 if (u8TrapNo != 1)
1569 {
1570#ifdef LOG_ENABLED
1571 DBGFR3InfoLog(pVM, "cpumguest", "Trap in patch code");
1572 DBGFR3DisasInstrCurrentLog(pVM, "Patch code");
1573
1574 DISCPUSTATE Cpu;
1575 int rc;
1576
1577 rc = CPUMR3DisasmInstrCPU(pVM, pCtx, pCtx->eip, &Cpu, "Patch code: ");
1578 if ( VBOX_SUCCESS(rc)
1579 && Cpu.pCurInstr->opcode == OP_IRET)
1580 {
1581 uint32_t eip, selCS, uEFlags;
1582
1583 /* Iret crashes are bad as we have already changed the flags on the stack */
1584 rc = PGMPhysReadGCPtr(pVM, &eip, pCtx->esp, 4);
1585 rc |= PGMPhysReadGCPtr(pVM, &selCS, pCtx->esp+4, 4);
1586 rc |= PGMPhysReadGCPtr(pVM, &uEFlags, pCtx->esp+8, 4);
1587 if (rc == VINF_SUCCESS)
1588 {
1589 if ( (uEFlags & X86_EFL_VM)
1590 || (selCS & X86_SEL_RPL) == 3)
1591 {
1592 uint32_t selSS, esp;
1593
1594 rc |= PGMPhysReadGCPtr(pVM, &esp, pCtx->esp + 12, 4);
1595 rc |= PGMPhysReadGCPtr(pVM, &selSS, pCtx->esp + 16, 4);
1596
1597 if (uEFlags & X86_EFL_VM)
1598 {
1599 uint32_t selDS, selES, selFS, selGS;
1600 rc = PGMPhysReadGCPtr(pVM, &selES, pCtx->esp + 20, 4);
1601 rc |= PGMPhysReadGCPtr(pVM, &selDS, pCtx->esp + 24, 4);
1602 rc |= PGMPhysReadGCPtr(pVM, &selFS, pCtx->esp + 28, 4);
1603 rc |= PGMPhysReadGCPtr(pVM, &selGS, pCtx->esp + 32, 4);
1604 if (rc == VINF_SUCCESS)
1605 {
1606 Log(("Patch code: IRET->VM stack frame: return address %04X:%VGv eflags=%08x ss:esp=%04X:%VGv\n", selCS, eip, uEFlags, selSS, esp));
1607 Log(("Patch code: IRET->VM stack frame: DS=%04X ES=%04X FS=%04X GS=%04X\n", selDS, selES, selFS, selGS));
1608 }
1609 }
1610 else
1611 Log(("Patch code: IRET stack frame: return address %04X:%VGv eflags=%08x ss:esp=%04X:%VGv\n", selCS, eip, uEFlags, selSS, esp));
1612 }
1613 else
1614 Log(("Patch code: IRET stack frame: return address %04X:%VGv eflags=%08x\n", selCS, eip, uEFlags));
1615 }
1616 }
1617#endif
1618 Log(("emR3PatchTrap: in patch: eip=%08x: trap=%02x err=%08x cr2=%08x cr0=%08x\n",
1619 pCtx->eip, u8TrapNo, uErrorCode, uCR2, pCtx->cr0));
1620
1621 RTGCPTR pNewEip;
1622 rc = PATMR3HandleTrap(pVM, pCtx, pCtx->eip, &pNewEip);
1623 switch (rc)
1624 {
1625 /*
1626 * Execute the faulting instruction.
1627 */
1628 case VINF_SUCCESS:
1629 {
1630 /** @todo execute a whole block */
1631 Log(("emR3PatchTrap: Executing faulting instruction at new address %VGv\n", pNewEip));
1632 if (!(pVM->em.s.pPatmGCState->uVMFlags & X86_EFL_IF))
1633 Log(("emR3PatchTrap: Virtual IF flag disabled!!\n"));
1634
1635 pCtx->eip = pNewEip;
1636 AssertRelease(pCtx->eip);
1637
1638 if (pCtx->eflags.Bits.u1IF)
1639 {
1640 /* Windows XP lets irets fault intentionally and then takes action based on the opcode; an
1641 * int3 patch overwrites it and leads to blue screens. Remove the patch in this case.
1642 */
1643 if ( u8TrapNo == X86_XCPT_GP
1644 && PATMIsInt3Patch(pVM, pCtx->eip, NULL, NULL))
1645 {
1646 /** @todo move to PATMR3HandleTrap */
1647 Log(("Possible Windows XP iret fault at %VGv\n", pCtx->eip));
1648 PATMR3RemovePatch(pVM, pCtx->eip);
1649 }
1650
1651 /** @todo Knoppix 5 regression when returning VINF_SUCCESS here and going back to raw mode. */
1652 /** @note possibly because a reschedule is required (e.g. iret to V86 code) */
1653
1654 return emR3RawExecuteInstruction(pVM, "PATCHIR");
1655 /* Interrupts are enabled; just go back to the original instruction.
1656 return VINF_SUCCESS; */
1657 }
1658 return VINF_EM_RESCHEDULE_REM;
1659 }
1660
1661 /*
1662 * One instruction.
1663 */
1664 case VINF_PATCH_EMULATE_INSTR:
1665 Log(("emR3PatchTrap: Emulate patched instruction at %VGv IF=%d VMIF=%x\n",
1666 pNewEip, pCtx->eflags.Bits.u1IF, pVM->em.s.pPatmGCState->uVMFlags));
1667 pCtx->eip = pNewEip;
1668 AssertRelease(pCtx->eip);
1669 return emR3RawExecuteInstruction(pVM, "PATCHEMUL: ");
1670
1671 /*
1672 * The patch was disabled, hand it to the REM.
1673 */
1674 case VERR_PATCH_DISABLED:
1675 if (!(pVM->em.s.pPatmGCState->uVMFlags & X86_EFL_IF))
1676 Log(("emR3PatchTrap: Virtual IF flag disabled!!\n"));
1677 pCtx->eip = pNewEip;
1678 AssertRelease(pCtx->eip);
1679
1680 if (pCtx->eflags.Bits.u1IF)
1681 {
1682 /*
1683 * The last instruction in the patch block needs to be executed!! (sti/sysexit for example)
1684 */
1685 Log(("PATCH: IF=1 -> emulate last instruction as it can't be interrupted!!\n"));
1686 return emR3RawExecuteInstruction(pVM, "PATCHIR");
1687 }
1688 return VINF_EM_RESCHEDULE_REM;
1689
1690 /* Force continued patch exection; usually due to write monitored stack. */
1691 case VINF_PATCH_CONTINUE:
1692 return VINF_SUCCESS;
1693
1694 /*
1695 * Anything else is *fatal*.
1696 */
1697 default:
1698 AssertReleaseMsgFailed(("Unknown return code %Vrc from PATMR3HandleTrap!\n", rc));
1699 return VERR_INTERNAL_ERROR;
1700 }
1701 }
1702 return VINF_SUCCESS;
1703}
1704
1705
1706/**
1707 * Handle a privileged instruction.
1708 *
1709 * @returns VBox status code suitable for EM.
1710 * @param pVM VM handle.
1711 */
1712int emR3RawPrivileged(PVM pVM)
1713{
1714 STAM_PROFILE_START(&pVM->em.s.StatPrivEmu, a);
1715 PCPUMCTX pCtx = pVM->em.s.pCtx;
1716
1717 Assert(!pCtx->eflags.Bits.u1VM);
1718
1719 if (PATMIsEnabled(pVM))
1720 {
1721 /*
1722 * Check if in patch code.
1723 */
1724 if (PATMR3IsInsidePatchJump(pVM, pCtx->eip, NULL))
1725 {
1726#ifdef LOG_ENABLED
1727 DBGFR3InfoLog(pVM, "cpumguest", "PRIV");
1728#endif
1729 AssertMsgFailed(("FATAL ERROR: executing random instruction inside generated patch jump %08X\n", pCtx->eip));
1730 return VERR_EM_RAW_PATCH_CONFLICT;
1731 }
1732 if ( (pCtx->ss & X86_SEL_RPL) == 0
1733 && !pCtx->eflags.Bits.u1VM
1734 && !PATMIsPatchGCAddr(pVM, pCtx->eip))
1735 {
1736 int rc = PATMR3InstallPatch(pVM, SELMToFlat(pVM, pCtx->eflags, pCtx->cs, &pCtx->csHid, pCtx->eip),
1737 SELMIsSelector32Bit(pVM, pCtx->eflags, pCtx->cs, &pCtx->csHid) ? PATMFL_CODE32 : 0);
1738 if (VBOX_SUCCESS(rc))
1739 {
1740#ifdef LOG_ENABLED
1741 DBGFR3InfoLog(pVM, "cpumguest", "PRIV");
1742#endif
1743 DBGFR3DisasInstrCurrentLog(pVM, "Patched privileged instruction");
1744 return VINF_SUCCESS;
1745 }
1746 }
1747 }
1748
1749#ifdef LOG_ENABLED
1750 if (!PATMIsPatchGCAddr(pVM, pCtx->eip))
1751 {
1752 DBGFR3InfoLog(pVM, "cpumguest", "PRIV");
1753 DBGFR3DisasInstrCurrentLog(pVM, "Privileged instr: ");
1754 }
1755#endif
1756
1757 /*
1758 * Instruction statistics and logging.
1759 */
1760 DISCPUSTATE Cpu;
1761 int rc;
1762
1763 rc = CPUMR3DisasmInstrCPU(pVM, pCtx, pCtx->eip, &Cpu, "PRIV: ");
1764 if (VBOX_SUCCESS(rc))
1765 {
1766#ifdef VBOX_WITH_STATISTICS
1767 PEMSTATS pStats = pVM->em.s.CTXSUFF(pStats);
1768 switch (Cpu.pCurInstr->opcode)
1769 {
1770 case OP_INVLPG:
1771 STAM_COUNTER_INC(&pStats->StatInvlpg);
1772 break;
1773 case OP_IRET:
1774 STAM_COUNTER_INC(&pStats->StatIret);
1775 break;
1776 case OP_CLI:
1777 STAM_COUNTER_INC(&pStats->StatCli);
1778 emR3RecordCli(pVM, pCtx->eip);
1779 break;
1780 case OP_STI:
1781 STAM_COUNTER_INC(&pStats->StatSti);
1782 break;
1783 case OP_INSB:
1784 case OP_INSWD:
1785 case OP_IN:
1786 case OP_OUTSB:
1787 case OP_OUTSWD:
1788 case OP_OUT:
1789 AssertMsgFailed(("Unexpected privileged exception due to port IO\n"));
1790 break;
1791
1792 case OP_MOV_CR:
1793 if (Cpu.param1.flags & USE_REG_GEN32)
1794 {
1795 //read
1796 Assert(Cpu.param2.flags & USE_REG_CR);
1797 Assert(Cpu.param2.base.reg_ctrl <= USE_REG_CR4);
1798 STAM_COUNTER_INC(&pStats->StatMovReadCR[Cpu.param2.base.reg_ctrl]);
1799 }
1800 else
1801 {
1802 //write
1803 Assert(Cpu.param1.flags & USE_REG_CR);
1804 Assert(Cpu.param1.base.reg_ctrl <= USE_REG_CR4);
1805 STAM_COUNTER_INC(&pStats->StatMovWriteCR[Cpu.param1.base.reg_ctrl]);
1806 }
1807 break;
1808
1809 case OP_MOV_DR:
1810 STAM_COUNTER_INC(&pStats->StatMovDRx);
1811 break;
1812 case OP_LLDT:
1813 STAM_COUNTER_INC(&pStats->StatMovLldt);
1814 break;
1815 case OP_LIDT:
1816 STAM_COUNTER_INC(&pStats->StatMovLidt);
1817 break;
1818 case OP_LGDT:
1819 STAM_COUNTER_INC(&pStats->StatMovLgdt);
1820 break;
1821 case OP_SYSENTER:
1822 STAM_COUNTER_INC(&pStats->StatSysEnter);
1823 break;
1824 case OP_SYSEXIT:
1825 STAM_COUNTER_INC(&pStats->StatSysExit);
1826 break;
1827 case OP_SYSCALL:
1828 STAM_COUNTER_INC(&pStats->StatSysCall);
1829 break;
1830 case OP_SYSRET:
1831 STAM_COUNTER_INC(&pStats->StatSysRet);
1832 break;
1833 case OP_HLT:
1834 STAM_COUNTER_INC(&pStats->StatHlt);
1835 break;
1836 default:
1837 STAM_COUNTER_INC(&pStats->StatMisc);
1838 Log4(("emR3RawPrivileged: opcode=%d\n", Cpu.pCurInstr->opcode));
1839 break;
1840 }
1841#endif
1842 if ( (pCtx->ss & X86_SEL_RPL) == 0
1843 && !pCtx->eflags.Bits.u1VM
1844 && SELMIsSelector32Bit(pVM, pCtx->eflags, pCtx->cs, &pCtx->csHid))
1845 {
1846 uint32_t size;
1847
1848 STAM_PROFILE_START(&pVM->em.s.StatPrivEmu, a);
1849 switch (Cpu.pCurInstr->opcode)
1850 {
1851 case OP_CLI:
1852 pCtx->eflags.u32 &= ~X86_EFL_IF;
1853 Assert(Cpu.opsize == 1);
1854 pCtx->eip += Cpu.opsize;
1855 STAM_PROFILE_STOP(&pVM->em.s.StatPrivEmu, a);
1856 return VINF_EM_RESCHEDULE_REM; /* must go to the recompiler now! */
1857
1858 case OP_STI:
1859 pCtx->eflags.u32 |= X86_EFL_IF;
1860 EMSetInhibitInterruptsPC(pVM, pCtx->eip + Cpu.opsize);
1861 Assert(Cpu.opsize == 1);
1862 pCtx->eip += Cpu.opsize;
1863 STAM_PROFILE_STOP(&pVM->em.s.StatPrivEmu, a);
1864 return VINF_SUCCESS;
1865
1866 case OP_HLT:
1867 if (PATMIsPatchGCAddr(pVM, (RTGCPTR)pCtx->eip))
1868 {
1869 PATMTRANSSTATE enmState;
1870 RTGCPTR pOrgInstrGC = PATMR3PatchToGCPtr(pVM, pCtx->eip, &enmState);
1871
1872 if (enmState == PATMTRANS_OVERWRITTEN)
1873 {
1874 rc = PATMR3DetectConflict(pVM, pOrgInstrGC, pOrgInstrGC);
1875 Assert(rc == VERR_PATCH_DISABLED);
1876 /* Conflict detected, patch disabled */
1877 Log(("emR3RawPrivileged: detected conflict -> disabled patch at %VGv\n", pCtx->eip));
1878
1879 enmState = PATMTRANS_SAFE;
1880 }
1881
1882 /* The translation had better be successful. Otherwise we can't recover. */
1883 AssertReleaseMsg(pOrgInstrGC && enmState != PATMTRANS_OVERWRITTEN, ("Unable to translate instruction address at %VGv\n", pCtx->eip));
1884 if (enmState != PATMTRANS_OVERWRITTEN)
1885 pCtx->eip = pOrgInstrGC;
1886 }
1887 /* no break; we could just return VINF_EM_HALT here */
1888
1889 case OP_MOV_CR:
1890 case OP_MOV_DR:
1891#ifdef LOG_ENABLED
1892 if (PATMIsPatchGCAddr(pVM, pCtx->eip))
1893 {
1894 DBGFR3InfoLog(pVM, "cpumguest", "PRIV");
1895 DBGFR3DisasInstrCurrentLog(pVM, "Privileged instr: ");
1896 }
1897#endif
1898
1899 rc = EMInterpretInstructionCPU(pVM, &Cpu, CPUMCTX2CORE(pCtx), 0, &size);
1900 if (VBOX_SUCCESS(rc))
1901 {
1902 pCtx->eip += Cpu.opsize;
1903 STAM_PROFILE_STOP(&pVM->em.s.StatPrivEmu, a);
1904
1905 if ( Cpu.pCurInstr->opcode == OP_MOV_CR
1906 && Cpu.param1.flags == USE_REG_CR /* write */
1907 )
1908 {
1909 /* Reschedule is necessary as the execution/paging mode might have changed. */
1910 return VINF_EM_RESCHEDULE;
1911 }
1912 return rc; /* can return VINF_EM_HALT as well. */
1913 }
1914 AssertMsgReturn(rc == VERR_EM_INTERPRETER, ("%Vrc\n", rc), rc);
1915 break; /* fall back to the recompiler */
1916 }
1917 STAM_PROFILE_STOP(&pVM->em.s.StatPrivEmu, a);
1918 }
1919 }
1920
1921 if (PATMIsPatchGCAddr(pVM, pCtx->eip))
1922 return emR3PatchTrap(pVM, pCtx, VINF_PATM_PATCH_TRAP_GP);
1923
1924 return emR3RawExecuteInstruction(pVM, "PRIV");
1925}
1926
1927
1928/**
1929 * Update the forced rawmode execution modifier.
1930 *
1931 * This function is called when we're returning from the raw-mode loop(s). If we're
1932 * in patch code, it will set a flag forcing execution to be resumed in raw-mode,
1933 * if not in patch code, the flag will be cleared.
1934 *
1935 * We should never interrupt patch code while it's being executed. Cli patches can
1936 * contain big code blocks, but they are always executed with IF=0. Other patches
1937 * replace single instructions and should be atomic.
1938 *
1939 * @returns Updated rc.
1940 *
1941 * @param pVM The VM handle.
1942 * @param pCtx The guest CPU context.
1943 * @param rc The result code.
1944 */
1945DECLINLINE(int) emR3RawUpdateForceFlag(PVM pVM, PCPUMCTX pCtx, int rc)
1946{
1947 if (PATMIsPatchGCAddr(pVM, pCtx->eip)) /** @todo check cs selector base/type */
1948 {
1949 /* ignore reschedule attempts. */
1950 switch (rc)
1951 {
1952 case VINF_EM_RESCHEDULE:
1953 case VINF_EM_RESCHEDULE_REM:
1954 rc = VINF_SUCCESS;
1955 break;
1956 }
1957 pVM->em.s.fForceRAW = true;
1958 }
1959 else
1960 pVM->em.s.fForceRAW = false;
1961 return rc;
1962}
1963
1964
1965/**
1966 * Process a subset of the raw-mode return code.
1967 *
1968 * Since we have to share this with raw-mode single stepping, this inline
1969 * function has been created to avoid code duplication.
1970 *
1971 * @returns VINF_SUCCESS if it's ok to continue raw mode.
1972 * @returns VBox status code to return to the EM main loop.
1973 *
1974 * @param pVM The VM handle
1975 * @param rc The return code.
1976 * @param pCtx The guest cpu context.
1977 */
1978DECLINLINE(int) emR3RawHandleRC(PVM pVM, PCPUMCTX pCtx, int rc)
1979{
1980 switch (rc)
1981 {
1982 /*
1983 * Common & simple ones.
1984 */
1985 case VINF_SUCCESS:
1986 break;
1987 case VINF_EM_RESCHEDULE_RAW:
1988 case VINF_EM_RESCHEDULE_HWACC:
1989 case VINF_EM_RAW_INTERRUPT:
1990 case VINF_EM_RAW_TO_R3:
1991 case VINF_EM_RAW_TIMER_PENDING:
1992 case VINF_EM_PENDING_REQUEST:
1993 rc = VINF_SUCCESS;
1994 break;
1995
1996 /*
1997 * Privileged instruction.
1998 */
1999 case VINF_EM_RAW_EXCEPTION_PRIVILEGED:
2000 case VINF_PATM_PATCH_TRAP_GP:
2001 rc = emR3RawPrivileged(pVM);
2002 break;
2003
2004 /*
2005 * Got a trap which needs dispatching.
2006 */
2007 case VINF_EM_RAW_GUEST_TRAP:
2008 if (PATMR3IsInsidePatchJump(pVM, pCtx->eip, NULL))
2009 {
2010 AssertReleaseMsgFailed(("FATAL ERROR: executing random instruction inside generated patch jump %08X\n", CPUMGetGuestEIP(pVM)));
2011 rc = VERR_EM_RAW_PATCH_CONFLICT;
2012 break;
2013 }
2014
2015 Assert(TRPMHasTrap(pVM));
2016 Assert(!PATMIsPatchGCAddr(pVM, (RTGCPTR)pCtx->eip));
2017
2018 if (TRPMHasTrap(pVM))
2019 {
2020 uint8_t u8Interrupt;
2021 uint32_t uErrorCode;
2022 TRPMERRORCODE enmError = TRPM_TRAP_NO_ERRORCODE;
2023
2024 rc = TRPMQueryTrapAll(pVM, &u8Interrupt, NULL, &uErrorCode, NULL);
2025 AssertRC(rc);
2026
2027 if (uErrorCode != ~0U)
2028 enmError = TRPM_TRAP_HAS_ERRORCODE;
2029
2030 /* If the guest gate is marked unpatched, then we will check again if we can patch it. */
2031 if (TRPMR3GetGuestTrapHandler(pVM, u8Interrupt) == TRPM_INVALID_HANDLER)
2032 {
2033 CSAMR3CheckGates(pVM, u8Interrupt, 1);
2034 Log(("emR3RawHandleRC: recheck gate %x -> valid=%d\n", u8Interrupt, TRPMR3GetGuestTrapHandler(pVM, u8Interrupt) != TRPM_INVALID_HANDLER));
2035
2036 /** If it was successful, then we could go back to raw mode. */
2037 if (TRPMR3GetGuestTrapHandler(pVM, u8Interrupt) != TRPM_INVALID_HANDLER)
2038 {
2039 /* Must check pending forced actions as our IDT or GDT might be out of sync */
2040 EMR3CheckRawForcedActions(pVM);
2041
2042 rc = TRPMForwardTrap(pVM, CPUMCTX2CORE(pCtx), u8Interrupt, uErrorCode, enmError, TRPM_TRAP);
2043 if (rc == VINF_SUCCESS /* Don't use VBOX_SUCCESS */)
2044 {
2045 TRPMResetTrap(pVM);
2046 return VINF_EM_RESCHEDULE_RAW;
2047 }
2048 }
2049 }
2050 }
2051 rc = emR3RawGuestTrap(pVM);
2052 break;
2053
2054 /*
2055 * Trap in patch code.
2056 */
2057 case VINF_PATM_PATCH_TRAP_PF:
2058 case VINF_PATM_PATCH_INT3:
2059 rc = emR3PatchTrap(pVM, pCtx, rc);
2060 break;
2061
2062 case VINF_PATM_DUPLICATE_FUNCTION:
2063 Assert(PATMIsPatchGCAddr(pVM, (RTGCPTR)pCtx->eip));
2064 rc = PATMR3DuplicateFunctionRequest(pVM, pCtx);
2065 AssertRC(rc);
2066 rc = VINF_SUCCESS;
2067 break;
2068
2069 case VINF_PATM_CHECK_PATCH_PAGE:
2070 rc = PATMR3HandleMonitoredPage(pVM);
2071 AssertRC(rc);
2072 rc = VINF_SUCCESS;
2073 break;
2074
2075 /*
2076 * Patch manager.
2077 */
2078 case VERR_EM_RAW_PATCH_CONFLICT:
2079 AssertReleaseMsgFailed(("%Vrc handling is not yet implemented\n", rc));
2080 break;
2081
2082 /*
2083 * Memory mapped I/O access - attempt to patch the instruction
2084 */
2085 case VINF_PATM_HC_MMIO_PATCH_READ:
2086 rc = PATMR3InstallPatch(pVM, SELMToFlat(pVM, pCtx->eflags, pCtx->cs, &pCtx->csHid, pCtx->eip),
2087 PATMFL_MMIO_ACCESS | (SELMIsSelector32Bit(pVM, pCtx->eflags, pCtx->cs, &pCtx->csHid) ? PATMFL_CODE32 : 0));
2088 if (VBOX_FAILURE(rc))
2089 rc = emR3RawExecuteInstruction(pVM, "MMIO");
2090 break;
2091
2092 case VINF_PATM_HC_MMIO_PATCH_WRITE:
2093 AssertFailed(); /* not yet implemented. */
2094 rc = emR3RawExecuteInstruction(pVM, "MMIO");
2095 break;
2096
2097 /*
2098 * Conflict or out of page tables.
2099 *
2100 * VM_FF_PGM_SYNC_CR3 is set by the hypervisor and all we need to
2101 * do here is to execute the pending forced actions.
2102 */
2103 case VINF_PGM_SYNC_CR3:
2104 AssertMsg(VM_FF_ISPENDING(pVM, VM_FF_PGM_SYNC_CR3 | VM_FF_PGM_SYNC_CR3_NON_GLOBAL),
2105 ("VINF_PGM_SYNC_CR3 and no VM_FF_PGM_SYNC_CR3*!\n"));
2106 rc = VINF_SUCCESS;
2107 break;
2108
2109 /*
2110 * Paging mode change.
2111 */
2112 case VINF_PGM_CHANGE_MODE:
2113 rc = PGMChangeMode(pVM, pCtx->cr0, pCtx->cr4, 0);
2114 if (VBOX_SUCCESS(rc))
2115 rc = VINF_EM_RESCHEDULE;
2116 break;
2117
2118 /*
2119 * CSAM wants to perform a task in ring-3. It has set an FF action flag.
2120 */
2121 case VINF_CSAM_PENDING_ACTION:
2122 rc = VINF_SUCCESS;
2123 break;
2124
2125 /*
2126 * Invoked Interrupt gate - must directly (!) go to the recompiler.
2127 */
2128 case VINF_EM_RAW_INTERRUPT_PENDING:
2129 case VINF_EM_RAW_RING_SWITCH_INT:
2130 {
2131 uint8_t u8Interrupt;
2132
2133 Assert(TRPMHasTrap(pVM));
2134 Assert(!PATMIsPatchGCAddr(pVM, (RTGCPTR)pCtx->eip));
2135
2136 if (TRPMHasTrap(pVM))
2137 {
2138 u8Interrupt = TRPMGetTrapNo(pVM);
2139
2140 /* If the guest gate is marked unpatched, then we will check again if we can patch it. */
2141 if (TRPMR3GetGuestTrapHandler(pVM, u8Interrupt) == TRPM_INVALID_HANDLER)
2142 {
2143 CSAMR3CheckGates(pVM, u8Interrupt, 1);
2144 Log(("emR3RawHandleRC: recheck gate %x -> valid=%d\n", u8Interrupt, TRPMR3GetGuestTrapHandler(pVM, u8Interrupt) != TRPM_INVALID_HANDLER));
2145 /** @note If it was successful, then we could go back to raw mode, but let's keep things simple for now. */
2146 }
2147 }
2148 rc = VINF_EM_RESCHEDULE_REM;
2149 break;
2150 }
2151
2152 /*
2153 * Other ring switch types.
2154 */
2155 case VINF_EM_RAW_RING_SWITCH:
2156 rc = emR3RawRingSwitch(pVM);
2157 break;
2158
2159 /*
2160 * REMGCNotifyInvalidatePage() failed because of overflow.
2161 */
2162 case VERR_REM_FLUSHED_PAGES_OVERFLOW:
2163 Assert((pCtx->ss & X86_SEL_RPL) != 1);
2164 REMR3ReplayInvalidatedPages(pVM);
2165 break;
2166
2167 /*
2168 * I/O Port access - emulate the instruction.
2169 */
2170 case VINF_IOM_HC_IOPORT_READ:
2171 case VINF_IOM_HC_IOPORT_WRITE:
2172 rc = emR3RawExecuteIOInstruction(pVM);
2173 break;
2174
2175 /*
2176 * Memory mapped I/O access - emulate the instruction.
2177 */
2178 case VINF_IOM_HC_MMIO_READ:
2179 case VINF_IOM_HC_MMIO_WRITE:
2180 case VINF_IOM_HC_MMIO_READ_WRITE:
2181 rc = emR3RawExecuteInstruction(pVM, "MMIO");
2182 break;
2183
2184 /*
2185 * Execute instruction.
2186 */
2187 case VINF_EM_RAW_EMULATE_INSTR_LDT_FAULT:
2188 rc = emR3RawExecuteInstruction(pVM, "LDT FAULT: ");
2189 break;
2190 case VINF_EM_RAW_EMULATE_INSTR_GDT_FAULT:
2191 rc = emR3RawExecuteInstruction(pVM, "GDT FAULT: ");
2192 break;
2193 case VINF_EM_RAW_EMULATE_INSTR_IDT_FAULT:
2194 rc = emR3RawExecuteInstruction(pVM, "IDT FAULT: ");
2195 break;
2196 case VINF_EM_RAW_EMULATE_INSTR_TSS_FAULT:
2197 rc = emR3RawExecuteInstruction(pVM, "TSS FAULT: ");
2198 break;
2199 case VINF_EM_RAW_EMULATE_INSTR_PD_FAULT:
2200 rc = emR3RawExecuteInstruction(pVM, "PD FAULT: ");
2201 break;
2202
2203 case VINF_EM_RAW_EMULATE_INSTR_HLT:
2204 /** @todo skip instruction and go directly to the halt state. (see REM for implementation details) */
2205 rc = emR3RawPrivileged(pVM);
2206 break;
2207
2208 case VINF_PATM_PENDING_IRQ_AFTER_IRET:
2209 rc = emR3RawExecuteInstruction(pVM, "EMUL: ", VINF_PATM_PENDING_IRQ_AFTER_IRET);
2210 break;
2211
2212 case VINF_EM_RAW_EMULATE_INSTR:
2213 case VINF_PATCH_EMULATE_INSTR:
2214 rc = emR3RawExecuteInstruction(pVM, "EMUL: ");
2215 break;
2216
2217 /*
2218 * Stale selector and iret traps => REM.
2219 */
2220 case VINF_EM_RAW_STALE_SELECTOR:
2221 case VINF_EM_RAW_IRET_TRAP:
2222 /* We will not go to the recompiler if EIP points to patch code. */
2223 if (PATMIsPatchGCAddr(pVM, pCtx->eip))
2224 {
2225 pCtx->eip = PATMR3PatchToGCPtr(pVM, (RTGCPTR)pCtx->eip, 0);
2226 }
2227 LogFlow(("emR3RawHandleRC: %Vrc -> %Vrc\n", rc, VINF_EM_RESCHEDULE_REM));
2228 rc = VINF_EM_RESCHEDULE_REM;
2229 break;
2230
2231 /*
2232 * Up a level.
2233 */
2234 case VINF_EM_TERMINATE:
2235 case VINF_EM_OFF:
2236 case VINF_EM_RESET:
2237 case VINF_EM_SUSPEND:
2238 case VINF_EM_HALT:
2239 case VINF_EM_RESUME:
2240 case VINF_EM_RESCHEDULE:
2241 case VINF_EM_RESCHEDULE_REM:
2242 break;
2243
2244 /*
2245 * Up a level and invoke the debugger.
2246 */
2247 case VINF_EM_DBG_STEPPED:
2248 case VINF_EM_DBG_BREAKPOINT:
2249 case VINF_EM_DBG_STEP:
2250 case VINF_EM_DBG_HYPER_ASSERTION:
2251 case VINF_EM_DBG_HYPER_BREAKPOINT:
2252 case VINF_EM_DBG_HYPER_STEPPED:
2253 case VINF_EM_DBG_STOP:
2254 break;
2255
2256 /*
2257 * Up a level, dump and debug.
2258 */
2259 case VERR_TRPM_DONT_PANIC:
2260 case VERR_TRPM_PANIC:
2261 break;
2262
2263 /*
2264 * Anything which is not known to us means an internal error
2265 * and the termination of the VM!
2266 */
2267 default:
2268 AssertMsgFailed(("Unknown GC return code: %Vra\n", rc));
2269 break;
2270 }
2271 return rc;
2272}
2273
2274/**
2275 * Check for pending raw actions
2276 *
2277 * @returns VBox status code.
2278 * @param pVM The VM to operate on.
2279 */
2280EMR3DECL(int) EMR3CheckRawForcedActions(PVM pVM)
2281{
2282 return emR3RawForcedActions(pVM, pVM->em.s.pCtx);
2283}
2284
2285
2286/**
2287 * Process raw-mode specific forced actions.
2288 *
2289 * This function is called when any FFs in the VM_FF_HIGH_PRIORITY_PRE_RAW_MASK is pending.
2290 *
2291 * @returns VBox status code.
2292 * Only the normal success/failure stuff, no VINF_EM_*.
2293 * @param pVM The VM handle.
2294 * @param pCtx The guest CPUM register context.
2295 */
2296static int emR3RawForcedActions(PVM pVM, PCPUMCTX pCtx)
2297{
2298 /*
2299 * Note that the order is *vitally* important!
2300 * Also note that SELMR3UpdateFromCPUM may trigger VM_FF_SELM_SYNC_TSS.
2301 */
2302
2303
2304 /*
2305 * Sync selector tables.
2306 */
2307 if (VM_FF_ISPENDING(pVM, VM_FF_SELM_SYNC_GDT | VM_FF_SELM_SYNC_LDT))
2308 {
2309 int rc = SELMR3UpdateFromCPUM(pVM);
2310 if (VBOX_FAILURE(rc))
2311 return rc;
2312 }
2313
2314 /*
2315 * Sync IDT.
2316 */
2317 if (VM_FF_ISSET(pVM, VM_FF_TRPM_SYNC_IDT))
2318 {
2319 int rc = TRPMR3SyncIDT(pVM);
2320 if (VBOX_FAILURE(rc))
2321 return rc;
2322 }
2323
2324 /*
2325 * Sync TSS.
2326 */
2327 if (VM_FF_ISSET(pVM, VM_FF_SELM_SYNC_TSS))
2328 {
2329 int rc = SELMR3SyncTSS(pVM);
2330 if (VBOX_FAILURE(rc))
2331 return rc;
2332 }
2333
2334 /*
2335 * Sync page directory.
2336 */
2337 if (VM_FF_ISPENDING(pVM, VM_FF_PGM_SYNC_CR3 | VM_FF_PGM_SYNC_CR3_NON_GLOBAL))
2338 {
2339 int rc = PGMSyncCR3(pVM, pCtx->cr0, pCtx->cr3, pCtx->cr4, VM_FF_ISSET(pVM, VM_FF_PGM_SYNC_CR3));
2340 if (VBOX_FAILURE(rc))
2341 return rc;
2342
2343 Assert(!VM_FF_ISPENDING(pVM, VM_FF_SELM_SYNC_GDT | VM_FF_SELM_SYNC_LDT));
2344
2345 /* Prefetch pages for EIP and ESP */
2346 /** @todo This is rather expensive. Should investigate if it really helps at all. */
2347 rc = PGMPrefetchPage(pVM, SELMToFlat(pVM, pCtx->eflags, pCtx->cs, &pCtx->csHid, pCtx->eip));
2348 if (rc == VINF_SUCCESS)
2349 rc = PGMPrefetchPage(pVM, SELMToFlat(pVM, pCtx->eflags, pCtx->ss, &pCtx->ssHid, pCtx->esp));
2350 if (rc != VINF_SUCCESS)
2351 {
2352 if (rc != VINF_PGM_SYNC_CR3)
2353 return rc;
2354 rc = PGMSyncCR3(pVM, pCtx->cr0, pCtx->cr3, pCtx->cr4, VM_FF_ISSET(pVM, VM_FF_PGM_SYNC_CR3));
2355 if (VBOX_FAILURE(rc))
2356 return rc;
2357 }
2358 /** @todo maybe prefetch the supervisor stack page as well */
2359 }
2360
2361 return VINF_SUCCESS;
2362}
2363
2364
2365/**
2366 * Executes raw code.
2367 *
2368 * This function contains the raw-mode version of the inner
2369 * execution loop (the outer loop being in EMR3ExecuteVM()).
2370 *
2371 * @returns VBox status code. The most important ones are: VINF_EM_RESCHEDULE,
2372 * VINF_EM_RESCHEDULE_REM, VINF_EM_SUSPEND, VINF_EM_RESET and VINF_EM_TERMINATE.
2373 *
2374 * @param pVM VM handle.
2375 * @param pfFFDone Where to store an indicator telling whether or not
2376 * FFs were done before returning.
2377 */
2378static int emR3RawExecute(PVM pVM, bool *pfFFDone)
2379{
2380 STAM_PROFILE_ADV_START(&pVM->em.s.StatRAWTotal, a);
2381
2382 int rc = VERR_INTERNAL_ERROR;
2383 PCPUMCTX pCtx = pVM->em.s.pCtx;
2384 LogFlow(("emR3RawExecute: (cs:eip=%04x:%08x)\n", pCtx->cs, pCtx->eip));
2385 pVM->em.s.fForceRAW = false;
2386 *pfFFDone = false;
2387
2388
2389 /*
2390 *
2391 * Spin till we get a forced action or raw mode status code resulting in
2392 * in anything but VINF_SUCCESS or VINF_EM_RESCHEDULE_RAW.
2393 *
2394 */
2395 for (;;)
2396 {
2397 STAM_PROFILE_ADV_START(&pVM->em.s.StatRAWEntry, b);
2398
2399 /*
2400 * Check various preconditions.
2401 */
2402#ifdef VBOX_STRICT
2403 Assert(REMR3QueryPendingInterrupt(pVM) == REM_NO_PENDING_IRQ);
2404 Assert(!(pCtx->cr4 & X86_CR4_PAE));
2405 Assert(pCtx->eflags.Bits.u1VM || (pCtx->ss & X86_SEL_RPL) == 3 || (pCtx->ss & X86_SEL_RPL) == 0);
2406 AssertMsg( (pCtx->eflags.u32 & X86_EFL_IF)
2407 || PATMShouldUseRawMode(pVM, (RTGCPTR)pCtx->eip),
2408 ("Tried to execute code with IF at EIP=%08x!\n", pCtx->eip));
2409 if ( !VM_FF_ISPENDING(pVM, VM_FF_PGM_SYNC_CR3 | VM_FF_PGM_SYNC_CR3_NON_GLOBAL)
2410 && PGMR3MapHasConflicts(pVM, pCtx->cr3, pVM->fRawR0Enabled))
2411 {
2412 AssertMsgFailed(("We should not get conflicts any longer!!!\n"));
2413 return VERR_INTERNAL_ERROR;
2414 }
2415#endif /* VBOX_STRICT */
2416
2417 /*
2418 * Process high priority pre-execution raw-mode FFs.
2419 */
2420 if (VM_FF_ISPENDING(pVM, VM_FF_HIGH_PRIORITY_PRE_RAW_MASK))
2421 {
2422 rc = emR3RawForcedActions(pVM, pCtx);
2423 if (VBOX_FAILURE(rc))
2424 break;
2425 }
2426
2427 /*
2428 * If we're going to execute ring-0 code, the guest state needs to
2429 * be modified a bit and some of the state components (IF, SS/CS RPL,
2430 * and perhaps EIP) needs to be stored with PATM.
2431 */
2432 rc = CPUMRawEnter(pVM, NULL);
2433 if (rc != VINF_SUCCESS)
2434 {
2435 STAM_PROFILE_ADV_STOP(&pVM->em.s.StatRAWEntry, b);
2436 break;
2437 }
2438
2439 /*
2440 * Scan code before executing it. Don't bother with user mode or V86 code
2441 */
2442 if ( (pCtx->ss & X86_SEL_RPL) <= 1
2443 && !pCtx->eflags.Bits.u1VM
2444 && !PATMIsPatchGCAddr(pVM, pCtx->eip))
2445 {
2446 STAM_PROFILE_ADV_SUSPEND(&pVM->em.s.StatRAWEntry, b);
2447 CSAMR3CheckCodeEx(pVM, pCtx->cs, &pCtx->csHid, pCtx->eip);
2448 STAM_PROFILE_ADV_RESUME(&pVM->em.s.StatRAWEntry, b);
2449 }
2450
2451#ifdef LOG_ENABLED
2452 /*
2453 * Log important stuff before entering GC.
2454 */
2455 PPATMGCSTATE pGCState = PATMR3QueryGCStateHC(pVM);
2456 if (pCtx->eflags.Bits.u1VM)
2457 Log(("RV86: %04X:%08X IF=%d VMFlags=%x\n", pCtx->cs, pCtx->eip, pCtx->eflags.Bits.u1IF, pGCState->uVMFlags));
2458 else if ((pCtx->ss & X86_SEL_RPL) == 1)
2459 {
2460 bool fCSAMScanned = CSAMIsPageScanned(pVM, (RTGCPTR)pCtx->eip);
2461 Log(("RR0: %08X ESP=%08X IF=%d VMFlags=%x PIF=%d CPL=%d (Scanned=%d)\n", pCtx->eip, pCtx->esp, pCtx->eflags.Bits.u1IF, pGCState->uVMFlags, pGCState->fPIF, (pCtx->ss & X86_SEL_RPL), fCSAMScanned));
2462 }
2463 else if ((pCtx->ss & X86_SEL_RPL) == 3)
2464 Log(("RR3: %08X ESP=%08X IF=%d VMFlags=%x\n", pCtx->eip, pCtx->esp, pCtx->eflags.Bits.u1IF, pGCState->uVMFlags));
2465#endif /* LOG_ENABLED */
2466
2467
2468
2469 /*
2470 * Execute the code.
2471 */
2472 STAM_PROFILE_ADV_STOP(&pVM->em.s.StatRAWEntry, b);
2473 STAM_PROFILE_START(&pVM->em.s.StatRAWExec, c);
2474 VMMR3Unlock(pVM);
2475 rc = VMMR3RawRunGC(pVM);
2476 VMMR3Lock(pVM);
2477 STAM_PROFILE_STOP(&pVM->em.s.StatRAWExec, c);
2478 STAM_PROFILE_ADV_START(&pVM->em.s.StatRAWTail, d);
2479
2480 LogFlow(("RR0-E: %08X ESP=%08X IF=%d VMFlags=%x PIF=%d CPL=%d\n", pCtx->eip, pCtx->esp, pCtx->eflags.Bits.u1IF, pGCState->uVMFlags, pGCState->fPIF, (pCtx->ss & X86_SEL_RPL)));
2481 LogFlow(("VMMR3RawRunGC returned %Vrc\n", rc));
2482
2483 /*
2484 * Restore the real CPU state and deal with high priority post
2485 * execution FFs before doing anything else.
2486 */
2487 rc = CPUMRawLeave(pVM, NULL, rc);
2488 VM_FF_CLEAR(pVM, VM_FF_RESUME_GUEST_MASK);
2489 if (VM_FF_ISPENDING(pVM, VM_FF_HIGH_PRIORITY_POST_MASK))
2490 rc = emR3HighPriorityPostForcedActions(pVM, rc);
2491
2492#ifdef PGM_CACHE_VERY_STRICT
2493 /*
2494 * Page manager cache checks.
2495 */
2496 if ( rc == VINF_EM_RAW_INTERRUPT
2497 || rc == VINF_EM_RAW_GUEST_TRAP
2498 || rc == VINF_IOM_HC_IOPORT_READ
2499 || rc == VINF_IOM_HC_IOPORT_WRITE
2500 //|| rc == VINF_PATM_PATCH_INT3
2501 )
2502 pgmCacheCheckPD(pVM, pCtx->cr0, pCtx->cr3, pCtx->cr4);
2503#endif
2504
2505#ifdef VBOX_STRICT
2506 /*
2507 * Assert TSS consistency & rc vs patch code.
2508 */
2509 if ( !VM_FF_ISPENDING(pVM, VM_FF_SELM_SYNC_TSS | VM_FF_SELM_SYNC_GDT) /* GDT implies TSS at the moment. */
2510 && EMIsRawRing0Enabled(pVM))
2511 SELMR3CheckTSS(pVM);
2512 switch (rc)
2513 {
2514 case VINF_SUCCESS:
2515 case VINF_EM_RAW_INTERRUPT:
2516 case VINF_PATM_PATCH_TRAP_PF:
2517 case VINF_PATM_PATCH_TRAP_GP:
2518 case VINF_PATM_PATCH_INT3:
2519 case VINF_PATM_CHECK_PATCH_PAGE:
2520 case VINF_EM_RAW_EXCEPTION_PRIVILEGED:
2521 case VINF_EM_RAW_GUEST_TRAP:
2522 case VINF_EM_RESCHEDULE_RAW:
2523 break;
2524
2525 default:
2526 if (PATMIsPatchGCAddr(pVM, pCtx->eip) && !(pCtx->eflags.u32 & X86_EFL_TF))
2527 LogIt(NULL, 0, LOG_GROUP_PATM, ("Patch code interrupted at %VGv for reason %Vrc\n", CPUMGetGuestEIP(pVM), rc));
2528 break;
2529 }
2530 /*
2531 * Let's go paranoid!
2532 */
2533 if ( !VM_FF_ISPENDING(pVM, VM_FF_PGM_SYNC_CR3 | VM_FF_PGM_SYNC_CR3_NON_GLOBAL)
2534 && PGMR3MapHasConflicts(pVM, pCtx->cr3, pVM->fRawR0Enabled))
2535 {
2536 AssertMsgFailed(("We should not get conflicts any longer!!!\n"));
2537 return VERR_INTERNAL_ERROR;
2538 }
2539#endif /* VBOX_STRICT */
2540
2541 /*
2542 * Process the returned status code.
2543 */
2544 if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
2545 {
2546 STAM_PROFILE_ADV_STOP(&pVM->em.s.StatRAWTail, d);
2547 break;
2548 }
2549 rc = emR3RawHandleRC(pVM, pCtx, rc);
2550 if (rc != VINF_SUCCESS)
2551 {
2552 rc = emR3RawUpdateForceFlag(pVM, pCtx, rc);
2553 if (rc != VINF_SUCCESS)
2554 {
2555 STAM_PROFILE_ADV_STOP(&pVM->em.s.StatRAWTail, d);
2556 break;
2557 }
2558 }
2559
2560 /*
2561 * Check and execute forced actions.
2562 */
2563#ifdef VBOX_HIGH_RES_TIMERS_HACK
2564 TMTimerPoll(pVM);
2565#endif
2566 STAM_PROFILE_ADV_STOP(&pVM->em.s.StatRAWTail, d);
2567 if (VM_FF_ISPENDING(pVM, ~VM_FF_HIGH_PRIORITY_PRE_RAW_MASK))
2568 {
2569 Assert(pCtx->eflags.Bits.u1VM || (pCtx->ss & X86_SEL_RPL) != 1);
2570
2571 STAM_PROFILE_ADV_SUSPEND(&pVM->em.s.StatRAWTotal, a);
2572 rc = emR3ForcedActions(pVM, rc);
2573 STAM_PROFILE_ADV_RESUME(&pVM->em.s.StatRAWTotal, a);
2574 if ( rc != VINF_SUCCESS
2575 && rc != VINF_EM_RESCHEDULE_RAW)
2576 {
2577 rc = emR3RawUpdateForceFlag(pVM, pCtx, rc);
2578 if (rc != VINF_SUCCESS)
2579 {
2580 *pfFFDone = true;
2581 break;
2582 }
2583 }
2584 }
2585 }
2586
2587 /*
2588 * Return to outer loop.
2589 */
2590#if defined(LOG_ENABLED) && defined(DEBUG)
2591 RTLogFlush(NULL);
2592#endif
2593 STAM_PROFILE_ADV_STOP(&pVM->em.s.StatRAWTotal, a);
2594 return rc;
2595}
2596
2597
2598/**
2599 * Executes hardware accelerated raw code. (Intel VMX & AMD SVM)
2600 *
2601 * This function contains the raw-mode version of the inner
2602 * execution loop (the outer loop being in EMR3ExecuteVM()).
2603 *
2604 * @returns VBox status code. The most important ones are: VINF_EM_RESCHEDULE, VINF_EM_RESCHEDULE_RAW,
2605 * VINF_EM_RESCHEDULE_REM, VINF_EM_SUSPEND, VINF_EM_RESET and VINF_EM_TERMINATE.
2606 *
2607 * @param pVM VM handle.
2608 * @param pfFFDone Where to store an indicator telling whether or not
2609 * FFs were done before returning.
2610 */
2611static int emR3HwAccExecute(PVM pVM, bool *pfFFDone)
2612{
2613 int rc = VERR_INTERNAL_ERROR;
2614 PCPUMCTX pCtx = pVM->em.s.pCtx;
2615
2616 LogFlow(("emR3HwAccExecute: (cs:eip=%04x:%08x)\n", pCtx->cs, pCtx->eip));
2617 *pfFFDone = false;
2618
2619 STAM_COUNTER_INC(&pVM->em.s.StatHwAccExecuteEntry);
2620
2621 /*
2622 * Spin till we get a forced action which returns anything but VINF_SUCCESS.
2623 */
2624 for (;;)
2625 {
2626 STAM_PROFILE_ADV_START(&pVM->em.s.StatHwAccEntry, a);
2627
2628 /*
2629 * Check various preconditions.
2630 */
2631 VM_FF_CLEAR(pVM, (VM_FF_SELM_SYNC_GDT | VM_FF_SELM_SYNC_LDT | VM_FF_TRPM_SYNC_IDT | VM_FF_SELM_SYNC_TSS));
2632
2633 /*
2634 * Process high priority pre-execution raw-mode FFs.
2635 */
2636 if (VM_FF_ISPENDING(pVM, VM_FF_HIGH_PRIORITY_PRE_RAW_MASK))
2637 {
2638 rc = emR3RawForcedActions(pVM, pCtx);
2639 if (VBOX_FAILURE(rc))
2640 break;
2641 }
2642
2643#ifdef LOG_ENABLED
2644 uint8_t u8Vector;
2645
2646 rc = TRPMQueryTrapAll(pVM, &u8Vector, 0, 0, 0);
2647 if (rc == VINF_SUCCESS)
2648 {
2649 Log(("Pending hardware interrupt %d\n", u8Vector));
2650 }
2651 /*
2652 * Log important stuff before entering GC.
2653 */
2654 if (pCtx->eflags.Bits.u1VM)
2655 Log(("HWV86: %08X IF=%d\n", pCtx->eip, pCtx->eflags.Bits.u1IF));
2656 else if ((pCtx->ss & X86_SEL_RPL) == 0)
2657 Log(("HWR0: %08X ESP=%08X IF=%d CPL=%d\n", pCtx->eip, pCtx->esp, pCtx->eflags.Bits.u1IF, (pCtx->ss & X86_SEL_RPL)));
2658 else if ((pCtx->ss & X86_SEL_RPL) == 3)
2659 Log(("HWR3: %08X ESP=%08X IF=%d\n", pCtx->eip, pCtx->esp, pCtx->eflags.Bits.u1IF));
2660#endif
2661
2662 /*
2663 * Execute the code.
2664 */
2665 STAM_PROFILE_ADV_STOP(&pVM->em.s.StatHwAccEntry, a);
2666 STAM_PROFILE_START(&pVM->em.s.StatHwAccExec, x);
2667 VMMR3Unlock(pVM);
2668 rc = VMMR3HwAccRunGC(pVM);
2669 VMMR3Lock(pVM);
2670 STAM_PROFILE_STOP(&pVM->em.s.StatHwAccExec, x);
2671
2672 /*
2673 * Deal with high priority post execution FFs before doing anything else.
2674 */
2675 VM_FF_CLEAR(pVM, VM_FF_RESUME_GUEST_MASK);
2676 if (VM_FF_ISPENDING(pVM, VM_FF_HIGH_PRIORITY_POST_MASK))
2677 rc = emR3HighPriorityPostForcedActions(pVM, rc);
2678
2679 /*
2680 * Process the returned status code.
2681 */
2682 if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
2683 break;
2684
2685 rc = emR3RawHandleRC(pVM, pCtx, rc);
2686 if (rc != VINF_SUCCESS)
2687 break;
2688
2689 /*
2690 * Check and execute forced actions.
2691 */
2692#ifdef VBOX_HIGH_RES_TIMERS_HACK
2693 TMTimerPoll(pVM);
2694#endif
2695 if (VM_FF_ISPENDING(pVM, VM_FF_ALL_MASK))
2696 {
2697 rc = emR3ForcedActions(pVM, rc);
2698 if ( rc != VINF_SUCCESS
2699 && rc != VINF_EM_RESCHEDULE_HWACC)
2700 {
2701 *pfFFDone = true;
2702 break;
2703 }
2704 }
2705 }
2706 /*
2707 * Return to outer loop.
2708 */
2709#if defined(LOG_ENABLED) && defined(DEBUG)
2710 RTLogFlush(NULL);
2711#endif
2712 return rc;
2713}
2714
2715
2716/**
2717 * Decides whether to execute RAW, HWACC or REM.
2718 *
2719 * @returns new EM state
2720 * @param pVM The VM.
2721 * @param pCtx The CPU context.
2722 */
2723inline EMSTATE emR3Reschedule(PVM pVM, PCPUMCTX pCtx)
2724{
2725 /*
2726 * When forcing raw-mode execution, things are simple.
2727 */
2728 if (pVM->em.s.fForceRAW)
2729 return EMSTATE_RAW;
2730
2731 /* !!! THIS MUST BE IN SYNC WITH remR3CanExecuteRaw !!! */
2732 /* !!! THIS MUST BE IN SYNC WITH remR3CanExecuteRaw !!! */
2733 /* !!! THIS MUST BE IN SYNC WITH remR3CanExecuteRaw !!! */
2734
2735 X86EFLAGS EFlags = pCtx->eflags;
2736 if (HWACCMIsEnabled(pVM))
2737 {
2738 /* Hardware accelerated raw-mode:
2739 *
2740 * Typically only 32-bits protected mode, with paging enabled, code is allowed here.
2741 */
2742 if (HWACCMR3CanExecuteGuest(pVM, pCtx) == true)
2743 return EMSTATE_HWACC;
2744
2745 /** @note Raw mode and hw accelerated mode are incompatible. The latter turns off monitoring features essential for raw mode! */
2746 return EMSTATE_REM;
2747 }
2748
2749 /* Standard raw-mode:
2750 *
2751 * Here we only support 16 & 32 bits protected mode ring 3 code that has no IO privileges
2752 * or 32 bits protected mode ring 0 code
2753 *
2754 * The tests are ordered by the likelyhood of being true during normal execution.
2755 */
2756 if (EFlags.u32 & (X86_EFL_TF /* | HF_INHIBIT_IRQ_MASK*/))
2757 {
2758 Log2(("raw mode refused: EFlags=%#x\n", EFlags.u32));
2759 return EMSTATE_REM;
2760 }
2761
2762#ifndef VBOX_RAW_V86
2763 if (EFlags.u32 & X86_EFL_VM) {
2764 Log2(("raw mode refused: VM_MASK\n"));
2765 return EMSTATE_REM;
2766 }
2767#endif
2768
2769 /** @todo check up the X86_CR0_AM flag in respect to raw mode!!! We're probably not emulating it right! */
2770 uint32_t u32CR0 = pCtx->cr0;
2771 if ((u32CR0 & (X86_CR0_PG | X86_CR0_PE)) != (X86_CR0_PG | X86_CR0_PE))
2772 {
2773 //Log2(("raw mode refused: %s%s%s\n", (u32CR0 & X86_CR0_PG) ? "" : " !PG", (u32CR0 & X86_CR0_PE) ? "" : " !PE", (u32CR0 & X86_CR0_AM) ? "" : " !AM"));
2774 return EMSTATE_REM;
2775 }
2776
2777 if (pCtx->cr4 & X86_CR4_PAE)
2778 {
2779 //Log2(("raw mode refused: PAE\n"));
2780 return EMSTATE_REM;
2781 }
2782
2783 unsigned uSS = pCtx->ss;
2784 if ( pCtx->eflags.Bits.u1VM
2785 || (uSS & X86_SEL_RPL) == 3)
2786 {
2787 if (!EMIsRawRing3Enabled(pVM))
2788 return EMSTATE_REM;
2789
2790 if (!(EFlags.u32 & X86_EFL_IF))
2791 {
2792 Log2(("raw mode refused: IF (RawR3)\n"));
2793 return EMSTATE_REM;
2794 }
2795
2796 if (!(u32CR0 & X86_CR0_WP) && EMIsRawRing0Enabled(pVM))
2797 {
2798 Log2(("raw mode refused: CR0.WP + RawR0\n"));
2799 return EMSTATE_REM;
2800 }
2801 }
2802 else
2803 {
2804 if (!EMIsRawRing0Enabled(pVM))
2805 return EMSTATE_REM;
2806
2807 /* Only ring 0 supervisor code. */
2808 if ((uSS & X86_SEL_RPL) != 0)
2809 {
2810 Log2(("raw r0 mode refused: CPL %d\n", uSS & X86_SEL_RPL));
2811 return EMSTATE_REM;
2812 }
2813
2814 // Let's start with pure 32 bits ring 0 code first
2815 /** @todo What's pure 32-bit mode? flat? */
2816 if ( !(pCtx->ssHid.Attr.n.u1DefBig)
2817 || !(pCtx->csHid.Attr.n.u1DefBig))
2818 {
2819 Log2(("raw r0 mode refused: SS/CS not 32bit\n"));
2820 return EMSTATE_REM;
2821 }
2822
2823 /* Write protection muts be turned on, or else the guest can overwrite our hypervisor code and data. */
2824 if (!(u32CR0 & X86_CR0_WP))
2825 {
2826 Log2(("raw r0 mode refused: CR0.WP=0!\n"));
2827 return EMSTATE_REM;
2828 }
2829
2830 if (PATMShouldUseRawMode(pVM, (RTGCPTR)pCtx->eip))
2831 {
2832 Log2(("raw r0 mode forced: patch code\n"));
2833 return EMSTATE_RAW;
2834 }
2835
2836#if !defined(VBOX_ALLOW_IF0) && !defined(VBOX_RUN_INTERRUPT_GATE_HANDLERS)
2837 if (!(EFlags.u32 & X86_EFL_IF))
2838 {
2839 ////Log2(("R0: IF=0 VIF=%d %08X\n", eip, pVMeflags));
2840 //Log2(("RR0: Interrupts turned off; fall back to emulation\n"));
2841 return EMSTATE_REM;
2842 }
2843#endif
2844
2845 /** @todo still necessary??? */
2846 if (EFlags.Bits.u2IOPL != 0)
2847 {
2848 Log2(("raw r0 mode refused: IOPL %d\n", EFlags.Bits.u2IOPL));
2849 return EMSTATE_REM;
2850 }
2851 }
2852
2853 Assert(PGMPhysIsA20Enabled(pVM));
2854 return EMSTATE_RAW;
2855}
2856
2857
2858/**
2859 * Executes all high priority post execution force actions.
2860 *
2861 * @returns rc or a fatal status code.
2862 *
2863 * @param pVM VM handle.
2864 * @param rc The current rc.
2865 */
2866static int emR3HighPriorityPostForcedActions(PVM pVM, int rc)
2867{
2868 if (VM_FF_ISSET(pVM, VM_FF_PDM_CRITSECT))
2869 PDMR3CritSectFF(pVM);
2870
2871 if (VM_FF_ISSET(pVM, VM_FF_CSAM_PENDING_ACTION))
2872 CSAMR3DoPendingAction(pVM);
2873
2874 return rc;
2875}
2876
2877
2878/**
2879 * Executes all pending forced actions.
2880 *
2881 * Forced actions can cause execution delays and execution
2882 * rescheduling. The first we deal with using action priority, so
2883 * that for instance pending timers aren't scheduled and ran until
2884 * right before execution. The rescheduling we deal with using
2885 * return codes. The same goes for VM termination, only in that case
2886 * we exit everything.
2887 *
2888 * @returns VBox status code of equal or greater importance/severity than rc.
2889 * The most important ones are: VINF_EM_RESCHEDULE,
2890 * VINF_EM_SUSPEND, VINF_EM_RESET and VINF_EM_TERMINATE.
2891 *
2892 * @param pVM VM handle.
2893 * @param rc The current rc.
2894 *
2895 */
2896static int emR3ForcedActions(PVM pVM, int rc)
2897{
2898#ifdef VBOX_STRICT
2899 int rcIrq = VINF_SUCCESS;
2900#endif
2901 STAM_PROFILE_START(&pVM->em.s.StatForcedActions, a);
2902
2903#define UPDATE_RC() \
2904 do { \
2905 AssertMsg(rc2 <= 0 || (rc2 >= VINF_EM_FIRST && rc2 <= VINF_EM_LAST), ("Invalid FF return code: %Vra\n", rc2)); \
2906 if (rc2 == VINF_SUCCESS || rc < VINF_SUCCESS) \
2907 break; \
2908 if (!rc || rc2 < rc) \
2909 rc = rc2; \
2910 } while (0)
2911
2912 int rc2;
2913
2914 /*
2915 * Post execution chunk first.
2916 */
2917 if (VM_FF_ISPENDING(pVM, VM_FF_NORMAL_PRIORITY_POST_MASK))
2918 {
2919 /*
2920 * Termination request.
2921 */
2922 if (VM_FF_ISSET(pVM, VM_FF_TERMINATE))
2923 {
2924 Log2(("emR3ForcedActions: returns VINF_EM_TERMINATE\n"));
2925 STAM_PROFILE_STOP(&pVM->em.s.StatForcedActions, a);
2926 return VINF_EM_TERMINATE;
2927 }
2928
2929 /*
2930 * Debugger Facility polling.
2931 */
2932 if (VM_FF_ISSET(pVM, VM_FF_DBGF))
2933 {
2934 rc2 = DBGFR3VMMForcedAction(pVM);
2935 UPDATE_RC();
2936 }
2937
2938 /*
2939 * Postponed reset request.
2940 */
2941 if (VM_FF_ISSET(pVM, VM_FF_RESET))
2942 {
2943 rc2 = VMR3Reset(pVM);
2944 UPDATE_RC();
2945 VM_FF_CLEAR(pVM, VM_FF_RESET);
2946 }
2947
2948 /*
2949 * CSAM page scanning.
2950 */
2951 if (VM_FF_ISSET(pVM, VM_FF_CSAM_SCAN_PAGE))
2952 {
2953 PCPUMCTX pCtx = pVM->em.s.pCtx;
2954
2955 /** @todo: check for 16 or 32 bits code! (D bit in the code selector) */
2956 Log(("Forced action VM_FF_CSAM_SCAN_PAGE\n"));
2957
2958 CSAMR3CheckCodeEx(pVM, pCtx->cs, &pCtx->csHid, pCtx->eip);
2959 VM_FF_CLEAR(pVM, VM_FF_CSAM_SCAN_PAGE);
2960 }
2961
2962 /* check that we got them all */
2963 Assert(!(VM_FF_NORMAL_PRIORITY_POST_MASK & ~(VM_FF_TERMINATE | VM_FF_DBGF | VM_FF_RESET | VM_FF_CSAM_SCAN_PAGE)));
2964 }
2965
2966 /*
2967 * Normal priority then.
2968 * (Executed in no particular order.)
2969 */
2970 if (VM_FF_ISPENDING(pVM, VM_FF_NORMAL_PRIORITY_MASK))
2971 {
2972 /*
2973 * PDM Queues are pending.
2974 */
2975 if (VM_FF_ISSET(pVM, VM_FF_PDM_QUEUES))
2976 PDMR3QueueFlushAll(pVM);
2977
2978 /*
2979 * PDM DMA transfers are pending.
2980 */
2981 if (VM_FF_ISSET(pVM, VM_FF_PDM_DMA))
2982 PDMR3DmaRun(pVM);
2983
2984 /*
2985 * Requests from other threads.
2986 */
2987 if (VM_FF_ISSET(pVM, VM_FF_REQUEST))
2988 {
2989 rc2 = VMR3ReqProcess(pVM);
2990 if (rc2 == VINF_EM_OFF || rc2 == VINF_EM_TERMINATE)
2991 {
2992 Log2(("emR3ForcedActions: returns %Vrc\n", rc2));
2993 STAM_PROFILE_STOP(&pVM->em.s.StatForcedActions, a);
2994 return rc2;
2995 }
2996 UPDATE_RC();
2997 }
2998
2999 /* check that we got them all */
3000 Assert(!(VM_FF_NORMAL_PRIORITY_MASK & ~(VM_FF_REQUEST | VM_FF_PDM_QUEUES | VM_FF_PDM_DMA)));
3001 }
3002
3003 /*
3004 * Execute polling function ever so often.
3005 * THIS IS A HACK, IT WILL BE *REPLACED* BY PROPER ASYNC NETWORKING SOON!
3006 */
3007 static unsigned cLast = 0;
3008 if (!((++cLast) % 4))
3009 PDMR3Poll(pVM);
3010
3011 /*
3012 * High priority pre execution chunk last.
3013 * (Executed in ascending priority order.)
3014 */
3015 if (VM_FF_ISPENDING(pVM, VM_FF_HIGH_PRIORITY_PRE_MASK))
3016 {
3017 /*
3018 * Timers before interrupts.
3019 */
3020 if (VM_FF_ISSET(pVM, VM_FF_TIMER))
3021 TMR3TimerQueuesDo(pVM);
3022
3023 /*
3024 * The instruction following an emulated STI should *always* be executed!
3025 */
3026 if (VM_FF_ISSET(pVM, VM_FF_INHIBIT_INTERRUPTS))
3027 {
3028 Log(("VM_FF_EMULATED_STI at %VGv successor %VGv\n", CPUMGetGuestEIP(pVM), EMGetInhibitInterruptsPC(pVM)));
3029 if (CPUMGetGuestEIP(pVM) != EMGetInhibitInterruptsPC(pVM))
3030 {
3031 /** @note we intentionally don't clear VM_FF_INHIBIT_INTERRUPTS here if the eip is the same as the inhibited instr address.
3032 * Before we are able to execute this instruction in raw mode (iret to guest code) an external interrupt might
3033 * force a world switch again. Possibly allowing a guest interrupt to be dispatched in the process. This could
3034 * break the guest. Sounds very unlikely, but such timing sensitive problem are not as rare as you might think.
3035 */
3036 VM_FF_CLEAR(pVM, VM_FF_INHIBIT_INTERRUPTS);
3037 }
3038 if (HWACCMR3IsActive(pVM))
3039 rc2 = VINF_EM_RESCHEDULE_HWACC;
3040 else
3041 rc2 = PATMAreInterruptsEnabled(pVM) ? VINF_EM_RESCHEDULE_RAW : VINF_EM_RESCHEDULE_REM;
3042
3043 UPDATE_RC();
3044 }
3045
3046 /*
3047 * Interrupts.
3048 */
3049 if ( !VM_FF_ISSET(pVM, VM_FF_INHIBIT_INTERRUPTS)
3050 && (!rc || rc >= VINF_EM_RESCHEDULE_RAW)
3051 && !TRPMHasTrap(pVM) /* an interrupt could already be scheduled for dispatching in the recompiler. */
3052 && PATMAreInterruptsEnabled(pVM)
3053 && !HWACCMR3IsEventPending(pVM))
3054 {
3055 if (VM_FF_ISPENDING(pVM, VM_FF_INTERRUPT_APIC | VM_FF_INTERRUPT_PIC))
3056 {
3057 /** @note it's important to make sure the return code from TRPMR3InjectEvent isn't ignored! */
3058 /** @todo this really isn't nice, should properly handle this */
3059 rc2 = TRPMR3InjectEvent(pVM, TRPM_HARDWARE_INT);
3060#ifdef VBOX_STRICT
3061 rcIrq = rc2;
3062#endif
3063 UPDATE_RC();
3064 }
3065 /** @todo really ugly; if we entered the hlt state when exiting the recompiler and an interrupt was pending, we previously got stuck in the halted state. */
3066 else if (REMR3QueryPendingInterrupt(pVM) != REM_NO_PENDING_IRQ)
3067 {
3068 rc2 = VINF_EM_RESCHEDULE_REM;
3069 UPDATE_RC();
3070 }
3071 }
3072
3073 /*
3074 * Debugger Facility request.
3075 */
3076 if (VM_FF_ISSET(pVM, VM_FF_DBGF))
3077 {
3078 rc2 = DBGFR3VMMForcedAction(pVM);
3079 UPDATE_RC();
3080 }
3081
3082 /*
3083 * Termination request.
3084 */
3085 if (VM_FF_ISSET(pVM, VM_FF_TERMINATE))
3086 {
3087 Log2(("emR3ForcedActions: returns VINF_EM_TERMINATE\n"));
3088 STAM_PROFILE_STOP(&pVM->em.s.StatForcedActions, a);
3089 return VINF_EM_TERMINATE;
3090 }
3091
3092#ifdef DEBUG
3093 /*
3094 * Debug, pause the VM.
3095 */
3096 if (VM_FF_ISSET(pVM, VM_FF_DEBUG_SUSPEND))
3097 {
3098 VM_FF_CLEAR(pVM, VM_FF_DEBUG_SUSPEND);
3099 Log(("emR3ForcedActions: returns VINF_EM_SUSPEND\n"));
3100 return VINF_EM_SUSPEND;
3101 }
3102
3103#endif
3104 /* check that we got them all */
3105 Assert(!(VM_FF_HIGH_PRIORITY_PRE_MASK & ~(VM_FF_TIMER | VM_FF_INTERRUPT_APIC | VM_FF_INTERRUPT_PIC | VM_FF_DBGF | VM_FF_PGM_SYNC_CR3 | VM_FF_PGM_SYNC_CR3_NON_GLOBAL | VM_FF_SELM_SYNC_TSS | VM_FF_TRPM_SYNC_IDT | VM_FF_SELM_SYNC_GDT | VM_FF_SELM_SYNC_LDT | VM_FF_TERMINATE | VM_FF_DEBUG_SUSPEND | VM_FF_INHIBIT_INTERRUPTS)));
3106 }
3107
3108#undef UPDATE_RC
3109 Log2(("emR3ForcedActions: returns %Vrc\n", rc));
3110 STAM_PROFILE_STOP(&pVM->em.s.StatForcedActions, a);
3111 Assert(rcIrq == VINF_SUCCESS || rcIrq == rc);
3112 return rc;
3113}
3114
3115
3116/**
3117 * Execute VM.
3118 *
3119 * This function is the main loop of the VM. The emulation thread
3120 * calls this function when the VM has been successfully constructed
3121 * and we're ready for executing the VM.
3122 *
3123 * Returning from this function means that the VM is turned off or
3124 * suspended (state already saved) and deconstruction in next in line.
3125 *
3126 * All interaction from other thread are done using forced actions
3127 * and signaling of the wait object.
3128 *
3129 * @returns VBox status code.
3130 * @param pVM The VM to operate on.
3131 */
3132EMR3DECL(int) EMR3ExecuteVM(PVM pVM)
3133{
3134 LogFlow(("EMR3ExecuteVM: pVM=%p enmVMState=%d enmState=%d (%s) fForceRAW=%d\n", pVM, pVM->enmVMState,
3135 pVM->em.s.enmState, EMR3GetStateName(pVM->em.s.enmState), pVM->em.s.fForceRAW));
3136 VM_ASSERT_EMT(pVM);
3137 Assert(pVM->em.s.enmState == EMSTATE_NONE || pVM->em.s.enmState == EMSTATE_SUSPENDED);
3138
3139 VMMR3Lock(pVM);
3140
3141 int rc = setjmp(pVM->em.s.u.FatalLongJump);
3142 if (rc == 0)
3143 {
3144 /*
3145 * Start the virtual time.
3146 */
3147 rc = TMVirtualResume(pVM);
3148 Assert(rc == VINF_SUCCESS);
3149 rc = TMCpuTickResume(pVM);
3150 Assert(rc == VINF_SUCCESS);
3151
3152 /*
3153 * The Outer Main Loop.
3154 */
3155 bool fFFDone = false;
3156 rc = VINF_EM_RESCHEDULE;
3157 pVM->em.s.enmState = EMSTATE_REM;
3158 STAM_PROFILE_ADV_START(&pVM->em.s.StatTotal, x);
3159 for (;;)
3160 {
3161 /*
3162 * Before we can schedule anything (we're here because
3163 * scheduling is required) we must service any pending
3164 * forced actions to avoid any pending action causing
3165 * immidate rescheduling upon entering an inner loop
3166 *
3167 * Do forced actions.
3168 */
3169 if ( !fFFDone
3170 && rc != VINF_EM_TERMINATE
3171 && rc != VINF_EM_OFF
3172 && VM_FF_ISPENDING(pVM, VM_FF_ALL_BUT_RAW_MASK))
3173 {
3174 rc = emR3ForcedActions(pVM, rc);
3175 if ( ( rc == VINF_EM_RESCHEDULE_REM
3176 || rc == VINF_EM_RESCHEDULE_HWACC)
3177 && pVM->em.s.fForceRAW)
3178 rc = VINF_EM_RESCHEDULE_RAW;
3179 }
3180 else if (fFFDone)
3181 fFFDone = false;
3182
3183 /*
3184 * Now what to do?
3185 */
3186 Log2(("EMR3ExecuteVM: rc=%Vrc\n", rc));
3187 switch (rc)
3188 {
3189 /*
3190 * Keep doing what we're currently doing.
3191 */
3192 case VINF_SUCCESS:
3193 break;
3194
3195 /*
3196 * Reschedule - to raw-mode execution.
3197 */
3198 case VINF_EM_RESCHEDULE_RAW:
3199 Log2(("EMR3ExecuteVM: VINF_EM_RESCHEDULE_RAW: %d -> %d (EMSTATE_RAW)\n", pVM->em.s.enmState, EMSTATE_RAW));
3200 pVM->em.s.enmState = EMSTATE_RAW;
3201 break;
3202
3203 /*
3204 * Reschedule - to hardware accelerated raw-mode execution.
3205 */
3206 case VINF_EM_RESCHEDULE_HWACC:
3207 Log2(("EMR3ExecuteVM: VINF_EM_RESCHEDULE_HWACC: %d -> %d (EMSTATE_HWACC)\n", pVM->em.s.enmState, EMSTATE_HWACC));
3208 Assert(!pVM->em.s.fForceRAW);
3209 pVM->em.s.enmState = EMSTATE_HWACC;
3210 break;
3211
3212 /*
3213 * Reschedule - to recompiled execution.
3214 */
3215 case VINF_EM_RESCHEDULE_REM:
3216 Log2(("EMR3ExecuteVM: VINF_EM_RESCHEDULE_REM: %d -> %d (EMSTATE_REM)\n", pVM->em.s.enmState, EMSTATE_REM));
3217 pVM->em.s.enmState = EMSTATE_REM;
3218 break;
3219
3220 /*
3221 * Resume.
3222 */
3223 case VINF_EM_RESUME:
3224 Log2(("EMR3ExecuteVM: VINF_EM_RESUME: %d -> VINF_EM_RESCHEDULE\n", pVM->em.s.enmState));
3225 /* fall through and get scheduled. */
3226
3227 /*
3228 * Reschedule.
3229 */
3230 case VINF_EM_RESCHEDULE:
3231 {
3232 EMSTATE enmState = emR3Reschedule(pVM, pVM->em.s.pCtx);
3233 Log2(("EMR3ExecuteVM: VINF_EM_RESCHEDULE: %d -> %d (%s)\n", pVM->em.s.enmState, enmState, EMR3GetStateName(enmState)));
3234 pVM->em.s.enmState = enmState;
3235 break;
3236 }
3237
3238 /*
3239 * Halted.
3240 */
3241 case VINF_EM_HALT:
3242 Log2(("EMR3ExecuteVM: VINF_EM_HALT: %d -> %d\n", pVM->em.s.enmState, EMSTATE_HALTED));
3243 pVM->em.s.enmState = EMSTATE_HALTED;
3244 break;
3245
3246 /*
3247 * Suspend.
3248 */
3249 case VINF_EM_SUSPEND:
3250 Log2(("EMR3ExecuteVM: VINF_EM_SUSPEND: %d -> %d\n", pVM->em.s.enmState, EMSTATE_SUSPENDED));
3251 pVM->em.s.enmState = EMSTATE_SUSPENDED;
3252 break;
3253
3254 /*
3255 * Reset.
3256 * We might end up doing a double reset for now, we'll have to clean up the mess later.
3257 */
3258 case VINF_EM_RESET:
3259 Log2(("EMR3ExecuteVM: VINF_EM_RESET: %d -> %d\n", pVM->em.s.enmState, EMSTATE_REM));
3260 pVM->em.s.enmState = EMSTATE_REM;
3261 break;
3262
3263 /*
3264 * Power Off.
3265 */
3266 case VINF_EM_OFF:
3267 pVM->em.s.enmState = EMSTATE_TERMINATING;
3268 Log2(("EMR3ExecuteVM: returns VINF_EM_OFF (%d -> %d)\n", pVM->em.s.enmState, EMSTATE_TERMINATING));
3269 TMVirtualPause(pVM);
3270 TMCpuTickPause(pVM);
3271 VMMR3Unlock(pVM);
3272 STAM_PROFILE_ADV_STOP(&pVM->em.s.StatTotal, x);
3273 return rc;
3274
3275 /*
3276 * Terminate the VM.
3277 */
3278 case VINF_EM_TERMINATE:
3279 pVM->em.s.enmState = EMSTATE_TERMINATING;
3280 Log(("EMR3ExecuteVM returns VINF_EM_TERMINATE (%d -> %d)\n", pVM->em.s.enmState, EMSTATE_TERMINATING));
3281 TMVirtualPause(pVM);
3282 TMCpuTickPause(pVM);
3283 STAM_PROFILE_ADV_STOP(&pVM->em.s.StatTotal, x);
3284 return rc;
3285
3286 /*
3287 * Guest debug events.
3288 */
3289 case VINF_EM_DBG_STEPPED:
3290 AssertMsgFailed(("VINF_EM_DBG_STEPPED cannot be here!"));
3291 case VINF_EM_DBG_STOP:
3292 case VINF_EM_DBG_BREAKPOINT:
3293 case VINF_EM_DBG_STEP:
3294 if (pVM->em.s.enmState == EMSTATE_RAW)
3295 {
3296 Log2(("EMR3ExecuteVM: %Vrc: %d -> %d\n", rc, pVM->em.s.enmState, EMSTATE_DEBUG_GUEST_RAW));
3297 pVM->em.s.enmState = EMSTATE_DEBUG_GUEST_RAW;
3298 }
3299 else
3300 {
3301 Log2(("EMR3ExecuteVM: %Vrc: %d -> %d\n", rc, pVM->em.s.enmState, EMSTATE_DEBUG_GUEST_REM));
3302 pVM->em.s.enmState = EMSTATE_DEBUG_GUEST_REM;
3303 }
3304 break;
3305
3306 /*
3307 * Hypervisor debug events.
3308 */
3309 case VINF_EM_DBG_HYPER_STEPPED:
3310 case VINF_EM_DBG_HYPER_BREAKPOINT:
3311 case VINF_EM_DBG_HYPER_ASSERTION:
3312 Log2(("EMR3ExecuteVM: %Vrc: %d -> %d\n", rc, pVM->em.s.enmState, EMSTATE_DEBUG_HYPER));
3313 pVM->em.s.enmState = EMSTATE_DEBUG_HYPER;
3314 break;
3315
3316 /*
3317 * Any error code showing up here other than the ones we
3318 * know and process above are considered to be FATAL.
3319 *
3320 * Unknown warnings and informational status codes are also
3321 * included in this.
3322 */
3323 default:
3324 if (VBOX_SUCCESS(rc))
3325 {
3326 AssertMsgFailed(("Unexpected warning or informational status code %Vra!\n", rc));
3327 rc = VERR_EM_INTERNAL_ERROR;
3328 }
3329 pVM->em.s.enmState = EMSTATE_GURU_MEDITATION;
3330 Log(("EMR3ExecuteVM returns %d\n", rc));
3331 break;
3332 }
3333
3334
3335 /*
3336 * Any waiters can now be woken up
3337 */
3338 VMMR3Unlock(pVM);
3339 VMMR3Lock(pVM);
3340
3341 STAM_PROFILE_ADV_STOP(&pVM->em.s.StatTotal, x);
3342 STAM_PROFILE_ADV_START(&pVM->em.s.StatTotal, x);
3343
3344 /*
3345 * Act on the state.
3346 */
3347 switch (pVM->em.s.enmState)
3348 {
3349 /*
3350 * Execute raw.
3351 */
3352 case EMSTATE_RAW:
3353 rc = emR3RawExecute(pVM, &fFFDone);
3354 break;
3355
3356 /*
3357 * Execute hardware accelerated raw.
3358 */
3359 case EMSTATE_HWACC:
3360 rc = emR3HwAccExecute(pVM, &fFFDone);
3361 break;
3362
3363 /*
3364 * Execute recompiled.
3365 */
3366 case EMSTATE_REM:
3367 rc = emR3RemExecute(pVM, &fFFDone);
3368 Log2(("EMR3ExecuteVM: emR3RemExecute -> %Vrc\n", rc));
3369 break;
3370
3371 /*
3372 * hlt - execution halted until interrupt.
3373 */
3374 case EMSTATE_HALTED:
3375 {
3376 STAM_PROFILE_START(&pVM->em.s.StatHalted, y);
3377 rc = VMR3WaitHalted(pVM, !(CPUMGetGuestEFlags(pVM) & X86_EFL_IF));
3378 STAM_PROFILE_STOP(&pVM->em.s.StatHalted, y);
3379 break;
3380 }
3381
3382 /*
3383 * Suspended - return to VM.cpp.
3384 */
3385 case EMSTATE_SUSPENDED:
3386 TMVirtualPause(pVM);
3387 TMCpuTickPause(pVM);
3388 VMMR3Unlock(pVM);
3389 STAM_PROFILE_ADV_STOP(&pVM->em.s.StatTotal, x);
3390 return VINF_EM_SUSPEND;
3391
3392 /*
3393 * Debugging in the guest.
3394 */
3395 case EMSTATE_DEBUG_GUEST_REM:
3396 case EMSTATE_DEBUG_GUEST_RAW:
3397 TMVirtualPause(pVM);
3398 TMCpuTickPause(pVM);
3399 rc = emR3Debug(pVM, rc);
3400 TMVirtualResume(pVM);
3401 TMCpuTickResume(pVM);
3402 Log2(("EMR3ExecuteVM: enmr3Debug -> %Vrc (state %d)\n", rc, pVM->em.s.enmState));
3403 break;
3404
3405 /*
3406 * Debugging in the hypervisor.
3407 */
3408 case EMSTATE_DEBUG_HYPER:
3409 {
3410 TMVirtualPause(pVM);
3411 TMCpuTickPause(pVM);
3412 STAM_PROFILE_ADV_STOP(&pVM->em.s.StatTotal, x);
3413
3414 rc = emR3Debug(pVM, rc);
3415 Log2(("EMR3ExecuteVM: enmr3Debug -> %Vrc (state %d)\n", rc, pVM->em.s.enmState));
3416 if (rc != VINF_SUCCESS)
3417 {
3418 /* switch to guru meditation mode */
3419 pVM->em.s.enmState = EMSTATE_GURU_MEDITATION;
3420 VMMR3FatalDump(pVM, rc);
3421 return rc;
3422 }
3423
3424 STAM_PROFILE_ADV_START(&pVM->em.s.StatTotal, x);
3425 TMVirtualResume(pVM);
3426 TMCpuTickResume(pVM);
3427 break;
3428 }
3429
3430 /*
3431 * Guru meditation takes place in the debugger.
3432 */
3433 case EMSTATE_GURU_MEDITATION:
3434 {
3435 /** @todo this ain't entirely safe. make a better return code check and specify this in DBGF/emR3Debug. */
3436 TMVirtualPause(pVM);
3437 TMCpuTickPause(pVM);
3438 VMMR3FatalDump(pVM, rc);
3439 int rc2 = emR3Debug(pVM, rc);
3440 if (rc2 == VERR_DBGF_NOT_ATTACHED)
3441 {
3442 VMMR3Unlock(pVM);
3443 /** @todo change the VM state! */
3444 STAM_PROFILE_ADV_STOP(&pVM->em.s.StatTotal, x);
3445 return rc;
3446 }
3447 TMVirtualResume(pVM);
3448 TMCpuTickResume(pVM);
3449 rc = rc2;
3450 /** @todo we're not doing the right thing in emR3Debug and will cause code to be executed on disconnect and stuff.. */
3451 Log2(("EMR3ExecuteVM: enmr3Debug -> %Vrc (state %d)\n", rc, pVM->em.s.enmState));
3452 break;
3453 }
3454
3455 /*
3456 * The states we don't expect here.
3457 */
3458 case EMSTATE_NONE:
3459 case EMSTATE_TERMINATING:
3460 default:
3461 AssertMsgFailed(("EMR3ExecuteVM: Invalid state %d!\n", pVM->em.s.enmState));
3462 pVM->em.s.enmState = EMSTATE_GURU_MEDITATION;
3463 TMVirtualPause(pVM);
3464 TMCpuTickPause(pVM);
3465 VMMR3Unlock(pVM);
3466 STAM_PROFILE_ADV_STOP(&pVM->em.s.StatTotal, x);
3467 return VERR_EM_INTERNAL_ERROR;
3468 }
3469 } /* The Outer Main Loop */
3470 }
3471 else
3472 {
3473 /*
3474 * Fatal error.
3475 */
3476 LogFlow(("EMR3ExecuteVM: returns %Vrc (longjmp / fatal error)\n", rc));
3477 TMVirtualPause(pVM);
3478 TMCpuTickPause(pVM);
3479 VMMR3FatalDump(pVM, rc);
3480 emR3Debug(pVM, rc);
3481 VMMR3Unlock(pVM);
3482 /** @todo change the VM state! */
3483 return rc;
3484 }
3485
3486 /* (won't ever get here). */
3487 AssertFailed();
3488}
3489
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