lkml.org 
[lkml]   [2021]   [Jun]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH Part2 RFC v3 24/37] KVM: X86: Add kvm_x86_ops to get the max page level for the TDP
    Date
    When running an SEV-SNP VM, the sPA used to index the RMP entry is
    obtained through the TDP translation (gva->gpa->spa). The TDP page
    level is checked against the page level programmed in the RMP entry.
    If the page level does not match, then it will cause a nested page
    fault with the RMP bit set to indicate the RMP violation.

    To keep the TDP and RMP page level's in sync, the KVM fault handle
    kvm_handle_page_fault() will call get_tdp_max_page_level() to get
    the maximum allowed page level so that it can limit the TDP level.

    In the case of SEV-SNP guest, the get_tdp_max_page_level() will consult
    the RMP table to compute the maximum allowed page level for a given
    GPA.

    Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
    ---
    arch/x86/include/asm/kvm_host.h | 1 +
    arch/x86/kvm/mmu/mmu.c | 6 ++++--
    arch/x86/kvm/svm/sev.c | 20 ++++++++++++++++++++
    arch/x86/kvm/svm/svm.c | 1 +
    arch/x86/kvm/svm/svm.h | 1 +
    arch/x86/kvm/vmx/vmx.c | 8 ++++++++
    6 files changed, 35 insertions(+), 2 deletions(-)

    diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
    index 188110ab2c02..cd2e19e1d323 100644
    --- a/arch/x86/include/asm/kvm_host.h
    +++ b/arch/x86/include/asm/kvm_host.h
    @@ -1384,6 +1384,7 @@ struct kvm_x86_ops {

    void (*vcpu_deliver_sipi_vector)(struct kvm_vcpu *vcpu, u8 vector);
    void *(*alloc_apic_backing_page)(struct kvm_vcpu *vcpu);
    + int (*get_tdp_max_page_level)(struct kvm_vcpu *vcpu, gpa_t gpa, int max_level);
    };

    struct kvm_x86_nested_ops {
    diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
    index 0144c40d09c7..7991ffae7b31 100644
    --- a/arch/x86/kvm/mmu/mmu.c
    +++ b/arch/x86/kvm/mmu/mmu.c
    @@ -3781,11 +3781,13 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code,
    static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gpa_t gpa,
    u32 error_code, bool prefault)
    {
    + int max_level = kvm_x86_ops.get_tdp_max_page_level(vcpu, gpa, PG_LEVEL_2M);
    +
    pgprintk("%s: gva %lx error %x\n", __func__, gpa, error_code);

    /* This path builds a PAE pagetable, we can map 2mb pages at maximum. */
    return direct_page_fault(vcpu, gpa & PAGE_MASK, error_code, prefault,
    - PG_LEVEL_2M, false);
    + max_level, false);
    }

    int kvm_handle_page_fault(struct kvm_vcpu *vcpu, u64 error_code,
    @@ -3826,7 +3828,7 @@ int kvm_tdp_page_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code,
    {
    int max_level;

    - for (max_level = KVM_MAX_HUGEPAGE_LEVEL;
    + for (max_level = kvm_x86_ops.get_tdp_max_page_level(vcpu, gpa, KVM_MAX_HUGEPAGE_LEVEL);
    max_level > PG_LEVEL_4K;
    max_level--) {
    int page_num = KVM_PAGES_PER_HPAGE(max_level);
    diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
    index 856a6cf99a61..6b0c230c5f37 100644
    --- a/arch/x86/kvm/svm/sev.c
    +++ b/arch/x86/kvm/svm/sev.c
    @@ -3184,3 +3184,23 @@ struct page *snp_safe_alloc_page(struct kvm_vcpu *vcpu)

    return pfn_to_page(pfn);
    }
    +
    +int sev_get_tdp_max_page_level(struct kvm_vcpu *vcpu, gpa_t gpa, int max_level)
    +{
    + struct rmpentry *e;
    + kvm_pfn_t pfn;
    + int level;
    +
    + if (!sev_snp_guest(vcpu->kvm))
    + return max_level;
    +
    + pfn = gfn_to_pfn(vcpu->kvm, gpa_to_gfn(gpa));
    + if (is_error_noslot_pfn(pfn))
    + return max_level;
    +
    + e = snp_lookup_page_in_rmptable(pfn_to_page(pfn), &level);
    + if (unlikely(!e))
    + return max_level;
    +
    + return min_t(uint32_t, level, max_level);
    +}
    diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
    index a7adf6ca1713..2632eae52aa3 100644
    --- a/arch/x86/kvm/svm/svm.c
    +++ b/arch/x86/kvm/svm/svm.c
    @@ -4576,6 +4576,7 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
    .vcpu_deliver_sipi_vector = svm_vcpu_deliver_sipi_vector,

    .alloc_apic_backing_page = svm_alloc_apic_backing_page,
    + .get_tdp_max_page_level = sev_get_tdp_max_page_level,
    };

    static struct kvm_x86_init_ops svm_init_ops __initdata = {
    diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
    index bc5582b44356..32abcbd774d0 100644
    --- a/arch/x86/kvm/svm/svm.h
    +++ b/arch/x86/kvm/svm/svm.h
    @@ -568,6 +568,7 @@ void sev_vcpu_deliver_sipi_vector(struct kvm_vcpu *vcpu, u8 vector);
    void sev_es_prepare_guest_switch(struct vcpu_svm *svm, unsigned int cpu);
    void sev_es_unmap_ghcb(struct vcpu_svm *svm);
    struct page *snp_safe_alloc_page(struct kvm_vcpu *vcpu);
    +int sev_get_tdp_max_page_level(struct kvm_vcpu *vcpu, gpa_t gpa, int max_level);

    /* vmenter.S */

    diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
    index 4bceb5ca3a89..fbc9034edf16 100644
    --- a/arch/x86/kvm/vmx/vmx.c
    +++ b/arch/x86/kvm/vmx/vmx.c
    @@ -7612,6 +7612,12 @@ static bool vmx_check_apicv_inhibit_reasons(ulong bit)
    return supported & BIT(bit);
    }

    +
    +static int vmx_get_tdp_max_page_level(struct kvm_vcpu *vcpu, gpa_t gpa, int max_level)
    +{
    + return max_level;
    +}
    +
    static struct kvm_x86_ops vmx_x86_ops __initdata = {
    .hardware_unsetup = hardware_unsetup,

    @@ -7742,6 +7748,8 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = {
    .complete_emulated_msr = kvm_complete_insn_gp,

    .vcpu_deliver_sipi_vector = kvm_vcpu_deliver_sipi_vector,
    +
    + .get_tdp_max_page_level = vmx_get_tdp_max_page_level,
    };

    static __init void vmx_setup_user_return_msrs(void)
    --
    2.17.1
    \
     
     \ /
      Last update: 2021-06-02 16:16    [W:5.936 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site