lkml.org 
[lkml]   [2022]   [Feb]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH RESEND 26/30] KVM: x86: nSVM: implement nested vGIF
    Date
    In case L1 enables vGIF for L2, the L2 cannot affect L1's GIF, regardless
    of STGI/CLGI intercepts, and since VM entry enables GIF, this means
    that L1's GIF is always 1 while L2 is running.

    Thus in this case leave L1's vGIF in vmcb01, while letting L2
    control the vGIF thus implementing nested vGIF.

    Also allow KVM to toggle L1's GIF during nested entry/exit
    by always using vmcb01.

    Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
    ---
    arch/x86/kvm/svm/nested.c | 17 +++++++++++++----
    arch/x86/kvm/svm/svm.c | 5 +++++
    arch/x86/kvm/svm/svm.h | 25 +++++++++++++++++++++----
    3 files changed, 39 insertions(+), 8 deletions(-)

    diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
    index 601d38ae05cc6..a426d4d3dcd82 100644
    --- a/arch/x86/kvm/svm/nested.c
    +++ b/arch/x86/kvm/svm/nested.c
    @@ -408,6 +408,10 @@ void nested_sync_control_from_vmcb02(struct vcpu_svm *svm)
    */
    mask &= ~V_IRQ_MASK;
    }
    +
    + if (nested_vgif_enabled(svm))
    + mask |= V_GIF_MASK;
    +
    svm->nested.ctl.int_ctl &= ~mask;
    svm->nested.ctl.int_ctl |= svm->vmcb->control.int_ctl & mask;
    }
    @@ -573,10 +577,8 @@ static void nested_vmcb02_prepare_save(struct vcpu_svm *svm, struct vmcb *vmcb12

    static void nested_vmcb02_prepare_control(struct vcpu_svm *svm)
    {
    - const u32 int_ctl_vmcb01_bits =
    - V_INTR_MASKING_MASK | V_GIF_MASK | V_GIF_ENABLE_MASK;
    -
    - const u32 int_ctl_vmcb12_bits = V_TPR_MASK | V_IRQ_INJECTION_BITS_MASK;
    + u32 int_ctl_vmcb01_bits = V_INTR_MASKING_MASK;
    + u32 int_ctl_vmcb12_bits = V_TPR_MASK | V_IRQ_INJECTION_BITS_MASK;

    struct kvm_vcpu *vcpu = &svm->vcpu;

    @@ -586,6 +588,13 @@ static void nested_vmcb02_prepare_control(struct vcpu_svm *svm)
    */


    +
    +
    + if (svm->vgif_enabled && (svm->nested.ctl.int_ctl & V_GIF_ENABLE_MASK))
    + int_ctl_vmcb12_bits |= (V_GIF_MASK | V_GIF_ENABLE_MASK);
    + else
    + int_ctl_vmcb01_bits |= (V_GIF_MASK | V_GIF_ENABLE_MASK);
    +
    /* Copied from vmcb01. msrpm_base can be overwritten later. */
    svm->vmcb->control.nested_ctl = svm->vmcb01.ptr->control.nested_ctl;
    svm->vmcb->control.iopm_base_pa = svm->vmcb01.ptr->control.iopm_base_pa;
    diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
    index e49043807ec44..1cf682d1553cc 100644
    --- a/arch/x86/kvm/svm/svm.c
    +++ b/arch/x86/kvm/svm/svm.c
    @@ -4008,6 +4008,8 @@ static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
    svm->pause_threshold_enabled = false;
    }

    + svm->vgif_enabled = vgif && guest_cpuid_has(vcpu, X86_FEATURE_VGIF);
    +
    svm_recalc_instruction_intercepts(vcpu, svm);

    /* For sev guests, the memory encryption bit is not reserved in CR3. */
    @@ -4823,6 +4825,9 @@ static __init void svm_set_cpu_caps(void)
    if (pause_filter_thresh)
    kvm_cpu_cap_set(X86_FEATURE_PFTHRESHOLD);

    + if (vgif)
    + kvm_cpu_cap_set(X86_FEATURE_VGIF);
    +
    /* Nested VM can receive #VMEXIT instead of triggering #GP */
    kvm_cpu_cap_set(X86_FEATURE_SVME_ADDR_CHK);
    }
    diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
    index 297ec57f9941c..73cc9d3e784bd 100644
    --- a/arch/x86/kvm/svm/svm.h
    +++ b/arch/x86/kvm/svm/svm.h
    @@ -224,6 +224,7 @@ struct vcpu_svm {
    bool v_vmload_vmsave_enabled : 1;
    bool pause_filter_enabled : 1;
    bool pause_threshold_enabled : 1;
    + bool vgif_enabled : 1;

    u32 ldr_reg;
    u32 dfr_reg;
    @@ -442,31 +443,47 @@ static inline bool svm_is_intercept(struct vcpu_svm *svm, int bit)
    return vmcb_is_intercept(&svm->vmcb->control, bit);
    }

    +static bool nested_vgif_enabled(struct vcpu_svm *svm)
    +{
    + if (!is_guest_mode(&svm->vcpu) || !svm->vgif_enabled)
    + return false;
    + return svm->nested.ctl.int_ctl & V_GIF_ENABLE_MASK;
    +}
    +
    static inline bool vgif_enabled(struct vcpu_svm *svm)
    {
    - return !!(svm->vmcb->control.int_ctl & V_GIF_ENABLE_MASK);
    + struct vmcb *vmcb = nested_vgif_enabled(svm) ? svm->vmcb01.ptr : svm->vmcb;
    +
    + return !!(vmcb->control.int_ctl & V_GIF_ENABLE_MASK);
    }

    static inline void enable_gif(struct vcpu_svm *svm)
    {
    + struct vmcb *vmcb = nested_vgif_enabled(svm) ? svm->vmcb01.ptr : svm->vmcb;
    +
    if (vgif_enabled(svm))
    - svm->vmcb->control.int_ctl |= V_GIF_MASK;
    + vmcb->control.int_ctl |= V_GIF_MASK;
    else
    svm->vcpu.arch.hflags |= HF_GIF_MASK;
    }

    static inline void disable_gif(struct vcpu_svm *svm)
    {
    + struct vmcb *vmcb = nested_vgif_enabled(svm) ? svm->vmcb01.ptr : svm->vmcb;
    +
    if (vgif_enabled(svm))
    - svm->vmcb->control.int_ctl &= ~V_GIF_MASK;
    + vmcb->control.int_ctl &= ~V_GIF_MASK;
    else
    svm->vcpu.arch.hflags &= ~HF_GIF_MASK;
    +
    }

    static inline bool gif_set(struct vcpu_svm *svm)
    {
    + struct vmcb *vmcb = nested_vgif_enabled(svm) ? svm->vmcb01.ptr : svm->vmcb;
    +
    if (vgif_enabled(svm))
    - return !!(svm->vmcb->control.int_ctl & V_GIF_MASK);
    + return !!(vmcb->control.int_ctl & V_GIF_MASK);
    else
    return !!(svm->vcpu.arch.hflags & HF_GIF_MASK);
    }
    --
    2.26.3
    \
     
     \ /
      Last update: 2022-02-07 17:11    [W:2.362 / U:0.076 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site