Message ID | 20200108202448.9669-5-sean.j.christopherson@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | KVM: x86/mmu: Huge page fixes, cleanup, and DAX | expand |
On 08/01/20 21:24, Sean Christopherson wrote: > diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c > index 5f7f06824c2b..d9aced677ddd 100644 > --- a/virt/kvm/kvm_main.c > +++ b/virt/kvm/kvm_main.c > @@ -1418,15 +1418,23 @@ EXPORT_SYMBOL_GPL(kvm_is_visible_gfn); > > unsigned long kvm_host_page_size(struct kvm_vcpu *vcpu, gfn_t gfn) > { > + struct kvm_memory_slot *slot; > struct vm_area_struct *vma; > unsigned long addr, size; > > size = PAGE_SIZE; > > - addr = kvm_vcpu_gfn_to_hva(vcpu, gfn); > - if (kvm_is_error_hva(addr)) > + /* > + * Manually do the equivalent of kvm_vcpu_gfn_to_hva() to avoid the > + * "writable" check in __gfn_to_hva_many(), which will always fail on > + * read-only memslots due to gfn_to_hva() assuming writes. > + */ > + slot = kvm_vcpu_gfn_to_memslot(vcpu, gfn); > + if (!slot || slot->flags & KVM_MEMSLOT_INVALID) > return PAGE_SIZE; > > + addr = __gfn_to_hva_memslot(slot, gfn); > + > down_read(¤t->mm->mmap_sem); > vma = find_vma(current->mm, addr); > if (!vma) > Even simpler: use kvm_vcpu_gfn_to_hva_prot - addr = kvm_vcpu_gfn_to_hva(vcpu, gfn); + addr = kvm_vcpu_gfn_to_hva_prot(vcpu, gfn, NULL); "You are in a maze of twisty little functions, all alike". Paolo
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 5f7f06824c2b..d9aced677ddd 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -1418,15 +1418,23 @@ EXPORT_SYMBOL_GPL(kvm_is_visible_gfn); unsigned long kvm_host_page_size(struct kvm_vcpu *vcpu, gfn_t gfn) { + struct kvm_memory_slot *slot; struct vm_area_struct *vma; unsigned long addr, size; size = PAGE_SIZE; - addr = kvm_vcpu_gfn_to_hva(vcpu, gfn); - if (kvm_is_error_hva(addr)) + /* + * Manually do the equivalent of kvm_vcpu_gfn_to_hva() to avoid the + * "writable" check in __gfn_to_hva_many(), which will always fail on + * read-only memslots due to gfn_to_hva() assuming writes. + */ + slot = kvm_vcpu_gfn_to_memslot(vcpu, gfn); + if (!slot || slot->flags & KVM_MEMSLOT_INVALID) return PAGE_SIZE; + addr = __gfn_to_hva_memslot(slot, gfn); + down_read(¤t->mm->mmap_sem); vma = find_vma(current->mm, addr); if (!vma)
Open code an equivalent of kvm_vcpu_gfn_to_memslot() when querying the host page size to avoid the "writable" check in __gfn_to_hva_many(), which will always fail on read-only memslots due to gfn_to_hva() assuming writes. Functionally, this allows x86 to create large mappings for read-only memslots that are backed by HugeTLB mappings. Note, the changelog for commit 05da45583de9 ("KVM: MMU: large page support") states "If the largepage contains write-protected pages, a large pte is not used.", but "write-protected" refers to pages that are temporarily read-only, e.g. read-only memslots didn't even exist at the time. Fixes: 4d8b81abc47b ("KVM: introduce readonly memslot") Cc: stable@vger.kernel.org Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com> --- virt/kvm/kvm_main.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)