| From 2b93f62e75e794eac9a24e40df01835a4847177c Mon Sep 17 00:00:00 2001 |
| From: Sean Christopherson <sean.j.christopherson@intel.com> |
| Date: Wed, 8 Jan 2020 12:24:37 -0800 |
| Subject: [PATCH] KVM: Use vcpu-specific gva->hva translation when querying |
| host page size |
| |
| commit f9b84e19221efc5f493156ee0329df3142085f28 upstream. |
| |
| Use kvm_vcpu_gfn_to_hva() when retrieving the host page size so that the |
| correct set of memslots is used when handling x86 page faults in SMM. |
| |
| Fixes: 54bf36aac520 ("KVM: x86: use vcpu-specific functions to read/write/translate GFNs") |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com> |
| Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/arch/powerpc/kvm/book3s_xive_native.c b/arch/powerpc/kvm/book3s_xive_native.c |
| index 5a3373e06e60..235d57d6c205 100644 |
| --- a/arch/powerpc/kvm/book3s_xive_native.c |
| +++ b/arch/powerpc/kvm/book3s_xive_native.c |
| @@ -638,7 +638,7 @@ static int kvmppc_xive_native_set_queue_config(struct kvmppc_xive *xive, |
| srcu_idx = srcu_read_lock(&kvm->srcu); |
| gfn = gpa_to_gfn(kvm_eq.qaddr); |
| |
| - page_size = kvm_host_page_size(kvm, gfn); |
| + page_size = kvm_host_page_size(vcpu, gfn); |
| if (1ull << kvm_eq.qshift > page_size) { |
| srcu_read_unlock(&kvm->srcu, srcu_idx); |
| pr_warn("Incompatible host page size %lx!\n", page_size); |
| diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c |
| index eafb78590030..8614dae82270 100644 |
| --- a/arch/x86/kvm/mmu.c |
| +++ b/arch/x86/kvm/mmu.c |
| @@ -1246,12 +1246,12 @@ static bool mmu_gfn_lpage_is_disallowed(struct kvm_vcpu *vcpu, gfn_t gfn, |
| return __mmu_gfn_lpage_is_disallowed(gfn, level, slot); |
| } |
| |
| -static int host_mapping_level(struct kvm *kvm, gfn_t gfn) |
| +static int host_mapping_level(struct kvm_vcpu *vcpu, gfn_t gfn) |
| { |
| unsigned long page_size; |
| int i, ret = 0; |
| |
| - page_size = kvm_host_page_size(kvm, gfn); |
| + page_size = kvm_host_page_size(vcpu, gfn); |
| |
| for (i = PT_PAGE_TABLE_LEVEL; i <= PT_MAX_HUGEPAGE_LEVEL; ++i) { |
| if (page_size >= KVM_HPAGE_SIZE(i)) |
| @@ -1301,7 +1301,7 @@ static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn, |
| if (unlikely(*force_pt_level)) |
| return PT_PAGE_TABLE_LEVEL; |
| |
| - host_level = host_mapping_level(vcpu->kvm, large_gfn); |
| + host_level = host_mapping_level(vcpu, large_gfn); |
| |
| if (host_level == PT_PAGE_TABLE_LEVEL) |
| return host_level; |
| diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h |
| index f18626ca7df1..fba302c2c692 100644 |
| --- a/include/linux/kvm_host.h |
| +++ b/include/linux/kvm_host.h |
| @@ -750,7 +750,7 @@ int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len); |
| int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len); |
| struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn); |
| bool kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn); |
| -unsigned long kvm_host_page_size(struct kvm *kvm, gfn_t gfn); |
| +unsigned long kvm_host_page_size(struct kvm_vcpu *vcpu, gfn_t gfn); |
| void mark_page_dirty(struct kvm *kvm, gfn_t gfn); |
| |
| struct kvm_memslots *kvm_vcpu_memslots(struct kvm_vcpu *vcpu); |
| diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c |
| index f19943bfa362..6d808e0d4ea2 100644 |
| --- a/virt/kvm/kvm_main.c |
| +++ b/virt/kvm/kvm_main.c |
| @@ -1376,14 +1376,14 @@ bool kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn) |
| } |
| EXPORT_SYMBOL_GPL(kvm_is_visible_gfn); |
| |
| -unsigned long kvm_host_page_size(struct kvm *kvm, gfn_t gfn) |
| +unsigned long kvm_host_page_size(struct kvm_vcpu *vcpu, gfn_t gfn) |
| { |
| struct vm_area_struct *vma; |
| unsigned long addr, size; |
| |
| size = PAGE_SIZE; |
| |
| - addr = gfn_to_hva(kvm, gfn); |
| + addr = kvm_vcpu_gfn_to_hva(vcpu, gfn); |
| if (kvm_is_error_hva(addr)) |
| return PAGE_SIZE; |
| |
| -- |
| 2.7.4 |
| |