VirtualBox

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

Last change on this file since 74962 was 74899, checked in by vboxsync, 6 years ago

VMM/EM: Nested VMX: bugref:9180 Interrupt-window must work even if an interrupt isn't actually pending when interrupts are enabled.
The problem is we don't have hooks when EFLAGS change, so this is the best we can do atm.

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

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