VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/EMHM.cpp@ 99220

Last change on this file since 99220 was 99220, checked in by vboxsync, 20 months ago

Disassember,*: Start separating the disassembler into a architecture specific and common part, bugref:10394

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.6 KB
Line 
1/* $Id: EMHM.cpp 99220 2023-03-30 12:40:46Z vboxsync $ */
2/** @file
3 * EM - Execution Monitor / Manager - hardware virtualization
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_EM
33#define VMCPU_INCL_CPUM_GST_CTX
34#include <VBox/vmm/em.h>
35#include <VBox/vmm/vmm.h>
36#include <VBox/vmm/selm.h>
37#include <VBox/vmm/trpm.h>
38#include <VBox/vmm/iem.h>
39#include <VBox/vmm/iom.h>
40#include <VBox/vmm/dbgf.h>
41#include <VBox/vmm/pgm.h>
42#include <VBox/vmm/tm.h>
43#include <VBox/vmm/mm.h>
44#include <VBox/vmm/ssm.h>
45#include <VBox/vmm/pdmapi.h>
46#include <VBox/vmm/pdmcritsect.h>
47#include <VBox/vmm/pdmqueue.h>
48#include <VBox/vmm/hm.h>
49#include "EMInternal.h"
50#include <VBox/vmm/vm.h>
51#include <VBox/vmm/gim.h>
52#include <VBox/vmm/cpumdis.h>
53#include <VBox/dis.h>
54#include <VBox/err.h>
55#include <VBox/vmm/dbgf.h>
56#include "VMMTracing.h"
57
58#include <iprt/asm.h>
59
60
61/*********************************************************************************************************************************
62* Internal Functions *
63*********************************************************************************************************************************/
64static int emR3HmHandleRC(PVM pVM, PVMCPU pVCpu, int rc);
65DECLINLINE(int) emR3HmExecuteInstruction(PVM pVM, PVMCPU pVCpu, const char *pszPrefix, int rcGC = VINF_SUCCESS);
66static int emR3HmExecuteIOInstruction(PVM pVM, PVMCPU pVCpu);
67static int emR3HmForcedActions(PVM pVM, PVMCPU pVCpu);
68
69#define EMHANDLERC_WITH_HM
70#define emR3ExecuteInstruction emR3HmExecuteInstruction
71#define emR3ExecuteIOInstruction emR3HmExecuteIOInstruction
72#include "EMHandleRCTmpl.h"
73
74
75/**
76 * Executes instruction in HM mode if we can.
77 *
78 * This is somewhat comparable to REMR3EmulateInstruction.
79 *
80 * @returns VBox strict status code.
81 * @retval VINF_EM_DBG_STEPPED on success.
82 * @retval VERR_EM_CANNOT_EXEC_GUEST if we cannot execute guest instructions in
83 * HM right now.
84 *
85 * @param pVM The cross context VM structure.
86 * @param pVCpu The cross context virtual CPU structure for the calling EMT.
87 * @param fFlags Combinations of EM_ONE_INS_FLAGS_XXX.
88 * @thread EMT.
89 */
90VMMR3_INT_DECL(VBOXSTRICTRC) EMR3HmSingleInstruction(PVM pVM, PVMCPU pVCpu, uint32_t fFlags)
91{
92 Assert(!(fFlags & ~EM_ONE_INS_FLAGS_MASK));
93
94 if (!HMCanExecuteGuest(pVM, pVCpu, &pVCpu->cpum.GstCtx))
95 return VINF_EM_RESCHEDULE;
96
97 uint64_t const uOldRip = pVCpu->cpum.GstCtx.rip;
98 for (;;)
99 {
100 /*
101 * Service necessary FFs before going into HM.
102 */
103 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HIGH_PRIORITY_PRE_RAW_MASK)
104 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HIGH_PRIORITY_PRE_RAW_MASK))
105 {
106 VBOXSTRICTRC rcStrict = emR3HmForcedActions(pVM, pVCpu);
107 if (rcStrict != VINF_SUCCESS)
108 {
109 Log(("EMR3HmSingleInstruction: FFs before -> %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
110 return rcStrict;
111 }
112 }
113
114 /*
115 * Go execute it.
116 */
117 bool fOld = HMSetSingleInstruction(pVM, pVCpu, true);
118 VBOXSTRICTRC rcStrict = VMMR3HmRunGC(pVM, pVCpu);
119 HMSetSingleInstruction(pVM, pVCpu, fOld);
120 LogFlow(("EMR3HmSingleInstruction: %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
121
122 /*
123 * Handle high priority FFs and informational status codes. We don't do
124 * normal FF processing the caller or the next call can deal with them.
125 */
126 VMCPU_FF_CLEAR_MASK(pVCpu, VMCPU_FF_RESUME_GUEST_MASK);
127 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HIGH_PRIORITY_POST_MASK)
128 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HIGH_PRIORITY_POST_MASK))
129 {
130 rcStrict = emR3HighPriorityPostForcedActions(pVM, pVCpu, rcStrict);
131 LogFlow(("EMR3HmSingleInstruction: FFs after -> %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
132 }
133
134 if (rcStrict != VINF_SUCCESS && (rcStrict < VINF_EM_FIRST || rcStrict > VINF_EM_LAST))
135 {
136 rcStrict = emR3HmHandleRC(pVM, pVCpu, VBOXSTRICTRC_TODO(rcStrict));
137 Log(("EMR3HmSingleInstruction: emR3HmHandleRC -> %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
138 }
139
140 /*
141 * Done?
142 */
143 if ( (rcStrict != VINF_SUCCESS && rcStrict != VINF_EM_DBG_STEPPED)
144 || !(fFlags & EM_ONE_INS_FLAGS_RIP_CHANGE)
145 || pVCpu->cpum.GstCtx.rip != uOldRip)
146 {
147 if (rcStrict == VINF_SUCCESS && pVCpu->cpum.GstCtx.rip != uOldRip)
148 rcStrict = VINF_EM_DBG_STEPPED;
149 Log(("EMR3HmSingleInstruction: returns %Rrc (rip %llx -> %llx)\n", VBOXSTRICTRC_VAL(rcStrict), uOldRip, pVCpu->cpum.GstCtx.rip));
150 CPUM_IMPORT_EXTRN_RET(pVCpu, ~CPUMCTX_EXTRN_KEEPER_MASK);
151 return rcStrict;
152 }
153 }
154}
155
156
157/**
158 * Executes one (or perhaps a few more) instruction(s).
159 *
160 * @returns VBox status code suitable for EM.
161 *
162 * @param pVM The cross context VM structure.
163 * @param pVCpu The cross context virtual CPU structure.
164 * @param rcRC Return code from RC.
165 * @param pszPrefix Disassembly prefix. If not NULL we'll disassemble the
166 * instruction and prefix the log output with this text.
167 */
168#if defined(LOG_ENABLED) || defined(DOXYGEN_RUNNING)
169static int emR3HmExecuteInstructionWorker(PVM pVM, PVMCPU pVCpu, int rcRC, const char *pszPrefix)
170#else
171static int emR3HmExecuteInstructionWorker(PVM pVM, PVMCPU pVCpu, int rcRC)
172#endif
173{
174 RT_NOREF(rcRC, pVM);
175
176#ifdef LOG_ENABLED
177 /*
178 * Log it.
179 */
180 Log(("EMINS: %04x:%RGv RSP=%RGv\n", pVCpu->cpum.GstCtx.cs.Sel, (RTGCPTR)pVCpu->cpum.GstCtx.rip, (RTGCPTR)pVCpu->cpum.GstCtx.rsp));
181 if (pszPrefix)
182 {
183 DBGFR3_INFO_LOG(pVM, pVCpu, "cpumguest", pszPrefix);
184 DBGFR3_DISAS_INSTR_CUR_LOG(pVCpu, pszPrefix);
185 }
186#endif
187
188 /*
189 * Use IEM and fallback on REM if the functionality is missing.
190 * Once IEM gets mature enough, nothing should ever fall back.
191 */
192 STAM_PROFILE_START(&pVCpu->em.s.StatIEMEmu, a);
193 VBOXSTRICTRC rcStrict;
194 uint32_t idxContinueExitRec = pVCpu->em.s.idxContinueExitRec;
195 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
196 if (idxContinueExitRec >= RT_ELEMENTS(pVCpu->em.s.aExitRecords))
197 {
198 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_MUST_MASK);
199 rcStrict = VBOXSTRICTRC_TODO(IEMExecOne(pVCpu));
200 }
201 else
202 {
203 RT_UNTRUSTED_VALIDATED_FENCE();
204 rcStrict = EMHistoryExec(pVCpu, &pVCpu->em.s.aExitRecords[idxContinueExitRec], 0);
205 LogFlow(("emR3HmExecuteInstruction: %Rrc (EMHistoryExec)\n", VBOXSTRICTRC_VAL(rcStrict)));
206 }
207 STAM_PROFILE_STOP(&pVCpu->em.s.StatIEMEmu, a);
208
209 return VBOXSTRICTRC_TODO(rcStrict);
210}
211
212
213/**
214 * Executes one (or perhaps a few more) instruction(s).
215 * This is just a wrapper for discarding pszPrefix in non-logging builds.
216 *
217 * @returns VBox status code suitable for EM.
218 * @param pVM The cross context VM structure.
219 * @param pVCpu The cross context virtual CPU structure.
220 * @param pszPrefix Disassembly prefix. If not NULL we'll disassemble the
221 * instruction and prefix the log output with this text.
222 * @param rcGC GC return code
223 */
224DECLINLINE(int) emR3HmExecuteInstruction(PVM pVM, PVMCPU pVCpu, const char *pszPrefix, int rcGC)
225{
226#ifdef LOG_ENABLED
227 return emR3HmExecuteInstructionWorker(pVM, pVCpu, rcGC, pszPrefix);
228#else
229 RT_NOREF_PV(pszPrefix);
230 return emR3HmExecuteInstructionWorker(pVM, pVCpu, rcGC);
231#endif
232}
233
234
235/**
236 * Executes one (or perhaps a few more) IO instruction(s).
237 *
238 * @returns VBox status code suitable for EM.
239 * @param pVM The cross context VM structure.
240 * @param pVCpu The cross context virtual CPU structure.
241 */
242static int emR3HmExecuteIOInstruction(PVM pVM, PVMCPU pVCpu)
243{
244 RT_NOREF(pVM);
245 STAM_PROFILE_START(&pVCpu->em.s.StatIOEmu, a);
246
247 VBOXSTRICTRC rcStrict;
248 uint32_t idxContinueExitRec = pVCpu->em.s.idxContinueExitRec;
249 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
250 if (idxContinueExitRec >= RT_ELEMENTS(pVCpu->em.s.aExitRecords))
251 {
252 /*
253 * Hand it over to the interpreter.
254 */
255 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_MUST_MASK);
256 rcStrict = IEMExecOne(pVCpu);
257 LogFlow(("emR3HmExecuteIOInstruction: %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
258 }
259 else
260 {
261 RT_UNTRUSTED_VALIDATED_FENCE();
262 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_MUST_MASK);
263 rcStrict = EMHistoryExec(pVCpu, &pVCpu->em.s.aExitRecords[idxContinueExitRec], 0);
264 LogFlow(("emR3HmExecuteIOInstruction: %Rrc (EMHistoryExec)\n", VBOXSTRICTRC_VAL(rcStrict)));
265 STAM_COUNTER_INC(&pVCpu->em.s.StatIoRestarted);
266 }
267
268 STAM_COUNTER_INC(&pVCpu->em.s.StatIoIem);
269 STAM_PROFILE_STOP(&pVCpu->em.s.StatIOEmu, a);
270 return VBOXSTRICTRC_TODO(rcStrict);
271}
272
273
274/**
275 * Process HM specific forced actions.
276 *
277 * This function is called when any FFs in the VM_FF_HIGH_PRIORITY_PRE_RAW_MASK
278 * or/and VMCPU_FF_HIGH_PRIORITY_PRE_RAW_MASK are pending.
279 *
280 * @returns VBox status code. May return VINF_EM_NO_MEMORY but none of the other
281 * EM statuses.
282 * @param pVM The cross context VM structure.
283 * @param pVCpu The cross context virtual CPU structure.
284 */
285static int emR3HmForcedActions(PVM pVM, PVMCPU pVCpu)
286{
287 /*
288 * Sync page directory.
289 */
290 if (VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL))
291 {
292 CPUM_IMPORT_EXTRN_RET(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4);
293 Assert(pVCpu->em.s.enmState != EMSTATE_WAIT_SIPI);
294 int rc = PGMSyncCR3(pVCpu, pVCpu->cpum.GstCtx.cr0, pVCpu->cpum.GstCtx.cr3, pVCpu->cpum.GstCtx.cr4, VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
295 if (RT_FAILURE(rc))
296 return rc;
297
298 /* Prefetch pages for EIP and ESP. */
299 /** @todo This is rather expensive. Should investigate if it really helps at all. */
300 /** @todo this should be skipped! */
301 CPUM_IMPORT_EXTRN_RET(pVCpu, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_SS);
302 rc = PGMPrefetchPage(pVCpu, SELMToFlat(pVCpu, X86_SREG_CS, &pVCpu->cpum.GstCtx, pVCpu->cpum.GstCtx.rip));
303 if (rc == VINF_SUCCESS)
304 rc = PGMPrefetchPage(pVCpu, SELMToFlat(pVCpu, X86_SREG_SS, &pVCpu->cpum.GstCtx, pVCpu->cpum.GstCtx.rsp));
305 if (rc != VINF_SUCCESS)
306 {
307 if (rc != VINF_PGM_SYNC_CR3)
308 {
309 AssertLogRelMsgReturn(RT_FAILURE(rc), ("%Rrc\n", rc), VERR_IPE_UNEXPECTED_INFO_STATUS);
310 return rc;
311 }
312 rc = PGMSyncCR3(pVCpu, pVCpu->cpum.GstCtx.cr0, pVCpu->cpum.GstCtx.cr3, pVCpu->cpum.GstCtx.cr4, VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
313 if (RT_FAILURE(rc))
314 return rc;
315 }
316 /** @todo maybe prefetch the supervisor stack page as well */
317 }
318
319 /*
320 * Allocate handy pages (just in case the above actions have consumed some pages).
321 */
322 if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_PGM_NEED_HANDY_PAGES, VM_FF_PGM_NO_MEMORY))
323 {
324 int rc = PGMR3PhysAllocateHandyPages(pVM);
325 if (RT_FAILURE(rc))
326 return rc;
327 }
328
329 /*
330 * Check whether we're out of memory now.
331 *
332 * This may stem from some of the above actions or operations that has been executed
333 * since we ran FFs. The allocate handy pages must for instance always be followed by
334 * this check.
335 */
336 if (VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY))
337 return VINF_EM_NO_MEMORY;
338
339 return VINF_SUCCESS;
340}
341
342
343/**
344 * Executes hardware accelerated raw code. (Intel VT-x & AMD-V)
345 *
346 * This function contains the raw-mode version of the inner
347 * execution loop (the outer loop being in EMR3ExecuteVM()).
348 *
349 * @returns VBox status code. The most important ones are: VINF_EM_RESCHEDULE, VINF_EM_RESCHEDULE_RAW,
350 * VINF_EM_RESCHEDULE_REM, VINF_EM_SUSPEND, VINF_EM_RESET and VINF_EM_TERMINATE.
351 *
352 * @param pVM The cross context VM structure.
353 * @param pVCpu The cross context virtual CPU structure.
354 * @param pfFFDone Where to store an indicator telling whether or not
355 * FFs were done before returning.
356 */
357int emR3HmExecute(PVM pVM, PVMCPU pVCpu, bool *pfFFDone)
358{
359 int rc = VERR_IPE_UNINITIALIZED_STATUS;
360
361 LogFlow(("emR3HmExecute%d: (cs:eip=%04x:%RGv)\n", pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, (RTGCPTR)pVCpu->cpum.GstCtx.rip));
362 *pfFFDone = false;
363
364 STAM_REL_COUNTER_INC(&pVCpu->em.s.StatHMExecuteCalled);
365
366 /*
367 * Spin till we get a forced action which returns anything but VINF_SUCCESS.
368 */
369 for (;;)
370 {
371 STAM_PROFILE_ADV_START(&pVCpu->em.s.StatHMEntry, a);
372
373 /* Check if a forced reschedule is pending. */
374 if (HMR3IsRescheduleRequired(pVM, &pVCpu->cpum.GstCtx))
375 {
376 rc = VINF_EM_RESCHEDULE;
377 break;
378 }
379
380 /*
381 * Process high priority pre-execution raw-mode FFs.
382 */
383 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HIGH_PRIORITY_PRE_RAW_MASK)
384 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HIGH_PRIORITY_PRE_RAW_MASK))
385 {
386 rc = emR3HmForcedActions(pVM, pVCpu);
387 if (rc != VINF_SUCCESS)
388 break;
389 }
390
391#ifdef LOG_ENABLED
392 /*
393 * Log important stuff before entering GC.
394 */
395 if (TRPMHasTrap(pVCpu))
396 Log(("CPU%d: Pending hardware interrupt=0x%x cs:rip=%04X:%RGv\n", pVCpu->idCpu, TRPMGetTrapNo(pVCpu), pVCpu->cpum.GstCtx.cs.Sel, (RTGCPTR)pVCpu->cpum.GstCtx.rip));
397
398 uint32_t cpl = CPUMGetGuestCPL(pVCpu);
399 if (pVM->cCpus == 1)
400 {
401 if (pVCpu->cpum.GstCtx.eflags.Bits.u1VM)
402 Log(("HWV86: %08X IF=%d\n", pVCpu->cpum.GstCtx.eip, pVCpu->cpum.GstCtx.eflags.Bits.u1IF));
403 else if (CPUMIsGuestIn64BitCodeEx(&pVCpu->cpum.GstCtx))
404 Log(("HWR%d: %04X:%RGv ESP=%RGv IF=%d IOPL=%d CR0=%x CR4=%x EFER=%x\n", cpl, pVCpu->cpum.GstCtx.cs.Sel, (RTGCPTR)pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.rsp, pVCpu->cpum.GstCtx.eflags.Bits.u1IF, pVCpu->cpum.GstCtx.eflags.Bits.u2IOPL, (uint32_t)pVCpu->cpum.GstCtx.cr0, (uint32_t)pVCpu->cpum.GstCtx.cr4, (uint32_t)pVCpu->cpum.GstCtx.msrEFER));
405 else
406 Log(("HWR%d: %04X:%08X ESP=%08X IF=%d IOPL=%d CR0=%x CR4=%x EFER=%x\n", cpl, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.eip, pVCpu->cpum.GstCtx.esp, pVCpu->cpum.GstCtx.eflags.Bits.u1IF, pVCpu->cpum.GstCtx.eflags.Bits.u2IOPL, (uint32_t)pVCpu->cpum.GstCtx.cr0, (uint32_t)pVCpu->cpum.GstCtx.cr4, (uint32_t)pVCpu->cpum.GstCtx.msrEFER));
407 }
408 else
409 {
410 if (pVCpu->cpum.GstCtx.eflags.Bits.u1VM)
411 Log(("HWV86-CPU%d: %08X IF=%d\n", pVCpu->idCpu, pVCpu->cpum.GstCtx.eip, pVCpu->cpum.GstCtx.eflags.Bits.u1IF));
412 else if (CPUMIsGuestIn64BitCodeEx(&pVCpu->cpum.GstCtx))
413 Log(("HWR%d-CPU%d: %04X:%RGv ESP=%RGv IF=%d IOPL=%d CR0=%x CR4=%x EFER=%x\n", cpl, pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, (RTGCPTR)pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.rsp, pVCpu->cpum.GstCtx.eflags.Bits.u1IF, pVCpu->cpum.GstCtx.eflags.Bits.u2IOPL, (uint32_t)pVCpu->cpum.GstCtx.cr0, (uint32_t)pVCpu->cpum.GstCtx.cr4, (uint32_t)pVCpu->cpum.GstCtx.msrEFER));
414 else
415 Log(("HWR%d-CPU%d: %04X:%08X ESP=%08X IF=%d IOPL=%d CR0=%x CR4=%x EFER=%x\n", cpl, pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.eip, pVCpu->cpum.GstCtx.esp, pVCpu->cpum.GstCtx.eflags.Bits.u1IF, pVCpu->cpum.GstCtx.eflags.Bits.u2IOPL, (uint32_t)pVCpu->cpum.GstCtx.cr0, (uint32_t)pVCpu->cpum.GstCtx.cr4, (uint32_t)pVCpu->cpum.GstCtx.msrEFER));
416 }
417#endif /* LOG_ENABLED */
418
419 /*
420 * Execute the code.
421 */
422 STAM_PROFILE_ADV_STOP(&pVCpu->em.s.StatHMEntry, a);
423
424 if (RT_LIKELY(emR3IsExecutionAllowed(pVM, pVCpu)))
425 {
426 STAM_REL_PROFILE_START(&pVCpu->em.s.StatHMExec, x);
427 rc = VMMR3HmRunGC(pVM, pVCpu);
428 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatHMExec, x);
429 }
430 else
431 {
432 /* Give up this time slice; virtual time continues */
433 STAM_REL_PROFILE_ADV_START(&pVCpu->em.s.StatCapped, u);
434 RTThreadSleep(5);
435 STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatCapped, u);
436 rc = VINF_SUCCESS;
437 }
438
439
440 /*
441 * Deal with high priority post execution FFs before doing anything else.
442 */
443 VMCPU_FF_CLEAR_MASK(pVCpu, VMCPU_FF_RESUME_GUEST_MASK);
444 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HIGH_PRIORITY_POST_MASK)
445 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HIGH_PRIORITY_POST_MASK))
446 rc = VBOXSTRICTRC_TODO(emR3HighPriorityPostForcedActions(pVM, pVCpu, rc));
447
448 /*
449 * Process the returned status code.
450 */
451 if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
452 break;
453
454 rc = emR3HmHandleRC(pVM, pVCpu, rc);
455 if (rc != VINF_SUCCESS)
456 break;
457
458 /*
459 * Check and execute forced actions.
460 */
461#ifdef VBOX_HIGH_RES_TIMERS_HACK
462 TMTimerPollVoid(pVM, pVCpu);
463#endif
464 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_ALL_MASK)
465 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_ALL_MASK))
466 {
467 rc = emR3ForcedActions(pVM, pVCpu, rc);
468 VBOXVMM_EM_FF_ALL_RET(pVCpu, rc);
469 if ( rc != VINF_SUCCESS
470 && rc != VINF_EM_RESCHEDULE_HM)
471 {
472 *pfFFDone = true;
473 break;
474 }
475 }
476 }
477
478 /*
479 * Return to outer loop.
480 */
481#if defined(LOG_ENABLED) && defined(DEBUG)
482 RTLogFlush(NULL);
483#endif
484 return rc;
485}
486
Note: See TracBrowser for help on using the repository browser.

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