From patchwork Thu Feb 8 16:03:03 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?C=C3=A9dric_Le_Goater?= X-Patchwork-Id: 871144 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=kvm-ppc-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3zcr150VWpz9sPk for ; Fri, 9 Feb 2018 07:50:00 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752020AbeBHUuA (ORCPT ); Thu, 8 Feb 2018 15:50:00 -0500 Received: from 14.mo7.mail-out.ovh.net ([178.33.251.19]:44462 "EHLO 14.mo7.mail-out.ovh.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751756AbeBHUt7 (ORCPT ); Thu, 8 Feb 2018 15:49:59 -0500 X-Greylist: delayed 17188 seconds by postgrey-1.27 at vger.kernel.org; Thu, 08 Feb 2018 15:49:59 EST Received: from player697.ha.ovh.net (gw6.ovh.net [213.251.189.206]) by mo7.mail-out.ovh.net (Postfix) with ESMTP id 4B0AA8DE0A for ; Thu, 8 Feb 2018 17:03:29 +0100 (CET) Received: from zorba.kaod.org.com (LFbn-1-2226-150.w90-76.abo.wanadoo.fr [90.76.48.150]) (Authenticated sender: clg@kaod.org) by player697.ha.ovh.net (Postfix) with ESMTPSA id 6866948009A; Thu, 8 Feb 2018 17:03:23 +0100 (CET) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: kvm-ppc@vger.kernel.org, kvm@vger.kernel.org, Paolo Bonzini , Paul Mackerras Cc: Benjamin Herrenschmidt , =?utf-8?b?Q8OpZHJp?= =?utf-8?q?c_Le_Goater?= Subject: [RFC PATCH] KVM: PPC: Book3S HV: add support for page faults in VM_IO|VM_PFNMAP vmas Date: Thu, 8 Feb 2018 17:03:03 +0100 Message-Id: <20180208160303.19016-1-clg@kaod.org> X-Mailer: git-send-email 2.13.6 MIME-Version: 1.0 X-Ovh-Tracer-Id: 8417509182598974423 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedtfedrudekgdekgecutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfqggfjpdevjffgvefmvefgnecuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org On the POWER9 processor, the XIVE interrupt controller can control interrupt sources using MMIO to trigger events, to EOI or to turn off the sources. Priority management and interrupt acknowledgment is also controlled by MMIO in the presenter subengine. These MMIO regions are exposed to guests in QEMU with a set of memory mappings, similarly to VFIO, and it would be good to populate dynamically the VMAs with the appropriate pages using a fault handler. Largy inspired by Paulo's commit add6a0cd1c5b ("KVM: MMU: try to fix up page faults before giving up"), this adds support for page faults under KVM/PPC for memory mappings of host MMIO regions exposed in guests. If this is the right approach, can we externalize the hva_to_pfn_remapped() routine to use it under kvm/ppc in the Radix tree and HPT MMU modes ? Signed-off-by: Cédric Le Goater Cc: Paolo Bonzini --- arch/powerpc/kvm/book3s_64_mmu_radix.c | 59 ++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kvm/book3s_64_mmu_radix.c b/arch/powerpc/kvm/book3s_64_mmu_radix.c index 58618f644c56..74e889575bf0 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_radix.c +++ b/arch/powerpc/kvm/book3s_64_mmu_radix.c @@ -291,6 +291,54 @@ static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa, return ret; } +/* + * Stolen from virt/kvm/kvm_main.c + */ +static int hva_to_pfn_remapped(struct vm_area_struct *vma, + unsigned long addr, bool write_fault, + unsigned long *p_pfn) +{ + unsigned long pfn; + int r; + + r = follow_pfn(vma, addr, &pfn); + if (r) { + /* + * get_user_pages fails for VM_IO and VM_PFNMAP vmas and does + * not call the fault handler, so do it here. + */ + bool unlocked = false; + + r = fixup_user_fault(current, current->mm, addr, + (write_fault ? FAULT_FLAG_WRITE : 0), + &unlocked); + if (unlocked) + return -EAGAIN; + if (r) + return r; + + r = follow_pfn(vma, addr, &pfn); + if (r) + return r; + } + + /* + * Get a reference here because callers of *hva_to_pfn* and + * *gfn_to_pfn* ultimately call kvm_release_pfn_clean on the + * returned pfn. This is only needed if the VMA has VM_MIXEDMAP + * set, but the kvm_get_pfn/kvm_release_pfn_clean pair will + * simply do nothing for reserved pfns. + * + * Whoever called remap_pfn_range is also going to call e.g. + * unmap_mapping_range before the underlying pages are freed, + * causing a call to our MMU notifier. + */ + kvm_get_pfn(pfn); + + *p_pfn = pfn; + return 0; +} + int kvmppc_book3s_radix_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, unsigned long ea, unsigned long dsisr) { @@ -402,8 +450,15 @@ int kvmppc_book3s_radix_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, vma = find_vma(current->mm, hva); if (vma && vma->vm_start <= hva && hva < vma->vm_end && (vma->vm_flags & VM_PFNMAP)) { - pfn = vma->vm_pgoff + - ((hva - vma->vm_start) >> PAGE_SHIFT); + if (vma->vm_flags & (VM_IO | VM_PFNMAP)) { + ret = hva_to_pfn_remapped(vma, hva, writing, + &pfn); + if (ret == -EAGAIN) + return RESUME_GUEST; + } else { + pfn = vma->vm_pgoff + + ((hva - vma->vm_start) >> PAGE_SHIFT); + } pgflags = pgprot_val(vma->vm_page_prot); } up_read(¤t->mm->mmap_sem);