static int emR3SingleStepExecHm(PVM pVM, PVMCPU pVCpu, uint32_t cIterations) { int rc = VINF_SUCCESS; EMSTATE enmOldState = pVCpu->em.s.enmState; pVCpu->em.s.enmState = EMSTATE_DEBUG_GUEST_HM; Log(("Single step BEGIN:\n")); for (uint32_t i = 0; i < cIterations; i++) { DBGFR3PrgStep(pVCpu); DBGFR3_DISAS_INSTR_CUR_LOG(pVCpu, "RSS: "); rc = emR3HmStep(pVM, pVCpu); if ( rc != VINF_SUCCESS || !HMR3CanExecuteGuest(pVM, pVCpu->em.s.pCtx)) break; } Log(("Single step END: rc=%Rrc\n", rc)); CPUMSetGuestEFlags(pVCpu, CPUMGetGuestEFlags(pVCpu) & ~X86_EFL_TF); pVCpu->em.s.enmState = enmOldState; return rc == VINF_SUCCESS ? VINF_EM_RESCHEDULE_REM : rc; }
/** * Executes instruction in HM mode if we can. * * This is somewhat comparable to REMR3EmulateInstruction. * * @returns VBox strict status code. * @retval VINF_EM_DBG_STEPPED on success. * @retval VERR_EM_CANNOT_EXEC_GUEST if we cannot execute guest instructions in * HM right now. * * @param pVM The cross context VM structure. * @param pVCpu The cross context virtual CPU structure for the calling EMT. * @param fFlags Combinations of EM_ONE_INS_FLAGS_XXX. * @thread EMT. */ VMMR3_INT_DECL(VBOXSTRICTRC) EMR3HmSingleInstruction(PVM pVM, PVMCPU pVCpu, uint32_t fFlags) { PCPUMCTX pCtx = pVCpu->em.s.pCtx; Assert(!(fFlags & ~EM_ONE_INS_FLAGS_MASK)); if (!HMR3CanExecuteGuest(pVM, pCtx)) return VINF_EM_RESCHEDULE; uint64_t const uOldRip = pCtx->rip; for (;;) { /* * Service necessary FFs before going into HM. */ if ( VM_FF_IS_PENDING(pVM, VM_FF_HIGH_PRIORITY_PRE_RAW_MASK) || VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_HIGH_PRIORITY_PRE_RAW_MASK)) { VBOXSTRICTRC rcStrict = emR3HmForcedActions(pVM, pVCpu, pCtx); if (rcStrict != VINF_SUCCESS) { Log(("EMR3HmSingleInstruction: FFs before -> %Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); return rcStrict; } } /* * Go execute it. */ bool fOld = HMSetSingleInstruction(pVM, pVCpu, true); VBOXSTRICTRC rcStrict = VMMR3HmRunGC(pVM, pVCpu); HMSetSingleInstruction(pVM, pVCpu, fOld); LogFlow(("EMR3HmSingleInstruction: %Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); /* * Handle high priority FFs and informational status codes. We don't do * normal FF processing the caller or the next call can deal with them. */ VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_RESUME_GUEST_MASK); if ( VM_FF_IS_PENDING(pVM, VM_FF_HIGH_PRIORITY_POST_MASK) || VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_HIGH_PRIORITY_POST_MASK)) { rcStrict = emR3HighPriorityPostForcedActions(pVM, pVCpu, VBOXSTRICTRC_TODO(rcStrict)); LogFlow(("EMR3HmSingleInstruction: FFs after -> %Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); } if (rcStrict != VINF_SUCCESS && (rcStrict < VINF_EM_FIRST || rcStrict > VINF_EM_LAST)) { rcStrict = emR3HmHandleRC(pVM, pVCpu, pCtx, VBOXSTRICTRC_TODO(rcStrict)); Log(("EMR3HmSingleInstruction: emR3HmHandleRC -> %Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); } /* * Done? */ if ( (rcStrict != VINF_SUCCESS && rcStrict != VINF_EM_DBG_STEPPED) || !(fFlags & EM_ONE_INS_FLAGS_RIP_CHANGE) || pCtx->rip != uOldRip) { if (rcStrict == VINF_SUCCESS && pCtx->rip != uOldRip) rcStrict = VINF_EM_DBG_STEPPED; Log(("EMR3HmSingleInstruction: returns %Rrc (rip %llx -> %llx)\n", VBOXSTRICTRC_VAL(rcStrict), uOldRip, pCtx->rip)); return rcStrict; } } }