VirtualBox

Changeset 54201 in vbox for trunk/src/VBox/HostDrivers


Ignore:
Timestamp:
Feb 13, 2015 5:13:28 PM (10 years ago)
Author:
vboxsync
Message:

HostDrivers/Support, VMM: avoid code duplication.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/SUPDrv.c

    r54181 r54201  
    216216    { "SUPR0SuspendVTxOnCpu",                   (void *)SUPR0SuspendVTxOnCpu },
    217217    { "SUPR0ResumeVTxOnCpu",                    (void *)SUPR0ResumeVTxOnCpu },
     218    { "SUPR0GetKernelFeatures",                 (void *)SUPR0GetKernelFeatures },
    218219    { "SUPR0GetPagingMode",                     (void *)SUPR0GetPagingMode },
    219     { "SUPR0GetKernelFeatures",                 (void *)SUPR0GetKernelFeatures },
     220    { "SUPR0GetSvmUsability",                   (void *)SUPR0GetSvmUsability },
     221    { "SUPR0GetVmxUsability",                   (void *)SUPR0GetVmxUsability },
    220222    { "SUPR0LockMem",                           (void *)SUPR0LockMem },
    221223    { "SUPR0LowAlloc",                          (void *)SUPR0LowAlloc },
     
    37413743
    37423744/**
     3745 * Checks if Intel VT-x feature is usable on this CPU.
     3746 *
     3747 * @returns VBox status code.
     3748 * @param   fIsSmxModeAmbiguous   Where to write whether the SMX mode causes
     3749 *                                ambiguity that makes us unsure whether we
     3750 *                                really can use VT-x or not.
     3751 *
     3752 * @remarks Must be called with preemption disabled.
     3753 */
     3754SUPR0DECL(int) SUPR0GetVmxUsability(bool *pfIsSmxModeAmbiguous)
     3755{
     3756    Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
     3757
     3758    uint64_t   u64FeatMsr          = ASMRdMsr(MSR_IA32_FEATURE_CONTROL);
     3759    bool const fMaybeSmxMode       = RT_BOOL(ASMGetCR4() & X86_CR4_SMXE);
     3760    bool       fMsrLocked          = RT_BOOL(u64FeatMsr & MSR_IA32_FEATURE_CONTROL_LOCK);
     3761    bool       fSmxVmxAllowed      = RT_BOOL(u64FeatMsr & MSR_IA32_FEATURE_CONTROL_SMX_VMXON);
     3762    bool       fVmxAllowed         = RT_BOOL(u64FeatMsr & MSR_IA32_FEATURE_CONTROL_VMXON);
     3763    bool       fIsSmxModeAmbiguous = false;
     3764    int        rc                  = VERR_INTERNAL_ERROR_5;
     3765
     3766    /* Check if the LOCK bit is set but excludes the required VMXON bit. */
     3767    if (fMsrLocked)
     3768    {
     3769        if (fVmxAllowed && fSmxVmxAllowed)
     3770            rc = VINF_SUCCESS;
     3771        else if (!fVmxAllowed && !fSmxVmxAllowed)
     3772            rc = VERR_VMX_MSR_ALL_VMXON_DISABLED;
     3773        else if (!fMaybeSmxMode)
     3774        {
     3775            if (fVmxAllowed)
     3776                rc = VINF_SUCCESS;
     3777            else
     3778                rc = VERR_VMX_MSR_VMXON_DISABLED;
     3779        }
     3780        else
     3781        {
     3782            /*
     3783             * CR4.SMXE is set but this doesn't mean the CPU is necessarily in SMX mode. We shall assume
     3784             * that it is -not- and that it is a stupid BIOS/OS setting CR4.SMXE for no good reason.
     3785             * See @bugref{6873}.
     3786             */
     3787            Assert(fMaybeSmxMode == true);
     3788            fIsSmxModeAmbiguous = true;
     3789            rc = VINF_SUCCESS;
     3790        }
     3791    }
     3792    else
     3793    {
     3794        /*
     3795         * MSR is not yet locked; we can change it ourselves here.
     3796         * Once the lock bit is set, this MSR can no longer be modified.
     3797         *
     3798         * Set both the VMXON and SMX_VMXON bits as we can't determine SMX mode
     3799         * accurately. See @bugref{6873}.
     3800         */
     3801        u64FeatMsr |= MSR_IA32_FEATURE_CONTROL_LOCK
     3802                    | MSR_IA32_FEATURE_CONTROL_SMX_VMXON
     3803                    | MSR_IA32_FEATURE_CONTROL_VMXON;
     3804        ASMWrMsr(MSR_IA32_FEATURE_CONTROL, u64FeatMsr);
     3805
     3806        /* Verify. */
     3807        u64FeatMsr     = ASMRdMsr(MSR_IA32_FEATURE_CONTROL);
     3808        fMsrLocked     = RT_BOOL(u64FeatMsr & MSR_IA32_FEATURE_CONTROL_LOCK);
     3809        fSmxVmxAllowed = fMsrLocked && RT_BOOL(u64FeatMsr & MSR_IA32_FEATURE_CONTROL_SMX_VMXON);
     3810        fVmxAllowed    = fMsrLocked && RT_BOOL(u64FeatMsr & MSR_IA32_FEATURE_CONTROL_VMXON);
     3811        if (fSmxVmxAllowed && fVmxAllowed)
     3812            rc = VINF_SUCCESS;
     3813        else
     3814            rc = VERR_VMX_MSR_LOCKING_FAILED;
     3815    }
     3816
     3817    if (pfIsSmxModeAmbiguous)
     3818        *pfIsSmxModeAmbiguous = fIsSmxModeAmbiguous;
     3819
     3820    return rc;
     3821}
     3822
     3823
     3824/**
     3825 * Checks if AMD-V SVM feature is usable on this CPU.
     3826 *
     3827 * @returns VBox status code.
     3828 * @param   fInitSvm    If usable, try to initialize SVM on this CPU.
     3829 *
     3830 * @remarks Must be called with preemption disabled.
     3831 */
     3832SUPR0DECL(int) SUPR0GetSvmUsability(bool fInitSvm)
     3833{
     3834    int      rc;
     3835    uint64_t fVmCr;
     3836    uint64_t fEfer;
     3837
     3838    Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
     3839    fVmCr = ASMRdMsr(MSR_K8_VM_CR);
     3840    if (!(fVmCr & MSR_K8_VM_CR_SVM_DISABLE))
     3841    {
     3842        rc = VINF_SUCCESS;
     3843        if (fInitSvm)
     3844        {
     3845            /* Turn on SVM in the EFER MSR. */
     3846            fEfer = ASMRdMsr(MSR_K6_EFER);
     3847            if (fEfer & MSR_K6_EFER_SVME)
     3848                rc = VERR_SVM_IN_USE;
     3849            else
     3850            {
     3851                ASMWrMsr(MSR_K6_EFER, fEfer | MSR_K6_EFER_SVME);
     3852
     3853                /* Paranoia. */
     3854                fEfer = ASMRdMsr(MSR_K6_EFER);
     3855                if (fEfer & MSR_K6_EFER_SVME)
     3856                {
     3857                    /* Restore previous value. */
     3858                    ASMWrMsr(MSR_K6_EFER, fEfer & ~MSR_K6_EFER_SVME);
     3859                }
     3860                else
     3861                    rc = VERR_SVM_ILLEGAL_EFER_MSR;
     3862            }
     3863        }
     3864    }
     3865    else
     3866        rc = VERR_SVM_DISABLED;
     3867    return rc;
     3868}
     3869
     3870
     3871/**
    37433872 * Queries the AMD-V and VT-x capabilities of the calling CPU.
    37443873 *
     
    37893918               )
    37903919            {
    3791                 /** @todo Unify code with hmR0InitIntelCpu(). */
    3792                 uint64_t   u64FeatMsr     = ASMRdMsr(MSR_IA32_FEATURE_CONTROL);
    3793                 bool const fMaybeSmxMode  = RT_BOOL(ASMGetCR4() & X86_CR4_SMXE);
    3794                 bool       fMsrLocked     = RT_BOOL(u64FeatMsr & MSR_IA32_FEATURE_CONTROL_LOCK);
    3795                 bool       fSmxVmxAllowed = RT_BOOL(u64FeatMsr & MSR_IA32_FEATURE_CONTROL_SMX_VMXON);
    3796                 bool       fVmxAllowed    = RT_BOOL(u64FeatMsr & MSR_IA32_FEATURE_CONTROL_VMXON);
    3797 
    3798                 /* Check if the LOCK bit is set but excludes the required VMXON bit. */
    3799                 if (fMsrLocked)
    3800                 {
    3801                     if (fVmxAllowed && fSmxVmxAllowed)
    3802                         rc = VINF_SUCCESS;
    3803                     else if (!fVmxAllowed && !fSmxVmxAllowed)
    3804                         rc = VERR_VMX_MSR_ALL_VMXON_DISABLED;
    3805                     else if (!fMaybeSmxMode)
    3806                     {
    3807                         if (fVmxAllowed)
    3808                             rc = VINF_SUCCESS;
    3809                         else
    3810                             rc = VERR_VMX_MSR_VMXON_DISABLED;
    3811                     }
    3812                     else
    3813                     {
    3814                         /*
    3815                          * CR4.SMXE is set but this doesn't mean the CPU is necessarily in SMX mode. We shall assume
    3816                          * that it is -not- and that it is a stupid BIOS/OS setting CR4.SMXE for no good reason.
    3817                          * See @bugref{6873}.
    3818                          */
    3819                         Assert(fMaybeSmxMode == true);
    3820                         fIsSmxModeAmbiguous = true;
    3821                         rc = VINF_SUCCESS;
    3822                     }
    3823                 }
    3824                 else
    3825                 {
    3826                     /*
    3827                      * MSR is not yet locked; we can change it ourselves here.
    3828                      * Once the lock bit is set, this MSR can no longer be modified.
    3829                      *
    3830                      * Set both the VMXON and SMX_VMXON bits as we can't determine SMX mode
    3831                      * accurately. See @bugref{6873}.
    3832                      */
    3833                     u64FeatMsr |=   MSR_IA32_FEATURE_CONTROL_LOCK
    3834                                   | MSR_IA32_FEATURE_CONTROL_SMX_VMXON
    3835                                   | MSR_IA32_FEATURE_CONTROL_VMXON;
    3836                     ASMWrMsr(MSR_IA32_FEATURE_CONTROL, u64FeatMsr);
    3837 
    3838                     /* Verify. */
    3839                     u64FeatMsr     = ASMRdMsr(MSR_IA32_FEATURE_CONTROL);
    3840                     fMsrLocked     = RT_BOOL(u64FeatMsr & MSR_IA32_FEATURE_CONTROL_LOCK);
    3841                     fSmxVmxAllowed = fMsrLocked && RT_BOOL(u64FeatMsr & MSR_IA32_FEATURE_CONTROL_SMX_VMXON);
    3842                     fVmxAllowed    = fMsrLocked && RT_BOOL(u64FeatMsr & MSR_IA32_FEATURE_CONTROL_VMXON);
    3843                     if (fSmxVmxAllowed && fVmxAllowed)
    3844                         rc = VINF_SUCCESS;
    3845                     else
    3846                         rc = VERR_VMX_MSR_LOCKING_FAILED;
    3847                 }
    3848 
     3920                rc = SUPR0GetVmxUsability(&fIsSmxModeAmbiguous);
    38493921                if (rc == VINF_SUCCESS)
    38503922                {
     
    38713943            ASMCpuId(0x80000000, &uExtMaxId, &uDummy, &uDummy, &uDummy);
    38723944            ASMCpuId(0x80000001, &uDummy, &uDummy, &fExtFeaturesEcx, &uDummy);
     3945
     3946            /* Check if SVM is available. */
    38733947            if (   ASMIsValidExtRange(uExtMaxId)
    38743948                && uExtMaxId >= 0x8000000a
     
    38783952               )
    38793953            {
    3880                 /* Check if SVM is disabled */
    3881                 uint64_t u64FeatMsr = ASMRdMsr(MSR_K8_VM_CR);
    3882                 if (!(u64FeatMsr & MSR_K8_VM_CR_SVM_DISABLE))
     3954                rc = SUPR0GetSvmUsability(false /* fInitSvm */);
     3955                if (RT_SUCCESS(rc))
    38833956                {
    38843957                    uint32_t fSvmFeatures;
     
    38893962                    if (fSvmFeatures & AMD_CPUID_SVM_FEATURE_EDX_NESTED_PAGING)
    38903963                        *pfCaps |= SUPVTCAPS_NESTED_PAGING;
    3891 
    3892                     rc = VINF_SUCCESS;
    38933964                }
    3894                 else
    3895                     rc = VERR_SVM_DISABLED;
    38963965            }
    38973966            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