lkml.org 
[lkml]   [2016]   [Aug]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Subject[RFC PATCH v1 03/28] kvm: svm: Use the hardware provided GPA instead of page walk
    From
    Date
    From: Tom Lendacky <thomas.lendacky@amd.com>

    When a guest causes a NPF which requires emulation, KVM sometimes walks
    the guest page tables to translate the GVA to a GPA. This is unnecessary
    most of the time on AMD hardware since the hardware provides the GPA in
    EXITINFO2.

    The only exception cases involve string operations involving rep or
    operations that use two memory locations. With rep, the GPA will only be
    the value of the initial NPF and with dual memory locations we won't know
    which memory address was translated into EXITINFO2.

    Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
    ---
    arch/x86/include/asm/kvm_emulate.h | 3 +++
    arch/x86/include/asm/kvm_host.h | 3 +++
    arch/x86/kvm/svm.c | 2 ++
    arch/x86/kvm/x86.c | 17 ++++++++++++++++-
    4 files changed, 24 insertions(+), 1 deletion(-)

    diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
    index e9cd7be..2d1ac09 100644
    --- a/arch/x86/include/asm/kvm_emulate.h
    +++ b/arch/x86/include/asm/kvm_emulate.h
    @@ -344,6 +344,9 @@ struct x86_emulate_ctxt {
    struct read_cache mem_read;
    };

    +/* String operation identifier (matches the definition in emulate.c) */
    +#define CTXT_STRING_OP (1 << 13)
    +
    /* Repeat String Operation Prefix */
    #define REPE_PREFIX 0xf3
    #define REPNE_PREFIX 0xf2
    diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
    index c38f878..b1dd673 100644
    --- a/arch/x86/include/asm/kvm_host.h
    +++ b/arch/x86/include/asm/kvm_host.h
    @@ -667,6 +667,9 @@ struct kvm_vcpu_arch {

    int pending_ioapic_eoi;
    int pending_external_vector;
    +
    + /* GPA available (AMD only) */
    + bool gpa_available;
    };

    struct kvm_lpage_info {
    diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
    index fd5a9a8..9b2de7c 100644
    --- a/arch/x86/kvm/svm.c
    +++ b/arch/x86/kvm/svm.c
    @@ -4055,6 +4055,8 @@ static int handle_exit(struct kvm_vcpu *vcpu)

    trace_kvm_exit(exit_code, vcpu, KVM_ISA_SVM);

    + vcpu->arch.gpa_available = (exit_code == SVM_EXIT_NPF);
    +
    if (!is_cr_intercept(svm, INTERCEPT_CR0_WRITE))
    vcpu->arch.cr0 = svm->vmcb->save.cr0;
    if (npt_enabled)
    diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
    index 78295b0..d6f2f4b 100644
    --- a/arch/x86/kvm/x86.c
    +++ b/arch/x86/kvm/x86.c
    @@ -4382,7 +4382,19 @@ static int vcpu_mmio_gva_to_gpa(struct kvm_vcpu *vcpu, unsigned long gva,
    return 1;
    }

    - *gpa = vcpu->arch.walk_mmu->gva_to_gpa(vcpu, gva, access, exception);
    + /*
    + * If the exit was due to a NPF we may already have a GPA.
    + * If the GPA is present, use it to avoid the GVA to GPA table
    + * walk. Note, this cannot be used on string operations since
    + * string operation using rep will only have the initial GPA
    + * from when the NPF occurred.
    + */
    + if (vcpu->arch.gpa_available &&
    + !(vcpu->arch.emulate_ctxt.d & CTXT_STRING_OP))
    + *gpa = exception->address;
    + else
    + *gpa = vcpu->arch.walk_mmu->gva_to_gpa(vcpu, gva, access,
    + exception);

    if (*gpa == UNMAPPED_GVA)
    return -1;
    @@ -5504,6 +5516,9 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
    }

    restart:
    + /* Save the faulting GPA (cr2) in the address field */
    + ctxt->exception.address = cr2;
    +
    r = x86_emulate_insn(ctxt);

    if (r == EMULATION_INTERCEPTED)
    \
     
     \ /
      Last update: 2016-09-17 09:57    [W:4.459 / U:0.044 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site