VirtualBox

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

Last change on this file was 103415, checked in by vboxsync, 3 months ago

Additions,Main,VMM,Runtime: Fix some unused expression warnings, bugref:3409

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

© 2023 Oracle
ContactPrivacy policyTerms of Use