- Timestamp:
- Jan 29, 2014 5:27:37 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp
r50271 r50275 7015 7015 7016 7016 /** 7017 * Sets a pending-debug exception to be delivered to the guest if the guest is 7018 * single-stepping. 7019 * 7020 * @param pVCpu Pointer to the VMCPU. 7021 * @param pMixedCtx Pointer to the guest-CPU context. The data may be 7022 * out-of-sync. Make sure to update the required fields 7023 * before using them. 7024 */ 7025 DECLINLINE(void) hmR0VmxSetPendingDebugXcpt(PVMCPU pVCpu, PCPUMCTX pMixedCtx) 7026 { 7027 HMVMXCPU_GST_IS_UPDATED(pVCpu, HMVMX_UPDATED_GUEST_RFLAGS); 7028 if (pMixedCtx->eflags.Bits.u1TF) /* We don't have any IA32_DEBUGCTL MSR for guests. Treat as all bits 0. */ 7029 { 7030 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_EXCEPTIONS, VMX_VMCS_GUEST_DEBUG_EXCEPTIONS_BS); 7031 AssertRC(rc); 7032 } 7033 } 7034 7035 7036 /** 7017 7037 * Injects any pending events into the guest if the guest is in a state to 7018 7038 * receive them. … … 7085 7105 && !DBGFIsStepping(pVCpu)) 7086 7106 { 7107 /* 7108 * The pending-debug exceptions field is cleared on all VM-exits except VMX_EXIT_TPR_BELOW_THRESHOLD, 7109 * VMX_EXIT_MTF, VMX_EXIT_APIC_WRITE and VMX_EXIT_VIRTUALIZED_EOI. 7110 * See Intel spec. 27.3.4 "Saving Non-Register State". 7111 */ 7087 7112 int rc2 = hmR0VmxSaveGuestRflags(pVCpu, pMixedCtx); 7088 7113 AssertRCReturn(rc2, rc2); 7089 if (pMixedCtx->eflags.Bits.u1TF) /* We don't have any IA32_DEBUGCTL MSR for guests. Treat as all bits 0. */ 7090 { 7091 /* 7092 * The pending-debug exceptions field is cleared on all VM-exits except VMX_EXIT_TPR_BELOW_THRESHOLD, 7093 * VMX_EXIT_MTF, VMX_EXIT_APIC_WRITE and VMX_EXIT_VIRTUALIZED_EOI. 7094 * See Intel spec. 27.3.4 "Saving Non-Register State". 7095 */ 7096 rc2 = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_EXCEPTIONS, VMX_VMCS_GUEST_DEBUG_EXCEPTIONS_BS); 7097 AssertRCReturn(rc2, rc2); 7098 } 7114 hmR0VmxSetPendingDebugXcpt(pVCpu, pMixedCtx); 7099 7115 } 7100 7116 else if (pMixedCtx->eflags.Bits.u1TF) … … 8619 8635 * See Intel spec. 32.2.1 "Debug Exceptions". 8620 8636 */ 8621 if (pMixedCtx->eflags.Bits.u1TF) 8622 { 8623 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_EXCEPTIONS, VMX_VMCS_GUEST_DEBUG_EXCEPTIONS_BS); 8624 AssertRCReturn(rc, rc); 8625 } 8637 hmR0VmxSetPendingDebugXcpt(pVCpu, pMixedCtx); 8626 8638 8627 8639 return rc; … … 11132 11144 pMixedCtx->rip += pDis->cbInstr; 11133 11145 HMCPU_CF_SET(pVCpu, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS); 11146 hmR0VmxSetPendingDebugXcpt(pVCpu, pMixedCtx); 11134 11147 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCli); 11135 11148 break; … … 11143 11156 Assert(VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)); 11144 11157 HMCPU_CF_SET(pVCpu, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS); 11158 hmR0VmxSetPendingDebugXcpt(pVCpu, pMixedCtx); 11145 11159 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitSti); 11146 11160 break; … … 11161 11175 uint32_t cbParm = 0; 11162 11176 uint32_t uMask = 0; 11177 bool fAlreadyStepping = RT_BOOL(pMixedCtx->eflags.Bits.u1TF); 11163 11178 if (pDis->fPrefix & DISPREFIX_OPSIZE) 11164 11179 { … … 11195 11210 pMixedCtx->esp &= uMask; 11196 11211 pMixedCtx->rip += pDis->cbInstr; 11197 11198 11212 HMCPU_CF_SET(pVCpu, HM_CHANGED_GUEST_RIP 11199 11213 | HM_CHANGED_GUEST_RSP 11200 11214 | HM_CHANGED_GUEST_RFLAGS); 11215 11216 /* Only generate a debug execption after POPF if the guest is already stepping over POPF and 11217 POPF restores EFLAGS.TF. The CPU looks at the EFLAGS.TF after the instruction is done manipulating it. */ 11218 if ( fAlreadyStepping 11219 && pMixedCtx->eflags.Bits.u1TF) 11220 { 11221 hmR0VmxSetPendingDebugXcpt(pVCpu, pMixedCtx); 11222 } 11223 11201 11224 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitPopf); 11202 11225 break; … … 11243 11266 pMixedCtx->rip += pDis->cbInstr; 11244 11267 HMCPU_CF_SET(pVCpu, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP); 11268 hmR0VmxSetPendingDebugXcpt(pVCpu, pMixedCtx); 11245 11269 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitPushf); 11246 11270 break; … … 11254 11278 uint32_t uMask = 0xffff; 11255 11279 uint16_t aIretFrame[3]; 11280 bool fAlreadyStepping = RT_BOOL(pMixedCtx->eflags.Bits.u1TF); 11256 11281 if (pDis->fPrefix & (DISPREFIX_OPSIZE | DISPREFIX_ADDRSIZE)) 11257 11282 { … … 11280 11305 | HM_CHANGED_GUEST_RSP 11281 11306 | HM_CHANGED_GUEST_RFLAGS); 11307 11308 /* Only generate a debug execption after IRET if the guest is already stepping over IRET and 11309 IRET restores EFLAGS.TF. The CPU looks at the EFLAGS.TF after the instruction is done manipulating it. */ 11310 if ( fAlreadyStepping 11311 && pMixedCtx->eflags.Bits.u1TF) 11312 { 11313 hmR0VmxSetPendingDebugXcpt(pVCpu, pMixedCtx); 11314 } 11315 11282 11316 Log4(("IRET %#RX32 to %04x:%x\n", GCPtrStack, pMixedCtx->cs.Sel, pMixedCtx->ip)); 11283 11317 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIret); … … 11289 11323 uint16_t uVector = pDis->Param1.uValue & 0xff; 11290 11324 hmR0VmxSetPendingIntN(pVCpu, pMixedCtx, uVector, pDis->cbInstr); 11325 /* INT clears EFLAGS.TF, we mustn't set any pending debug exceptions here. */ 11291 11326 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitInt); 11292 11327 break; … … 11298 11333 { 11299 11334 hmR0VmxSetPendingXcptOF(pVCpu, pMixedCtx, pDis->cbInstr); 11335 /* INTO clears EFLAGS.TF, we mustn't set any pending debug exceptions here. */ 11300 11336 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitInt); 11301 11337 } … … 11309 11345 rc = VBOXSTRICTRC_VAL(rc2); 11310 11346 HMCPU_CF_SET(pVCpu, HM_CHANGED_ALL_GUEST); 11347 /** @todo We have to set pending-debug exceptions here when the guest is 11348 * single-stepping depending on the instruction that was interpreted. */ 11311 11349 Log4(("#GP rc=%Rrc\n", rc)); 11312 11350 break;
Note:
See TracChangeset
for help on using the changeset viewer.