VirtualBox

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

Last change on this file since 84044 was 82968, checked in by vboxsync, 4 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 118.0 KB
Line 
1/* $Id: EM.cpp 82968 2020-02-04 10:35:17Z vboxsync $ */
2/** @file
3 * EM - Execution Monitor / Manager.
4 */
5
6/*
7 * Copyright (C) 2006-2020 Oracle Corporation
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
18/** @page pg_em EM - The Execution Monitor / Manager
19 *
20 * The Execution Monitor/Manager is responsible for running the VM, scheduling
21 * the right kind of execution (Raw-mode, Hardware Assisted, Recompiled or
22 * Interpreted), and keeping the CPU states in sync. The function
23 * EMR3ExecuteVM() is the 'main-loop' of the VM, while each of the execution
24 * modes has different inner loops (emR3RawExecute, emR3HmExecute, and
25 * emR3RemExecute).
26 *
27 * The interpreted execution is only used to avoid switching between
28 * raw-mode/hm and the recompiler when fielding virtualization traps/faults.
29 * The interpretation is thus implemented as part of EM.
30 *
31 * @see grp_em
32 */
33
34
35/*********************************************************************************************************************************
36* Header Files *
37*********************************************************************************************************************************/
38#define LOG_GROUP LOG_GROUP_EM
39#define VMCPU_INCL_CPUM_GST_CTX /* for CPUM_IMPORT_GUEST_STATE_RET */
40#include <VBox/vmm/em.h>
41#include <VBox/vmm/vmm.h>
42#include <VBox/vmm/selm.h>
43#include <VBox/vmm/trpm.h>
44#include <VBox/vmm/iem.h>
45#include <VBox/vmm/nem.h>
46#include <VBox/vmm/iom.h>
47#include <VBox/vmm/dbgf.h>
48#include <VBox/vmm/pgm.h>
49#include <VBox/vmm/apic.h>
50#include <VBox/vmm/tm.h>
51#include <VBox/vmm/mm.h>
52#include <VBox/vmm/ssm.h>
53#include <VBox/vmm/pdmapi.h>
54#include <VBox/vmm/pdmcritsect.h>
55#include <VBox/vmm/pdmqueue.h>
56#include <VBox/vmm/hm.h>
57#include "EMInternal.h"
58#include <VBox/vmm/vm.h>
59#include <VBox/vmm/uvm.h>
60#include <VBox/vmm/cpumdis.h>
61#include <VBox/dis.h>
62#include <VBox/disopcode.h>
63#include <VBox/err.h>
64#include "VMMTracing.h"
65
66#include <iprt/asm.h>
67#include <iprt/string.h>
68#include <iprt/stream.h>
69#include <iprt/thread.h>
70
71
72/*********************************************************************************************************************************
73* Internal Functions *
74*********************************************************************************************************************************/
75static DECLCALLBACK(int) emR3Save(PVM pVM, PSSMHANDLE pSSM);
76static DECLCALLBACK(int) emR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
77#if defined(LOG_ENABLED) || defined(VBOX_STRICT)
78static const char *emR3GetStateName(EMSTATE enmState);
79#endif
80static VBOXSTRICTRC emR3Debug(PVM pVM, PVMCPU pVCpu, VBOXSTRICTRC rc);
81#if defined(VBOX_WITH_REM) || defined(DEBUG)
82static int emR3RemStep(PVM pVM, PVMCPU pVCpu);
83#endif
84static int emR3RemExecute(PVM pVM, PVMCPU pVCpu, bool *pfFFDone);
85
86
87/**
88 * Initializes the EM.
89 *
90 * @returns VBox status code.
91 * @param pVM The cross context VM structure.
92 */
93VMMR3_INT_DECL(int) EMR3Init(PVM pVM)
94{
95 LogFlow(("EMR3Init\n"));
96 /*
97 * Assert alignment and sizes.
98 */
99 AssertCompileMemberAlignment(VM, em.s, 32);
100 AssertCompile(sizeof(pVM->em.s) <= sizeof(pVM->em.padding));
101 AssertCompile(RT_SIZEOFMEMB(VMCPU, em.s.u.FatalLongJump) <= RT_SIZEOFMEMB(VMCPU, em.s.u.achPaddingFatalLongJump));
102 AssertCompile(RT_SIZEOFMEMB(VMCPU, em.s) <= RT_SIZEOFMEMB(VMCPU, em.padding));
103
104 /*
105 * Init the structure.
106 */
107 PCFGMNODE pCfgRoot = CFGMR3GetRoot(pVM);
108 PCFGMNODE pCfgEM = CFGMR3GetChild(pCfgRoot, "EM");
109
110 int rc = CFGMR3QueryBoolDef(pCfgEM, "IemExecutesAll", &pVM->em.s.fIemExecutesAll, false);
111 AssertLogRelRCReturn(rc, rc);
112
113 bool fEnabled;
114 rc = CFGMR3QueryBoolDef(pCfgEM, "TripleFaultReset", &fEnabled, false);
115 AssertLogRelRCReturn(rc, rc);
116 pVM->em.s.fGuruOnTripleFault = !fEnabled;
117 if (!pVM->em.s.fGuruOnTripleFault && pVM->cCpus > 1)
118 {
119 LogRel(("EM: Overriding /EM/TripleFaultReset, must be false on SMP.\n"));
120 pVM->em.s.fGuruOnTripleFault = true;
121 }
122
123 LogRel(("EMR3Init: fIemExecutesAll=%RTbool fGuruOnTripleFault=%RTbool\n", pVM->em.s.fIemExecutesAll, pVM->em.s.fGuruOnTripleFault));
124
125 /** @cfgm{/EM/ExitOptimizationEnabled, bool, true}
126 * Whether to try correlate exit history in any context, detect hot spots and
127 * try optimize these using IEM if there are other exits close by. This
128 * overrides the context specific settings. */
129 bool fExitOptimizationEnabled = true;
130 rc = CFGMR3QueryBoolDef(pCfgEM, "ExitOptimizationEnabled", &fExitOptimizationEnabled, true);
131 AssertLogRelRCReturn(rc, rc);
132
133 /** @cfgm{/EM/ExitOptimizationEnabledR0, bool, true}
134 * Whether to optimize exits in ring-0. Setting this to false will also disable
135 * the /EM/ExitOptimizationEnabledR0PreemptDisabled setting. Depending on preemption
136 * capabilities of the host kernel, this optimization may be unavailable. */
137 bool fExitOptimizationEnabledR0 = true;
138 rc = CFGMR3QueryBoolDef(pCfgEM, "ExitOptimizationEnabledR0", &fExitOptimizationEnabledR0, true);
139 AssertLogRelRCReturn(rc, rc);
140 fExitOptimizationEnabledR0 &= fExitOptimizationEnabled;
141
142 /** @cfgm{/EM/ExitOptimizationEnabledR0PreemptDisabled, bool, false}
143 * Whether to optimize exits in ring-0 when preemption is disable (or preemption
144 * hooks are in effect). */
145 /** @todo change the default to true here */
146 bool fExitOptimizationEnabledR0PreemptDisabled = true;
147 rc = CFGMR3QueryBoolDef(pCfgEM, "ExitOptimizationEnabledR0PreemptDisabled", &fExitOptimizationEnabledR0PreemptDisabled, false);
148 AssertLogRelRCReturn(rc, rc);
149 fExitOptimizationEnabledR0PreemptDisabled &= fExitOptimizationEnabledR0;
150
151 /** @cfgm{/EM/HistoryExecMaxInstructions, integer, 16, 65535, 8192}
152 * Maximum number of instruction to let EMHistoryExec execute in one go. */
153 uint16_t cHistoryExecMaxInstructions = 8192;
154 rc = CFGMR3QueryU16Def(pCfgEM, "HistoryExecMaxInstructions", &cHistoryExecMaxInstructions, cHistoryExecMaxInstructions);
155 AssertLogRelRCReturn(rc, rc);
156 if (cHistoryExecMaxInstructions < 16)
157 return VMSetError(pVM, VERR_OUT_OF_RANGE, RT_SRC_POS, "/EM/HistoryExecMaxInstructions value is too small, min 16");
158
159 /** @cfgm{/EM/HistoryProbeMaxInstructionsWithoutExit, integer, 2, 65535, 24 for HM, 32 for NEM}
160 * Maximum number of instruction between exits during probing. */
161 uint16_t cHistoryProbeMaxInstructionsWithoutExit = 24;
162#ifdef RT_OS_WINDOWS
163 if (VM_IS_NEM_ENABLED(pVM))
164 cHistoryProbeMaxInstructionsWithoutExit = 32;
165#endif
166 rc = CFGMR3QueryU16Def(pCfgEM, "HistoryProbeMaxInstructionsWithoutExit", &cHistoryProbeMaxInstructionsWithoutExit,
167 cHistoryProbeMaxInstructionsWithoutExit);
168 AssertLogRelRCReturn(rc, rc);
169 if (cHistoryProbeMaxInstructionsWithoutExit < 2)
170 return VMSetError(pVM, VERR_OUT_OF_RANGE, RT_SRC_POS,
171 "/EM/HistoryProbeMaxInstructionsWithoutExit value is too small, min 16");
172
173 /** @cfgm{/EM/HistoryProbMinInstructions, integer, 0, 65535, depends}
174 * The default is (/EM/HistoryProbeMaxInstructionsWithoutExit + 1) * 3. */
175 uint16_t cHistoryProbeMinInstructions = cHistoryProbeMaxInstructionsWithoutExit < 0x5554
176 ? (cHistoryProbeMaxInstructionsWithoutExit + 1) * 3 : 0xffff;
177 rc = CFGMR3QueryU16Def(pCfgEM, "HistoryProbMinInstructions", &cHistoryProbeMinInstructions,
178 cHistoryProbeMinInstructions);
179 AssertLogRelRCReturn(rc, rc);
180
181 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
182 {
183 PVMCPU pVCpu = pVM->apCpusR3[idCpu];
184 pVCpu->em.s.fExitOptimizationEnabled = fExitOptimizationEnabled;
185 pVCpu->em.s.fExitOptimizationEnabledR0 = fExitOptimizationEnabledR0;
186 pVCpu->em.s.fExitOptimizationEnabledR0PreemptDisabled = fExitOptimizationEnabledR0PreemptDisabled;
187 pVCpu->em.s.cHistoryExecMaxInstructions = cHistoryExecMaxInstructions;
188 pVCpu->em.s.cHistoryProbeMinInstructions = cHistoryProbeMinInstructions;
189 pVCpu->em.s.cHistoryProbeMaxInstructionsWithoutExit = cHistoryProbeMaxInstructionsWithoutExit;
190 }
191
192 /*
193 * Saved state.
194 */
195 rc = SSMR3RegisterInternal(pVM, "em", 0, EM_SAVED_STATE_VERSION, 16,
196 NULL, NULL, NULL,
197 NULL, emR3Save, NULL,
198 NULL, emR3Load, NULL);
199 if (RT_FAILURE(rc))
200 return rc;
201
202 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
203 {
204 PVMCPU pVCpu = pVM->apCpusR3[idCpu];
205
206 pVCpu->em.s.enmState = idCpu == 0 ? EMSTATE_NONE : EMSTATE_WAIT_SIPI;
207 pVCpu->em.s.enmPrevState = EMSTATE_NONE;
208 pVCpu->em.s.u64TimeSliceStart = 0; /* paranoia */
209 pVCpu->em.s.idxContinueExitRec = UINT16_MAX;
210
211# define EM_REG_COUNTER(a, b, c) \
212 rc = STAMR3RegisterF(pVM, a, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, c, b, idCpu); \
213 AssertRC(rc);
214
215# define EM_REG_COUNTER_USED(a, b, c) \
216 rc = STAMR3RegisterF(pVM, a, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, c, b, idCpu); \
217 AssertRC(rc);
218
219# define EM_REG_PROFILE(a, b, c) \
220 rc = STAMR3RegisterF(pVM, a, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, c, b, idCpu); \
221 AssertRC(rc);
222
223# define EM_REG_PROFILE_ADV(a, b, c) \
224 rc = STAMR3RegisterF(pVM, a, STAMTYPE_PROFILE_ADV, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, c, b, idCpu); \
225 AssertRC(rc);
226
227 /*
228 * Statistics.
229 */
230#ifdef VBOX_WITH_STATISTICS
231 PEMSTATS pStats;
232 rc = MMHyperAlloc(pVM, sizeof(*pStats), 0, MM_TAG_EM, (void **)&pStats);
233 if (RT_FAILURE(rc))
234 return rc;
235
236 pVCpu->em.s.pStatsR3 = pStats;
237 pVCpu->em.s.pStatsR0 = MMHyperR3ToR0(pVM, pStats);
238
239# if 1 /* rawmode only? */
240 EM_REG_COUNTER_USED(&pStats->StatIoRestarted, "/EM/CPU%u/R3/PrivInst/IoRestarted", "I/O instructions restarted in ring-3.");
241 EM_REG_COUNTER_USED(&pStats->StatIoIem, "/EM/CPU%u/R3/PrivInst/IoIem", "I/O instructions end to IEM in ring-3.");
242 EM_REG_COUNTER_USED(&pStats->StatCli, "/EM/CPU%u/R3/PrivInst/Cli", "Number of cli instructions.");
243 EM_REG_COUNTER_USED(&pStats->StatSti, "/EM/CPU%u/R3/PrivInst/Sti", "Number of sli instructions.");
244 EM_REG_COUNTER_USED(&pStats->StatHlt, "/EM/CPU%u/R3/PrivInst/Hlt", "Number of hlt instructions not handled in GC because of PATM.");
245 EM_REG_COUNTER_USED(&pStats->StatInvlpg, "/EM/CPU%u/R3/PrivInst/Invlpg", "Number of invlpg instructions.");
246 EM_REG_COUNTER_USED(&pStats->StatMisc, "/EM/CPU%u/R3/PrivInst/Misc", "Number of misc. instructions.");
247 EM_REG_COUNTER_USED(&pStats->StatMovWriteCR[0], "/EM/CPU%u/R3/PrivInst/Mov CR0, X", "Number of mov CR0 write instructions.");
248 EM_REG_COUNTER_USED(&pStats->StatMovWriteCR[1], "/EM/CPU%u/R3/PrivInst/Mov CR1, X", "Number of mov CR1 write instructions.");
249 EM_REG_COUNTER_USED(&pStats->StatMovWriteCR[2], "/EM/CPU%u/R3/PrivInst/Mov CR2, X", "Number of mov CR2 write instructions.");
250 EM_REG_COUNTER_USED(&pStats->StatMovWriteCR[3], "/EM/CPU%u/R3/PrivInst/Mov CR3, X", "Number of mov CR3 write instructions.");
251 EM_REG_COUNTER_USED(&pStats->StatMovWriteCR[4], "/EM/CPU%u/R3/PrivInst/Mov CR4, X", "Number of mov CR4 write instructions.");
252 EM_REG_COUNTER_USED(&pStats->StatMovReadCR[0], "/EM/CPU%u/R3/PrivInst/Mov X, CR0", "Number of mov CR0 read instructions.");
253 EM_REG_COUNTER_USED(&pStats->StatMovReadCR[1], "/EM/CPU%u/R3/PrivInst/Mov X, CR1", "Number of mov CR1 read instructions.");
254 EM_REG_COUNTER_USED(&pStats->StatMovReadCR[2], "/EM/CPU%u/R3/PrivInst/Mov X, CR2", "Number of mov CR2 read instructions.");
255 EM_REG_COUNTER_USED(&pStats->StatMovReadCR[3], "/EM/CPU%u/R3/PrivInst/Mov X, CR3", "Number of mov CR3 read instructions.");
256 EM_REG_COUNTER_USED(&pStats->StatMovReadCR[4], "/EM/CPU%u/R3/PrivInst/Mov X, CR4", "Number of mov CR4 read instructions.");
257 EM_REG_COUNTER_USED(&pStats->StatMovDRx, "/EM/CPU%u/R3/PrivInst/MovDRx", "Number of mov DRx instructions.");
258 EM_REG_COUNTER_USED(&pStats->StatIret, "/EM/CPU%u/R3/PrivInst/Iret", "Number of iret instructions.");
259 EM_REG_COUNTER_USED(&pStats->StatMovLgdt, "/EM/CPU%u/R3/PrivInst/Lgdt", "Number of lgdt instructions.");
260 EM_REG_COUNTER_USED(&pStats->StatMovLidt, "/EM/CPU%u/R3/PrivInst/Lidt", "Number of lidt instructions.");
261 EM_REG_COUNTER_USED(&pStats->StatMovLldt, "/EM/CPU%u/R3/PrivInst/Lldt", "Number of lldt instructions.");
262 EM_REG_COUNTER_USED(&pStats->StatSysEnter, "/EM/CPU%u/R3/PrivInst/Sysenter", "Number of sysenter instructions.");
263 EM_REG_COUNTER_USED(&pStats->StatSysExit, "/EM/CPU%u/R3/PrivInst/Sysexit", "Number of sysexit instructions.");
264 EM_REG_COUNTER_USED(&pStats->StatSysCall, "/EM/CPU%u/R3/PrivInst/Syscall", "Number of syscall instructions.");
265 EM_REG_COUNTER_USED(&pStats->StatSysRet, "/EM/CPU%u/R3/PrivInst/Sysret", "Number of sysret instructions.");
266 EM_REG_COUNTER(&pVCpu->em.s.StatTotalClis, "/EM/CPU%u/Cli/Total", "Total number of cli instructions executed.");
267#endif
268 pVCpu->em.s.pCliStatTree = 0;
269
270 /* these should be considered for release statistics. */
271 EM_REG_COUNTER(&pVCpu->em.s.StatIOEmu, "/PROF/CPU%u/EM/Emulation/IO", "Profiling of emR3RawExecuteIOInstruction.");
272 EM_REG_COUNTER(&pVCpu->em.s.StatPrivEmu, "/PROF/CPU%u/EM/Emulation/Priv", "Profiling of emR3RawPrivileged.");
273 EM_REG_PROFILE(&pVCpu->em.s.StatHMEntry, "/PROF/CPU%u/EM/HMEnter", "Profiling Hardware Accelerated Mode entry overhead.");
274 EM_REG_PROFILE(&pVCpu->em.s.StatHMExec, "/PROF/CPU%u/EM/HMExec", "Profiling Hardware Accelerated Mode execution.");
275 EM_REG_COUNTER(&pVCpu->em.s.StatHMExecuteCalled, "/PROF/CPU%u/EM/HMExecuteCalled", "Number of times enmR3HMExecute is called.");
276 EM_REG_PROFILE(&pVCpu->em.s.StatIEMEmu, "/PROF/CPU%u/EM/IEMEmuSingle", "Profiling single instruction IEM execution.");
277 EM_REG_PROFILE(&pVCpu->em.s.StatIEMThenREM, "/PROF/CPU%u/EM/IEMThenRem", "Profiling IEM-then-REM instruction execution (by IEM).");
278 EM_REG_PROFILE(&pVCpu->em.s.StatNEMEntry, "/PROF/CPU%u/EM/NEMEnter", "Profiling NEM entry overhead.");
279#endif /* VBOX_WITH_STATISTICS */
280 EM_REG_PROFILE(&pVCpu->em.s.StatNEMExec, "/PROF/CPU%u/EM/NEMExec", "Profiling NEM execution.");
281 EM_REG_COUNTER(&pVCpu->em.s.StatNEMExecuteCalled, "/PROF/CPU%u/EM/NEMExecuteCalled", "Number of times enmR3NEMExecute is called.");
282#ifdef VBOX_WITH_STATISTICS
283 EM_REG_PROFILE(&pVCpu->em.s.StatREMEmu, "/PROF/CPU%u/EM/REMEmuSingle", "Profiling single instruction REM execution.");
284 EM_REG_PROFILE(&pVCpu->em.s.StatREMExec, "/PROF/CPU%u/EM/REMExec", "Profiling REM execution.");
285 EM_REG_PROFILE(&pVCpu->em.s.StatREMSync, "/PROF/CPU%u/EM/REMSync", "Profiling REM context syncing.");
286 EM_REG_PROFILE(&pVCpu->em.s.StatRAWEntry, "/PROF/CPU%u/EM/RAWEnter", "Profiling Raw Mode entry overhead.");
287 EM_REG_PROFILE(&pVCpu->em.s.StatRAWExec, "/PROF/CPU%u/EM/RAWExec", "Profiling Raw Mode execution.");
288 EM_REG_PROFILE(&pVCpu->em.s.StatRAWTail, "/PROF/CPU%u/EM/RAWTail", "Profiling Raw Mode tail overhead.");
289#endif /* VBOX_WITH_STATISTICS */
290
291 EM_REG_COUNTER(&pVCpu->em.s.StatForcedActions, "/PROF/CPU%u/EM/ForcedActions", "Profiling forced action execution.");
292 EM_REG_COUNTER(&pVCpu->em.s.StatHalted, "/PROF/CPU%u/EM/Halted", "Profiling halted state (VMR3WaitHalted).");
293 EM_REG_PROFILE_ADV(&pVCpu->em.s.StatCapped, "/PROF/CPU%u/EM/Capped", "Profiling capped state (sleep).");
294 EM_REG_COUNTER(&pVCpu->em.s.StatREMTotal, "/PROF/CPU%u/EM/REMTotal", "Profiling emR3RemExecute (excluding FFs).");
295 EM_REG_COUNTER(&pVCpu->em.s.StatRAWTotal, "/PROF/CPU%u/EM/RAWTotal", "Profiling emR3RawExecute (excluding FFs).");
296
297 EM_REG_PROFILE_ADV(&pVCpu->em.s.StatTotal, "/PROF/CPU%u/EM/Total", "Profiling EMR3ExecuteVM.");
298
299 rc = STAMR3RegisterF(pVM, &pVCpu->em.s.iNextExit, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
300 "Number of recorded exits.", "/PROF/CPU%u/EM/RecordedExits", idCpu);
301 AssertRC(rc);
302
303 /* History record statistics */
304 rc = STAMR3RegisterF(pVM, &pVCpu->em.s.cExitRecordUsed, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
305 "Number of used hash table entries.", "/EM/CPU%u/ExitHashing/Used", idCpu);
306 AssertRC(rc);
307
308 for (uint32_t iStep = 0; iStep < RT_ELEMENTS(pVCpu->em.s.aStatHistoryRecHits); iStep++)
309 {
310 rc = STAMR3RegisterF(pVM, &pVCpu->em.s.aStatHistoryRecHits[iStep], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
311 "Number of hits at this step.", "/EM/CPU%u/ExitHashing/Step%02u-Hits", idCpu, iStep);
312 AssertRC(rc);
313 rc = STAMR3RegisterF(pVM, &pVCpu->em.s.aStatHistoryRecTypeChanged[iStep], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
314 "Number of type changes at this step.", "/EM/CPU%u/ExitHashing/Step%02u-TypeChanges", idCpu, iStep);
315 AssertRC(rc);
316 rc = STAMR3RegisterF(pVM, &pVCpu->em.s.aStatHistoryRecTypeChanged[iStep], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
317 "Number of replacments at this step.", "/EM/CPU%u/ExitHashing/Step%02u-Replacments", idCpu, iStep);
318 AssertRC(rc);
319 rc = STAMR3RegisterF(pVM, &pVCpu->em.s.aStatHistoryRecNew[iStep], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
320 "Number of new inserts at this step.", "/EM/CPU%u/ExitHashing/Step%02u-NewInserts", idCpu, iStep);
321 AssertRC(rc);
322 }
323
324 EM_REG_PROFILE(&pVCpu->em.s.StatHistoryExec, "/EM/CPU%u/ExitOpt/Exec", "Profiling normal EMHistoryExec operation.");
325 EM_REG_COUNTER(&pVCpu->em.s.StatHistoryExecSavedExits, "/EM/CPU%u/ExitOpt/ExecSavedExit", "Net number of saved exits.");
326 EM_REG_COUNTER(&pVCpu->em.s.StatHistoryExecInstructions, "/EM/CPU%u/ExitOpt/ExecInstructions", "Number of instructions executed during normal operation.");
327 EM_REG_PROFILE(&pVCpu->em.s.StatHistoryProbe, "/EM/CPU%u/ExitOpt/Probe", "Profiling EMHistoryExec when probing.");
328 EM_REG_COUNTER(&pVCpu->em.s.StatHistoryProbeInstructions, "/EM/CPU%u/ExitOpt/ProbeInstructions", "Number of instructions executed during probing.");
329 EM_REG_COUNTER(&pVCpu->em.s.StatHistoryProbedNormal, "/EM/CPU%u/ExitOpt/ProbedNormal", "Number of EMEXITACTION_NORMAL_PROBED results.");
330 EM_REG_COUNTER(&pVCpu->em.s.StatHistoryProbedExecWithMax, "/EM/CPU%u/ExitOpt/ProbedExecWithMax", "Number of EMEXITACTION_EXEC_WITH_MAX results.");
331 EM_REG_COUNTER(&pVCpu->em.s.StatHistoryProbedToRing3, "/EM/CPU%u/ExitOpt/ProbedToRing3", "Number of ring-3 probe continuations.");
332 }
333
334 emR3InitDbg(pVM);
335 return VINF_SUCCESS;
336}
337
338
339/**
340 * Called when a VM initialization stage is completed.
341 *
342 * @returns VBox status code.
343 * @param pVM The cross context VM structure.
344 * @param enmWhat The initialization state that was completed.
345 */
346VMMR3_INT_DECL(int) EMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat)
347{
348 if (enmWhat == VMINITCOMPLETED_RING0)
349 LogRel(("EM: Exit history optimizations: enabled=%RTbool enabled-r0=%RTbool enabled-r0-no-preemption=%RTbool\n",
350 pVM->apCpusR3[0]->em.s.fExitOptimizationEnabled, pVM->apCpusR3[0]->em.s.fExitOptimizationEnabledR0,
351 pVM->apCpusR3[0]->em.s.fExitOptimizationEnabledR0PreemptDisabled));
352 return VINF_SUCCESS;
353}
354
355
356/**
357 * Applies relocations to data and code managed by this
358 * component. This function will be called at init and
359 * whenever the VMM need to relocate it self inside the GC.
360 *
361 * @param pVM The cross context VM structure.
362 */
363VMMR3_INT_DECL(void) EMR3Relocate(PVM pVM)
364{
365 LogFlow(("EMR3Relocate\n"));
366 RT_NOREF(pVM);
367}
368
369
370/**
371 * Reset the EM state for a CPU.
372 *
373 * Called by EMR3Reset and hot plugging.
374 *
375 * @param pVCpu The cross context virtual CPU structure.
376 */
377VMMR3_INT_DECL(void) EMR3ResetCpu(PVMCPU pVCpu)
378{
379 /* Reset scheduling state. */
380 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_UNHALT);
381
382 /* VMR3ResetFF may return VINF_EM_RESET or VINF_EM_SUSPEND, so transition
383 out of the HALTED state here so that enmPrevState doesn't end up as
384 HALTED when EMR3Execute returns. */
385 if (pVCpu->em.s.enmState == EMSTATE_HALTED)
386 {
387 Log(("EMR3ResetCpu: Cpu#%u %s -> %s\n", pVCpu->idCpu, emR3GetStateName(pVCpu->em.s.enmState), pVCpu->idCpu == 0 ? "EMSTATE_NONE" : "EMSTATE_WAIT_SIPI"));
388 pVCpu->em.s.enmState = pVCpu->idCpu == 0 ? EMSTATE_NONE : EMSTATE_WAIT_SIPI;
389 }
390}
391
392
393/**
394 * Reset notification.
395 *
396 * @param pVM The cross context VM structure.
397 */
398VMMR3_INT_DECL(void) EMR3Reset(PVM pVM)
399{
400 Log(("EMR3Reset: \n"));
401 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
402 EMR3ResetCpu(pVM->apCpusR3[idCpu]);
403}
404
405
406/**
407 * Terminates the EM.
408 *
409 * Termination means cleaning up and freeing all resources,
410 * the VM it self is at this point powered off or suspended.
411 *
412 * @returns VBox status code.
413 * @param pVM The cross context VM structure.
414 */
415VMMR3_INT_DECL(int) EMR3Term(PVM pVM)
416{
417 RT_NOREF(pVM);
418 return VINF_SUCCESS;
419}
420
421
422/**
423 * Execute state save operation.
424 *
425 * @returns VBox status code.
426 * @param pVM The cross context VM structure.
427 * @param pSSM SSM operation handle.
428 */
429static DECLCALLBACK(int) emR3Save(PVM pVM, PSSMHANDLE pSSM)
430{
431 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
432 {
433 PVMCPU pVCpu = pVM->apCpusR3[idCpu];
434
435 SSMR3PutBool(pSSM, false /*fForceRAW*/);
436
437 Assert(pVCpu->em.s.enmState == EMSTATE_SUSPENDED);
438 Assert(pVCpu->em.s.enmPrevState != EMSTATE_SUSPENDED);
439 SSMR3PutU32(pSSM, pVCpu->em.s.enmPrevState);
440
441 /* Save mwait state. */
442 SSMR3PutU32(pSSM, pVCpu->em.s.MWait.fWait);
443 SSMR3PutGCPtr(pSSM, pVCpu->em.s.MWait.uMWaitRAX);
444 SSMR3PutGCPtr(pSSM, pVCpu->em.s.MWait.uMWaitRCX);
445 SSMR3PutGCPtr(pSSM, pVCpu->em.s.MWait.uMonitorRAX);
446 SSMR3PutGCPtr(pSSM, pVCpu->em.s.MWait.uMonitorRCX);
447 int rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.MWait.uMonitorRDX);
448 AssertRCReturn(rc, rc);
449 }
450 return VINF_SUCCESS;
451}
452
453
454/**
455 * Execute state load operation.
456 *
457 * @returns VBox status code.
458 * @param pVM The cross context VM structure.
459 * @param pSSM SSM operation handle.
460 * @param uVersion Data layout version.
461 * @param uPass The data pass.
462 */
463static DECLCALLBACK(int) emR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
464{
465 /*
466 * Validate version.
467 */
468 if ( uVersion > EM_SAVED_STATE_VERSION
469 || uVersion < EM_SAVED_STATE_VERSION_PRE_SMP)
470 {
471 AssertMsgFailed(("emR3Load: Invalid version uVersion=%d (current %d)!\n", uVersion, EM_SAVED_STATE_VERSION));
472 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
473 }
474 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
475
476 /*
477 * Load the saved state.
478 */
479 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
480 {
481 PVMCPU pVCpu = pVM->apCpusR3[idCpu];
482
483 bool fForceRAWIgnored;
484 int rc = SSMR3GetBool(pSSM, &fForceRAWIgnored);
485 AssertRCReturn(rc, rc);
486
487 if (uVersion > EM_SAVED_STATE_VERSION_PRE_SMP)
488 {
489 SSM_GET_ENUM32_RET(pSSM, pVCpu->em.s.enmPrevState, EMSTATE);
490 Assert(pVCpu->em.s.enmPrevState != EMSTATE_SUSPENDED);
491
492 pVCpu->em.s.enmState = EMSTATE_SUSPENDED;
493 }
494 if (uVersion > EM_SAVED_STATE_VERSION_PRE_MWAIT)
495 {
496 /* Load mwait state. */
497 rc = SSMR3GetU32(pSSM, &pVCpu->em.s.MWait.fWait);
498 AssertRCReturn(rc, rc);
499 rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.MWait.uMWaitRAX);
500 AssertRCReturn(rc, rc);
501 rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.MWait.uMWaitRCX);
502 AssertRCReturn(rc, rc);
503 rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.MWait.uMonitorRAX);
504 AssertRCReturn(rc, rc);
505 rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.MWait.uMonitorRCX);
506 AssertRCReturn(rc, rc);
507 rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.MWait.uMonitorRDX);
508 AssertRCReturn(rc, rc);
509 }
510
511 Assert(!pVCpu->em.s.pCliStatTree);
512 }
513 return VINF_SUCCESS;
514}
515
516
517/**
518 * Argument packet for emR3SetExecutionPolicy.
519 */
520struct EMR3SETEXECPOLICYARGS
521{
522 EMEXECPOLICY enmPolicy;
523 bool fEnforce;
524};
525
526
527/**
528 * @callback_method_impl{FNVMMEMTRENDEZVOUS, Rendezvous callback for EMR3SetExecutionPolicy.}
529 */
530static DECLCALLBACK(VBOXSTRICTRC) emR3SetExecutionPolicy(PVM pVM, PVMCPU pVCpu, void *pvUser)
531{
532 /*
533 * Only the first CPU changes the variables.
534 */
535 if (pVCpu->idCpu == 0)
536 {
537 struct EMR3SETEXECPOLICYARGS *pArgs = (struct EMR3SETEXECPOLICYARGS *)pvUser;
538 switch (pArgs->enmPolicy)
539 {
540 case EMEXECPOLICY_RECOMPILE_RING0:
541 case EMEXECPOLICY_RECOMPILE_RING3:
542 break;
543 case EMEXECPOLICY_IEM_ALL:
544 pVM->em.s.fIemExecutesAll = pArgs->fEnforce;
545 break;
546 default:
547 AssertFailedReturn(VERR_INVALID_PARAMETER);
548 }
549 Log(("EM: Set execution policy (fIemExecutesAll=%RTbool)\n", pVM->em.s.fIemExecutesAll));
550 }
551
552 /*
553 * Force rescheduling if in RAW, HM, NEM, IEM, or REM.
554 */
555 return pVCpu->em.s.enmState == EMSTATE_RAW
556 || pVCpu->em.s.enmState == EMSTATE_HM
557 || pVCpu->em.s.enmState == EMSTATE_NEM
558 || pVCpu->em.s.enmState == EMSTATE_IEM
559 || pVCpu->em.s.enmState == EMSTATE_REM
560 || pVCpu->em.s.enmState == EMSTATE_IEM_THEN_REM
561 ? VINF_EM_RESCHEDULE
562 : VINF_SUCCESS;
563}
564
565
566/**
567 * Changes an execution scheduling policy parameter.
568 *
569 * This is used to enable or disable raw-mode / hardware-virtualization
570 * execution of user and supervisor code.
571 *
572 * @returns VINF_SUCCESS on success.
573 * @returns VINF_RESCHEDULE if a rescheduling might be required.
574 * @returns VERR_INVALID_PARAMETER on an invalid enmMode value.
575 *
576 * @param pUVM The user mode VM handle.
577 * @param enmPolicy The scheduling policy to change.
578 * @param fEnforce Whether to enforce the policy or not.
579 */
580VMMR3DECL(int) EMR3SetExecutionPolicy(PUVM pUVM, EMEXECPOLICY enmPolicy, bool fEnforce)
581{
582 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
583 VM_ASSERT_VALID_EXT_RETURN(pUVM->pVM, VERR_INVALID_VM_HANDLE);
584 AssertReturn(enmPolicy > EMEXECPOLICY_INVALID && enmPolicy < EMEXECPOLICY_END, VERR_INVALID_PARAMETER);
585
586 struct EMR3SETEXECPOLICYARGS Args = { enmPolicy, fEnforce };
587 return VMMR3EmtRendezvous(pUVM->pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING, emR3SetExecutionPolicy, &Args);
588}
589
590
591/**
592 * Queries an execution scheduling policy parameter.
593 *
594 * @returns VBox status code
595 * @param pUVM The user mode VM handle.
596 * @param enmPolicy The scheduling policy to query.
597 * @param pfEnforced Where to return the current value.
598 */
599VMMR3DECL(int) EMR3QueryExecutionPolicy(PUVM pUVM, EMEXECPOLICY enmPolicy, bool *pfEnforced)
600{
601 AssertReturn(enmPolicy > EMEXECPOLICY_INVALID && enmPolicy < EMEXECPOLICY_END, VERR_INVALID_PARAMETER);
602 AssertPtrReturn(pfEnforced, VERR_INVALID_POINTER);
603 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
604 PVM pVM = pUVM->pVM;
605 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
606
607 /* No need to bother EMTs with a query. */
608 switch (enmPolicy)
609 {
610 case EMEXECPOLICY_RECOMPILE_RING0:
611 case EMEXECPOLICY_RECOMPILE_RING3:
612 *pfEnforced = false;
613 break;
614 case EMEXECPOLICY_IEM_ALL:
615 *pfEnforced = pVM->em.s.fIemExecutesAll;
616 break;
617 default:
618 AssertFailedReturn(VERR_INTERNAL_ERROR_2);
619 }
620
621 return VINF_SUCCESS;
622}
623
624
625/**
626 * Queries the main execution engine of the VM.
627 *
628 * @returns VBox status code
629 * @param pUVM The user mode VM handle.
630 * @param pbMainExecutionEngine Where to return the result, VM_EXEC_ENGINE_XXX.
631 */
632VMMR3DECL(int) EMR3QueryMainExecutionEngine(PUVM pUVM, uint8_t *pbMainExecutionEngine)
633{
634 AssertPtrReturn(pbMainExecutionEngine, VERR_INVALID_POINTER);
635 *pbMainExecutionEngine = VM_EXEC_ENGINE_NOT_SET;
636
637 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
638 PVM pVM = pUVM->pVM;
639 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
640
641 *pbMainExecutionEngine = pVM->bMainExecutionEngine;
642 return VINF_SUCCESS;
643}
644
645
646/**
647 * Raise a fatal error.
648 *
649 * Safely terminate the VM with full state report and stuff. This function
650 * will naturally never return.
651 *
652 * @param pVCpu The cross context virtual CPU structure.
653 * @param rc VBox status code.
654 */
655VMMR3DECL(void) EMR3FatalError(PVMCPU pVCpu, int rc)
656{
657 pVCpu->em.s.enmState = EMSTATE_GURU_MEDITATION;
658 longjmp(pVCpu->em.s.u.FatalLongJump, rc);
659}
660
661
662#if defined(LOG_ENABLED) || defined(VBOX_STRICT)
663/**
664 * Gets the EM state name.
665 *
666 * @returns pointer to read only state name,
667 * @param enmState The state.
668 */
669static const char *emR3GetStateName(EMSTATE enmState)
670{
671 switch (enmState)
672 {
673 case EMSTATE_NONE: return "EMSTATE_NONE";
674 case EMSTATE_RAW: return "EMSTATE_RAW";
675 case EMSTATE_HM: return "EMSTATE_HM";
676 case EMSTATE_IEM: return "EMSTATE_IEM";
677 case EMSTATE_REM: return "EMSTATE_REM";
678 case EMSTATE_HALTED: return "EMSTATE_HALTED";
679 case EMSTATE_WAIT_SIPI: return "EMSTATE_WAIT_SIPI";
680 case EMSTATE_SUSPENDED: return "EMSTATE_SUSPENDED";
681 case EMSTATE_TERMINATING: return "EMSTATE_TERMINATING";
682 case EMSTATE_DEBUG_GUEST_RAW: return "EMSTATE_DEBUG_GUEST_RAW";
683 case EMSTATE_DEBUG_GUEST_HM: return "EMSTATE_DEBUG_GUEST_HM";
684 case EMSTATE_DEBUG_GUEST_IEM: return "EMSTATE_DEBUG_GUEST_IEM";
685 case EMSTATE_DEBUG_GUEST_REM: return "EMSTATE_DEBUG_GUEST_REM";
686 case EMSTATE_DEBUG_HYPER: return "EMSTATE_DEBUG_HYPER";
687 case EMSTATE_GURU_MEDITATION: return "EMSTATE_GURU_MEDITATION";
688 case EMSTATE_IEM_THEN_REM: return "EMSTATE_IEM_THEN_REM";
689 case EMSTATE_NEM: return "EMSTATE_NEM";
690 case EMSTATE_DEBUG_GUEST_NEM: return "EMSTATE_DEBUG_GUEST_NEM";
691 default: return "Unknown!";
692 }
693}
694#endif /* LOG_ENABLED || VBOX_STRICT */
695
696
697/**
698 * Handle pending ring-3 I/O port write.
699 *
700 * This is in response to a VINF_EM_PENDING_R3_IOPORT_WRITE status code returned
701 * by EMRZSetPendingIoPortWrite() in ring-0 or raw-mode context.
702 *
703 * @returns Strict VBox status code.
704 * @param pVM The cross context VM structure.
705 * @param pVCpu The cross context virtual CPU structure.
706 */
707VBOXSTRICTRC emR3ExecutePendingIoPortWrite(PVM pVM, PVMCPU pVCpu)
708{
709 CPUM_ASSERT_NOT_EXTRN(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
710
711 /* Get and clear the pending data. */
712 RTIOPORT const uPort = pVCpu->em.s.PendingIoPortAccess.uPort;
713 uint32_t const uValue = pVCpu->em.s.PendingIoPortAccess.uValue;
714 uint8_t const cbValue = pVCpu->em.s.PendingIoPortAccess.cbValue;
715 uint8_t const cbInstr = pVCpu->em.s.PendingIoPortAccess.cbInstr;
716 pVCpu->em.s.PendingIoPortAccess.cbValue = 0;
717
718 /* Assert sanity. */
719 switch (cbValue)
720 {
721 case 1: Assert(!(cbValue & UINT32_C(0xffffff00))); break;
722 case 2: Assert(!(cbValue & UINT32_C(0xffff0000))); break;
723 case 4: break;
724 default: AssertMsgFailedReturn(("cbValue=%#x\n", cbValue), VERR_EM_INTERNAL_ERROR);
725 }
726 AssertReturn(cbInstr <= 15 && cbInstr >= 1, VERR_EM_INTERNAL_ERROR);
727
728 /* Do the work.*/
729 VBOXSTRICTRC rcStrict = IOMIOPortWrite(pVM, pVCpu, uPort, uValue, cbValue);
730 LogFlow(("EM/OUT: %#x, %#x LB %u -> %Rrc\n", uPort, uValue, cbValue, VBOXSTRICTRC_VAL(rcStrict) ));
731 if (IOM_SUCCESS(rcStrict))
732 {
733 pVCpu->cpum.GstCtx.rip += cbInstr;
734 pVCpu->cpum.GstCtx.rflags.Bits.u1RF = 0;
735 }
736 return rcStrict;
737}
738
739
740/**
741 * Handle pending ring-3 I/O port write.
742 *
743 * This is in response to a VINF_EM_PENDING_R3_IOPORT_WRITE status code returned
744 * by EMRZSetPendingIoPortRead() in ring-0 or raw-mode context.
745 *
746 * @returns Strict VBox status code.
747 * @param pVM The cross context VM structure.
748 * @param pVCpu The cross context virtual CPU structure.
749 */
750VBOXSTRICTRC emR3ExecutePendingIoPortRead(PVM pVM, PVMCPU pVCpu)
751{
752 CPUM_ASSERT_NOT_EXTRN(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_RAX);
753
754 /* Get and clear the pending data. */
755 RTIOPORT const uPort = pVCpu->em.s.PendingIoPortAccess.uPort;
756 uint8_t const cbValue = pVCpu->em.s.PendingIoPortAccess.cbValue;
757 uint8_t const cbInstr = pVCpu->em.s.PendingIoPortAccess.cbInstr;
758 pVCpu->em.s.PendingIoPortAccess.cbValue = 0;
759
760 /* Assert sanity. */
761 switch (cbValue)
762 {
763 case 1: break;
764 case 2: break;
765 case 4: break;
766 default: AssertMsgFailedReturn(("cbValue=%#x\n", cbValue), VERR_EM_INTERNAL_ERROR);
767 }
768 AssertReturn(pVCpu->em.s.PendingIoPortAccess.uValue == UINT32_C(0x52454144) /* READ*/, VERR_EM_INTERNAL_ERROR);
769 AssertReturn(cbInstr <= 15 && cbInstr >= 1, VERR_EM_INTERNAL_ERROR);
770
771 /* Do the work.*/
772 uint32_t uValue = 0;
773 VBOXSTRICTRC rcStrict = IOMIOPortRead(pVM, pVCpu, uPort, &uValue, cbValue);
774 LogFlow(("EM/IN: %#x LB %u -> %Rrc, %#x\n", uPort, cbValue, VBOXSTRICTRC_VAL(rcStrict), uValue ));
775 if (IOM_SUCCESS(rcStrict))
776 {
777 if (cbValue == 4)
778 pVCpu->cpum.GstCtx.rax = uValue;
779 else if (cbValue == 2)
780 pVCpu->cpum.GstCtx.ax = (uint16_t)uValue;
781 else
782 pVCpu->cpum.GstCtx.al = (uint8_t)uValue;
783 pVCpu->cpum.GstCtx.rip += cbInstr;
784 pVCpu->cpum.GstCtx.rflags.Bits.u1RF = 0;
785 }
786 return rcStrict;
787}
788
789
790/**
791 * Debug loop.
792 *
793 * @returns VBox status code for EM.
794 * @param pVM The cross context VM structure.
795 * @param pVCpu The cross context virtual CPU structure.
796 * @param rc Current EM VBox status code.
797 */
798static VBOXSTRICTRC emR3Debug(PVM pVM, PVMCPU pVCpu, VBOXSTRICTRC rc)
799{
800 for (;;)
801 {
802 Log(("emR3Debug: rc=%Rrc\n", VBOXSTRICTRC_VAL(rc)));
803 const VBOXSTRICTRC rcLast = rc;
804
805 /*
806 * Debug related RC.
807 */
808 switch (VBOXSTRICTRC_VAL(rc))
809 {
810 /*
811 * Single step an instruction.
812 */
813 case VINF_EM_DBG_STEP:
814 if ( pVCpu->em.s.enmState == EMSTATE_DEBUG_GUEST_RAW
815 || pVCpu->em.s.enmState == EMSTATE_DEBUG_HYPER)
816 AssertLogRelMsgFailedStmt(("Bad EM state."), VERR_EM_INTERNAL_ERROR);
817 else if (pVCpu->em.s.enmState == EMSTATE_DEBUG_GUEST_HM)
818 rc = EMR3HmSingleInstruction(pVM, pVCpu, 0 /*fFlags*/);
819 else if (pVCpu->em.s.enmState == EMSTATE_DEBUG_GUEST_NEM)
820 rc = VBOXSTRICTRC_TODO(emR3NemSingleInstruction(pVM, pVCpu, 0 /*fFlags*/));
821#ifdef VBOX_WITH_REM /** @todo fix me? */
822 else if (pVCpu->em.s.enmState == EMSTATE_DEBUG_GUEST_REM)
823 rc = emR3RemStep(pVM, pVCpu);
824#endif
825 else
826 {
827 rc = IEMExecOne(pVCpu); /** @todo add dedicated interface... */
828 if (rc == VINF_SUCCESS || rc == VINF_EM_RESCHEDULE)
829 rc = VINF_EM_DBG_STEPPED;
830 }
831 break;
832
833 /*
834 * Simple events: stepped, breakpoint, stop/assertion.
835 */
836 case VINF_EM_DBG_STEPPED:
837 rc = DBGFR3Event(pVM, DBGFEVENT_STEPPED);
838 break;
839
840 case VINF_EM_DBG_BREAKPOINT:
841 rc = DBGFR3EventBreakpoint(pVM, DBGFEVENT_BREAKPOINT);
842 break;
843
844 case VINF_EM_DBG_STOP:
845 rc = DBGFR3EventSrc(pVM, DBGFEVENT_DEV_STOP, NULL, 0, NULL, NULL);
846 break;
847
848 case VINF_EM_DBG_EVENT:
849 rc = DBGFR3EventHandlePending(pVM, pVCpu);
850 break;
851
852 case VINF_EM_DBG_HYPER_STEPPED:
853 rc = DBGFR3Event(pVM, DBGFEVENT_STEPPED_HYPER);
854 break;
855
856 case VINF_EM_DBG_HYPER_BREAKPOINT:
857 rc = DBGFR3EventBreakpoint(pVM, DBGFEVENT_BREAKPOINT_HYPER);
858 break;
859
860 case VINF_EM_DBG_HYPER_ASSERTION:
861 RTPrintf("\nVINF_EM_DBG_HYPER_ASSERTION:\n%s%s\n", VMMR3GetRZAssertMsg1(pVM), VMMR3GetRZAssertMsg2(pVM));
862 RTLogFlush(NULL);
863 rc = DBGFR3EventAssertion(pVM, DBGFEVENT_ASSERTION_HYPER, VMMR3GetRZAssertMsg1(pVM), VMMR3GetRZAssertMsg2(pVM));
864 break;
865
866 /*
867 * Guru meditation.
868 */
869 case VERR_VMM_RING0_ASSERTION: /** @todo Make a guru meditation event! */
870 rc = DBGFR3EventSrc(pVM, DBGFEVENT_FATAL_ERROR, "VERR_VMM_RING0_ASSERTION", 0, NULL, NULL);
871 break;
872 case VERR_REM_TOO_MANY_TRAPS: /** @todo Make a guru meditation event! */
873 rc = DBGFR3EventSrc(pVM, DBGFEVENT_DEV_STOP, "VERR_REM_TOO_MANY_TRAPS", 0, NULL, NULL);
874 break;
875 case VINF_EM_TRIPLE_FAULT: /** @todo Make a guru meditation event! */
876 rc = DBGFR3EventSrc(pVM, DBGFEVENT_DEV_STOP, "VINF_EM_TRIPLE_FAULT", 0, NULL, NULL);
877 break;
878
879 default: /** @todo don't use default for guru, but make special errors code! */
880 {
881 LogRel(("emR3Debug: rc=%Rrc\n", VBOXSTRICTRC_VAL(rc)));
882 rc = DBGFR3Event(pVM, DBGFEVENT_FATAL_ERROR);
883 break;
884 }
885 }
886
887 /*
888 * Process the result.
889 */
890 switch (VBOXSTRICTRC_VAL(rc))
891 {
892 /*
893 * Continue the debugging loop.
894 */
895 case VINF_EM_DBG_STEP:
896 case VINF_EM_DBG_STOP:
897 case VINF_EM_DBG_EVENT:
898 case VINF_EM_DBG_STEPPED:
899 case VINF_EM_DBG_BREAKPOINT:
900 case VINF_EM_DBG_HYPER_STEPPED:
901 case VINF_EM_DBG_HYPER_BREAKPOINT:
902 case VINF_EM_DBG_HYPER_ASSERTION:
903 break;
904
905 /*
906 * Resuming execution (in some form) has to be done here if we got
907 * a hypervisor debug event.
908 */
909 case VINF_SUCCESS:
910 case VINF_EM_RESUME:
911 case VINF_EM_SUSPEND:
912 case VINF_EM_RESCHEDULE:
913 case VINF_EM_RESCHEDULE_RAW:
914 case VINF_EM_RESCHEDULE_REM:
915 case VINF_EM_HALT:
916 if (pVCpu->em.s.enmState == EMSTATE_DEBUG_HYPER)
917 AssertLogRelMsgFailedReturn(("Not implemented\n"), VERR_EM_INTERNAL_ERROR);
918 if (rc == VINF_SUCCESS)
919 rc = VINF_EM_RESCHEDULE;
920 return rc;
921
922 /*
923 * The debugger isn't attached.
924 * We'll simply turn the thing off since that's the easiest thing to do.
925 */
926 case VERR_DBGF_NOT_ATTACHED:
927 switch (VBOXSTRICTRC_VAL(rcLast))
928 {
929 case VINF_EM_DBG_HYPER_STEPPED:
930 case VINF_EM_DBG_HYPER_BREAKPOINT:
931 case VINF_EM_DBG_HYPER_ASSERTION:
932 case VERR_TRPM_PANIC:
933 case VERR_TRPM_DONT_PANIC:
934 case VERR_VMM_RING0_ASSERTION:
935 case VERR_VMM_HYPER_CR3_MISMATCH:
936 case VERR_VMM_RING3_CALL_DISABLED:
937 return rcLast;
938 }
939 return VINF_EM_OFF;
940
941 /*
942 * Status codes terminating the VM in one or another sense.
943 */
944 case VINF_EM_TERMINATE:
945 case VINF_EM_OFF:
946 case VINF_EM_RESET:
947 case VINF_EM_NO_MEMORY:
948 case VINF_EM_RAW_STALE_SELECTOR:
949 case VINF_EM_RAW_IRET_TRAP:
950 case VERR_TRPM_PANIC:
951 case VERR_TRPM_DONT_PANIC:
952 case VERR_IEM_INSTR_NOT_IMPLEMENTED:
953 case VERR_IEM_ASPECT_NOT_IMPLEMENTED:
954 case VERR_VMM_RING0_ASSERTION:
955 case VERR_VMM_HYPER_CR3_MISMATCH:
956 case VERR_VMM_RING3_CALL_DISABLED:
957 case VERR_INTERNAL_ERROR:
958 case VERR_INTERNAL_ERROR_2:
959 case VERR_INTERNAL_ERROR_3:
960 case VERR_INTERNAL_ERROR_4:
961 case VERR_INTERNAL_ERROR_5:
962 case VERR_IPE_UNEXPECTED_STATUS:
963 case VERR_IPE_UNEXPECTED_INFO_STATUS:
964 case VERR_IPE_UNEXPECTED_ERROR_STATUS:
965 return rc;
966
967 /*
968 * The rest is unexpected, and will keep us here.
969 */
970 default:
971 AssertMsgFailed(("Unexpected rc %Rrc!\n", VBOXSTRICTRC_VAL(rc)));
972 break;
973 }
974 } /* debug for ever */
975}
976
977
978#if defined(VBOX_WITH_REM) || defined(DEBUG)
979/**
980 * Steps recompiled code.
981 *
982 * @returns VBox status code. The most important ones are: VINF_EM_STEP_EVENT,
983 * VINF_EM_RESCHEDULE, VINF_EM_SUSPEND, VINF_EM_RESET and VINF_EM_TERMINATE.
984 *
985 * @param pVM The cross context VM structure.
986 * @param pVCpu The cross context virtual CPU structure.
987 */
988static int emR3RemStep(PVM pVM, PVMCPU pVCpu)
989{
990 Log3(("emR3RemStep: cs:eip=%04x:%08x\n", CPUMGetGuestCS(pVCpu), CPUMGetGuestEIP(pVCpu)));
991
992 int rc = VBOXSTRICTRC_TODO(IEMExecOne(pVCpu)); NOREF(pVM);
993
994 Log3(("emR3RemStep: returns %Rrc cs:eip=%04x:%08x\n", rc, CPUMGetGuestCS(pVCpu), CPUMGetGuestEIP(pVCpu)));
995 return rc;
996}
997#endif /* VBOX_WITH_REM || DEBUG */
998
999
1000/**
1001 * Executes recompiled code.
1002 *
1003 * This function contains the recompiler version of the inner
1004 * execution loop (the outer loop being in EMR3ExecuteVM()).
1005 *
1006 * @returns VBox status code. The most important ones are: VINF_EM_RESCHEDULE,
1007 * VINF_EM_SUSPEND, VINF_EM_RESET and VINF_EM_TERMINATE.
1008 *
1009 * @param pVM The cross context VM structure.
1010 * @param pVCpu The cross context virtual CPU structure.
1011 * @param pfFFDone Where to store an indicator telling whether or not
1012 * FFs were done before returning.
1013 *
1014 */
1015static int emR3RemExecute(PVM pVM, PVMCPU pVCpu, bool *pfFFDone)
1016{
1017#ifdef LOG_ENABLED
1018 uint32_t cpl = CPUMGetGuestCPL(pVCpu);
1019
1020 if (pVCpu->cpum.GstCtx.eflags.Bits.u1VM)
1021 Log(("EMV86: %04X:%08X IF=%d\n", pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.eip, pVCpu->cpum.GstCtx.eflags.Bits.u1IF));
1022 else
1023 Log(("EMR%d: %04X:%08X ESP=%08X IF=%d CR0=%x eflags=%x\n", cpl, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.eip, pVCpu->cpum.GstCtx.esp, pVCpu->cpum.GstCtx.eflags.Bits.u1IF, (uint32_t)pVCpu->cpum.GstCtx.cr0, pVCpu->cpum.GstCtx.eflags.u));
1024#endif
1025 STAM_REL_PROFILE_ADV_START(&pVCpu->em.s.StatREMTotal, a);
1026
1027#if defined(VBOX_STRICT) && defined(DEBUG_bird)
1028 AssertMsg( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL)
1029 || !MMHyperIsInsideArea(pVM, CPUMGetGuestEIP(pVCpu)), /** @todo @bugref{1419} - get flat address. */
1030 ("cs:eip=%RX16:%RX32\n", CPUMGetGuestCS(pVCpu), CPUMGetGuestEIP(pVCpu)));
1031#endif
1032
1033 /*
1034 * Spin till we get a forced action which returns anything but VINF_SUCCESS
1035 * or the REM suggests raw-mode execution.
1036 */
1037 *pfFFDone = false;
1038 uint32_t cLoops = 0;
1039 int rc = VINF_SUCCESS;
1040 for (;;)
1041 {
1042 /*
1043 * Execute REM.
1044 */
1045 if (RT_LIKELY(emR3IsExecutionAllowed(pVM, pVCpu)))
1046 {
1047 STAM_PROFILE_START(&pVCpu->em.s.StatREMExec, c);
1048 rc = VBOXSTRICTRC_TODO(IEMExecLots(pVCpu, 8192 /*cMaxInstructions*/, 4095 /*cPollRate*/, NULL /*pcInstructions*/));
1049 STAM_PROFILE_STOP(&pVCpu->em.s.StatREMExec, c);
1050 }
1051 else
1052 {
1053 /* Give up this time slice; virtual time continues */
1054 STAM_REL_PROFILE_ADV_START(&pVCpu->em.s.StatCapped, u);
1055 RTThreadSleep(5);
1056 STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatCapped, u);
1057 rc = VINF_SUCCESS;
1058 }
1059
1060 /*
1061 * Deal with high priority post execution FFs before doing anything
1062 * else. Sync back the state and leave the lock to be on the safe side.
1063 */
1064 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HIGH_PRIORITY_POST_MASK)
1065 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HIGH_PRIORITY_POST_MASK))
1066 rc = VBOXSTRICTRC_TODO(emR3HighPriorityPostForcedActions(pVM, pVCpu, rc));
1067
1068 /*
1069 * Process the returned status code.
1070 */
1071 if (rc != VINF_SUCCESS)
1072 {
1073 if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
1074 break;
1075 if (rc != VINF_REM_INTERRUPED_FF)
1076 {
1077 /* Try dodge unimplemented IEM trouble by reschduling. */
1078 if ( rc == VERR_IEM_ASPECT_NOT_IMPLEMENTED
1079 || rc == VERR_IEM_INSTR_NOT_IMPLEMENTED)
1080 {
1081 EMSTATE enmNewState = emR3Reschedule(pVM, pVCpu);
1082 if (enmNewState != EMSTATE_REM && enmNewState != EMSTATE_IEM_THEN_REM)
1083 {
1084 rc = VINF_EM_RESCHEDULE;
1085 break;
1086 }
1087 }
1088
1089 /*
1090 * Anything which is not known to us means an internal error
1091 * and the termination of the VM!
1092 */
1093 AssertMsg(rc == VERR_REM_TOO_MANY_TRAPS, ("Unknown GC return code: %Rra\n", rc));
1094 break;
1095 }
1096 }
1097
1098
1099 /*
1100 * Check and execute forced actions.
1101 *
1102 * Sync back the VM state and leave the lock before calling any of
1103 * these, you never know what's going to happen here.
1104 */
1105#ifdef VBOX_HIGH_RES_TIMERS_HACK
1106 TMTimerPollVoid(pVM, pVCpu);
1107#endif
1108 AssertCompile(VMCPU_FF_ALL_REM_MASK & VMCPU_FF_TIMER);
1109 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_ALL_REM_MASK)
1110 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_ALL_REM_MASK) )
1111 {
1112 STAM_REL_PROFILE_ADV_SUSPEND(&pVCpu->em.s.StatREMTotal, a);
1113 rc = emR3ForcedActions(pVM, pVCpu, rc);
1114 VBOXVMM_EM_FF_ALL_RET(pVCpu, rc);
1115 STAM_REL_PROFILE_ADV_RESUME(&pVCpu->em.s.StatREMTotal, a);
1116 if ( rc != VINF_SUCCESS
1117 && rc != VINF_EM_RESCHEDULE_REM)
1118 {
1119 *pfFFDone = true;
1120 break;
1121 }
1122 }
1123
1124 /*
1125 * Have to check if we can get back to fast execution mode every so often.
1126 */
1127 if (!(++cLoops & 7))
1128 {
1129 EMSTATE enmCheck = emR3Reschedule(pVM, pVCpu);
1130 if ( enmCheck != EMSTATE_REM
1131 && enmCheck != EMSTATE_IEM_THEN_REM)
1132 return VINF_EM_RESCHEDULE;
1133 }
1134
1135 } /* The Inner Loop, recompiled execution mode version. */
1136
1137 STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatREMTotal, a);
1138 return rc;
1139}
1140
1141
1142#ifdef DEBUG
1143
1144int emR3SingleStepExecRem(PVM pVM, PVMCPU pVCpu, uint32_t cIterations)
1145{
1146 EMSTATE enmOldState = pVCpu->em.s.enmState;
1147
1148 pVCpu->em.s.enmState = EMSTATE_DEBUG_GUEST_REM;
1149
1150 Log(("Single step BEGIN:\n"));
1151 for (uint32_t i = 0; i < cIterations; i++)
1152 {
1153 DBGFR3PrgStep(pVCpu);
1154 DBGFR3_DISAS_INSTR_CUR_LOG(pVCpu, "RSS");
1155 emR3RemStep(pVM, pVCpu);
1156 if (emR3Reschedule(pVM, pVCpu) != EMSTATE_REM)
1157 break;
1158 }
1159 Log(("Single step END:\n"));
1160 CPUMSetGuestEFlags(pVCpu, CPUMGetGuestEFlags(pVCpu) & ~X86_EFL_TF);
1161 pVCpu->em.s.enmState = enmOldState;
1162 return VINF_EM_RESCHEDULE;
1163}
1164
1165#endif /* DEBUG */
1166
1167
1168/**
1169 * Try execute the problematic code in IEM first, then fall back on REM if there
1170 * is too much of it or if IEM doesn't implement something.
1171 *
1172 * @returns Strict VBox status code from IEMExecLots.
1173 * @param pVM The cross context VM structure.
1174 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
1175 * @param pfFFDone Force flags done indicator.
1176 *
1177 * @thread EMT(pVCpu)
1178 */
1179static VBOXSTRICTRC emR3ExecuteIemThenRem(PVM pVM, PVMCPU pVCpu, bool *pfFFDone)
1180{
1181 LogFlow(("emR3ExecuteIemThenRem: %04x:%RGv\n", CPUMGetGuestCS(pVCpu), CPUMGetGuestRIP(pVCpu)));
1182 *pfFFDone = false;
1183
1184 /*
1185 * Execute in IEM for a while.
1186 */
1187 while (pVCpu->em.s.cIemThenRemInstructions < 1024)
1188 {
1189 uint32_t cInstructions;
1190 VBOXSTRICTRC rcStrict = IEMExecLots(pVCpu, 1024 - pVCpu->em.s.cIemThenRemInstructions /*cMaxInstructions*/,
1191 UINT32_MAX/2 /*cPollRate*/, &cInstructions);
1192 pVCpu->em.s.cIemThenRemInstructions += cInstructions;
1193 if (rcStrict != VINF_SUCCESS)
1194 {
1195 if ( rcStrict == VERR_IEM_ASPECT_NOT_IMPLEMENTED
1196 || rcStrict == VERR_IEM_INSTR_NOT_IMPLEMENTED)
1197 break;
1198
1199 Log(("emR3ExecuteIemThenRem: returns %Rrc after %u instructions\n",
1200 VBOXSTRICTRC_VAL(rcStrict), pVCpu->em.s.cIemThenRemInstructions));
1201 return rcStrict;
1202 }
1203
1204 EMSTATE enmNewState = emR3Reschedule(pVM, pVCpu);
1205 if (enmNewState != EMSTATE_REM && enmNewState != EMSTATE_IEM_THEN_REM)
1206 {
1207 LogFlow(("emR3ExecuteIemThenRem: -> %d (%s) after %u instructions\n",
1208 enmNewState, emR3GetStateName(enmNewState), pVCpu->em.s.cIemThenRemInstructions));
1209 pVCpu->em.s.enmPrevState = pVCpu->em.s.enmState;
1210 pVCpu->em.s.enmState = enmNewState;
1211 return VINF_SUCCESS;
1212 }
1213
1214 /*
1215 * Check for pending actions.
1216 */
1217 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_ALL_REM_MASK)
1218 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_ALL_REM_MASK & ~VMCPU_FF_UNHALT))
1219 return VINF_SUCCESS;
1220 }
1221
1222 /*
1223 * Switch to REM.
1224 */
1225 Log(("emR3ExecuteIemThenRem: -> EMSTATE_REM (after %u instructions)\n", pVCpu->em.s.cIemThenRemInstructions));
1226 pVCpu->em.s.enmState = EMSTATE_REM;
1227 return VINF_SUCCESS;
1228}
1229
1230
1231/**
1232 * Decides whether to execute RAW, HWACC or REM.
1233 *
1234 * @returns new EM state
1235 * @param pVM The cross context VM structure.
1236 * @param pVCpu The cross context virtual CPU structure.
1237 */
1238EMSTATE emR3Reschedule(PVM pVM, PVMCPU pVCpu)
1239{
1240 /*
1241 * We stay in the wait for SIPI state unless explicitly told otherwise.
1242 */
1243 if (pVCpu->em.s.enmState == EMSTATE_WAIT_SIPI)
1244 return EMSTATE_WAIT_SIPI;
1245
1246 /*
1247 * Execute everything in IEM?
1248 */
1249 if (pVM->em.s.fIemExecutesAll)
1250 return EMSTATE_IEM;
1251
1252 /* !!! THIS MUST BE IN SYNC WITH remR3CanExecuteRaw !!! */
1253 /* !!! THIS MUST BE IN SYNC WITH remR3CanExecuteRaw !!! */
1254 /* !!! THIS MUST BE IN SYNC WITH remR3CanExecuteRaw !!! */
1255
1256 X86EFLAGS EFlags = pVCpu->cpum.GstCtx.eflags;
1257 if (!VM_IS_RAW_MODE_ENABLED(pVM))
1258 {
1259 if (VM_IS_HM_ENABLED(pVM))
1260 {
1261 if (HMCanExecuteGuest(pVM, pVCpu, &pVCpu->cpum.GstCtx))
1262 return EMSTATE_HM;
1263 }
1264 else if (NEMR3CanExecuteGuest(pVM, pVCpu))
1265 return EMSTATE_NEM;
1266
1267 /*
1268 * Note! Raw mode and hw accelerated mode are incompatible. The latter
1269 * turns off monitoring features essential for raw mode!
1270 */
1271 return EMSTATE_IEM_THEN_REM;
1272 }
1273
1274 /*
1275 * Standard raw-mode:
1276 *
1277 * Here we only support 16 & 32 bits protected mode ring 3 code that has no IO privileges
1278 * or 32 bits protected mode ring 0 code
1279 *
1280 * The tests are ordered by the likelihood of being true during normal execution.
1281 */
1282 if (EFlags.u32 & (X86_EFL_TF /* | HF_INHIBIT_IRQ_MASK*/))
1283 {
1284 Log2(("raw mode refused: EFlags=%#x\n", EFlags.u32));
1285 return EMSTATE_REM;
1286 }
1287
1288# ifndef VBOX_RAW_V86
1289 if (EFlags.u32 & X86_EFL_VM) {
1290 Log2(("raw mode refused: VM_MASK\n"));
1291 return EMSTATE_REM;
1292 }
1293# endif
1294
1295 /** @todo check up the X86_CR0_AM flag in respect to raw mode!!! We're probably not emulating it right! */
1296 uint32_t u32CR0 = pVCpu->cpum.GstCtx.cr0;
1297 if ((u32CR0 & (X86_CR0_PG | X86_CR0_PE)) != (X86_CR0_PG | X86_CR0_PE))
1298 {
1299 //Log2(("raw mode refused: %s%s%s\n", (u32CR0 & X86_CR0_PG) ? "" : " !PG", (u32CR0 & X86_CR0_PE) ? "" : " !PE", (u32CR0 & X86_CR0_AM) ? "" : " !AM"));
1300 return EMSTATE_REM;
1301 }
1302
1303 if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_PAE)
1304 {
1305 uint32_t u32Dummy, u32Features;
1306
1307 CPUMGetGuestCpuId(pVCpu, 1, 0, &u32Dummy, &u32Dummy, &u32Dummy, &u32Features);
1308 if (!(u32Features & X86_CPUID_FEATURE_EDX_PAE))
1309 return EMSTATE_REM;
1310 }
1311
1312 unsigned uSS = pVCpu->cpum.GstCtx.ss.Sel;
1313 if ( pVCpu->cpum.GstCtx.eflags.Bits.u1VM
1314 || (uSS & X86_SEL_RPL) == 3)
1315 {
1316 if (!(EFlags.u32 & X86_EFL_IF))
1317 {
1318 Log2(("raw mode refused: IF (RawR3)\n"));
1319 return EMSTATE_REM;
1320 }
1321
1322 if (!(u32CR0 & X86_CR0_WP))
1323 {
1324 Log2(("raw mode refused: CR0.WP + RawR0\n"));
1325 return EMSTATE_REM;
1326 }
1327 }
1328 else
1329 {
1330 /* Only ring 0 supervisor code. */
1331 if ((uSS & X86_SEL_RPL) != 0)
1332 {
1333 Log2(("raw r0 mode refused: CPL %d\n", uSS & X86_SEL_RPL));
1334 return EMSTATE_REM;
1335 }
1336
1337 // Let's start with pure 32 bits ring 0 code first
1338 /** @todo What's pure 32-bit mode? flat? */
1339 if ( !(pVCpu->cpum.GstCtx.ss.Attr.n.u1DefBig)
1340 || !(pVCpu->cpum.GstCtx.cs.Attr.n.u1DefBig))
1341 {
1342 Log2(("raw r0 mode refused: SS/CS not 32bit\n"));
1343 return EMSTATE_REM;
1344 }
1345
1346 /* Write protection must be turned on, or else the guest can overwrite our hypervisor code and data. */
1347 if (!(u32CR0 & X86_CR0_WP))
1348 {
1349 Log2(("raw r0 mode refused: CR0.WP=0!\n"));
1350 return EMSTATE_REM;
1351 }
1352
1353# if !defined(VBOX_ALLOW_IF0) && !defined(VBOX_RUN_INTERRUPT_GATE_HANDLERS)
1354 if (!(EFlags.u32 & X86_EFL_IF))
1355 {
1356 ////Log2(("R0: IF=0 VIF=%d %08X\n", eip, pVMeflags));
1357 //Log2(("RR0: Interrupts turned off; fall back to emulation\n"));
1358 return EMSTATE_REM;
1359 }
1360# endif
1361
1362# ifndef VBOX_WITH_RAW_RING1
1363 /** @todo still necessary??? */
1364 if (EFlags.Bits.u2IOPL != 0)
1365 {
1366 Log2(("raw r0 mode refused: IOPL %d\n", EFlags.Bits.u2IOPL));
1367 return EMSTATE_REM;
1368 }
1369# endif
1370 }
1371
1372 /*
1373 * Stale hidden selectors means raw-mode is unsafe (being very careful).
1374 */
1375 if (pVCpu->cpum.GstCtx.cs.fFlags & CPUMSELREG_FLAGS_STALE)
1376 {
1377 Log2(("raw mode refused: stale CS\n"));
1378 return EMSTATE_REM;
1379 }
1380 if (pVCpu->cpum.GstCtx.ss.fFlags & CPUMSELREG_FLAGS_STALE)
1381 {
1382 Log2(("raw mode refused: stale SS\n"));
1383 return EMSTATE_REM;
1384 }
1385 if (pVCpu->cpum.GstCtx.ds.fFlags & CPUMSELREG_FLAGS_STALE)
1386 {
1387 Log2(("raw mode refused: stale DS\n"));
1388 return EMSTATE_REM;
1389 }
1390 if (pVCpu->cpum.GstCtx.es.fFlags & CPUMSELREG_FLAGS_STALE)
1391 {
1392 Log2(("raw mode refused: stale ES\n"));
1393 return EMSTATE_REM;
1394 }
1395 if (pVCpu->cpum.GstCtx.fs.fFlags & CPUMSELREG_FLAGS_STALE)
1396 {
1397 Log2(("raw mode refused: stale FS\n"));
1398 return EMSTATE_REM;
1399 }
1400 if (pVCpu->cpum.GstCtx.gs.fFlags & CPUMSELREG_FLAGS_STALE)
1401 {
1402 Log2(("raw mode refused: stale GS\n"));
1403 return EMSTATE_REM;
1404 }
1405
1406# ifdef VBOX_WITH_SAFE_STR
1407 if (pVCpu->cpum.GstCtx.tr.Sel == 0)
1408 {
1409 Log(("Raw mode refused -> TR=0\n"));
1410 return EMSTATE_REM;
1411 }
1412# endif
1413
1414 /*Assert(PGMPhysIsA20Enabled(pVCpu));*/
1415 return EMSTATE_RAW;
1416}
1417
1418
1419/**
1420 * Executes all high priority post execution force actions.
1421 *
1422 * @returns Strict VBox status code. Typically @a rc, but may be upgraded to
1423 * fatal error status code.
1424 *
1425 * @param pVM The cross context VM structure.
1426 * @param pVCpu The cross context virtual CPU structure.
1427 * @param rc The current strict VBox status code rc.
1428 */
1429VBOXSTRICTRC emR3HighPriorityPostForcedActions(PVM pVM, PVMCPU pVCpu, VBOXSTRICTRC rc)
1430{
1431 VBOXVMM_EM_FF_HIGH(pVCpu, pVM->fGlobalForcedActions, pVCpu->fLocalForcedActions, VBOXSTRICTRC_VAL(rc));
1432
1433 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PDM_CRITSECT))
1434 PDMCritSectBothFF(pVCpu);
1435
1436 /* Update CR3 (Nested Paging case for HM). */
1437 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
1438 {
1439 CPUM_IMPORT_EXTRN_RCSTRICT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_EFER, rc);
1440 int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
1441 if (RT_FAILURE(rc2))
1442 return rc2;
1443 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
1444 }
1445
1446 /* Update PAE PDPEs. This must be done *after* PGMUpdateCR3() and used only by the Nested Paging case for HM. */
1447 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
1448 {
1449 CPUM_IMPORT_EXTRN_RCSTRICT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_EFER, rc);
1450 if (CPUMIsGuestInPAEMode(pVCpu))
1451 {
1452 PX86PDPE pPdpes = HMGetPaePdpes(pVCpu);
1453 AssertPtr(pPdpes);
1454
1455 PGMGstUpdatePaePdpes(pVCpu, pPdpes);
1456 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
1457 }
1458 else
1459 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES);
1460 }
1461
1462 /* IEM has pending work (typically memory write after INS instruction). */
1463 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_IEM))
1464 rc = IEMR3ProcessForceFlag(pVM, pVCpu, rc);
1465
1466 /* IOM has pending work (comitting an I/O or MMIO write). */
1467 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_IOM))
1468 {
1469 rc = IOMR3ProcessForceFlag(pVM, pVCpu, rc);
1470 if (pVCpu->em.s.idxContinueExitRec >= RT_ELEMENTS(pVCpu->em.s.aExitRecords))
1471 { /* half likely, or at least it's a line shorter. */ }
1472 else if (rc == VINF_SUCCESS)
1473 rc = VINF_EM_RESUME_R3_HISTORY_EXEC;
1474 else
1475 pVCpu->em.s.idxContinueExitRec = UINT16_MAX;
1476 }
1477
1478 if (VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY))
1479 {
1480 if ( rc > VINF_EM_NO_MEMORY
1481 && rc <= VINF_EM_LAST)
1482 rc = VINF_EM_NO_MEMORY;
1483 }
1484
1485 return rc;
1486}
1487
1488
1489/**
1490 * Helper for emR3ForcedActions() for VMX external interrupt VM-exit.
1491 *
1492 * @returns VBox status code.
1493 * @retval VINF_NO_CHANGE if the VMX external interrupt intercept was not active.
1494 * @param pVCpu The cross context virtual CPU structure.
1495 */
1496static int emR3VmxNstGstIntrIntercept(PVMCPU pVCpu)
1497{
1498#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1499 /* Handle the "external interrupt" VM-exit intercept. */
1500 if ( CPUMIsGuestVmxPinCtlsSet(&pVCpu->cpum.GstCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
1501 && !CPUMIsGuestVmxExitCtlsSet(&pVCpu->cpum.GstCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
1502 {
1503 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */);
1504 AssertMsg( rcStrict != VINF_PGM_CHANGE_MODE
1505 && rcStrict != VINF_VMX_VMEXIT
1506 && rcStrict != VINF_NO_CHANGE, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
1507 if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)
1508 return VBOXSTRICTRC_TODO(rcStrict);
1509 }
1510#else
1511 RT_NOREF(pVCpu);
1512#endif
1513 return VINF_NO_CHANGE;
1514}
1515
1516
1517/**
1518 * Helper for emR3ForcedActions() for SVM interrupt intercept.
1519 *
1520 * @returns VBox status code.
1521 * @retval VINF_NO_CHANGE if the SVM external interrupt intercept was not active.
1522 * @param pVCpu The cross context virtual CPU structure.
1523 */
1524static int emR3SvmNstGstIntrIntercept(PVMCPU pVCpu)
1525{
1526#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
1527 /* Handle the physical interrupt intercept (can be masked by the nested hypervisor). */
1528 if (CPUMIsGuestSvmCtrlInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, SVM_CTRL_INTERCEPT_INTR))
1529 {
1530 CPUM_ASSERT_NOT_EXTRN(pVCpu, IEM_CPUMCTX_EXTRN_SVM_VMEXIT_MASK);
1531 VBOXSTRICTRC rcStrict = IEMExecSvmVmexit(pVCpu, SVM_EXIT_INTR, 0, 0);
1532 if (RT_SUCCESS(rcStrict))
1533 {
1534 AssertMsg( rcStrict != VINF_PGM_CHANGE_MODE
1535 && rcStrict != VINF_SVM_VMEXIT
1536 && rcStrict != VINF_NO_CHANGE, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
1537 return VBOXSTRICTRC_VAL(rcStrict);
1538 }
1539
1540 AssertMsgFailed(("INTR #VMEXIT failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
1541 return VINF_EM_TRIPLE_FAULT;
1542 }
1543#else
1544 NOREF(pVCpu);
1545#endif
1546 return VINF_NO_CHANGE;
1547}
1548
1549
1550/**
1551 * Helper for emR3ForcedActions() for SVM virtual interrupt intercept.
1552 *
1553 * @returns VBox status code.
1554 * @retval VINF_NO_CHANGE if the SVM virtual interrupt intercept was not active.
1555 * @param pVCpu The cross context virtual CPU structure.
1556 */
1557static int emR3SvmNstGstVirtIntrIntercept(PVMCPU pVCpu)
1558{
1559#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
1560 if (CPUMIsGuestSvmCtrlInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, SVM_CTRL_INTERCEPT_VINTR))
1561 {
1562 CPUM_ASSERT_NOT_EXTRN(pVCpu, IEM_CPUMCTX_EXTRN_SVM_VMEXIT_MASK);
1563 VBOXSTRICTRC rcStrict = IEMExecSvmVmexit(pVCpu, SVM_EXIT_VINTR, 0, 0);
1564 if (RT_SUCCESS(rcStrict))
1565 {
1566 Assert(rcStrict != VINF_PGM_CHANGE_MODE);
1567 Assert(rcStrict != VINF_SVM_VMEXIT);
1568 return VBOXSTRICTRC_VAL(rcStrict);
1569 }
1570 AssertMsgFailed(("VINTR #VMEXIT failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
1571 return VINF_EM_TRIPLE_FAULT;
1572 }
1573#else
1574 NOREF(pVCpu);
1575#endif
1576 return VINF_NO_CHANGE;
1577}
1578
1579
1580/**
1581 * Executes all pending forced actions.
1582 *
1583 * Forced actions can cause execution delays and execution
1584 * rescheduling. The first we deal with using action priority, so
1585 * that for instance pending timers aren't scheduled and ran until
1586 * right before execution. The rescheduling we deal with using
1587 * return codes. The same goes for VM termination, only in that case
1588 * we exit everything.
1589 *
1590 * @returns VBox status code of equal or greater importance/severity than rc.
1591 * The most important ones are: VINF_EM_RESCHEDULE,
1592 * VINF_EM_SUSPEND, VINF_EM_RESET and VINF_EM_TERMINATE.
1593 *
1594 * @param pVM The cross context VM structure.
1595 * @param pVCpu The cross context virtual CPU structure.
1596 * @param rc The current rc.
1597 *
1598 */
1599int emR3ForcedActions(PVM pVM, PVMCPU pVCpu, int rc)
1600{
1601 STAM_REL_PROFILE_START(&pVCpu->em.s.StatForcedActions, a);
1602#ifdef VBOX_STRICT
1603 int rcIrq = VINF_SUCCESS;
1604#endif
1605 int rc2;
1606#define UPDATE_RC() \
1607 do { \
1608 AssertMsg(rc2 <= 0 || (rc2 >= VINF_EM_FIRST && rc2 <= VINF_EM_LAST), ("Invalid FF return code: %Rra\n", rc2)); \
1609 if (rc2 == VINF_SUCCESS || rc < VINF_SUCCESS) \
1610 break; \
1611 if (!rc || rc2 < rc) \
1612 rc = rc2; \
1613 } while (0)
1614 VBOXVMM_EM_FF_ALL(pVCpu, pVM->fGlobalForcedActions, pVCpu->fLocalForcedActions, rc);
1615
1616 /*
1617 * Post execution chunk first.
1618 */
1619 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_NORMAL_PRIORITY_POST_MASK)
1620 || (VMCPU_FF_NORMAL_PRIORITY_POST_MASK && VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_NORMAL_PRIORITY_POST_MASK)) )
1621 {
1622 /*
1623 * EMT Rendezvous (must be serviced before termination).
1624 */
1625 if (VM_FF_IS_SET(pVM, VM_FF_EMT_RENDEZVOUS))
1626 {
1627 CPUM_IMPORT_EXTRN_RCSTRICT(pVCpu, ~CPUMCTX_EXTRN_KEEPER_MASK, rc);
1628 rc2 = VMMR3EmtRendezvousFF(pVM, pVCpu);
1629 UPDATE_RC();
1630 /** @todo HACK ALERT! The following test is to make sure EM+TM
1631 * thinks the VM is stopped/reset before the next VM state change
1632 * is made. We need a better solution for this, or at least make it
1633 * possible to do: (rc >= VINF_EM_FIRST && rc <=
1634 * VINF_EM_SUSPEND). */
1635 if (RT_UNLIKELY(rc == VINF_EM_SUSPEND || rc == VINF_EM_RESET || rc == VINF_EM_OFF))
1636 {
1637 Log2(("emR3ForcedActions: returns %Rrc\n", rc));
1638 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
1639 return rc;
1640 }
1641 }
1642
1643 /*
1644 * State change request (cleared by vmR3SetStateLocked).
1645 */
1646 if (VM_FF_IS_SET(pVM, VM_FF_CHECK_VM_STATE))
1647 {
1648 VMSTATE enmState = VMR3GetState(pVM);
1649 switch (enmState)
1650 {
1651 case VMSTATE_FATAL_ERROR:
1652 case VMSTATE_FATAL_ERROR_LS:
1653 case VMSTATE_GURU_MEDITATION:
1654 case VMSTATE_GURU_MEDITATION_LS:
1655 Log2(("emR3ForcedActions: %s -> VINF_EM_SUSPEND\n", VMGetStateName(enmState) ));
1656 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
1657 return VINF_EM_SUSPEND;
1658
1659 case VMSTATE_DESTROYING:
1660 Log2(("emR3ForcedActions: %s -> VINF_EM_TERMINATE\n", VMGetStateName(enmState) ));
1661 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
1662 return VINF_EM_TERMINATE;
1663
1664 default:
1665 AssertMsgFailed(("%s\n", VMGetStateName(enmState)));
1666 }
1667 }
1668
1669 /*
1670 * Debugger Facility polling.
1671 */
1672 if ( VM_FF_IS_SET(pVM, VM_FF_DBGF)
1673 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_DBGF) )
1674 {
1675 CPUM_IMPORT_EXTRN_RCSTRICT(pVCpu, ~CPUMCTX_EXTRN_KEEPER_MASK, rc);
1676 rc2 = DBGFR3VMMForcedAction(pVM, pVCpu);
1677 UPDATE_RC();
1678 }
1679
1680 /*
1681 * Postponed reset request.
1682 */
1683 if (VM_FF_TEST_AND_CLEAR(pVM, VM_FF_RESET))
1684 {
1685 CPUM_IMPORT_EXTRN_RCSTRICT(pVCpu, ~CPUMCTX_EXTRN_KEEPER_MASK, rc);
1686 rc2 = VBOXSTRICTRC_TODO(VMR3ResetFF(pVM));
1687 UPDATE_RC();
1688 }
1689
1690 /*
1691 * Out of memory? Putting this after CSAM as it may in theory cause us to run out of memory.
1692 */
1693 if (VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY))
1694 {
1695 rc2 = PGMR3PhysAllocateHandyPages(pVM);
1696 UPDATE_RC();
1697 if (rc == VINF_EM_NO_MEMORY)
1698 return rc;
1699 }
1700
1701 /* check that we got them all */
1702 AssertCompile(VM_FF_NORMAL_PRIORITY_POST_MASK == (VM_FF_CHECK_VM_STATE | VM_FF_DBGF | VM_FF_RESET | VM_FF_PGM_NO_MEMORY | VM_FF_EMT_RENDEZVOUS));
1703 AssertCompile(VMCPU_FF_NORMAL_PRIORITY_POST_MASK == VMCPU_FF_DBGF);
1704 }
1705
1706 /*
1707 * Normal priority then.
1708 * (Executed in no particular order.)
1709 */
1710 if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_NORMAL_PRIORITY_MASK, VM_FF_PGM_NO_MEMORY))
1711 {
1712 /*
1713 * PDM Queues are pending.
1714 */
1715 if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_PDM_QUEUES, VM_FF_PGM_NO_MEMORY))
1716 PDMR3QueueFlushAll(pVM);
1717
1718 /*
1719 * PDM DMA transfers are pending.
1720 */
1721 if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_PDM_DMA, VM_FF_PGM_NO_MEMORY))
1722 PDMR3DmaRun(pVM);
1723
1724 /*
1725 * EMT Rendezvous (make sure they are handled before the requests).
1726 */
1727 if (VM_FF_IS_SET(pVM, VM_FF_EMT_RENDEZVOUS))
1728 {
1729 CPUM_IMPORT_EXTRN_RCSTRICT(pVCpu, ~CPUMCTX_EXTRN_KEEPER_MASK, rc);
1730 rc2 = VMMR3EmtRendezvousFF(pVM, pVCpu);
1731 UPDATE_RC();
1732 /** @todo HACK ALERT! The following test is to make sure EM+TM
1733 * thinks the VM is stopped/reset before the next VM state change
1734 * is made. We need a better solution for this, or at least make it
1735 * possible to do: (rc >= VINF_EM_FIRST && rc <=
1736 * VINF_EM_SUSPEND). */
1737 if (RT_UNLIKELY(rc == VINF_EM_SUSPEND || rc == VINF_EM_RESET || rc == VINF_EM_OFF))
1738 {
1739 Log2(("emR3ForcedActions: returns %Rrc\n", rc));
1740 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
1741 return rc;
1742 }
1743 }
1744
1745 /*
1746 * Requests from other threads.
1747 */
1748 if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_REQUEST, VM_FF_PGM_NO_MEMORY))
1749 {
1750 CPUM_IMPORT_EXTRN_RCSTRICT(pVCpu, ~CPUMCTX_EXTRN_KEEPER_MASK, rc);
1751 rc2 = VMR3ReqProcessU(pVM->pUVM, VMCPUID_ANY, false /*fPriorityOnly*/);
1752 if (rc2 == VINF_EM_OFF || rc2 == VINF_EM_TERMINATE) /** @todo this shouldn't be necessary */
1753 {
1754 Log2(("emR3ForcedActions: returns %Rrc\n", rc2));
1755 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
1756 return rc2;
1757 }
1758 UPDATE_RC();
1759 /** @todo HACK ALERT! The following test is to make sure EM+TM
1760 * thinks the VM is stopped/reset before the next VM state change
1761 * is made. We need a better solution for this, or at least make it
1762 * possible to do: (rc >= VINF_EM_FIRST && rc <=
1763 * VINF_EM_SUSPEND). */
1764 if (RT_UNLIKELY(rc == VINF_EM_SUSPEND || rc == VINF_EM_RESET || rc == VINF_EM_OFF))
1765 {
1766 Log2(("emR3ForcedActions: returns %Rrc\n", rc));
1767 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
1768 return rc;
1769 }
1770 }
1771
1772 /* check that we got them all */
1773 AssertCompile(VM_FF_NORMAL_PRIORITY_MASK == (VM_FF_REQUEST | VM_FF_PDM_QUEUES | VM_FF_PDM_DMA | VM_FF_EMT_RENDEZVOUS));
1774 }
1775
1776 /*
1777 * Normal priority then. (per-VCPU)
1778 * (Executed in no particular order.)
1779 */
1780 if ( !VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)
1781 && VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_NORMAL_PRIORITY_MASK))
1782 {
1783 /*
1784 * Requests from other threads.
1785 */
1786 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
1787 {
1788 CPUM_IMPORT_EXTRN_RCSTRICT(pVCpu, ~CPUMCTX_EXTRN_KEEPER_MASK, rc);
1789 rc2 = VMR3ReqProcessU(pVM->pUVM, pVCpu->idCpu, false /*fPriorityOnly*/);
1790 if (rc2 == VINF_EM_OFF || rc2 == VINF_EM_TERMINATE || rc2 == VINF_EM_RESET)
1791 {
1792 Log2(("emR3ForcedActions: returns %Rrc\n", rc2));
1793 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
1794 return rc2;
1795 }
1796 UPDATE_RC();
1797 /** @todo HACK ALERT! The following test is to make sure EM+TM
1798 * thinks the VM is stopped/reset before the next VM state change
1799 * is made. We need a better solution for this, or at least make it
1800 * possible to do: (rc >= VINF_EM_FIRST && rc <=
1801 * VINF_EM_SUSPEND). */
1802 if (RT_UNLIKELY(rc == VINF_EM_SUSPEND || rc == VINF_EM_RESET || rc == VINF_EM_OFF))
1803 {
1804 Log2(("emR3ForcedActions: returns %Rrc\n", rc));
1805 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
1806 return rc;
1807 }
1808 }
1809
1810 /* check that we got them all */
1811 Assert(!(VMCPU_FF_NORMAL_PRIORITY_MASK & ~VMCPU_FF_REQUEST));
1812 }
1813
1814 /*
1815 * High priority pre execution chunk last.
1816 * (Executed in ascending priority order.)
1817 */
1818 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HIGH_PRIORITY_PRE_MASK)
1819 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HIGH_PRIORITY_PRE_MASK))
1820 {
1821 /*
1822 * Timers before interrupts.
1823 */
1824 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_TIMER)
1825 && !VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY))
1826 TMR3TimerQueuesDo(pVM);
1827
1828 /*
1829 * Pick up asynchronously posted interrupts into the APIC.
1830 */
1831 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
1832 APICUpdatePendingInterrupts(pVCpu);
1833
1834 /*
1835 * The instruction following an emulated STI should *always* be executed!
1836 *
1837 * Note! We intentionally don't clear VM_FF_INHIBIT_INTERRUPTS here if
1838 * the eip is the same as the inhibited instr address. Before we
1839 * are able to execute this instruction in raw mode (iret to
1840 * guest code) an external interrupt might force a world switch
1841 * again. Possibly allowing a guest interrupt to be dispatched
1842 * in the process. This could break the guest. Sounds very
1843 * unlikely, but such timing sensitive problem are not as rare as
1844 * you might think.
1845 */
1846 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
1847 && !VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY))
1848 {
1849 CPUM_ASSERT_NOT_EXTRN(pVCpu, CPUMCTX_EXTRN_RIP);
1850 if (CPUMGetGuestRIP(pVCpu) != EMGetInhibitInterruptsPC(pVCpu))
1851 {
1852 Log(("Clearing VMCPU_FF_INHIBIT_INTERRUPTS at %RGv - successor %RGv\n", (RTGCPTR)CPUMGetGuestRIP(pVCpu), EMGetInhibitInterruptsPC(pVCpu)));
1853 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
1854 }
1855 else
1856 Log(("Leaving VMCPU_FF_INHIBIT_INTERRUPTS set at %RGv\n", (RTGCPTR)CPUMGetGuestRIP(pVCpu)));
1857 }
1858
1859 /** @todo SMIs. If we implement SMIs, this is where they will have to be
1860 * delivered. */
1861
1862#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1863 if (VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE | VMCPU_FF_VMX_MTF | VMCPU_FF_VMX_PREEMPT_TIMER))
1864 {
1865 /*
1866 * VMX Nested-guest APIC-write pending (can cause VM-exits).
1867 * Takes priority over even SMI and INIT signals.
1868 * See Intel spec. 29.4.3.2 "APIC-Write Emulation".
1869 */
1870 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE))
1871 {
1872 rc2 = VBOXSTRICTRC_VAL(IEMExecVmxVmexitApicWrite(pVCpu));
1873 if (rc2 != VINF_VMX_INTERCEPT_NOT_ACTIVE)
1874 UPDATE_RC();
1875 }
1876
1877 /*
1878 * VMX Nested-guest monitor-trap flag (MTF) VM-exit.
1879 * Takes priority over "Traps on the previous instruction".
1880 * See Intel spec. 6.9 "Priority Among Simultaneous Exceptions And Interrupts".
1881 */
1882 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_MTF))
1883 {
1884 rc2 = VBOXSTRICTRC_VAL(IEMExecVmxVmexit(pVCpu, VMX_EXIT_MTF, 0 /* uExitQual */));
1885 Assert(rc2 != VINF_VMX_INTERCEPT_NOT_ACTIVE);
1886 UPDATE_RC();
1887 }
1888
1889 /*
1890 * VMX Nested-guest preemption timer VM-exit.
1891 * Takes priority over NMI-window VM-exits.
1892 */
1893 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_PREEMPT_TIMER))
1894 {
1895 rc2 = VBOXSTRICTRC_VAL(IEMExecVmxVmexitPreemptTimer(pVCpu));
1896 Assert(rc2 != VINF_VMX_INTERCEPT_NOT_ACTIVE);
1897 UPDATE_RC();
1898 }
1899 }
1900#endif
1901
1902 /*
1903 * Guest event injection.
1904 */
1905 bool fWakeupPending = false;
1906 if ( !VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)
1907 && (!rc || rc >= VINF_EM_RESCHEDULE_HM)
1908 && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS) /* Interrupt shadows block both NMIs and interrupts. */
1909 && !TRPMHasTrap(pVCpu)) /* An event could already be scheduled for dispatching. */
1910 {
1911 bool fInVmxNonRootMode;
1912 bool fInSvmHwvirtMode;
1913 bool const fInNestedGuest = CPUMIsGuestInNestedHwvirtMode(&pVCpu->cpum.GstCtx);
1914 if (fInNestedGuest)
1915 {
1916 fInVmxNonRootMode = CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx);
1917 fInSvmHwvirtMode = CPUMIsGuestInSvmNestedHwVirtMode(&pVCpu->cpum.GstCtx);
1918 }
1919 else
1920 {
1921 fInVmxNonRootMode = false;
1922 fInSvmHwvirtMode = false;
1923 }
1924
1925 bool fGif = CPUMGetGuestGif(&pVCpu->cpum.GstCtx);
1926 if (fGif)
1927 {
1928#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1929 /*
1930 * VMX NMI-window VM-exit.
1931 * Takes priority over non-maskable interrupts (NMIs).
1932 * Interrupt shadows block NMI-window VM-exits.
1933 * Any event that is already in TRPM (e.g. injected during VM-entry) takes priority.
1934 *
1935 * See Intel spec. 25.2 "Other Causes Of VM Exits".
1936 * See Intel spec. 26.7.6 "NMI-Window Exiting".
1937 */
1938 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_NMI_WINDOW)
1939 && !CPUMIsGuestVmxVirtNmiBlocking(&pVCpu->cpum.GstCtx))
1940 {
1941 Assert(CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_NMI_WINDOW_EXIT));
1942 Assert(CPUMIsGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx));
1943 rc2 = VBOXSTRICTRC_VAL(IEMExecVmxVmexit(pVCpu, VMX_EXIT_NMI_WINDOW, 0 /* uExitQual */));
1944 AssertMsg( rc2 != VINF_VMX_INTERCEPT_NOT_ACTIVE
1945 && rc2 != VINF_PGM_CHANGE_MODE
1946 && rc2 != VINF_VMX_VMEXIT
1947 && rc2 != VINF_NO_CHANGE, ("%Rrc\n", rc2));
1948 UPDATE_RC();
1949 }
1950 else
1951#endif
1952 /*
1953 * NMIs (take priority over external interrupts).
1954 */
1955 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI)
1956 && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS))
1957 {
1958#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1959 if ( fInVmxNonRootMode
1960 && CPUMIsGuestVmxPinCtlsSet(&pVCpu->cpum.GstCtx, VMX_PIN_CTLS_NMI_EXIT))
1961 {
1962 rc2 = VBOXSTRICTRC_VAL(IEMExecVmxVmexitXcptNmi(pVCpu));
1963 Assert(rc2 != VINF_VMX_INTERCEPT_NOT_ACTIVE);
1964 UPDATE_RC();
1965 }
1966 else
1967#endif
1968#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
1969 if ( fInSvmHwvirtMode
1970 && CPUMIsGuestSvmCtrlInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, SVM_CTRL_INTERCEPT_NMI))
1971 {
1972 rc2 = VBOXSTRICTRC_VAL(IEMExecSvmVmexit(pVCpu, SVM_EXIT_NMI, 0 /* uExitInfo1 */, 0 /* uExitInfo2 */));
1973 AssertMsg( rc2 != VINF_PGM_CHANGE_MODE
1974 && rc2 != VINF_SVM_VMEXIT
1975 && rc2 != VINF_NO_CHANGE, ("%Rrc\n", rc2));
1976 UPDATE_RC();
1977 }
1978 else
1979#endif
1980 {
1981 rc2 = TRPMAssertTrap(pVCpu, X86_XCPT_NMI, TRPM_TRAP);
1982 if (rc2 == VINF_SUCCESS)
1983 {
1984 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
1985 fWakeupPending = true;
1986 if (pVM->em.s.fIemExecutesAll)
1987 rc2 = VINF_EM_RESCHEDULE;
1988 else
1989 {
1990 rc2 = HMR3IsActive(pVCpu) ? VINF_EM_RESCHEDULE_HM
1991 : VM_IS_NEM_ENABLED(pVM) ? VINF_EM_RESCHEDULE
1992 : VINF_EM_RESCHEDULE_REM;
1993 }
1994 }
1995 UPDATE_RC();
1996 }
1997 }
1998#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1999 /*
2000 * VMX Interrupt-window VM-exits.
2001 * Takes priority over external interrupts.
2002 */
2003 else if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_INT_WINDOW)
2004 && CPUMIsGuestVmxVirtIntrEnabled(&pVCpu->cpum.GstCtx))
2005 {
2006 Assert(CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT));
2007 Assert(CPUMIsGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx));
2008 rc2 = VBOXSTRICTRC_VAL(IEMExecVmxVmexit(pVCpu, VMX_EXIT_INT_WINDOW, 0 /* uExitQual */));
2009 AssertMsg( rc2 != VINF_VMX_INTERCEPT_NOT_ACTIVE
2010 && rc2 != VINF_PGM_CHANGE_MODE
2011 && rc2 != VINF_VMX_VMEXIT
2012 && rc2 != VINF_NO_CHANGE, ("%Rrc\n", rc2));
2013 UPDATE_RC();
2014 }
2015#endif
2016#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
2017 /** @todo NSTSVM: Handle this for SVM here too later not when an interrupt is
2018 * actually pending like we currently do. */
2019#endif
2020 /*
2021 * External interrupts.
2022 */
2023 else
2024 {
2025 /*
2026 * VMX: virtual interrupts takes priority over physical interrupts.
2027 * SVM: physical interrupts takes priority over virtual interrupts.
2028 */
2029 if ( fInVmxNonRootMode
2030 && VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST)
2031 && CPUMIsGuestVmxVirtIntrEnabled(&pVCpu->cpum.GstCtx))
2032 {
2033 /** @todo NSTVMX: virtual-interrupt delivery. */
2034 rc2 = VINF_SUCCESS;
2035 }
2036 else if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
2037 && CPUMIsGuestPhysIntrEnabled(pVCpu))
2038 {
2039 Assert(pVCpu->em.s.enmState != EMSTATE_WAIT_SIPI);
2040 if (fInVmxNonRootMode)
2041 rc2 = emR3VmxNstGstIntrIntercept(pVCpu);
2042 else if (fInSvmHwvirtMode)
2043 rc2 = emR3SvmNstGstIntrIntercept(pVCpu);
2044 else
2045 rc2 = VINF_NO_CHANGE;
2046
2047 if (rc2 == VINF_NO_CHANGE)
2048 {
2049 bool fInjected = false;
2050 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_XCPT_MASK);
2051 /** @todo this really isn't nice, should properly handle this */
2052 /* Note! This can still cause a VM-exit (on Intel). */
2053 rc2 = TRPMR3InjectEvent(pVM, pVCpu, TRPM_HARDWARE_INT, &fInjected);
2054 fWakeupPending = true;
2055 if ( pVM->em.s.fIemExecutesAll
2056 && ( rc2 == VINF_EM_RESCHEDULE_REM
2057 || rc2 == VINF_EM_RESCHEDULE_HM
2058 || rc2 == VINF_EM_RESCHEDULE_RAW))
2059 {
2060 rc2 = VINF_EM_RESCHEDULE;
2061 }
2062#ifdef VBOX_STRICT
2063 if (fInjected)
2064 rcIrq = rc2;
2065#endif
2066 }
2067 UPDATE_RC();
2068 }
2069 else if ( fInSvmHwvirtMode
2070 && VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST)
2071 && CPUMIsGuestSvmVirtIntrEnabled(pVCpu, &pVCpu->cpum.GstCtx))
2072 {
2073 rc2 = emR3SvmNstGstVirtIntrIntercept(pVCpu);
2074 if (rc2 == VINF_NO_CHANGE)
2075 {
2076 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST);
2077 uint8_t const uNstGstVector = CPUMGetGuestSvmVirtIntrVector(&pVCpu->cpum.GstCtx);
2078 AssertMsg(uNstGstVector > 0 && uNstGstVector <= X86_XCPT_LAST, ("Invalid VINTR %#x\n", uNstGstVector));
2079 TRPMAssertTrap(pVCpu, uNstGstVector, TRPM_HARDWARE_INT);
2080 Log(("EM: Asserting nested-guest virt. hardware intr: %#x\n", uNstGstVector));
2081 rc2 = VINF_EM_RESCHEDULE;
2082#ifdef VBOX_STRICT
2083 rcIrq = rc2;
2084#endif
2085 }
2086 UPDATE_RC();
2087 }
2088 }
2089 }
2090 }
2091
2092 /*
2093 * Allocate handy pages.
2094 */
2095 if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_PGM_NEED_HANDY_PAGES, VM_FF_PGM_NO_MEMORY))
2096 {
2097 rc2 = PGMR3PhysAllocateHandyPages(pVM);
2098 UPDATE_RC();
2099 }
2100
2101 /*
2102 * Debugger Facility request.
2103 */
2104 if ( ( VM_FF_IS_SET(pVM, VM_FF_DBGF)
2105 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_DBGF) )
2106 && !VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY) )
2107 {
2108 CPUM_IMPORT_EXTRN_RCSTRICT(pVCpu, ~CPUMCTX_EXTRN_KEEPER_MASK, rc);
2109 rc2 = DBGFR3VMMForcedAction(pVM, pVCpu);
2110 UPDATE_RC();
2111 }
2112
2113 /*
2114 * EMT Rendezvous (must be serviced before termination).
2115 */
2116 if ( !fWakeupPending /* don't miss the wakeup from EMSTATE_HALTED! */
2117 && VM_FF_IS_SET(pVM, VM_FF_EMT_RENDEZVOUS))
2118 {
2119 CPUM_IMPORT_EXTRN_RCSTRICT(pVCpu, ~CPUMCTX_EXTRN_KEEPER_MASK, rc);
2120 rc2 = VMMR3EmtRendezvousFF(pVM, pVCpu);
2121 UPDATE_RC();
2122 /** @todo HACK ALERT! The following test is to make sure EM+TM thinks the VM is
2123 * stopped/reset before the next VM state change is made. We need a better
2124 * solution for this, or at least make it possible to do: (rc >= VINF_EM_FIRST
2125 * && rc >= VINF_EM_SUSPEND). */
2126 if (RT_UNLIKELY(rc == VINF_EM_SUSPEND || rc == VINF_EM_RESET || rc == VINF_EM_OFF))
2127 {
2128 Log2(("emR3ForcedActions: returns %Rrc\n", rc));
2129 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
2130 return rc;
2131 }
2132 }
2133
2134 /*
2135 * State change request (cleared by vmR3SetStateLocked).
2136 */
2137 if ( !fWakeupPending /* don't miss the wakeup from EMSTATE_HALTED! */
2138 && VM_FF_IS_SET(pVM, VM_FF_CHECK_VM_STATE))
2139 {
2140 VMSTATE enmState = VMR3GetState(pVM);
2141 switch (enmState)
2142 {
2143 case VMSTATE_FATAL_ERROR:
2144 case VMSTATE_FATAL_ERROR_LS:
2145 case VMSTATE_GURU_MEDITATION:
2146 case VMSTATE_GURU_MEDITATION_LS:
2147 Log2(("emR3ForcedActions: %s -> VINF_EM_SUSPEND\n", VMGetStateName(enmState) ));
2148 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
2149 return VINF_EM_SUSPEND;
2150
2151 case VMSTATE_DESTROYING:
2152 Log2(("emR3ForcedActions: %s -> VINF_EM_TERMINATE\n", VMGetStateName(enmState) ));
2153 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
2154 return VINF_EM_TERMINATE;
2155
2156 default:
2157 AssertMsgFailed(("%s\n", VMGetStateName(enmState)));
2158 }
2159 }
2160
2161 /*
2162 * Out of memory? Since most of our fellow high priority actions may cause us
2163 * to run out of memory, we're employing VM_FF_IS_PENDING_EXCEPT and putting this
2164 * at the end rather than the start. Also, VM_FF_TERMINATE has higher priority
2165 * than us since we can terminate without allocating more memory.
2166 */
2167 if (VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY))
2168 {
2169 rc2 = PGMR3PhysAllocateHandyPages(pVM);
2170 UPDATE_RC();
2171 if (rc == VINF_EM_NO_MEMORY)
2172 return rc;
2173 }
2174
2175 /*
2176 * If the virtual sync clock is still stopped, make TM restart it.
2177 */
2178 if (VM_FF_IS_SET(pVM, VM_FF_TM_VIRTUAL_SYNC))
2179 TMR3VirtualSyncFF(pVM, pVCpu);
2180
2181#ifdef DEBUG
2182 /*
2183 * Debug, pause the VM.
2184 */
2185 if (VM_FF_IS_SET(pVM, VM_FF_DEBUG_SUSPEND))
2186 {
2187 VM_FF_CLEAR(pVM, VM_FF_DEBUG_SUSPEND);
2188 Log(("emR3ForcedActions: returns VINF_EM_SUSPEND\n"));
2189 return VINF_EM_SUSPEND;
2190 }
2191#endif
2192
2193 /* check that we got them all */
2194 AssertCompile(VM_FF_HIGH_PRIORITY_PRE_MASK == (VM_FF_TM_VIRTUAL_SYNC | VM_FF_DBGF | VM_FF_CHECK_VM_STATE | VM_FF_DEBUG_SUSPEND | VM_FF_PGM_NEED_HANDY_PAGES | VM_FF_PGM_NO_MEMORY | VM_FF_EMT_RENDEZVOUS));
2195 AssertCompile(VMCPU_FF_HIGH_PRIORITY_PRE_MASK == (VMCPU_FF_TIMER | VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_UPDATE_APIC | VMCPU_FF_INTERRUPT_PIC | VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL | VMCPU_FF_INHIBIT_INTERRUPTS | VMCPU_FF_DBGF | VMCPU_FF_INTERRUPT_NESTED_GUEST | VMCPU_FF_VMX_MTF | VMCPU_FF_VMX_APIC_WRITE | VMCPU_FF_VMX_PREEMPT_TIMER | VMCPU_FF_VMX_INT_WINDOW | VMCPU_FF_VMX_NMI_WINDOW));
2196 }
2197
2198#undef UPDATE_RC
2199 Log2(("emR3ForcedActions: returns %Rrc\n", rc));
2200 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
2201 Assert(rcIrq == VINF_SUCCESS || rcIrq == rc);
2202 return rc;
2203}
2204
2205
2206/**
2207 * Check if the preset execution time cap restricts guest execution scheduling.
2208 *
2209 * @returns true if allowed, false otherwise
2210 * @param pVM The cross context VM structure.
2211 * @param pVCpu The cross context virtual CPU structure.
2212 */
2213bool emR3IsExecutionAllowed(PVM pVM, PVMCPU pVCpu)
2214{
2215 uint64_t u64UserTime, u64KernelTime;
2216
2217 if ( pVM->uCpuExecutionCap != 100
2218 && RT_SUCCESS(RTThreadGetExecutionTimeMilli(&u64KernelTime, &u64UserTime)))
2219 {
2220 uint64_t u64TimeNow = RTTimeMilliTS();
2221 if (pVCpu->em.s.u64TimeSliceStart + EM_TIME_SLICE < u64TimeNow)
2222 {
2223 /* New time slice. */
2224 pVCpu->em.s.u64TimeSliceStart = u64TimeNow;
2225 pVCpu->em.s.u64TimeSliceStartExec = u64KernelTime + u64UserTime;
2226 pVCpu->em.s.u64TimeSliceExec = 0;
2227 }
2228 pVCpu->em.s.u64TimeSliceExec = u64KernelTime + u64UserTime - pVCpu->em.s.u64TimeSliceStartExec;
2229
2230 Log2(("emR3IsExecutionAllowed: start=%RX64 startexec=%RX64 exec=%RX64 (cap=%x)\n", pVCpu->em.s.u64TimeSliceStart, pVCpu->em.s.u64TimeSliceStartExec, pVCpu->em.s.u64TimeSliceExec, (EM_TIME_SLICE * pVM->uCpuExecutionCap) / 100));
2231 if (pVCpu->em.s.u64TimeSliceExec >= (EM_TIME_SLICE * pVM->uCpuExecutionCap) / 100)
2232 return false;
2233 }
2234 return true;
2235}
2236
2237
2238/**
2239 * Execute VM.
2240 *
2241 * This function is the main loop of the VM. The emulation thread
2242 * calls this function when the VM has been successfully constructed
2243 * and we're ready for executing the VM.
2244 *
2245 * Returning from this function means that the VM is turned off or
2246 * suspended (state already saved) and deconstruction is next in line.
2247 *
2248 * All interaction from other thread are done using forced actions
2249 * and signalling of the wait object.
2250 *
2251 * @returns VBox status code, informational status codes may indicate failure.
2252 * @param pVM The cross context VM structure.
2253 * @param pVCpu The cross context virtual CPU structure.
2254 */
2255VMMR3_INT_DECL(int) EMR3ExecuteVM(PVM pVM, PVMCPU pVCpu)
2256{
2257 Log(("EMR3ExecuteVM: pVM=%p enmVMState=%d (%s) enmState=%d (%s) enmPrevState=%d (%s)\n",
2258 pVM,
2259 pVM->enmVMState, VMR3GetStateName(pVM->enmVMState),
2260 pVCpu->em.s.enmState, emR3GetStateName(pVCpu->em.s.enmState),
2261 pVCpu->em.s.enmPrevState, emR3GetStateName(pVCpu->em.s.enmPrevState) ));
2262 VM_ASSERT_EMT(pVM);
2263 AssertMsg( pVCpu->em.s.enmState == EMSTATE_NONE
2264 || pVCpu->em.s.enmState == EMSTATE_WAIT_SIPI
2265 || pVCpu->em.s.enmState == EMSTATE_SUSPENDED,
2266 ("%s\n", emR3GetStateName(pVCpu->em.s.enmState)));
2267
2268 int rc = setjmp(pVCpu->em.s.u.FatalLongJump);
2269 if (rc == 0)
2270 {
2271 /*
2272 * Start the virtual time.
2273 */
2274 TMR3NotifyResume(pVM, pVCpu);
2275
2276 /*
2277 * The Outer Main Loop.
2278 */
2279 bool fFFDone = false;
2280
2281 /* Reschedule right away to start in the right state. */
2282 rc = VINF_SUCCESS;
2283
2284 /* If resuming after a pause or a state load, restore the previous
2285 state or else we'll start executing code. Else, just reschedule. */
2286 if ( pVCpu->em.s.enmState == EMSTATE_SUSPENDED
2287 && ( pVCpu->em.s.enmPrevState == EMSTATE_WAIT_SIPI
2288 || pVCpu->em.s.enmPrevState == EMSTATE_HALTED))
2289 pVCpu->em.s.enmState = pVCpu->em.s.enmPrevState;
2290 else
2291 pVCpu->em.s.enmState = emR3Reschedule(pVM, pVCpu);
2292 pVCpu->em.s.cIemThenRemInstructions = 0;
2293 Log(("EMR3ExecuteVM: enmState=%s\n", emR3GetStateName(pVCpu->em.s.enmState)));
2294
2295 STAM_REL_PROFILE_ADV_START(&pVCpu->em.s.StatTotal, x);
2296 for (;;)
2297 {
2298 /*
2299 * Before we can schedule anything (we're here because
2300 * scheduling is required) we must service any pending
2301 * forced actions to avoid any pending action causing
2302 * immediate rescheduling upon entering an inner loop
2303 *
2304 * Do forced actions.
2305 */
2306 if ( !fFFDone
2307 && RT_SUCCESS(rc)
2308 && rc != VINF_EM_TERMINATE
2309 && rc != VINF_EM_OFF
2310 && ( VM_FF_IS_ANY_SET(pVM, VM_FF_ALL_REM_MASK)
2311 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_ALL_REM_MASK & ~VMCPU_FF_UNHALT)))
2312 {
2313 rc = emR3ForcedActions(pVM, pVCpu, rc);
2314 VBOXVMM_EM_FF_ALL_RET(pVCpu, rc);
2315 }
2316 else if (fFFDone)
2317 fFFDone = false;
2318
2319 /*
2320 * Now what to do?
2321 */
2322 Log2(("EMR3ExecuteVM: rc=%Rrc\n", rc));
2323 EMSTATE const enmOldState = pVCpu->em.s.enmState;
2324 switch (rc)
2325 {
2326 /*
2327 * Keep doing what we're currently doing.
2328 */
2329 case VINF_SUCCESS:
2330 break;
2331
2332 /*
2333 * Reschedule - to raw-mode execution.
2334 */
2335/** @todo r=bird: consider merging VINF_EM_RESCHEDULE_RAW with VINF_EM_RESCHEDULE_HM, they serve the same purpose here at least. */
2336 case VINF_EM_RESCHEDULE_RAW:
2337 Assert(!pVM->em.s.fIemExecutesAll || pVCpu->em.s.enmState != EMSTATE_IEM);
2338 if (VM_IS_RAW_MODE_ENABLED(pVM))
2339 {
2340 Log2(("EMR3ExecuteVM: VINF_EM_RESCHEDULE_RAW: %d -> %d (EMSTATE_RAW)\n", enmOldState, EMSTATE_RAW));
2341 pVCpu->em.s.enmState = EMSTATE_RAW;
2342 }
2343 else
2344 {
2345 AssertLogRelFailed();
2346 pVCpu->em.s.enmState = EMSTATE_NONE;
2347 }
2348 break;
2349
2350 /*
2351 * Reschedule - to HM or NEM.
2352 */
2353 case VINF_EM_RESCHEDULE_HM:
2354 Assert(!pVM->em.s.fIemExecutesAll || pVCpu->em.s.enmState != EMSTATE_IEM);
2355 if (VM_IS_HM_ENABLED(pVM))
2356 {
2357 Log2(("EMR3ExecuteVM: VINF_EM_RESCHEDULE_HM: %d -> %d (EMSTATE_HM)\n", enmOldState, EMSTATE_HM));
2358 pVCpu->em.s.enmState = EMSTATE_HM;
2359 }
2360 else if (VM_IS_NEM_ENABLED(pVM))
2361 {
2362 Log2(("EMR3ExecuteVM: VINF_EM_RESCHEDULE_HM: %d -> %d (EMSTATE_NEM)\n", enmOldState, EMSTATE_NEM));
2363 pVCpu->em.s.enmState = EMSTATE_NEM;
2364 }
2365 else
2366 {
2367 AssertLogRelFailed();
2368 pVCpu->em.s.enmState = EMSTATE_NONE;
2369 }
2370 break;
2371
2372 /*
2373 * Reschedule - to recompiled execution.
2374 */
2375 case VINF_EM_RESCHEDULE_REM:
2376 Assert(!pVM->em.s.fIemExecutesAll || pVCpu->em.s.enmState != EMSTATE_IEM);
2377 if (!VM_IS_RAW_MODE_ENABLED(pVM))
2378 {
2379 Log2(("EMR3ExecuteVM: VINF_EM_RESCHEDULE_REM: %d -> %d (EMSTATE_IEM_THEN_REM)\n",
2380 enmOldState, EMSTATE_IEM_THEN_REM));
2381 if (pVCpu->em.s.enmState != EMSTATE_IEM_THEN_REM)
2382 {
2383 pVCpu->em.s.enmState = EMSTATE_IEM_THEN_REM;
2384 pVCpu->em.s.cIemThenRemInstructions = 0;
2385 }
2386 }
2387 else
2388 {
2389 Log2(("EMR3ExecuteVM: VINF_EM_RESCHEDULE_REM: %d -> %d (EMSTATE_REM)\n", enmOldState, EMSTATE_REM));
2390 pVCpu->em.s.enmState = EMSTATE_REM;
2391 }
2392 break;
2393
2394 /*
2395 * Resume.
2396 */
2397 case VINF_EM_RESUME:
2398 Log2(("EMR3ExecuteVM: VINF_EM_RESUME: %d -> VINF_EM_RESCHEDULE\n", enmOldState));
2399 /* Don't reschedule in the halted or wait for SIPI case. */
2400 if ( pVCpu->em.s.enmPrevState == EMSTATE_WAIT_SIPI
2401 || pVCpu->em.s.enmPrevState == EMSTATE_HALTED)
2402 {
2403 pVCpu->em.s.enmState = pVCpu->em.s.enmPrevState;
2404 break;
2405 }
2406 /* fall through and get scheduled. */
2407 RT_FALL_THRU();
2408
2409 /*
2410 * Reschedule.
2411 */
2412 case VINF_EM_RESCHEDULE:
2413 {
2414 EMSTATE enmState = emR3Reschedule(pVM, pVCpu);
2415 Log2(("EMR3ExecuteVM: VINF_EM_RESCHEDULE: %d -> %d (%s)\n", enmOldState, enmState, emR3GetStateName(enmState)));
2416 if (pVCpu->em.s.enmState != enmState && enmState == EMSTATE_IEM_THEN_REM)
2417 pVCpu->em.s.cIemThenRemInstructions = 0;
2418 pVCpu->em.s.enmState = enmState;
2419 break;
2420 }
2421
2422 /*
2423 * Halted.
2424 */
2425 case VINF_EM_HALT:
2426 Log2(("EMR3ExecuteVM: VINF_EM_HALT: %d -> %d\n", enmOldState, EMSTATE_HALTED));
2427 pVCpu->em.s.enmState = EMSTATE_HALTED;
2428 break;
2429
2430 /*
2431 * Switch to the wait for SIPI state (application processor only)
2432 */
2433 case VINF_EM_WAIT_SIPI:
2434 Assert(pVCpu->idCpu != 0);
2435 Log2(("EMR3ExecuteVM: VINF_EM_WAIT_SIPI: %d -> %d\n", enmOldState, EMSTATE_WAIT_SIPI));
2436 pVCpu->em.s.enmState = EMSTATE_WAIT_SIPI;
2437 break;
2438
2439
2440 /*
2441 * Suspend.
2442 */
2443 case VINF_EM_SUSPEND:
2444 Log2(("EMR3ExecuteVM: VINF_EM_SUSPEND: %d -> %d\n", enmOldState, EMSTATE_SUSPENDED));
2445 Assert(enmOldState != EMSTATE_SUSPENDED);
2446 pVCpu->em.s.enmPrevState = enmOldState;
2447 pVCpu->em.s.enmState = EMSTATE_SUSPENDED;
2448 break;
2449
2450 /*
2451 * Reset.
2452 * We might end up doing a double reset for now, we'll have to clean up the mess later.
2453 */
2454 case VINF_EM_RESET:
2455 {
2456 if (pVCpu->idCpu == 0)
2457 {
2458 EMSTATE enmState = emR3Reschedule(pVM, pVCpu);
2459 Log2(("EMR3ExecuteVM: VINF_EM_RESET: %d -> %d (%s)\n", enmOldState, enmState, emR3GetStateName(enmState)));
2460 if (pVCpu->em.s.enmState != enmState && enmState == EMSTATE_IEM_THEN_REM)
2461 pVCpu->em.s.cIemThenRemInstructions = 0;
2462 pVCpu->em.s.enmState = enmState;
2463 }
2464 else
2465 {
2466 /* All other VCPUs go into the wait for SIPI state. */
2467 pVCpu->em.s.enmState = EMSTATE_WAIT_SIPI;
2468 }
2469 break;
2470 }
2471
2472 /*
2473 * Power Off.
2474 */
2475 case VINF_EM_OFF:
2476 pVCpu->em.s.enmState = EMSTATE_TERMINATING;
2477 Log2(("EMR3ExecuteVM: returns VINF_EM_OFF (%d -> %d)\n", enmOldState, EMSTATE_TERMINATING));
2478 TMR3NotifySuspend(pVM, pVCpu);
2479 STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x);
2480 return rc;
2481
2482 /*
2483 * Terminate the VM.
2484 */
2485 case VINF_EM_TERMINATE:
2486 pVCpu->em.s.enmState = EMSTATE_TERMINATING;
2487 Log(("EMR3ExecuteVM returns VINF_EM_TERMINATE (%d -> %d)\n", enmOldState, EMSTATE_TERMINATING));
2488 if (pVM->enmVMState < VMSTATE_DESTROYING) /* ugly */
2489 TMR3NotifySuspend(pVM, pVCpu);
2490 STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x);
2491 return rc;
2492
2493
2494 /*
2495 * Out of memory, suspend the VM and stuff.
2496 */
2497 case VINF_EM_NO_MEMORY:
2498 Log2(("EMR3ExecuteVM: VINF_EM_NO_MEMORY: %d -> %d\n", enmOldState, EMSTATE_SUSPENDED));
2499 Assert(enmOldState != EMSTATE_SUSPENDED);
2500 pVCpu->em.s.enmPrevState = enmOldState;
2501 pVCpu->em.s.enmState = EMSTATE_SUSPENDED;
2502 TMR3NotifySuspend(pVM, pVCpu);
2503 STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x);
2504
2505 rc = VMSetRuntimeError(pVM, VMSETRTERR_FLAGS_SUSPEND, "HostMemoryLow",
2506 N_("Unable to allocate and lock memory. The virtual machine will be paused. Please close applications to free up memory or close the VM"));
2507 if (rc != VINF_EM_SUSPEND)
2508 {
2509 if (RT_SUCCESS_NP(rc))
2510 {
2511 AssertLogRelMsgFailed(("%Rrc\n", rc));
2512 rc = VERR_EM_INTERNAL_ERROR;
2513 }
2514 pVCpu->em.s.enmState = EMSTATE_GURU_MEDITATION;
2515 }
2516 return rc;
2517
2518 /*
2519 * Guest debug events.
2520 */
2521 case VINF_EM_DBG_STEPPED:
2522 case VINF_EM_DBG_STOP:
2523 case VINF_EM_DBG_EVENT:
2524 case VINF_EM_DBG_BREAKPOINT:
2525 case VINF_EM_DBG_STEP:
2526 if (enmOldState == EMSTATE_RAW)
2527 {
2528 Log2(("EMR3ExecuteVM: %Rrc: %d -> %d\n", rc, enmOldState, EMSTATE_DEBUG_GUEST_RAW));
2529 pVCpu->em.s.enmState = EMSTATE_DEBUG_GUEST_RAW;
2530 }
2531 else if (enmOldState == EMSTATE_HM)
2532 {
2533 Log2(("EMR3ExecuteVM: %Rrc: %d -> %d\n", rc, enmOldState, EMSTATE_DEBUG_GUEST_HM));
2534 pVCpu->em.s.enmState = EMSTATE_DEBUG_GUEST_HM;
2535 }
2536 else if (enmOldState == EMSTATE_NEM)
2537 {
2538 Log2(("EMR3ExecuteVM: %Rrc: %d -> %d\n", rc, enmOldState, EMSTATE_DEBUG_GUEST_NEM));
2539 pVCpu->em.s.enmState = EMSTATE_DEBUG_GUEST_NEM;
2540 }
2541 else if (enmOldState == EMSTATE_REM)
2542 {
2543 Log2(("EMR3ExecuteVM: %Rrc: %d -> %d\n", rc, enmOldState, EMSTATE_DEBUG_GUEST_REM));
2544 pVCpu->em.s.enmState = EMSTATE_DEBUG_GUEST_REM;
2545 }
2546 else
2547 {
2548 Log2(("EMR3ExecuteVM: %Rrc: %d -> %d\n", rc, enmOldState, EMSTATE_DEBUG_GUEST_IEM));
2549 pVCpu->em.s.enmState = EMSTATE_DEBUG_GUEST_IEM;
2550 }
2551 break;
2552
2553 /*
2554 * Hypervisor debug events.
2555 */
2556 case VINF_EM_DBG_HYPER_STEPPED:
2557 case VINF_EM_DBG_HYPER_BREAKPOINT:
2558 case VINF_EM_DBG_HYPER_ASSERTION:
2559 Log2(("EMR3ExecuteVM: %Rrc: %d -> %d\n", rc, enmOldState, EMSTATE_DEBUG_HYPER));
2560 pVCpu->em.s.enmState = EMSTATE_DEBUG_HYPER;
2561 break;
2562
2563 /*
2564 * Triple fault.
2565 */
2566 case VINF_EM_TRIPLE_FAULT:
2567 if (!pVM->em.s.fGuruOnTripleFault)
2568 {
2569 Log(("EMR3ExecuteVM: VINF_EM_TRIPLE_FAULT: CPU reset...\n"));
2570 rc = VBOXSTRICTRC_TODO(VMR3ResetTripleFault(pVM));
2571 Log2(("EMR3ExecuteVM: VINF_EM_TRIPLE_FAULT: %d -> %d (rc=%Rrc)\n", enmOldState, pVCpu->em.s.enmState, rc));
2572 continue;
2573 }
2574 /* Else fall through and trigger a guru. */
2575 RT_FALL_THRU();
2576
2577 case VERR_VMM_RING0_ASSERTION:
2578 Log(("EMR3ExecuteVM: %Rrc: %d -> %d (EMSTATE_GURU_MEDITATION)\n", rc, enmOldState, EMSTATE_GURU_MEDITATION));
2579 pVCpu->em.s.enmState = EMSTATE_GURU_MEDITATION;
2580 break;
2581
2582 /*
2583 * Any error code showing up here other than the ones we
2584 * know and process above are considered to be FATAL.
2585 *
2586 * Unknown warnings and informational status codes are also
2587 * included in this.
2588 */
2589 default:
2590 if (RT_SUCCESS_NP(rc))
2591 {
2592 AssertMsgFailed(("Unexpected warning or informational status code %Rra!\n", rc));
2593 rc = VERR_EM_INTERNAL_ERROR;
2594 }
2595 Log(("EMR3ExecuteVM: %Rrc: %d -> %d (EMSTATE_GURU_MEDITATION)\n", rc, enmOldState, EMSTATE_GURU_MEDITATION));
2596 pVCpu->em.s.enmState = EMSTATE_GURU_MEDITATION;
2597 break;
2598 }
2599
2600 /*
2601 * Act on state transition.
2602 */
2603 EMSTATE const enmNewState = pVCpu->em.s.enmState;
2604 if (enmOldState != enmNewState)
2605 {
2606 VBOXVMM_EM_STATE_CHANGED(pVCpu, enmOldState, enmNewState, rc);
2607
2608 /* Clear MWait flags and the unhalt FF. */
2609 if ( enmOldState == EMSTATE_HALTED
2610 && ( (pVCpu->em.s.MWait.fWait & EMMWAIT_FLAG_ACTIVE)
2611 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_UNHALT))
2612 && ( enmNewState == EMSTATE_RAW
2613 || enmNewState == EMSTATE_HM
2614 || enmNewState == EMSTATE_NEM
2615 || enmNewState == EMSTATE_REM
2616 || enmNewState == EMSTATE_IEM_THEN_REM
2617 || enmNewState == EMSTATE_DEBUG_GUEST_RAW
2618 || enmNewState == EMSTATE_DEBUG_GUEST_HM
2619 || enmNewState == EMSTATE_DEBUG_GUEST_NEM
2620 || enmNewState == EMSTATE_DEBUG_GUEST_IEM
2621 || enmNewState == EMSTATE_DEBUG_GUEST_REM) )
2622 {
2623 if (pVCpu->em.s.MWait.fWait & EMMWAIT_FLAG_ACTIVE)
2624 {
2625 LogFlow(("EMR3ExecuteVM: Clearing MWAIT\n"));
2626 pVCpu->em.s.MWait.fWait &= ~(EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0);
2627 }
2628 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_UNHALT))
2629 {
2630 LogFlow(("EMR3ExecuteVM: Clearing UNHALT\n"));
2631 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_UNHALT);
2632 }
2633 }
2634 }
2635 else
2636 VBOXVMM_EM_STATE_UNCHANGED(pVCpu, enmNewState, rc);
2637
2638 STAM_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x); /* (skip this in release) */
2639 STAM_PROFILE_ADV_START(&pVCpu->em.s.StatTotal, x);
2640
2641 /*
2642 * Act on the new state.
2643 */
2644 switch (enmNewState)
2645 {
2646 /*
2647 * Execute raw.
2648 */
2649 case EMSTATE_RAW:
2650 AssertLogRelMsgFailed(("%Rrc\n", rc));
2651 rc = VERR_EM_INTERNAL_ERROR;
2652 break;
2653
2654 /*
2655 * Execute hardware accelerated raw.
2656 */
2657 case EMSTATE_HM:
2658 rc = emR3HmExecute(pVM, pVCpu, &fFFDone);
2659 break;
2660
2661 /*
2662 * Execute hardware accelerated raw.
2663 */
2664 case EMSTATE_NEM:
2665 rc = VBOXSTRICTRC_TODO(emR3NemExecute(pVM, pVCpu, &fFFDone));
2666 break;
2667
2668 /*
2669 * Execute recompiled.
2670 */
2671 case EMSTATE_REM:
2672 rc = emR3RemExecute(pVM, pVCpu, &fFFDone);
2673 Log2(("EMR3ExecuteVM: emR3RemExecute -> %Rrc\n", rc));
2674 break;
2675
2676 /*
2677 * Execute in the interpreter.
2678 */
2679 case EMSTATE_IEM:
2680 {
2681 uint32_t cInstructions = 0;
2682#if 0 /* For testing purposes. */
2683 STAM_PROFILE_START(&pVCpu->em.s.StatHmExec, x1);
2684 rc = VBOXSTRICTRC_TODO(EMR3HmSingleInstruction(pVM, pVCpu, EM_ONE_INS_FLAGS_RIP_CHANGE));
2685 STAM_PROFILE_STOP(&pVCpu->em.s.StatHmExec, x1);
2686 if (rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_RESCHEDULE_HM || rc == VINF_EM_RESCHEDULE_REM || rc == VINF_EM_RESCHEDULE_RAW)
2687 rc = VINF_SUCCESS;
2688 else if (rc == VERR_EM_CANNOT_EXEC_GUEST)
2689#endif
2690 rc = VBOXSTRICTRC_TODO(IEMExecLots(pVCpu, 4096 /*cMaxInstructions*/, 2047 /*cPollRate*/, &cInstructions));
2691 if (pVM->em.s.fIemExecutesAll)
2692 {
2693 Assert(rc != VINF_EM_RESCHEDULE_REM);
2694 Assert(rc != VINF_EM_RESCHEDULE_RAW);
2695 Assert(rc != VINF_EM_RESCHEDULE_HM);
2696#ifdef VBOX_HIGH_RES_TIMERS_HACK
2697 if (cInstructions < 2048)
2698 TMTimerPollVoid(pVM, pVCpu);
2699#endif
2700 }
2701 fFFDone = false;
2702 break;
2703 }
2704
2705 /*
2706 * Execute in IEM, hoping we can quickly switch aback to HM
2707 * or RAW execution. If our hopes fail, we go to REM.
2708 */
2709 case EMSTATE_IEM_THEN_REM:
2710 {
2711 STAM_PROFILE_START(&pVCpu->em.s.StatIEMThenREM, pIemThenRem);
2712 rc = VBOXSTRICTRC_TODO(emR3ExecuteIemThenRem(pVM, pVCpu, &fFFDone));
2713 STAM_PROFILE_STOP(&pVCpu->em.s.StatIEMThenREM, pIemThenRem);
2714 break;
2715 }
2716
2717 /*
2718 * Application processor execution halted until SIPI.
2719 */
2720 case EMSTATE_WAIT_SIPI:
2721 /* no break */
2722 /*
2723 * hlt - execution halted until interrupt.
2724 */
2725 case EMSTATE_HALTED:
2726 {
2727 STAM_REL_PROFILE_START(&pVCpu->em.s.StatHalted, y);
2728 /* If HM (or someone else) store a pending interrupt in
2729 TRPM, it must be dispatched ASAP without any halting.
2730 Anything pending in TRPM has been accepted and the CPU
2731 should already be the right state to receive it. */
2732 if (TRPMHasTrap(pVCpu))
2733 rc = VINF_EM_RESCHEDULE;
2734 /* MWAIT has a special extension where it's woken up when
2735 an interrupt is pending even when IF=0. */
2736 else if ( (pVCpu->em.s.MWait.fWait & (EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0))
2737 == (EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0))
2738 {
2739 rc = VMR3WaitHalted(pVM, pVCpu, false /*fIgnoreInterrupts*/);
2740 if (rc == VINF_SUCCESS)
2741 {
2742 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
2743 APICUpdatePendingInterrupts(pVCpu);
2744
2745 if (VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC
2746 | VMCPU_FF_INTERRUPT_NESTED_GUEST
2747 | VMCPU_FF_INTERRUPT_NMI | VMCPU_FF_INTERRUPT_SMI | VMCPU_FF_UNHALT))
2748 {
2749 Log(("EMR3ExecuteVM: Triggering reschedule on pending IRQ after MWAIT\n"));
2750 rc = VINF_EM_RESCHEDULE;
2751 }
2752 }
2753 }
2754 else
2755 {
2756 rc = VMR3WaitHalted(pVM, pVCpu, !(CPUMGetGuestEFlags(pVCpu) & X86_EFL_IF));
2757 /* We're only interested in NMI/SMIs here which have their own FFs, so we don't need to
2758 check VMCPU_FF_UPDATE_APIC here. */
2759 if ( rc == VINF_SUCCESS
2760 && VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI | VMCPU_FF_INTERRUPT_SMI | VMCPU_FF_UNHALT))
2761 {
2762 Log(("EMR3ExecuteVM: Triggering reschedule on pending NMI/SMI/UNHALT after HLT\n"));
2763 rc = VINF_EM_RESCHEDULE;
2764 }
2765 }
2766
2767 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatHalted, y);
2768 break;
2769 }
2770
2771 /*
2772 * Suspended - return to VM.cpp.
2773 */
2774 case EMSTATE_SUSPENDED:
2775 TMR3NotifySuspend(pVM, pVCpu);
2776 STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x);
2777 Log(("EMR3ExecuteVM: actually returns %Rrc (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(enmOldState)));
2778 return VINF_EM_SUSPEND;
2779
2780 /*
2781 * Debugging in the guest.
2782 */
2783 case EMSTATE_DEBUG_GUEST_RAW:
2784 case EMSTATE_DEBUG_GUEST_HM:
2785 case EMSTATE_DEBUG_GUEST_NEM:
2786 case EMSTATE_DEBUG_GUEST_IEM:
2787 case EMSTATE_DEBUG_GUEST_REM:
2788 TMR3NotifySuspend(pVM, pVCpu);
2789 rc = VBOXSTRICTRC_TODO(emR3Debug(pVM, pVCpu, rc));
2790 TMR3NotifyResume(pVM, pVCpu);
2791 Log2(("EMR3ExecuteVM: emR3Debug -> %Rrc (state %d)\n", rc, pVCpu->em.s.enmState));
2792 break;
2793
2794 /*
2795 * Debugging in the hypervisor.
2796 */
2797 case EMSTATE_DEBUG_HYPER:
2798 {
2799 TMR3NotifySuspend(pVM, pVCpu);
2800 STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x);
2801
2802 rc = VBOXSTRICTRC_TODO(emR3Debug(pVM, pVCpu, rc));
2803 Log2(("EMR3ExecuteVM: emR3Debug -> %Rrc (state %d)\n", rc, pVCpu->em.s.enmState));
2804 if (rc != VINF_SUCCESS)
2805 {
2806 if (rc == VINF_EM_OFF || rc == VINF_EM_TERMINATE)
2807 pVCpu->em.s.enmState = EMSTATE_TERMINATING;
2808 else
2809 {
2810 /* switch to guru meditation mode */
2811 pVCpu->em.s.enmState = EMSTATE_GURU_MEDITATION;
2812 VMR3SetGuruMeditation(pVM); /* This notifies the other EMTs. */
2813 VMMR3FatalDump(pVM, pVCpu, rc);
2814 }
2815 Log(("EMR3ExecuteVM: actually returns %Rrc (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(enmOldState)));
2816 return rc;
2817 }
2818
2819 STAM_REL_PROFILE_ADV_START(&pVCpu->em.s.StatTotal, x);
2820 TMR3NotifyResume(pVM, pVCpu);
2821 break;
2822 }
2823
2824 /*
2825 * Guru meditation takes place in the debugger.
2826 */
2827 case EMSTATE_GURU_MEDITATION:
2828 {
2829 TMR3NotifySuspend(pVM, pVCpu);
2830 VMR3SetGuruMeditation(pVM); /* This notifies the other EMTs. */
2831 VMMR3FatalDump(pVM, pVCpu, rc);
2832 emR3Debug(pVM, pVCpu, rc);
2833 STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x);
2834 Log(("EMR3ExecuteVM: actually returns %Rrc (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(enmOldState)));
2835 return rc;
2836 }
2837
2838 /*
2839 * The states we don't expect here.
2840 */
2841 case EMSTATE_NONE:
2842 case EMSTATE_TERMINATING:
2843 default:
2844 AssertMsgFailed(("EMR3ExecuteVM: Invalid state %d!\n", pVCpu->em.s.enmState));
2845 pVCpu->em.s.enmState = EMSTATE_GURU_MEDITATION;
2846 TMR3NotifySuspend(pVM, pVCpu);
2847 STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x);
2848 Log(("EMR3ExecuteVM: actually returns %Rrc (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(enmOldState)));
2849 return VERR_EM_INTERNAL_ERROR;
2850 }
2851 } /* The Outer Main Loop */
2852 }
2853 else
2854 {
2855 /*
2856 * Fatal error.
2857 */
2858 Log(("EMR3ExecuteVM: returns %Rrc because of longjmp / fatal error; (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(pVCpu->em.s.enmPrevState)));
2859 TMR3NotifySuspend(pVM, pVCpu);
2860 VMR3SetGuruMeditation(pVM); /* This notifies the other EMTs. */
2861 VMMR3FatalDump(pVM, pVCpu, rc);
2862 emR3Debug(pVM, pVCpu, rc);
2863 STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x);
2864 /** @todo change the VM state! */
2865 return rc;
2866 }
2867
2868 /* not reached */
2869}
2870
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use