VirtualBox

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

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

Interpret msr reads and writes (currently disabled in order not to break anything at this point in time)

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