VirtualBox

Changeset 45685 in vbox for trunk/src/VBox/VMM/VMMR0


Ignore:
Timestamp:
Apr 23, 2013 5:27:33 PM (12 years ago)
Author:
vboxsync
Message:

VMM/HMVMXR0: Safer to update CR2 while injecting exceptions and not earlier while converting from TRPM traps (from ring-3).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r45684 r45685  
    221221*******************************************************************************/
    222222static void               hmR0VmxFlushVpid(PVM pVM, PVMCPU pVCpu, VMX_FLUSH_VPID enmFlush, RTGCPTR GCPtr);
    223 static int                hmR0VmxInjectEventVmcs(PVMCPU pVCpu, PCPUMCTX pMixedCtx, uint64_t u64IntrInfo,
    224                                                  uint32_t cbInstr, uint32_t u32ErrCode, uint32_t *puIntrState);
     223static int                hmR0VmxInjectEventVmcs(PVMCPU pVCpu, PCPUMCTX pMixedCtx, uint64_t u64IntrInfo, uint32_t cbInstr,
     224                                                 uint32_t u32ErrCode, RTGCUINTREG uCR2, uint32_t *puIntrState);
    225225#if HC_ARCH_BITS == 32 && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL)
    226226static int                hmR0VmxInitVmcsReadCache(PVM pVM, PVMCPU pVCpu);
     
    54655465    /* Refer Intel spec. 24.8.3 "VM-entry Controls for Event Injection" for the format of u32IntrInfo. */
    54665466    uint32_t u32IntrInfo = uVector | (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT);
    5467     uint32_t u32ErrCode  = uErrCode;
    54685467    if (enmTrpmEvent == TRPM_TRAP)
    54695468    {
     
    54785477
    54795478            case X86_XCPT_PF:
    5480                 pCtx->cr2 = GCPtrFaultAddress;
    5481                 /* no break */
    54825479            case X86_XCPT_DF:
    54835480            case X86_XCPT_TS:
     
    55035500    }
    55045501    else if (enmTrpmEvent == TRPM_SOFTWARE_INT)
     5502    {
    55055503        u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_SW_INT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
     5504    }
    55065505    else
    55075506        AssertMsgFailed(("Invalid TRPM event type %d\n", enmTrpmEvent));
     
    55095508    rc = TRPMResetTrap(pVCpu);
    55105509    AssertRC(rc);
    5511     Log(("Converting TRPM trap: u32IntrInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u u32ErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n",
    5512          u32IntrInfo, enmTrpmEvent, cbInstr, u32ErrCode, GCPtrFaultAddress));
    5513     hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, cbInstr, u32ErrCode, GCPtrFaultAddress);
     5510    Log(("Converting TRPM trap: u32IntrInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u uErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n",
     5511         u32IntrInfo, enmTrpmEvent, cbInstr, uErrCode, GCPtrFaultAddress));
     5512    hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, cbInstr, uErrCode, GCPtrFaultAddress);
    55145513}
    55155514
     
    57955794            Log(("Injecting pending event\n"));
    57965795            rc = hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, pVCpu->hm.s.Event.u64IntrInfo, pVCpu->hm.s.Event.cbInstr,
    5797                                         pVCpu->hm.s.Event.u32ErrCode, &uIntrState);
     5796                                        pVCpu->hm.s.Event.u32ErrCode, pVCpu->hm.s.Event.GCPtrFaultAddress, &uIntrState);
    57985797            AssertRCReturn(rc, rc);
    57995798            pVCpu->hm.s.Event.fPending = false;
     
    58125811            uIntrInfo  = X86_XCPT_NMI | (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT);
    58135812            uIntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_NMI << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
    5814             rc = hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, uIntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, &uIntrState);
     5813            rc = hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, uIntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */,
     5814                                        0 /* GCPtrFaultAddress */, &uIntrState);
    58155815            AssertRCReturn(rc, rc);
    58165816            VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
     
    58365836                uint32_t u32IntrInfo = u8Interrupt | (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT);
    58375837                u32IntrInfo         |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_EXT_INT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
    5838                 rc = hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, u32IntrInfo, 0 /* cbInstr */,  0 /* u32ErrCode */, &uIntrState);
     5838                rc = hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, u32IntrInfo, 0 /* cbInstr */,  0 /* u32ErrCode */,
     5839                                            0 /* GCPtrFaultAddress */, &uIntrState);
    58395840            }
    58405841            else
     
    59235924    u32IntrInfo         |= VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID;
    59245925    STAM_COUNTER_INC(&pVCpu->hm.s.StatIntInject);
    5925     return hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, u32IntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, puIntrState);
     5926    return hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, u32IntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */,
     5927                                  puIntrState);
    59265928}
    59275929
     
    59815983        u32IntrInfo |= VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID;
    59825984    STAM_COUNTER_INC(&pVCpu->hm.s.StatIntInject);
    5983     return hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, u32IntrInfo, 0 /* cbInstr */, u32ErrorCode, puIntrState);
     5985    return hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, u32IntrInfo, 0 /* cbInstr */, u32ErrorCode, 0 /* GCPtrFaultAddress */,
     5986                                  puIntrState);
    59845987}
    59855988
     
    60456048 * @retval VINF_EM_RESET if event injection resulted in a triple-fault.
    60466049 *
    6047  * @param   pVCpu           Pointer to the VMCPU.
    6048  * @param   pMixedCtx       Pointer to the guest-CPU context. The data may be
    6049  *                          out-of-sync. Make sure to update the required fields
    6050  *                          before using them.
    6051  * @param   u64IntrInfo     The VM-entry interruption-information field.
    6052  * @param   cbInstr         The VM-entry instruction length in bytes (for software
    6053  *                          interrupts, exceptions and privileged software
    6054  *                          exceptions).
    6055  * @param   u32ErrCode      The VM-entry exception error code.
    6056  * @param   puIntrState     Pointer to the current guest interruptibility-state.
    6057  *                          This interruptibility-state will be updated if
    6058  *                          necessary. This cannot not be NULL.
     6050 * @param   pVCpu               Pointer to the VMCPU.
     6051 * @param   pMixedCtx           Pointer to the guest-CPU context. The data may
     6052 *                              be out-of-sync. Make sure to update the required
     6053 *                              fields before using them.
     6054 * @param   u64IntrInfo         The VM-entry interruption-information field.
     6055 * @param   cbInstr             The VM-entry instruction length in bytes (for
     6056 *                              software interrupts, exceptions and privileged
     6057 *                              software exceptions).
     6058 * @param   u32ErrCode          The VM-entry exception error code.
     6059 * @param   GCPtrFaultAddress   The page-fault address for #PF exceptions.
     6060 * @param   puIntrState         Pointer to the current guest interruptibility-state.
     6061 *                              This interruptibility-state will be updated if
     6062 *                              necessary. This cannot not be NULL.
    60596063 *
    60606064 * @remarks No-long-jump zone!!!
     
    60626066 */
    60636067static int hmR0VmxInjectEventVmcs(PVMCPU pVCpu, PCPUMCTX pMixedCtx, uint64_t u64IntrInfo, uint32_t cbInstr,
    6064                                   uint32_t u32ErrCode, uint32_t *puIntrState)
     6068                                  uint32_t u32ErrCode, RTGCUINTREG GCPtrFaultAddress, uint32_t *puIntrState)
    60656069{
    60666070    /* Intel spec. 24.8.3 "VM-Entry Controls for Event Injection" specifies the interruption-information field to be 32-bits. */
     
    61516155                pMixedCtx->cs.Sel      = selIdtEntry;
    61526156                pMixedCtx->cs.u64Base  = selIdtEntry << cbIdtEntry;
     6157                if (   VMX_EXIT_INTERRUPTION_INFO_TYPE(u32IntrInfo) == VMX_EXIT_INTERRUPTION_INFO_TYPE_HW_XCPT
     6158                    && uVector == X86_XCPT_PF)
     6159                {
     6160                    pMixedCtx->cr2 = GCPtrFaultAddress;
     6161                }
    61536162                pVCpu->hm.s.fContextUseFlags |=   HM_CHANGED_GUEST_SEGMENT_REGS
    61546163                                                | HM_CHANGED_GUEST_RIP
     
    61646173                    *puIntrState &= ~VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_STI;
    61656174                }
    6166                 Log(("Injecting u32IntrInfo=%#x u32ErrCode=%#x instrlen=%#x\n", u32IntrInfo, u32ErrCode, cbInstr));
     6175                Log(("Injecting real-mode: u32IntrInfo=%#x u32ErrCode=%#x instrlen=%#x\n", u32IntrInfo, u32ErrCode, cbInstr));
    61676176            }
    61686177            Assert(rc == VINF_SUCCESS || rc == VINF_EM_RESET);
     
    61856194
    61866195    /* Inject. */
    6187     Log(("Injecting u32IntrInfo=%#x u32ErrCode=%#x cbInstr=%#x uCR2=%#RGv\n", u32IntrInfo, u32ErrCode, cbInstr, pMixedCtx->cr2));
    61886196    rc  = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, u32IntrInfo);
    61896197    if (VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_IS_VALID(u32IntrInfo))
    61906198        rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, u32ErrCode);
    61916199    rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, cbInstr);
     6200
     6201    if (   VMX_EXIT_INTERRUPTION_INFO_TYPE(u32IntrInfo) == VMX_EXIT_INTERRUPTION_INFO_TYPE_HW_XCPT
     6202        && uVector == X86_XCPT_PF)
     6203    {
     6204        pMixedCtx->cr2 = GCPtrFaultAddress;
     6205    }
     6206    Log(("Injecting u32IntrInfo=%#x u32ErrCode=%#x cbInstr=%#x uCR2=%#RGv\n", u32IntrInfo, u32ErrCode, cbInstr, pMixedCtx->cr2));
     6207
    61926208    AssertRCReturn(rc, rc);
    61936209    return rc;
     
    87698785        if (RT_LIKELY(!pVmxTransient->fVectoringPF))
    87708786        {
    8771             pMixedCtx->cr2 = pVmxTransient->uExitQualification;
    87728787            pVCpu->hm.s.Event.fPending = false;     /* In case it's a contributory #PF. */
    87738788            hmR0VmxSetPendingEvent(pVCpu, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntrInfo),
    8774                                    0 /* cbInstr */, pVmxTransient->uExitIntrErrorCode, pMixedCtx->cr2);
     8789                                   0 /* cbInstr */, pVmxTransient->uExitIntrErrorCode, pVmxTransient->uExitQualification);
    87758790            STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
    87768791        }
     
    88498864            uint32_t uGstErrorCode = TRPMGetErrorCode(pVCpu);
    88508865            TRPMResetTrap(pVCpu);
    8851             pMixedCtx->cr2 = pVmxTransient->uExitQualification;
    88528866            pVCpu->hm.s.Event.fPending = false;     /* In case it's a contributory #PF. */
    88538867            hmR0VmxSetPendingEvent(pVCpu, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntrInfo),
    8854                                    0 /* cbInstr */, uGstErrorCode, pMixedCtx->cr2);
     8868                                   0 /* cbInstr */, uGstErrorCode, pVmxTransient->uExitQualification);
    88558869        }
    88568870        else
Note: See TracChangeset for help on using the changeset viewer.

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