lkml.org 
[lkml]   [2011]   [Jun]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH 12/15] KVM: MMU: abstract some functions to handle fault pfn
    Introduce handle_abnormal_pfn to handle fault pfn on page fault path,
    introduce mmu_invalid_pfn to handle fault pfn on prefetch path

    It is the preparing work for mmio page fault support

    Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com>
    ---
    arch/x86/kvm/mmu.c | 47 ++++++++++++++++++++++++++++++++-----------
    arch/x86/kvm/paging_tmpl.h | 12 +++++-----
    2 files changed, 41 insertions(+), 18 deletions(-)

    diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
    index 7286d2a..4f475ab 100644
    --- a/arch/x86/kvm/mmu.c
    +++ b/arch/x86/kvm/mmu.c
    @@ -2269,18 +2269,15 @@ static void kvm_send_hwpoison_signal(unsigned long address, struct task_struct *
    send_sig_info(SIGBUS, &info, tsk);
    }

    -static int kvm_handle_bad_page(struct kvm_vcpu *vcpu, gva_t gva,
    - unsigned access, gfn_t gfn, pfn_t pfn)
    +static int kvm_handle_bad_page(struct kvm_vcpu *vcpu, gfn_t gfn, pfn_t pfn)
    {
    kvm_release_pfn_clean(pfn);
    if (is_hwpoison_pfn(pfn)) {
    kvm_send_hwpoison_signal(gfn_to_hva(vcpu->kvm, gfn), current);
    return 0;
    - } else if (is_fault_pfn(pfn))
    - return -EFAULT;
    + }

    - vcpu_cache_mmio_info(vcpu, gva, gfn, access);
    - return 1;
    + return -EFAULT;
    }

    static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
    @@ -2325,6 +2322,33 @@ static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
    }
    }

    +static bool mmu_invalid_pfn(pfn_t pfn)
    +{
    + return unlikely(is_invalid_pfn(pfn) || is_mmio_pfn(pfn));
    +}
    +
    +static bool handle_abnormal_pfn(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn,
    + pfn_t pfn, unsigned access, int *ret_val)
    +{
    + bool ret = true;
    +
    + /* The pfn is invalid, report the error! */
    + if (unlikely(is_invalid_pfn(pfn))) {
    + *ret_val = kvm_handle_bad_page(vcpu, gfn, pfn);
    + goto exit;
    + }
    +
    + if (unlikely(is_mmio_pfn(pfn))) {
    + vcpu_cache_mmio_info(vcpu, gva, gfn, ACC_ALL);
    + *ret_val = 1;
    + goto exit;
    + }
    +
    + ret = false;
    +exit:
    + return ret;
    +}
    +
    static bool try_async_pf(struct kvm_vcpu *vcpu, bool prefault, gfn_t gfn,
    gva_t gva, pfn_t *pfn, bool write, bool *writable);

    @@ -2359,9 +2383,8 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write, gfn_t gfn,
    if (try_async_pf(vcpu, prefault, gfn, v, &pfn, write, &map_writable))
    return 0;

    - /* mmio */
    - if (is_error_pfn(pfn))
    - return kvm_handle_bad_page(vcpu, v, ACC_ALL, gfn, pfn);
    + if (handle_abnormal_pfn(vcpu, v, gfn, pfn, ACC_ALL, &r))
    + return r;

    spin_lock(&vcpu->kvm->mmu_lock);
    if (mmu_notifier_retry(vcpu, mmu_seq))
    @@ -2762,9 +2785,9 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code,
    if (try_async_pf(vcpu, prefault, gfn, gpa, &pfn, write, &map_writable))
    return 0;

    - /* mmio */
    - if (is_error_pfn(pfn))
    - return kvm_handle_bad_page(vcpu, 0, 0, gfn, pfn);
    + if (handle_abnormal_pfn(vcpu, 0, gfn, pfn, ACC_ALL, &r))
    + return r;
    +
    spin_lock(&vcpu->kvm->mmu_lock);
    if (mmu_notifier_retry(vcpu, mmu_seq))
    goto out_unlock;
    diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
    index 8353b69..4f960b2 100644
    --- a/arch/x86/kvm/paging_tmpl.h
    +++ b/arch/x86/kvm/paging_tmpl.h
    @@ -371,7 +371,7 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
    pgprintk("%s: gpte %llx spte %p\n", __func__, (u64)gpte, spte);
    pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte);
    pfn = gfn_to_pfn_atomic(vcpu->kvm, gpte_to_gfn(gpte));
    - if (is_error_pfn(pfn)) {
    + if (mmu_invalid_pfn(pfn)) {
    kvm_release_pfn_clean(pfn);
    return;
    }
    @@ -448,7 +448,7 @@ static void FNAME(pte_prefetch)(struct kvm_vcpu *vcpu, struct guest_walker *gw,
    gfn = gpte_to_gfn(gpte);
    pfn = pte_prefetch_gfn_to_pfn(vcpu, gfn,
    pte_access & ACC_WRITE_MASK);
    - if (is_error_pfn(pfn)) {
    + if (mmu_invalid_pfn(pfn)) {
    kvm_release_pfn_clean(pfn);
    break;
    }
    @@ -618,10 +618,10 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
    &map_writable))
    return 0;

    - /* mmio */
    - if (is_error_pfn(pfn))
    - return kvm_handle_bad_page(vcpu, mmu_is_nested(vcpu) ? 0 :
    - addr, walker.pte_access, walker.gfn, pfn);
    + if (handle_abnormal_pfn(vcpu, mmu_is_nested(vcpu) ? 0 : addr,
    + walker.gfn, pfn, walker.pte_access, &r))
    + return r;
    +
    spin_lock(&vcpu->kvm->mmu_lock);
    if (mmu_notifier_retry(vcpu, mmu_seq))
    goto out_unlock;
    --
    1.7.4.4


    \
     
     \ /
      Last update: 2011-06-07 15:05    [W:4.453 / U:0.128 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site