VirtualBox

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

Last change on this file since 74795 was 74791, checked in by vboxsync, 6 years ago

vm.h,VMM,REM: s/VM_FF_IS_PENDING/VM_FF_IS_ANY_SET/g to emphasize the plurality of the flags argument and encourage using VM_FF_IS_SET. bugref:9180

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 120.6 KB
Line 
1/* $Id: EM.cpp 74791 2018-10-12 10:44:17Z 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#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
1713/**
1714 * Helper for emR3ForcedActions() for injecting interrupts into the
1715 * nested-guest.
1716 *
1717 * @returns VBox status code.
1718 * @param pVCpu The cross context virtual CPU structure.
1719 * @param pfResched Where to store whether a reschedule is required.
1720 * @param pfInject Where to store whether an interrupt was injected (and if
1721 * a wake up is pending).
1722 */
1723static int emR3NstGstInjectIntr(PVMCPU pVCpu, bool *pfResched, bool *pfInject)
1724{
1725 *pfResched = false;
1726 *pfInject = false;
1727 if (CPUMIsGuestInSvmNestedHwVirtMode(&pVCpu->cpum.GstCtx))
1728 {
1729 PVM pVM = pVCpu->CTX_SUFF(pVM);
1730 Assert(pVCpu->cpum.GstCtx.hwvirt.fGif);
1731 bool fVirtualGif = CPUMGetSvmNstGstVGif(&pVCpu->cpum.GstCtx);
1732#ifdef VBOX_WITH_RAW_MODE
1733 fVirtualGif &= !PATMIsPatchGCAddr(pVM, pVCpu->cpum.GstCtx.eip);
1734#endif
1735 if (fVirtualGif)
1736 {
1737 if (CPUMCanSvmNstGstTakePhysIntr(pVCpu, &pVCpu->cpum.GstCtx))
1738 {
1739 Assert(pVCpu->em.s.enmState != EMSTATE_WAIT_SIPI);
1740 if (VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC))
1741 {
1742 if (CPUMIsGuestSvmCtrlInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, SVM_CTRL_INTERCEPT_INTR))
1743 {
1744 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_SVM_VMEXIT_MASK);
1745 VBOXSTRICTRC rcStrict = IEMExecSvmVmexit(pVCpu, SVM_EXIT_INTR, 0, 0);
1746 if (RT_SUCCESS(rcStrict))
1747 {
1748 /** @todo r=ramshankar: Do we need to signal a wakeup here? If a nested-guest
1749 * doesn't intercept HLT but intercepts INTR? */
1750 *pfResched = true;
1751 Assert(rcStrict != VINF_PGM_CHANGE_MODE);
1752 if (rcStrict == VINF_SVM_VMEXIT)
1753 return VINF_SUCCESS;
1754 return VBOXSTRICTRC_VAL(rcStrict);
1755 }
1756
1757 AssertMsgFailed(("INTR #VMEXIT failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
1758 return VINF_EM_TRIPLE_FAULT;
1759 }
1760
1761 /* Note: it's important to make sure the return code from TRPMR3InjectEvent isn't ignored! */
1762 /** @todo this really isn't nice, should properly handle this */
1763 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_XCPT_MASK);
1764 int rc = TRPMR3InjectEvent(pVM, pVCpu, TRPM_HARDWARE_INT);
1765 Assert(rc != VINF_PGM_CHANGE_MODE);
1766 if (rc == VINF_SVM_VMEXIT)
1767 rc = VINF_SUCCESS;
1768 if (pVM->em.s.fIemExecutesAll && ( rc == VINF_EM_RESCHEDULE_REM
1769 || rc == VINF_EM_RESCHEDULE_HM
1770 || rc == VINF_EM_RESCHEDULE_RAW))
1771 {
1772 rc = VINF_EM_RESCHEDULE;
1773 }
1774
1775 *pfResched = true;
1776 *pfInject = true;
1777 return rc;
1778 }
1779 }
1780
1781 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST)
1782 && CPUMCanSvmNstGstTakeVirtIntr(pVCpu, &pVCpu->cpum.GstCtx))
1783 {
1784 if (CPUMIsGuestSvmCtrlInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, SVM_CTRL_INTERCEPT_VINTR))
1785 {
1786 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_SVM_VMEXIT_MASK);
1787 VBOXSTRICTRC rcStrict = IEMExecSvmVmexit(pVCpu, SVM_EXIT_VINTR, 0, 0);
1788 if (RT_SUCCESS(rcStrict))
1789 {
1790 /** @todo r=ramshankar: Do we need to signal a wakeup here? If a nested-guest
1791 * doesn't intercept HLT but intercepts VINTR? */
1792 *pfResched = true;
1793 Assert(rcStrict != VINF_PGM_CHANGE_MODE);
1794 if (rcStrict == VINF_SVM_VMEXIT)
1795 return VINF_SUCCESS;
1796 return VBOXSTRICTRC_VAL(rcStrict);
1797 }
1798
1799 AssertMsgFailed(("VINTR #VMEXIT failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
1800 return VINF_EM_TRIPLE_FAULT;
1801 }
1802
1803 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST);
1804 uint8_t const uNstGstVector = CPUMGetSvmNstGstInterrupt(&pVCpu->cpum.GstCtx);
1805 AssertMsg(uNstGstVector > 0 && uNstGstVector <= X86_XCPT_LAST, ("Invalid VINTR vector %#x\n", uNstGstVector));
1806 TRPMAssertTrap(pVCpu, uNstGstVector, TRPM_HARDWARE_INT);
1807 Log(("EM: Asserting nested-guest virt. hardware intr: %#x\n", uNstGstVector));
1808
1809 *pfResched = true;
1810 *pfInject = true;
1811 return VINF_EM_RESCHEDULE;
1812 }
1813 }
1814 return VINF_SUCCESS;
1815 }
1816
1817 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
1818 { /** @todo Nested VMX. */ }
1819
1820 /* Shouldn't really get here. */
1821 AssertMsgFailed(("Unrecognized nested hwvirt. arch!\n"));
1822 return VERR_EM_INTERNAL_ERROR;
1823}
1824#endif
1825
1826/**
1827 * Executes all pending forced actions.
1828 *
1829 * Forced actions can cause execution delays and execution
1830 * rescheduling. The first we deal with using action priority, so
1831 * that for instance pending timers aren't scheduled and ran until
1832 * right before execution. The rescheduling we deal with using
1833 * return codes. The same goes for VM termination, only in that case
1834 * we exit everything.
1835 *
1836 * @returns VBox status code of equal or greater importance/severity than rc.
1837 * The most important ones are: VINF_EM_RESCHEDULE,
1838 * VINF_EM_SUSPEND, VINF_EM_RESET and VINF_EM_TERMINATE.
1839 *
1840 * @param pVM The cross context VM structure.
1841 * @param pVCpu The cross context virtual CPU structure.
1842 * @param rc The current rc.
1843 *
1844 */
1845int emR3ForcedActions(PVM pVM, PVMCPU pVCpu, int rc)
1846{
1847 STAM_REL_PROFILE_START(&pVCpu->em.s.StatForcedActions, a);
1848#ifdef VBOX_STRICT
1849 int rcIrq = VINF_SUCCESS;
1850#endif
1851 int rc2;
1852#define UPDATE_RC() \
1853 do { \
1854 AssertMsg(rc2 <= 0 || (rc2 >= VINF_EM_FIRST && rc2 <= VINF_EM_LAST), ("Invalid FF return code: %Rra\n", rc2)); \
1855 if (rc2 == VINF_SUCCESS || rc < VINF_SUCCESS) \
1856 break; \
1857 if (!rc || rc2 < rc) \
1858 rc = rc2; \
1859 } while (0)
1860 VBOXVMM_EM_FF_ALL(pVCpu, pVM->fGlobalForcedActions, pVCpu->fLocalForcedActions, rc);
1861
1862 /*
1863 * Post execution chunk first.
1864 */
1865 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_NORMAL_PRIORITY_POST_MASK)
1866 || (VMCPU_FF_NORMAL_PRIORITY_POST_MASK && VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_NORMAL_PRIORITY_POST_MASK)) )
1867 {
1868 /*
1869 * EMT Rendezvous (must be serviced before termination).
1870 */
1871 if (VM_FF_IS_SET(pVM, VM_FF_EMT_RENDEZVOUS))
1872 {
1873 CPUM_IMPORT_EXTRN_RCSTRICT(pVCpu, ~CPUMCTX_EXTRN_KEEPER_MASK, rc);
1874 rc2 = VMMR3EmtRendezvousFF(pVM, pVCpu);
1875 UPDATE_RC();
1876 /** @todo HACK ALERT! The following test is to make sure EM+TM
1877 * thinks the VM is stopped/reset before the next VM state change
1878 * is made. We need a better solution for this, or at least make it
1879 * possible to do: (rc >= VINF_EM_FIRST && rc <=
1880 * VINF_EM_SUSPEND). */
1881 if (RT_UNLIKELY(rc == VINF_EM_SUSPEND || rc == VINF_EM_RESET || rc == VINF_EM_OFF))
1882 {
1883 Log2(("emR3ForcedActions: returns %Rrc\n", rc));
1884 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
1885 return rc;
1886 }
1887 }
1888
1889 /*
1890 * State change request (cleared by vmR3SetStateLocked).
1891 */
1892 if (VM_FF_IS_SET(pVM, VM_FF_CHECK_VM_STATE))
1893 {
1894 VMSTATE enmState = VMR3GetState(pVM);
1895 switch (enmState)
1896 {
1897 case VMSTATE_FATAL_ERROR:
1898 case VMSTATE_FATAL_ERROR_LS:
1899 case VMSTATE_GURU_MEDITATION:
1900 case VMSTATE_GURU_MEDITATION_LS:
1901 Log2(("emR3ForcedActions: %s -> VINF_EM_SUSPEND\n", VMGetStateName(enmState) ));
1902 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
1903 return VINF_EM_SUSPEND;
1904
1905 case VMSTATE_DESTROYING:
1906 Log2(("emR3ForcedActions: %s -> VINF_EM_TERMINATE\n", VMGetStateName(enmState) ));
1907 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
1908 return VINF_EM_TERMINATE;
1909
1910 default:
1911 AssertMsgFailed(("%s\n", VMGetStateName(enmState)));
1912 }
1913 }
1914
1915 /*
1916 * Debugger Facility polling.
1917 */
1918 if ( VM_FF_IS_SET(pVM, VM_FF_DBGF)
1919 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_DBGF) )
1920 {
1921 CPUM_IMPORT_EXTRN_RCSTRICT(pVCpu, ~CPUMCTX_EXTRN_KEEPER_MASK, rc);
1922 rc2 = DBGFR3VMMForcedAction(pVM, pVCpu);
1923 UPDATE_RC();
1924 }
1925
1926 /*
1927 * Postponed reset request.
1928 */
1929 if (VM_FF_TEST_AND_CLEAR(pVM, VM_FF_RESET))
1930 {
1931 CPUM_IMPORT_EXTRN_RCSTRICT(pVCpu, ~CPUMCTX_EXTRN_KEEPER_MASK, rc);
1932 rc2 = VBOXSTRICTRC_TODO(VMR3ResetFF(pVM));
1933 UPDATE_RC();
1934 }
1935
1936#ifdef VBOX_WITH_RAW_MODE
1937 /*
1938 * CSAM page scanning.
1939 */
1940 if ( !VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)
1941 && VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_CSAM_SCAN_PAGE))
1942 {
1943 /** @todo check for 16 or 32 bits code! (D bit in the code selector) */
1944 Log(("Forced action VMCPU_FF_CSAM_SCAN_PAGE\n"));
1945 CPUM_IMPORT_EXTRN_RCSTRICT(pVCpu, ~CPUMCTX_EXTRN_KEEPER_MASK, rc);
1946 CSAMR3CheckCodeEx(pVM, &pVCpu->cpum.GstCtx, pVCpu->cpum.GstCtx.eip);
1947 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_CSAM_SCAN_PAGE);
1948 }
1949#endif
1950
1951 /*
1952 * Out of memory? Putting this after CSAM as it may in theory cause us to run out of memory.
1953 */
1954 if (VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY))
1955 {
1956 rc2 = PGMR3PhysAllocateHandyPages(pVM);
1957 UPDATE_RC();
1958 if (rc == VINF_EM_NO_MEMORY)
1959 return rc;
1960 }
1961
1962 /* check that we got them all */
1963 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));
1964 AssertCompile(VMCPU_FF_NORMAL_PRIORITY_POST_MASK == (VM_WHEN_RAW_MODE(VMCPU_FF_CSAM_SCAN_PAGE, 0) | VMCPU_FF_DBGF));
1965 }
1966
1967 /*
1968 * Normal priority then.
1969 * (Executed in no particular order.)
1970 */
1971 if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_NORMAL_PRIORITY_MASK, VM_FF_PGM_NO_MEMORY))
1972 {
1973 /*
1974 * PDM Queues are pending.
1975 */
1976 if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_PDM_QUEUES, VM_FF_PGM_NO_MEMORY))
1977 PDMR3QueueFlushAll(pVM);
1978
1979 /*
1980 * PDM DMA transfers are pending.
1981 */
1982 if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_PDM_DMA, VM_FF_PGM_NO_MEMORY))
1983 PDMR3DmaRun(pVM);
1984
1985 /*
1986 * EMT Rendezvous (make sure they are handled before the requests).
1987 */
1988 if (VM_FF_IS_SET(pVM, VM_FF_EMT_RENDEZVOUS))
1989 {
1990 CPUM_IMPORT_EXTRN_RCSTRICT(pVCpu, ~CPUMCTX_EXTRN_KEEPER_MASK, rc);
1991 rc2 = VMMR3EmtRendezvousFF(pVM, pVCpu);
1992 UPDATE_RC();
1993 /** @todo HACK ALERT! The following test is to make sure EM+TM
1994 * thinks the VM is stopped/reset before the next VM state change
1995 * is made. We need a better solution for this, or at least make it
1996 * possible to do: (rc >= VINF_EM_FIRST && rc <=
1997 * VINF_EM_SUSPEND). */
1998 if (RT_UNLIKELY(rc == VINF_EM_SUSPEND || rc == VINF_EM_RESET || rc == VINF_EM_OFF))
1999 {
2000 Log2(("emR3ForcedActions: returns %Rrc\n", rc));
2001 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
2002 return rc;
2003 }
2004 }
2005
2006 /*
2007 * Requests from other threads.
2008 */
2009 if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_REQUEST, VM_FF_PGM_NO_MEMORY))
2010 {
2011 CPUM_IMPORT_EXTRN_RCSTRICT(pVCpu, ~CPUMCTX_EXTRN_KEEPER_MASK, rc);
2012 rc2 = VMR3ReqProcessU(pVM->pUVM, VMCPUID_ANY, false /*fPriorityOnly*/);
2013 if (rc2 == VINF_EM_OFF || rc2 == VINF_EM_TERMINATE) /** @todo this shouldn't be necessary */
2014 {
2015 Log2(("emR3ForcedActions: returns %Rrc\n", rc2));
2016 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
2017 return rc2;
2018 }
2019 UPDATE_RC();
2020 /** @todo HACK ALERT! The following test is to make sure EM+TM
2021 * thinks the VM is stopped/reset before the next VM state change
2022 * is made. We need a better solution for this, or at least make it
2023 * possible to do: (rc >= VINF_EM_FIRST && rc <=
2024 * VINF_EM_SUSPEND). */
2025 if (RT_UNLIKELY(rc == VINF_EM_SUSPEND || rc == VINF_EM_RESET || rc == VINF_EM_OFF))
2026 {
2027 Log2(("emR3ForcedActions: returns %Rrc\n", rc));
2028 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
2029 return rc;
2030 }
2031 }
2032
2033#ifdef VBOX_WITH_REM
2034 /* Replay the handler notification changes. */
2035 if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_REM_HANDLER_NOTIFY, VM_FF_PGM_NO_MEMORY))
2036 {
2037 /* Try not to cause deadlocks. */
2038 if ( pVM->cCpus == 1
2039 || ( !PGMIsLockOwner(pVM)
2040 && !IOMIsLockWriteOwner(pVM))
2041 )
2042 {
2043 EMRemLock(pVM);
2044 REMR3ReplayHandlerNotifications(pVM);
2045 EMRemUnlock(pVM);
2046 }
2047 }
2048#endif
2049
2050 /* check that we got them all */
2051 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));
2052 }
2053
2054 /*
2055 * Normal priority then. (per-VCPU)
2056 * (Executed in no particular order.)
2057 */
2058 if ( !VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)
2059 && VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_NORMAL_PRIORITY_MASK))
2060 {
2061 /*
2062 * Requests from other threads.
2063 */
2064 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
2065 {
2066 CPUM_IMPORT_EXTRN_RCSTRICT(pVCpu, ~CPUMCTX_EXTRN_KEEPER_MASK, rc);
2067 rc2 = VMR3ReqProcessU(pVM->pUVM, pVCpu->idCpu, false /*fPriorityOnly*/);
2068 if (rc2 == VINF_EM_OFF || rc2 == VINF_EM_TERMINATE || rc2 == VINF_EM_RESET)
2069 {
2070 Log2(("emR3ForcedActions: returns %Rrc\n", rc2));
2071 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
2072 return rc2;
2073 }
2074 UPDATE_RC();
2075 /** @todo HACK ALERT! The following test is to make sure EM+TM
2076 * thinks the VM is stopped/reset before the next VM state change
2077 * is made. We need a better solution for this, or at least make it
2078 * possible to do: (rc >= VINF_EM_FIRST && rc <=
2079 * VINF_EM_SUSPEND). */
2080 if (RT_UNLIKELY(rc == VINF_EM_SUSPEND || rc == VINF_EM_RESET || rc == VINF_EM_OFF))
2081 {
2082 Log2(("emR3ForcedActions: returns %Rrc\n", rc));
2083 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
2084 return rc;
2085 }
2086 }
2087
2088 /* check that we got them all */
2089 Assert(!(VMCPU_FF_NORMAL_PRIORITY_MASK & ~VMCPU_FF_REQUEST));
2090 }
2091
2092 /*
2093 * High priority pre execution chunk last.
2094 * (Executed in ascending priority order.)
2095 */
2096 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HIGH_PRIORITY_PRE_MASK)
2097 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HIGH_PRIORITY_PRE_MASK))
2098 {
2099 /*
2100 * Timers before interrupts.
2101 */
2102 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_TIMER)
2103 && !VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY))
2104 TMR3TimerQueuesDo(pVM);
2105
2106 /*
2107 * Pick up asynchronously posted interrupts into the APIC.
2108 */
2109 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
2110 APICUpdatePendingInterrupts(pVCpu);
2111
2112 /*
2113 * The instruction following an emulated STI should *always* be executed!
2114 *
2115 * Note! We intentionally don't clear VM_FF_INHIBIT_INTERRUPTS here if
2116 * the eip is the same as the inhibited instr address. Before we
2117 * are able to execute this instruction in raw mode (iret to
2118 * guest code) an external interrupt might force a world switch
2119 * again. Possibly allowing a guest interrupt to be dispatched
2120 * in the process. This could break the guest. Sounds very
2121 * unlikely, but such timing sensitive problem are not as rare as
2122 * you might think.
2123 */
2124 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
2125 && !VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY))
2126 {
2127 CPUM_ASSERT_NOT_EXTRN(pVCpu, CPUMCTX_EXTRN_RIP);
2128 if (CPUMGetGuestRIP(pVCpu) != EMGetInhibitInterruptsPC(pVCpu))
2129 {
2130 Log(("Clearing VMCPU_FF_INHIBIT_INTERRUPTS at %RGv - successor %RGv\n", (RTGCPTR)CPUMGetGuestRIP(pVCpu), EMGetInhibitInterruptsPC(pVCpu)));
2131 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
2132 }
2133 else
2134 Log(("Leaving VMCPU_FF_INHIBIT_INTERRUPTS set at %RGv\n", (RTGCPTR)CPUMGetGuestRIP(pVCpu)));
2135 }
2136
2137 /*
2138 * Interrupts.
2139 */
2140 bool fWakeupPending = false;
2141 if ( !VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)
2142 && (!rc || rc >= VINF_EM_RESCHEDULE_HM))
2143 {
2144 if ( !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
2145 && !TRPMHasTrap(pVCpu)) /* an interrupt could already be scheduled for dispatching in the recompiler. */
2146 {
2147 Assert(!HMR3IsEventPending(pVCpu));
2148#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
2149 if (CPUMIsGuestInSvmNestedHwVirtMode(&pVCpu->cpum.GstCtx))
2150 {
2151 bool fResched, fInject;
2152 rc2 = emR3NstGstInjectIntr(pVCpu, &fResched, &fInject);
2153 if (fInject)
2154 {
2155 fWakeupPending = true;
2156# ifdef VBOX_STRICT
2157 rcIrq = rc2;
2158# endif
2159 }
2160 if (fResched)
2161 UPDATE_RC();
2162 }
2163 else
2164#endif
2165 {
2166 CPUM_ASSERT_NOT_EXTRN(pVCpu, CPUMCTX_EXTRN_RFLAGS);
2167 if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
2168#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
2169 && pVCpu->cpum.GstCtx.hwvirt.fGif
2170#endif
2171#ifdef VBOX_WITH_RAW_MODE
2172 && !PATMIsPatchGCAddr(pVM, pVCpu->cpum.GstCtx.eip)
2173#endif
2174 && pVCpu->cpum.GstCtx.eflags.Bits.u1IF)
2175 {
2176 Assert(pVCpu->em.s.enmState != EMSTATE_WAIT_SIPI);
2177 /* Note: it's important to make sure the return code from TRPMR3InjectEvent isn't ignored! */
2178 /** @todo this really isn't nice, should properly handle this */
2179 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_XCPT_MASK);
2180 rc2 = TRPMR3InjectEvent(pVM, pVCpu, TRPM_HARDWARE_INT);
2181 Log(("EM: TRPMR3InjectEvent -> %d\n", rc2));
2182 if (pVM->em.s.fIemExecutesAll && ( rc2 == VINF_EM_RESCHEDULE_REM
2183 || rc2 == VINF_EM_RESCHEDULE_HM
2184 || rc2 == VINF_EM_RESCHEDULE_RAW))
2185 {
2186 rc2 = VINF_EM_RESCHEDULE;
2187 }
2188#ifdef VBOX_STRICT
2189 rcIrq = rc2;
2190#endif
2191 UPDATE_RC();
2192 /* Reschedule required: We must not miss the wakeup below! */
2193 fWakeupPending = true;
2194 }
2195 }
2196 }
2197 }
2198
2199 /*
2200 * Allocate handy pages.
2201 */
2202 if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_PGM_NEED_HANDY_PAGES, VM_FF_PGM_NO_MEMORY))
2203 {
2204 rc2 = PGMR3PhysAllocateHandyPages(pVM);
2205 UPDATE_RC();
2206 }
2207
2208 /*
2209 * Debugger Facility request.
2210 */
2211 if ( ( VM_FF_IS_SET(pVM, VM_FF_DBGF)
2212 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_DBGF) )
2213 && !VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY) )
2214 {
2215 CPUM_IMPORT_EXTRN_RCSTRICT(pVCpu, ~CPUMCTX_EXTRN_KEEPER_MASK, rc);
2216 rc2 = DBGFR3VMMForcedAction(pVM, pVCpu);
2217 UPDATE_RC();
2218 }
2219
2220 /*
2221 * EMT Rendezvous (must be serviced before termination).
2222 */
2223 if ( !fWakeupPending /* don't miss the wakeup from EMSTATE_HALTED! */
2224 && VM_FF_IS_SET(pVM, VM_FF_EMT_RENDEZVOUS))
2225 {
2226 CPUM_IMPORT_EXTRN_RCSTRICT(pVCpu, ~CPUMCTX_EXTRN_KEEPER_MASK, rc);
2227 rc2 = VMMR3EmtRendezvousFF(pVM, pVCpu);
2228 UPDATE_RC();
2229 /** @todo HACK ALERT! The following test is to make sure EM+TM thinks the VM is
2230 * stopped/reset before the next VM state change is made. We need a better
2231 * solution for this, or at least make it possible to do: (rc >= VINF_EM_FIRST
2232 * && rc >= VINF_EM_SUSPEND). */
2233 if (RT_UNLIKELY(rc == VINF_EM_SUSPEND || rc == VINF_EM_RESET || rc == VINF_EM_OFF))
2234 {
2235 Log2(("emR3ForcedActions: returns %Rrc\n", rc));
2236 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
2237 return rc;
2238 }
2239 }
2240
2241 /*
2242 * State change request (cleared by vmR3SetStateLocked).
2243 */
2244 if ( !fWakeupPending /* don't miss the wakeup from EMSTATE_HALTED! */
2245 && VM_FF_IS_SET(pVM, VM_FF_CHECK_VM_STATE))
2246 {
2247 VMSTATE enmState = VMR3GetState(pVM);
2248 switch (enmState)
2249 {
2250 case VMSTATE_FATAL_ERROR:
2251 case VMSTATE_FATAL_ERROR_LS:
2252 case VMSTATE_GURU_MEDITATION:
2253 case VMSTATE_GURU_MEDITATION_LS:
2254 Log2(("emR3ForcedActions: %s -> VINF_EM_SUSPEND\n", VMGetStateName(enmState) ));
2255 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
2256 return VINF_EM_SUSPEND;
2257
2258 case VMSTATE_DESTROYING:
2259 Log2(("emR3ForcedActions: %s -> VINF_EM_TERMINATE\n", VMGetStateName(enmState) ));
2260 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
2261 return VINF_EM_TERMINATE;
2262
2263 default:
2264 AssertMsgFailed(("%s\n", VMGetStateName(enmState)));
2265 }
2266 }
2267
2268 /*
2269 * Out of memory? Since most of our fellow high priority actions may cause us
2270 * to run out of memory, we're employing VM_FF_IS_PENDING_EXCEPT and putting this
2271 * at the end rather than the start. Also, VM_FF_TERMINATE has higher priority
2272 * than us since we can terminate without allocating more memory.
2273 */
2274 if (VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY))
2275 {
2276 rc2 = PGMR3PhysAllocateHandyPages(pVM);
2277 UPDATE_RC();
2278 if (rc == VINF_EM_NO_MEMORY)
2279 return rc;
2280 }
2281
2282 /*
2283 * If the virtual sync clock is still stopped, make TM restart it.
2284 */
2285 if (VM_FF_IS_SET(pVM, VM_FF_TM_VIRTUAL_SYNC))
2286 TMR3VirtualSyncFF(pVM, pVCpu);
2287
2288#ifdef DEBUG
2289 /*
2290 * Debug, pause the VM.
2291 */
2292 if (VM_FF_IS_SET(pVM, VM_FF_DEBUG_SUSPEND))
2293 {
2294 VM_FF_CLEAR(pVM, VM_FF_DEBUG_SUSPEND);
2295 Log(("emR3ForcedActions: returns VINF_EM_SUSPEND\n"));
2296 return VINF_EM_SUSPEND;
2297 }
2298#endif
2299
2300 /* check that we got them all */
2301 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));
2302 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)));
2303 }
2304
2305#undef UPDATE_RC
2306 Log2(("emR3ForcedActions: returns %Rrc\n", rc));
2307 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatForcedActions, a);
2308 Assert(rcIrq == VINF_SUCCESS || rcIrq == rc);
2309 return rc;
2310}
2311
2312
2313/**
2314 * Check if the preset execution time cap restricts guest execution scheduling.
2315 *
2316 * @returns true if allowed, false otherwise
2317 * @param pVM The cross context VM structure.
2318 * @param pVCpu The cross context virtual CPU structure.
2319 */
2320bool emR3IsExecutionAllowed(PVM pVM, PVMCPU pVCpu)
2321{
2322 uint64_t u64UserTime, u64KernelTime;
2323
2324 if ( pVM->uCpuExecutionCap != 100
2325 && RT_SUCCESS(RTThreadGetExecutionTimeMilli(&u64KernelTime, &u64UserTime)))
2326 {
2327 uint64_t u64TimeNow = RTTimeMilliTS();
2328 if (pVCpu->em.s.u64TimeSliceStart + EM_TIME_SLICE < u64TimeNow)
2329 {
2330 /* New time slice. */
2331 pVCpu->em.s.u64TimeSliceStart = u64TimeNow;
2332 pVCpu->em.s.u64TimeSliceStartExec = u64KernelTime + u64UserTime;
2333 pVCpu->em.s.u64TimeSliceExec = 0;
2334 }
2335 pVCpu->em.s.u64TimeSliceExec = u64KernelTime + u64UserTime - pVCpu->em.s.u64TimeSliceStartExec;
2336
2337 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));
2338 if (pVCpu->em.s.u64TimeSliceExec >= (EM_TIME_SLICE * pVM->uCpuExecutionCap) / 100)
2339 return false;
2340 }
2341 return true;
2342}
2343
2344
2345/**
2346 * Execute VM.
2347 *
2348 * This function is the main loop of the VM. The emulation thread
2349 * calls this function when the VM has been successfully constructed
2350 * and we're ready for executing the VM.
2351 *
2352 * Returning from this function means that the VM is turned off or
2353 * suspended (state already saved) and deconstruction is next in line.
2354 *
2355 * All interaction from other thread are done using forced actions
2356 * and signaling of the wait object.
2357 *
2358 * @returns VBox status code, informational status codes may indicate failure.
2359 * @param pVM The cross context VM structure.
2360 * @param pVCpu The cross context virtual CPU structure.
2361 */
2362VMMR3_INT_DECL(int) EMR3ExecuteVM(PVM pVM, PVMCPU pVCpu)
2363{
2364 Log(("EMR3ExecuteVM: pVM=%p enmVMState=%d (%s) enmState=%d (%s) enmPrevState=%d (%s) fForceRAW=%RTbool\n",
2365 pVM,
2366 pVM->enmVMState, VMR3GetStateName(pVM->enmVMState),
2367 pVCpu->em.s.enmState, emR3GetStateName(pVCpu->em.s.enmState),
2368 pVCpu->em.s.enmPrevState, emR3GetStateName(pVCpu->em.s.enmPrevState),
2369 pVCpu->em.s.fForceRAW));
2370 VM_ASSERT_EMT(pVM);
2371 AssertMsg( pVCpu->em.s.enmState == EMSTATE_NONE
2372 || pVCpu->em.s.enmState == EMSTATE_WAIT_SIPI
2373 || pVCpu->em.s.enmState == EMSTATE_SUSPENDED,
2374 ("%s\n", emR3GetStateName(pVCpu->em.s.enmState)));
2375
2376 int rc = setjmp(pVCpu->em.s.u.FatalLongJump);
2377 if (rc == 0)
2378 {
2379 /*
2380 * Start the virtual time.
2381 */
2382 TMR3NotifyResume(pVM, pVCpu);
2383
2384 /*
2385 * The Outer Main Loop.
2386 */
2387 bool fFFDone = false;
2388
2389 /* Reschedule right away to start in the right state. */
2390 rc = VINF_SUCCESS;
2391
2392 /* If resuming after a pause or a state load, restore the previous
2393 state or else we'll start executing code. Else, just reschedule. */
2394 if ( pVCpu->em.s.enmState == EMSTATE_SUSPENDED
2395 && ( pVCpu->em.s.enmPrevState == EMSTATE_WAIT_SIPI
2396 || pVCpu->em.s.enmPrevState == EMSTATE_HALTED))
2397 pVCpu->em.s.enmState = pVCpu->em.s.enmPrevState;
2398 else
2399 pVCpu->em.s.enmState = emR3Reschedule(pVM, pVCpu);
2400 pVCpu->em.s.cIemThenRemInstructions = 0;
2401 Log(("EMR3ExecuteVM: enmState=%s\n", emR3GetStateName(pVCpu->em.s.enmState)));
2402
2403 STAM_REL_PROFILE_ADV_START(&pVCpu->em.s.StatTotal, x);
2404 for (;;)
2405 {
2406 /*
2407 * Before we can schedule anything (we're here because
2408 * scheduling is required) we must service any pending
2409 * forced actions to avoid any pending action causing
2410 * immediate rescheduling upon entering an inner loop
2411 *
2412 * Do forced actions.
2413 */
2414 if ( !fFFDone
2415 && RT_SUCCESS(rc)
2416 && rc != VINF_EM_TERMINATE
2417 && rc != VINF_EM_OFF
2418 && ( VM_FF_IS_ANY_SET(pVM, VM_FF_ALL_REM_MASK)
2419 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_ALL_REM_MASK & ~VMCPU_FF_UNHALT)))
2420 {
2421 rc = emR3ForcedActions(pVM, pVCpu, rc);
2422 VBOXVMM_EM_FF_ALL_RET(pVCpu, rc);
2423 if ( ( rc == VINF_EM_RESCHEDULE_REM
2424 || rc == VINF_EM_RESCHEDULE_HM)
2425 && pVCpu->em.s.fForceRAW)
2426 rc = VINF_EM_RESCHEDULE_RAW;
2427 }
2428 else if (fFFDone)
2429 fFFDone = false;
2430
2431 /*
2432 * Now what to do?
2433 */
2434 Log2(("EMR3ExecuteVM: rc=%Rrc\n", rc));
2435 EMSTATE const enmOldState = pVCpu->em.s.enmState;
2436 switch (rc)
2437 {
2438 /*
2439 * Keep doing what we're currently doing.
2440 */
2441 case VINF_SUCCESS:
2442 break;
2443
2444 /*
2445 * Reschedule - to raw-mode execution.
2446 */
2447/** @todo r=bird: consider merging VINF_EM_RESCHEDULE_RAW with VINF_EM_RESCHEDULE_HM, they serve the same purpose here at least. */
2448 case VINF_EM_RESCHEDULE_RAW:
2449 Assert(!pVM->em.s.fIemExecutesAll || pVCpu->em.s.enmState != EMSTATE_IEM);
2450 if (VM_IS_RAW_MODE_ENABLED(pVM))
2451 {
2452 Log2(("EMR3ExecuteVM: VINF_EM_RESCHEDULE_RAW: %d -> %d (EMSTATE_RAW)\n", enmOldState, EMSTATE_RAW));
2453 pVCpu->em.s.enmState = EMSTATE_RAW;
2454 }
2455 else
2456 {
2457 AssertLogRelFailed();
2458 pVCpu->em.s.enmState = EMSTATE_NONE;
2459 }
2460 break;
2461
2462 /*
2463 * Reschedule - to HM or NEM.
2464 */
2465 case VINF_EM_RESCHEDULE_HM:
2466 Assert(!pVM->em.s.fIemExecutesAll || pVCpu->em.s.enmState != EMSTATE_IEM);
2467 Assert(!pVCpu->em.s.fForceRAW);
2468 if (VM_IS_HM_ENABLED(pVM))
2469 {
2470 Log2(("EMR3ExecuteVM: VINF_EM_RESCHEDULE_HM: %d -> %d (EMSTATE_HM)\n", enmOldState, EMSTATE_HM));
2471 pVCpu->em.s.enmState = EMSTATE_HM;
2472 }
2473 else if (VM_IS_NEM_ENABLED(pVM))
2474 {
2475 Log2(("EMR3ExecuteVM: VINF_EM_RESCHEDULE_HM: %d -> %d (EMSTATE_NEM)\n", enmOldState, EMSTATE_NEM));
2476 pVCpu->em.s.enmState = EMSTATE_NEM;
2477 }
2478 else
2479 {
2480 AssertLogRelFailed();
2481 pVCpu->em.s.enmState = EMSTATE_NONE;
2482 }
2483 break;
2484
2485 /*
2486 * Reschedule - to recompiled execution.
2487 */
2488 case VINF_EM_RESCHEDULE_REM:
2489 Assert(!pVM->em.s.fIemExecutesAll || pVCpu->em.s.enmState != EMSTATE_IEM);
2490 if (!VM_IS_RAW_MODE_ENABLED(pVM))
2491 {
2492 Log2(("EMR3ExecuteVM: VINF_EM_RESCHEDULE_REM: %d -> %d (EMSTATE_IEM_THEN_REM)\n",
2493 enmOldState, EMSTATE_IEM_THEN_REM));
2494 if (pVCpu->em.s.enmState != EMSTATE_IEM_THEN_REM)
2495 {
2496 pVCpu->em.s.enmState = EMSTATE_IEM_THEN_REM;
2497 pVCpu->em.s.cIemThenRemInstructions = 0;
2498 }
2499 }
2500 else
2501 {
2502 Log2(("EMR3ExecuteVM: VINF_EM_RESCHEDULE_REM: %d -> %d (EMSTATE_REM)\n", enmOldState, EMSTATE_REM));
2503 pVCpu->em.s.enmState = EMSTATE_REM;
2504 }
2505 break;
2506
2507 /*
2508 * Resume.
2509 */
2510 case VINF_EM_RESUME:
2511 Log2(("EMR3ExecuteVM: VINF_EM_RESUME: %d -> VINF_EM_RESCHEDULE\n", enmOldState));
2512 /* Don't reschedule in the halted or wait for SIPI case. */
2513 if ( pVCpu->em.s.enmPrevState == EMSTATE_WAIT_SIPI
2514 || pVCpu->em.s.enmPrevState == EMSTATE_HALTED)
2515 {
2516 pVCpu->em.s.enmState = pVCpu->em.s.enmPrevState;
2517 break;
2518 }
2519 /* fall through and get scheduled. */
2520 RT_FALL_THRU();
2521
2522 /*
2523 * Reschedule.
2524 */
2525 case VINF_EM_RESCHEDULE:
2526 {
2527 EMSTATE enmState = emR3Reschedule(pVM, pVCpu);
2528 Log2(("EMR3ExecuteVM: VINF_EM_RESCHEDULE: %d -> %d (%s)\n", enmOldState, enmState, emR3GetStateName(enmState)));
2529 if (pVCpu->em.s.enmState != enmState && enmState == EMSTATE_IEM_THEN_REM)
2530 pVCpu->em.s.cIemThenRemInstructions = 0;
2531 pVCpu->em.s.enmState = enmState;
2532 break;
2533 }
2534
2535 /*
2536 * Halted.
2537 */
2538 case VINF_EM_HALT:
2539 Log2(("EMR3ExecuteVM: VINF_EM_HALT: %d -> %d\n", enmOldState, EMSTATE_HALTED));
2540 pVCpu->em.s.enmState = EMSTATE_HALTED;
2541 break;
2542
2543 /*
2544 * Switch to the wait for SIPI state (application processor only)
2545 */
2546 case VINF_EM_WAIT_SIPI:
2547 Assert(pVCpu->idCpu != 0);
2548 Log2(("EMR3ExecuteVM: VINF_EM_WAIT_SIPI: %d -> %d\n", enmOldState, EMSTATE_WAIT_SIPI));
2549 pVCpu->em.s.enmState = EMSTATE_WAIT_SIPI;
2550 break;
2551
2552
2553 /*
2554 * Suspend.
2555 */
2556 case VINF_EM_SUSPEND:
2557 Log2(("EMR3ExecuteVM: VINF_EM_SUSPEND: %d -> %d\n", enmOldState, EMSTATE_SUSPENDED));
2558 Assert(enmOldState != EMSTATE_SUSPENDED);
2559 pVCpu->em.s.enmPrevState = enmOldState;
2560 pVCpu->em.s.enmState = EMSTATE_SUSPENDED;
2561 break;
2562
2563 /*
2564 * Reset.
2565 * We might end up doing a double reset for now, we'll have to clean up the mess later.
2566 */
2567 case VINF_EM_RESET:
2568 {
2569 if (pVCpu->idCpu == 0)
2570 {
2571 EMSTATE enmState = emR3Reschedule(pVM, pVCpu);
2572 Log2(("EMR3ExecuteVM: VINF_EM_RESET: %d -> %d (%s)\n", enmOldState, enmState, emR3GetStateName(enmState)));
2573 if (pVCpu->em.s.enmState != enmState && enmState == EMSTATE_IEM_THEN_REM)
2574 pVCpu->em.s.cIemThenRemInstructions = 0;
2575 pVCpu->em.s.enmState = enmState;
2576 }
2577 else
2578 {
2579 /* All other VCPUs go into the wait for SIPI state. */
2580 pVCpu->em.s.enmState = EMSTATE_WAIT_SIPI;
2581 }
2582 break;
2583 }
2584
2585 /*
2586 * Power Off.
2587 */
2588 case VINF_EM_OFF:
2589 pVCpu->em.s.enmState = EMSTATE_TERMINATING;
2590 Log2(("EMR3ExecuteVM: returns VINF_EM_OFF (%d -> %d)\n", enmOldState, EMSTATE_TERMINATING));
2591 TMR3NotifySuspend(pVM, pVCpu);
2592 STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x);
2593 return rc;
2594
2595 /*
2596 * Terminate the VM.
2597 */
2598 case VINF_EM_TERMINATE:
2599 pVCpu->em.s.enmState = EMSTATE_TERMINATING;
2600 Log(("EMR3ExecuteVM returns VINF_EM_TERMINATE (%d -> %d)\n", enmOldState, EMSTATE_TERMINATING));
2601 if (pVM->enmVMState < VMSTATE_DESTROYING) /* ugly */
2602 TMR3NotifySuspend(pVM, pVCpu);
2603 STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x);
2604 return rc;
2605
2606
2607 /*
2608 * Out of memory, suspend the VM and stuff.
2609 */
2610 case VINF_EM_NO_MEMORY:
2611 Log2(("EMR3ExecuteVM: VINF_EM_NO_MEMORY: %d -> %d\n", enmOldState, EMSTATE_SUSPENDED));
2612 Assert(enmOldState != EMSTATE_SUSPENDED);
2613 pVCpu->em.s.enmPrevState = enmOldState;
2614 pVCpu->em.s.enmState = EMSTATE_SUSPENDED;
2615 TMR3NotifySuspend(pVM, pVCpu);
2616 STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x);
2617
2618 rc = VMSetRuntimeError(pVM, VMSETRTERR_FLAGS_SUSPEND, "HostMemoryLow",
2619 N_("Unable to allocate and lock memory. The virtual machine will be paused. Please close applications to free up memory or close the VM"));
2620 if (rc != VINF_EM_SUSPEND)
2621 {
2622 if (RT_SUCCESS_NP(rc))
2623 {
2624 AssertLogRelMsgFailed(("%Rrc\n", rc));
2625 rc = VERR_EM_INTERNAL_ERROR;
2626 }
2627 pVCpu->em.s.enmState = EMSTATE_GURU_MEDITATION;
2628 }
2629 return rc;
2630
2631 /*
2632 * Guest debug events.
2633 */
2634 case VINF_EM_DBG_STEPPED:
2635 case VINF_EM_DBG_STOP:
2636 case VINF_EM_DBG_EVENT:
2637 case VINF_EM_DBG_BREAKPOINT:
2638 case VINF_EM_DBG_STEP:
2639 if (enmOldState == EMSTATE_RAW)
2640 {
2641 Log2(("EMR3ExecuteVM: %Rrc: %d -> %d\n", rc, enmOldState, EMSTATE_DEBUG_GUEST_RAW));
2642 pVCpu->em.s.enmState = EMSTATE_DEBUG_GUEST_RAW;
2643 }
2644 else if (enmOldState == EMSTATE_HM)
2645 {
2646 Log2(("EMR3ExecuteVM: %Rrc: %d -> %d\n", rc, enmOldState, EMSTATE_DEBUG_GUEST_HM));
2647 pVCpu->em.s.enmState = EMSTATE_DEBUG_GUEST_HM;
2648 }
2649 else if (enmOldState == EMSTATE_NEM)
2650 {
2651 Log2(("EMR3ExecuteVM: %Rrc: %d -> %d\n", rc, enmOldState, EMSTATE_DEBUG_GUEST_NEM));
2652 pVCpu->em.s.enmState = EMSTATE_DEBUG_GUEST_NEM;
2653 }
2654 else if (enmOldState == EMSTATE_REM)
2655 {
2656 Log2(("EMR3ExecuteVM: %Rrc: %d -> %d\n", rc, enmOldState, EMSTATE_DEBUG_GUEST_REM));
2657 pVCpu->em.s.enmState = EMSTATE_DEBUG_GUEST_REM;
2658 }
2659 else
2660 {
2661 Log2(("EMR3ExecuteVM: %Rrc: %d -> %d\n", rc, enmOldState, EMSTATE_DEBUG_GUEST_IEM));
2662 pVCpu->em.s.enmState = EMSTATE_DEBUG_GUEST_IEM;
2663 }
2664 break;
2665
2666 /*
2667 * Hypervisor debug events.
2668 */
2669 case VINF_EM_DBG_HYPER_STEPPED:
2670 case VINF_EM_DBG_HYPER_BREAKPOINT:
2671 case VINF_EM_DBG_HYPER_ASSERTION:
2672 Log2(("EMR3ExecuteVM: %Rrc: %d -> %d\n", rc, enmOldState, EMSTATE_DEBUG_HYPER));
2673 pVCpu->em.s.enmState = EMSTATE_DEBUG_HYPER;
2674 break;
2675
2676 /*
2677 * Triple fault.
2678 */
2679 case VINF_EM_TRIPLE_FAULT:
2680 if (!pVM->em.s.fGuruOnTripleFault)
2681 {
2682 Log(("EMR3ExecuteVM: VINF_EM_TRIPLE_FAULT: CPU reset...\n"));
2683 rc = VBOXSTRICTRC_TODO(VMR3ResetTripleFault(pVM));
2684 Log2(("EMR3ExecuteVM: VINF_EM_TRIPLE_FAULT: %d -> %d (rc=%Rrc)\n", enmOldState, pVCpu->em.s.enmState, rc));
2685 continue;
2686 }
2687 /* Else fall through and trigger a guru. */
2688 RT_FALL_THRU();
2689
2690 case VERR_VMM_RING0_ASSERTION:
2691 Log(("EMR3ExecuteVM: %Rrc: %d -> %d (EMSTATE_GURU_MEDITATION)\n", rc, enmOldState, EMSTATE_GURU_MEDITATION));
2692 pVCpu->em.s.enmState = EMSTATE_GURU_MEDITATION;
2693 break;
2694
2695 /*
2696 * Any error code showing up here other than the ones we
2697 * know and process above are considered to be FATAL.
2698 *
2699 * Unknown warnings and informational status codes are also
2700 * included in this.
2701 */
2702 default:
2703 if (RT_SUCCESS_NP(rc))
2704 {
2705 AssertMsgFailed(("Unexpected warning or informational status code %Rra!\n", rc));
2706 rc = VERR_EM_INTERNAL_ERROR;
2707 }
2708 Log(("EMR3ExecuteVM: %Rrc: %d -> %d (EMSTATE_GURU_MEDITATION)\n", rc, enmOldState, EMSTATE_GURU_MEDITATION));
2709 pVCpu->em.s.enmState = EMSTATE_GURU_MEDITATION;
2710 break;
2711 }
2712
2713 /*
2714 * Act on state transition.
2715 */
2716 EMSTATE const enmNewState = pVCpu->em.s.enmState;
2717 if (enmOldState != enmNewState)
2718 {
2719 VBOXVMM_EM_STATE_CHANGED(pVCpu, enmOldState, enmNewState, rc);
2720
2721 /* Clear MWait flags and the unhalt FF. */
2722 if ( enmOldState == EMSTATE_HALTED
2723 && ( (pVCpu->em.s.MWait.fWait & EMMWAIT_FLAG_ACTIVE)
2724 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_UNHALT))
2725 && ( enmNewState == EMSTATE_RAW
2726 || enmNewState == EMSTATE_HM
2727 || enmNewState == EMSTATE_NEM
2728 || enmNewState == EMSTATE_REM
2729 || enmNewState == EMSTATE_IEM_THEN_REM
2730 || enmNewState == EMSTATE_DEBUG_GUEST_RAW
2731 || enmNewState == EMSTATE_DEBUG_GUEST_HM
2732 || enmNewState == EMSTATE_DEBUG_GUEST_NEM
2733 || enmNewState == EMSTATE_DEBUG_GUEST_IEM
2734 || enmNewState == EMSTATE_DEBUG_GUEST_REM) )
2735 {
2736 if (pVCpu->em.s.MWait.fWait & EMMWAIT_FLAG_ACTIVE)
2737 {
2738 LogFlow(("EMR3ExecuteVM: Clearing MWAIT\n"));
2739 pVCpu->em.s.MWait.fWait &= ~(EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0);
2740 }
2741 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_UNHALT))
2742 {
2743 LogFlow(("EMR3ExecuteVM: Clearing UNHALT\n"));
2744 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_UNHALT);
2745 }
2746 }
2747 }
2748 else
2749 VBOXVMM_EM_STATE_UNCHANGED(pVCpu, enmNewState, rc);
2750
2751 STAM_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x); /* (skip this in release) */
2752 STAM_PROFILE_ADV_START(&pVCpu->em.s.StatTotal, x);
2753
2754 /*
2755 * Act on the new state.
2756 */
2757 switch (enmNewState)
2758 {
2759 /*
2760 * Execute raw.
2761 */
2762 case EMSTATE_RAW:
2763#ifdef VBOX_WITH_RAW_MODE
2764 rc = emR3RawExecute(pVM, pVCpu, &fFFDone);
2765#else
2766 AssertLogRelMsgFailed(("%Rrc\n", rc));
2767 rc = VERR_EM_INTERNAL_ERROR;
2768#endif
2769 break;
2770
2771 /*
2772 * Execute hardware accelerated raw.
2773 */
2774 case EMSTATE_HM:
2775 rc = emR3HmExecute(pVM, pVCpu, &fFFDone);
2776 break;
2777
2778 /*
2779 * Execute hardware accelerated raw.
2780 */
2781 case EMSTATE_NEM:
2782 rc = VBOXSTRICTRC_TODO(emR3NemExecute(pVM, pVCpu, &fFFDone));
2783 break;
2784
2785 /*
2786 * Execute recompiled.
2787 */
2788 case EMSTATE_REM:
2789 rc = emR3RemExecute(pVM, pVCpu, &fFFDone);
2790 Log2(("EMR3ExecuteVM: emR3RemExecute -> %Rrc\n", rc));
2791 break;
2792
2793 /*
2794 * Execute in the interpreter.
2795 */
2796 case EMSTATE_IEM:
2797 {
2798#if 0 /* For testing purposes. */
2799 STAM_PROFILE_START(&pVCpu->em.s.StatHmExec, x1);
2800 rc = VBOXSTRICTRC_TODO(EMR3HmSingleInstruction(pVM, pVCpu, EM_ONE_INS_FLAGS_RIP_CHANGE));
2801 STAM_PROFILE_STOP(&pVCpu->em.s.StatHmExec, x1);
2802 if (rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_RESCHEDULE_HM || rc == VINF_EM_RESCHEDULE_REM || rc == VINF_EM_RESCHEDULE_RAW)
2803 rc = VINF_SUCCESS;
2804 else if (rc == VERR_EM_CANNOT_EXEC_GUEST)
2805#endif
2806 rc = VBOXSTRICTRC_TODO(IEMExecLots(pVCpu, NULL /*pcInstructions*/));
2807 if (pVM->em.s.fIemExecutesAll)
2808 {
2809 Assert(rc != VINF_EM_RESCHEDULE_REM);
2810 Assert(rc != VINF_EM_RESCHEDULE_RAW);
2811 Assert(rc != VINF_EM_RESCHEDULE_HM);
2812 }
2813 fFFDone = false;
2814 break;
2815 }
2816
2817 /*
2818 * Execute in IEM, hoping we can quickly switch aback to HM
2819 * or RAW execution. If our hopes fail, we go to REM.
2820 */
2821 case EMSTATE_IEM_THEN_REM:
2822 {
2823 STAM_PROFILE_START(&pVCpu->em.s.StatIEMThenREM, pIemThenRem);
2824 rc = VBOXSTRICTRC_TODO(emR3ExecuteIemThenRem(pVM, pVCpu, &fFFDone));
2825 STAM_PROFILE_STOP(&pVCpu->em.s.StatIEMThenREM, pIemThenRem);
2826 break;
2827 }
2828
2829 /*
2830 * Application processor execution halted until SIPI.
2831 */
2832 case EMSTATE_WAIT_SIPI:
2833 /* no break */
2834 /*
2835 * hlt - execution halted until interrupt.
2836 */
2837 case EMSTATE_HALTED:
2838 {
2839 STAM_REL_PROFILE_START(&pVCpu->em.s.StatHalted, y);
2840 /* If HM (or someone else) store a pending interrupt in
2841 TRPM, it must be dispatched ASAP without any halting.
2842 Anything pending in TRPM has been accepted and the CPU
2843 should already be the right state to receive it. */
2844 if (TRPMHasTrap(pVCpu))
2845 rc = VINF_EM_RESCHEDULE;
2846 /* MWAIT has a special extension where it's woken up when
2847 an interrupt is pending even when IF=0. */
2848 else if ( (pVCpu->em.s.MWait.fWait & (EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0))
2849 == (EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0))
2850 {
2851 rc = VMR3WaitHalted(pVM, pVCpu, false /*fIgnoreInterrupts*/);
2852 if (rc == VINF_SUCCESS)
2853 {
2854 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
2855 APICUpdatePendingInterrupts(pVCpu);
2856
2857 if (VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC
2858 | VMCPU_FF_INTERRUPT_NMI | VMCPU_FF_INTERRUPT_SMI | VMCPU_FF_UNHALT))
2859 {
2860 Log(("EMR3ExecuteVM: Triggering reschedule on pending IRQ after MWAIT\n"));
2861 rc = VINF_EM_RESCHEDULE;
2862 }
2863 }
2864 }
2865 else
2866 {
2867 rc = VMR3WaitHalted(pVM, pVCpu, !(CPUMGetGuestEFlags(pVCpu) & X86_EFL_IF));
2868 /* We're only interested in NMI/SMIs here which have their own FFs, so we don't need to
2869 check VMCPU_FF_UPDATE_APIC here. */
2870 if ( rc == VINF_SUCCESS
2871 && VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI | VMCPU_FF_INTERRUPT_SMI | VMCPU_FF_UNHALT))
2872 {
2873 Log(("EMR3ExecuteVM: Triggering reschedule on pending NMI/SMI/UNHALT after HLT\n"));
2874 rc = VINF_EM_RESCHEDULE;
2875 }
2876 }
2877
2878 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatHalted, y);
2879 break;
2880 }
2881
2882 /*
2883 * Suspended - return to VM.cpp.
2884 */
2885 case EMSTATE_SUSPENDED:
2886 TMR3NotifySuspend(pVM, pVCpu);
2887 STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x);
2888 Log(("EMR3ExecuteVM: actually returns %Rrc (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(enmOldState)));
2889 return VINF_EM_SUSPEND;
2890
2891 /*
2892 * Debugging in the guest.
2893 */
2894 case EMSTATE_DEBUG_GUEST_RAW:
2895 case EMSTATE_DEBUG_GUEST_HM:
2896 case EMSTATE_DEBUG_GUEST_NEM:
2897 case EMSTATE_DEBUG_GUEST_IEM:
2898 case EMSTATE_DEBUG_GUEST_REM:
2899 TMR3NotifySuspend(pVM, pVCpu);
2900 rc = VBOXSTRICTRC_TODO(emR3Debug(pVM, pVCpu, rc));
2901 TMR3NotifyResume(pVM, pVCpu);
2902 Log2(("EMR3ExecuteVM: emR3Debug -> %Rrc (state %d)\n", rc, pVCpu->em.s.enmState));
2903 break;
2904
2905 /*
2906 * Debugging in the hypervisor.
2907 */
2908 case EMSTATE_DEBUG_HYPER:
2909 {
2910 TMR3NotifySuspend(pVM, pVCpu);
2911 STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x);
2912
2913 rc = VBOXSTRICTRC_TODO(emR3Debug(pVM, pVCpu, rc));
2914 Log2(("EMR3ExecuteVM: emR3Debug -> %Rrc (state %d)\n", rc, pVCpu->em.s.enmState));
2915 if (rc != VINF_SUCCESS)
2916 {
2917 if (rc == VINF_EM_OFF || rc == VINF_EM_TERMINATE)
2918 pVCpu->em.s.enmState = EMSTATE_TERMINATING;
2919 else
2920 {
2921 /* switch to guru meditation mode */
2922 pVCpu->em.s.enmState = EMSTATE_GURU_MEDITATION;
2923 VMR3SetGuruMeditation(pVM); /* This notifies the other EMTs. */
2924 VMMR3FatalDump(pVM, pVCpu, rc);
2925 }
2926 Log(("EMR3ExecuteVM: actually returns %Rrc (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(enmOldState)));
2927 return rc;
2928 }
2929
2930 STAM_REL_PROFILE_ADV_START(&pVCpu->em.s.StatTotal, x);
2931 TMR3NotifyResume(pVM, pVCpu);
2932 break;
2933 }
2934
2935 /*
2936 * Guru meditation takes place in the debugger.
2937 */
2938 case EMSTATE_GURU_MEDITATION:
2939 {
2940 TMR3NotifySuspend(pVM, pVCpu);
2941 VMR3SetGuruMeditation(pVM); /* This notifies the other EMTs. */
2942 VMMR3FatalDump(pVM, pVCpu, rc);
2943 emR3Debug(pVM, pVCpu, rc);
2944 STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x);
2945 Log(("EMR3ExecuteVM: actually returns %Rrc (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(enmOldState)));
2946 return rc;
2947 }
2948
2949 /*
2950 * The states we don't expect here.
2951 */
2952 case EMSTATE_NONE:
2953 case EMSTATE_TERMINATING:
2954 default:
2955 AssertMsgFailed(("EMR3ExecuteVM: Invalid state %d!\n", pVCpu->em.s.enmState));
2956 pVCpu->em.s.enmState = EMSTATE_GURU_MEDITATION;
2957 TMR3NotifySuspend(pVM, pVCpu);
2958 STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x);
2959 Log(("EMR3ExecuteVM: actually returns %Rrc (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(enmOldState)));
2960 return VERR_EM_INTERNAL_ERROR;
2961 }
2962 } /* The Outer Main Loop */
2963 }
2964 else
2965 {
2966 /*
2967 * Fatal error.
2968 */
2969 Log(("EMR3ExecuteVM: returns %Rrc because of longjmp / fatal error; (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(pVCpu->em.s.enmPrevState)));
2970 TMR3NotifySuspend(pVM, pVCpu);
2971 VMR3SetGuruMeditation(pVM); /* This notifies the other EMTs. */
2972 VMMR3FatalDump(pVM, pVCpu, rc);
2973 emR3Debug(pVM, pVCpu, rc);
2974 STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x);
2975 /** @todo change the VM state! */
2976 return rc;
2977 }
2978
2979 /* not reached */
2980}
2981
2982/**
2983 * Notify EM of a state change (used by FTM)
2984 *
2985 * @param pVM The cross context VM structure.
2986 */
2987VMMR3_INT_DECL(int) EMR3NotifySuspend(PVM pVM)
2988{
2989 PVMCPU pVCpu = VMMGetCpu(pVM);
2990
2991 TMR3NotifySuspend(pVM, pVCpu); /* Stop the virtual time. */
2992 pVCpu->em.s.enmPrevState = pVCpu->em.s.enmState;
2993 pVCpu->em.s.enmState = EMSTATE_SUSPENDED;
2994 return VINF_SUCCESS;
2995}
2996
2997/**
2998 * Notify EM of a state change (used by FTM)
2999 *
3000 * @param pVM The cross context VM structure.
3001 */
3002VMMR3_INT_DECL(int) EMR3NotifyResume(PVM pVM)
3003{
3004 PVMCPU pVCpu = VMMGetCpu(pVM);
3005 EMSTATE enmCurState = pVCpu->em.s.enmState;
3006
3007 TMR3NotifyResume(pVM, pVCpu); /* Resume the virtual time. */
3008 pVCpu->em.s.enmState = pVCpu->em.s.enmPrevState;
3009 pVCpu->em.s.enmPrevState = enmCurState;
3010 return VINF_SUCCESS;
3011}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use