Skip to content

Commit ae49ded

Browse files
committed
KVM: PPC: Book3S HV: Handle non-present PTEs in page fault functions
Since cd758a9 "KVM: PPC: Book3S HV: Use __gfn_to_pfn_memslot in HPT page fault handler", it's been possible in fairly rare circumstances to load a non-present PTE in kvmppc_book3s_hv_page_fault() when running a guest on a POWER8 host. Because that case wasn't checked for, we could misinterpret the non-present PTE as being a cache-inhibited PTE. That could mismatch with the corresponding hash PTE, which would cause the function to fail with -EFAULT a little further down. That would propagate up to the KVM_RUN ioctl() generally causing the KVM userspace (usually qemu) to fall over. This addresses the problem by catching that case and returning to the guest instead. For completeness, this fixes the radix page fault handler in the same way. For radix this didn't cause any obvious misbehaviour, because we ended up putting the non-present PTE into the guest's partition-scoped page tables, leading immediately to another hypervisor data/instruction storage interrupt, which would go through the page fault path again and fix things up. Fixes: cd758a9 "KVM: PPC: Book3S HV: Use __gfn_to_pfn_memslot in HPT page fault handler" Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1820402 Reported-by: David Gibson <[email protected]> Tested-by: David Gibson <[email protected]> Signed-off-by: Paul Mackerras <[email protected]>
1 parent dbef280 commit ae49ded

File tree

2 files changed

+10
-8
lines changed

2 files changed

+10
-8
lines changed

arch/powerpc/kvm/book3s_64_mmu_hv.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -604,18 +604,19 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
604604
*/
605605
local_irq_disable();
606606
ptep = __find_linux_pte(vcpu->arch.pgdir, hva, NULL, &shift);
607+
pte = __pte(0);
608+
if (ptep)
609+
pte = *ptep;
610+
local_irq_enable();
607611
/*
608612
* If the PTE disappeared temporarily due to a THP
609613
* collapse, just return and let the guest try again.
610614
*/
611-
if (!ptep) {
612-
local_irq_enable();
615+
if (!pte_present(pte)) {
613616
if (page)
614617
put_page(page);
615618
return RESUME_GUEST;
616619
}
617-
pte = *ptep;
618-
local_irq_enable();
619620
hpa = pte_pfn(pte) << PAGE_SHIFT;
620621
pte_size = PAGE_SIZE;
621622
if (shift)

arch/powerpc/kvm/book3s_64_mmu_radix.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -815,18 +815,19 @@ int kvmppc_book3s_instantiate_page(struct kvm_vcpu *vcpu,
815815
*/
816816
local_irq_disable();
817817
ptep = __find_linux_pte(vcpu->arch.pgdir, hva, NULL, &shift);
818+
pte = __pte(0);
819+
if (ptep)
820+
pte = *ptep;
821+
local_irq_enable();
818822
/*
819823
* If the PTE disappeared temporarily due to a THP
820824
* collapse, just return and let the guest try again.
821825
*/
822-
if (!ptep) {
823-
local_irq_enable();
826+
if (!pte_present(pte)) {
824827
if (page)
825828
put_page(page);
826829
return RESUME_GUEST;
827830
}
828-
pte = *ptep;
829-
local_irq_enable();
830831

831832
/* If we're logging dirty pages, always map single pages */
832833
large_enable = !(memslot->flags & KVM_MEM_LOG_DIRTY_PAGES);

0 commit comments

Comments
 (0)