VirtualBox

Changeset 46603 in vbox


Ignore:
Timestamp:
Jun 17, 2013 4:31:02 PM (12 years ago)
Author:
vboxsync
Message:

VMM/HMSVMR0: AMD-V bits.

Location:
trunk/src/VBox/VMM
Files:
2 edited

Legend:

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

    r46594 r46603  
    538538#endif
    539539#ifdef HMSVM_ALWAYS_TRAP_ALL_XCPTS
     540        /* If you add any exceptions here, make sure to update hmR0SvmHandleExit(). */
    540541        pVmcb->ctrl.u32InterceptException |=   RT_BIT(X86_XCPT_BP)
    541542                                             | RT_BIT(X86_XCPT_DB)
     
    26462647    switch (pSvmTransient->u64ExitCode)
    26472648    {
    2648         /** @todo  */
    2649         //SVM_EXIT_EXCEPTION_x:
    2650 
    26512649        case SVM_EXIT_NPF:
    26522650            return hmR0SvmExitNestedPF(pVCpu, pCtx, pSvmTransient);
     
    26632661        case SVM_EXIT_CPUID:
    26642662            return hmR0SvmExitCpuid(pVCpu, pCtx, pSvmTransient);
     2663
     2664        case SVM_EXIT_EXCEPTION_E:   /* X86_XCPT_PF */
     2665            return hmR0SvmExitXcptPF(pVCpu, pCtx, pSvmTransient);
     2666
     2667        case SVM_EXIT_EXCEPTION_7:   /* X86_XCPT_NM */
     2668            return hmR0SvmExitXcptNM(pVCpu, pCtx, pSvmTransient);
     2669
     2670        case SVM_EXIT_EXCEPTION_10:  /* X86_XCPT_MF */
     2671            return hmR0SvmExitXcptMF(pVCpu, pCtx, pSvmTransient);
     2672
     2673        case SVM_EXIT_EXCEPTION_1:   /* X86_XCPT_DB */
     2674            return hmR0SvmExitXcptDB(pVCpu, pCtx, pSvmTransient);
    26652675
    26662676        case SVM_EXIT_MONITOR:
     
    27342744            case SVM_EXIT_SKINIT:
    27352745                return hmR0SvmExitSetPendingXcptUD(pVCpu, pCtx, pSvmTransient);
     2746
     2747#ifdef HMSVM_ALWAYS_TRAP_ALL_XCPTS
     2748            case SVM_EXIT_EXCEPTION_0:      /* X86_XCPT_DE */
     2749            case SVM_EXIT_EXCEPTION_3:      /* X86_XCPT_BP */
     2750            case SVM_EXIT_EXCEPTION_6:      /* X86_XCPT_UD */
     2751            case SVM_EXIT_EXCEPTION_B:      /* X86_XCPT_NP */
     2752            case SVM_EXIT_EXCEPTION_C:      /* X86_XCPT_SS */
     2753            case SVM_EXIT_EXCEPTION_D:      /* X86_XCPT_GP */
     2754                return
     2755#endif
    27362756
    27372757            default:
     
    28812901
    28822902/**
     2903 * Sets a page fault (#PF) exception as pending-for-injection into the VM.
     2904 *
     2905 * @param   pVCpu           Pointer to the VMCPU.
     2906 * @param   pCtx            Pointer to the guest-CPU context.
     2907 * @param   u32ErrCode      The error-code for the page-fault.
     2908 * @param   uFaultAddress   The page fault address (CR2).
     2909 *
     2910 * @remarks This updates the guest CR2 with @a uFaultAddress!
     2911 */
     2912DECLINLINE(void) hmR0SvmSetPendingXcptPF(PVMCPU pVCpu, PCPUMCTX pCtx, uint32_t u32ErrCode, RTGCUINTPTR uFaultAddress)
     2913{
     2914    SVMEVENT Event;
     2915    Event.u                  = 0;
     2916    Event.n.u1Valid          = 1;
     2917    Event.n.u3Type           = SVM_EVENT_EXCEPTION;
     2918    Event.n.u8Vector         = X86_XCPT_PF;
     2919    Event.n.u1ErrorCodeValid = 1;
     2920    Event.n.u32ErrorCode     = u32ErrCode;
     2921
     2922    /* Update CR2 of the guest. */
     2923    pCtx->cr2 = uFaultAddress;
     2924
     2925    hmR0SvmSetPendingEvent(pVCpu, &Event);
     2926    STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
     2927}
     2928
     2929
     2930/**
     2931 * Sets a device-not-available (#NM) exception as pending-for-injection into the
     2932 * VM.
     2933 *
     2934 * @param   pVCpu       Pointer to the VMCPU.
     2935 */
     2936DECLINLINE(void) hmR0SvmSetPendingXcptNM(PVMCPU pVCpu)
     2937{
     2938    SVMEVENT Event;
     2939    Event.u          = 0;
     2940    Event.n.u1Valid  = 1;
     2941    Event.n.u3Type   = SVM_EVENT_EXCEPTION;
     2942    Event.n.u8Vector = X86_XCPT_NM;
     2943    hmR0SvmSetPendingEvent(pVCpu, &Event);
     2944}
     2945
     2946
     2947/**
     2948 * Sets a math-fault (#MF) exception as pending-for-injection into the VM.
     2949 *
     2950 * @param   pVCpu       Pointer to the VMCPU.
     2951 */
     2952DECLINLINE(void) hmR0SvmSetPendingXcptMF(PVMCPU pVCpu)
     2953{
     2954    SVMEVENT Event;
     2955    Event.u          = 0;
     2956    Event.n.u1Valid  = 1;
     2957    Event.n.u3Type   = SVM_EVENT_EXCEPTION;
     2958    Event.n.u8Vector = X86_XCPT_MF;
     2959    hmR0SvmSetPendingEvent(pVCpu, &Event);
     2960}
     2961
     2962
     2963/**
    28832964 * Emulates a simple MOV TPR (CR8) instruction, used for TPR patching on 32-bit
    28842965 * guests. This simply looks up the patch record at EIP and does the required.
     
    36663747
    36673748
     3749/**
     3750 * #VMEXIT handler for page faults (SVM_EXIT_PF). Conditional #VMEXIT.
     3751 */
     3752HMSVM_EXIT_DECL hmR0SvmExitXcptPF(PVMCPU pVCpu, PCPUMCTX pCtx, PSVMTRANSIENT pSvmTransient)
     3753{
     3754    HMSVM_VALIDATE_EXIT_HANDLER_PARAMS();
     3755
     3756    /* -XXX- @todo Vectoring pagefaults!! */
     3757
     3758    /* See AMD spec. 15.12.15 "#PF (Page Fault)". */
     3759    PSVMVMCB    pVmcb         = (PSVMVMCB)pVCpu->hm.s.svm.pvVmcb;
     3760    uint32_t    u32ErrCode    = pVmcb->ctrl.u64ExitInfo1;
     3761    RTGCUINTPTR uFaultAddress = pVmcb->ctrl.u64ExitInfo2;
     3762
     3763#if defined(HMVMX_ALWAYS_TRAP_ALL_XCPTS) || defined(HMVMX_ALWAYS_TRAP_PF)
     3764    if (pVM->hm.s.fNestedPaging)
     3765    {
     3766        /* A genuine guest #PF, reflect it to the guest. */
     3767        Log4(("#PF: Guest page fault at %04X:%RGv FaultAddr=%RGv ErrCode=%#x\n", pCtx->cs, (RTGCPTR)pCtx->rip, uFaultAddress,
     3768              u32ErrCode));
     3769        hmR0SvmSetPendingXcptPF(pVCpu, pCtx, u32ErrCode, uFaultAddress);
     3770        return VINF_SUCCESS;
     3771    }
     3772#endif
     3773
     3774    Assert(!pVM->hm.s.fNestedPaging);
     3775
     3776#ifdef VBOX_HM_WITH_GUEST_PATCHING
     3777    /* Shortcut for APIC TPR reads and writes; only applicable to 32-bit guests. */
     3778    if (   pVM->hm.s.fTRPPatchingAllowed
     3779        && (uFaultAddress & 0xfff) == 0x80  /* TPR offset. */
     3780        && !(u32ErrCode & X86_TRAP_PF_P)    /* Not present */
     3781        && !CPUMGetGuestCPL(pVCpu)
     3782        && !CPUMIsGuestInLongModeEx(pCtx)
     3783        && pVM->hm.s.cPatches < RT_ELEMENTS(pVM->hm.s.aPatches))
     3784    {
     3785        RTGCPHYS GCPhysApicBase;
     3786        GCPhysApicBase  = pCtx->msrApicBase;
     3787        GCPhysApicBase &= PAGE_BASE_GC_MASK;
     3788
     3789        /* Check if the page at the fault-address is the APIC base. */
     3790        RTGCPHYS GCPhysPage;
     3791        rc = PGMGstGetPage(pVCpu, (RTGCPTR)uFaultAddress, NULL /* pfFlags */, &GCPhysPage);
     3792        if (   rc == VINF_SUCCESS
     3793            && GCPhys == GCPhysApicBase)
     3794        {
     3795            /* Only attempt to patch the instruction once. */
     3796            PHMTPRPATCH pPatch = (PHMTPRPATCH)RTAvloU32Get(&pVM->hm.s.PatchTree, (AVLOU32KEY)pCtx->eip);
     3797            if (!pPatch)
     3798                return VINF_EM_HM_PATCH_TPR_INSTR;
     3799        }
     3800    }
     3801#endif
     3802
     3803    Log4(("#PF: uFaultAddress=%#RX64 cs:rip=%#04x:%#RX64 u32ErrCode %#RX32 cr3=%#RX64\n", uFaultAddress, pCtx->cs.Sel,
     3804          pCtx->rip, u32ErrCode, pCtx->cr3));
     3805
     3806    TRPMAssertXcptPF(pVCpu, uFaultAddress, u32ErrCode);
     3807    int rc = PGMTrap0eHandler(pVCpu, errCode, CPUMCTX2CORE(pCtx), (RTGCPTR)uFaultAddress);
     3808
     3809    Log2(("#PF rc=%Rrc\n", rc));
     3810    if (rc == VINF_SUCCESS)
     3811    {
     3812        /* Successfully synced shadow pages tables or emulated an MMIO instruction. */
     3813        TRPMResetTrap(pVCpu);
     3814        STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
     3815        return rc;
     3816    }
     3817    else if (rc == VINF_EM_RAW_GUEST_TRAP)
     3818    {
     3819        /* It's a guest page fault and needs to be reflected to the guest. */
     3820
     3821        STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
     3822        u32ErrCode = TRPMGetErrorCode(pVCpu);        /* The error code might have been changed. */
     3823        TRPMResetTrap(pVCpu);
     3824
     3825        hmR0SvmSetPendingXcptPF(pVCpu, pCtx, u32ErrCode, uFaultAddress);
     3826        STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
     3827        return VINF_SUCCESS;
     3828    }
     3829
     3830    TRPMResetTrap(pVCpu);
     3831    STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
     3832    return rc;
     3833}
     3834
     3835
     3836/**
     3837 * #VMEXIT handler for device-not-available exception (SVM_EXIT_NM). Conditional
     3838 * #VMEXIT.
     3839 */
     3840HMSVM_EXIT_DECL hmR0SvmExitXcptNM(PVMCPU pVCpu, PCPUMCTX pCtx, PSVMTRANSIENT pSvmTransient)
     3841{
     3842    HMSVM_VALIDATE_EXIT_HANDLER_PARAMS();
     3843
     3844#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
     3845    Assert(!CPUMIsGuestFPUStateActive(pVCpu));
     3846#endif
     3847
     3848    /* Lazy FPU loading; load the guest-FPU state transparently and continue execution of the guest. */
     3849    PVM pVM = pVCpu->CTX_SUFF(pVM);
     3850    rc = CPUMR0LoadGuestFPU(pVM, pVCpu, pCtx);
     3851    if (rc == VINF_SUCCESS)
     3852    {
     3853        Assert(CPUMIsGuestFPUStateActive(pVCpu));
     3854        pVCpu->hm.s.fContextUseFlags |= HM_CHANGED_GUEST_CR0;
     3855        STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowNM);
     3856        return VINF_SUCCESS;
     3857    }
     3858
     3859    /* Forward #NM to the guest. */
     3860    Assert(rc == VINF_EM_RAW_GUEST_TRAP);
     3861    hmR0SvmSetPendingXcptNM(pVCpu);
     3862    STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNM);
     3863    return VINF_SUCCESS;
     3864}
     3865
     3866
     3867/**
     3868 * #VMEXIT handler for math-fault (SVM_EXIT_MF). Conditional #VMEXIT.
     3869 */
     3870HMSVM_EXIT_DECL hmR0SvmExitXcptMF(PVMCPU pVCpu, PCPUMCTX pCtx, PSVMTRANSIENT pSvmTransient)
     3871{
     3872    int rc;
     3873    if (!(pMixedCtx->cr0 & X86_CR0_NE))
     3874    {
     3875        /* Old-style FPU error reporting needs some extra work. */
     3876        /** @todo don't fall back to the recompiler, but do it manually. */
     3877        rc = VERR_EM_INTERPRETER;
     3878    }
     3879    else
     3880    {
     3881        hmR0SvmSetPendingXcptMF(pVCpu);
     3882        rc = VINF_SUCCESS;
     3883    }
     3884    STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF);
     3885    return rc;
     3886}
     3887
  • trunk/src/VBox/VMM/include/HMInternal.h

    r46531 r46603  
    130130/* AMD-V specific state. */
    131131# define HM_CHANGED_SVM_GUEST_APIC_STATE         RT_BIT(16)
    132 # define HM_CHANGED_SVM_RESERVED1                RT_BIT(17)
     132# define HM_CHANGED_SVM_GUEST_EFER_MSR           RT_BIT(17)
    133133# define HM_CHANGED_SVM_RESERVED2                RT_BIT(18)
    134134# define HM_CHANGED_SVM_RESERVED3                RT_BIT(19)
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