From mboxrd@z Thu Jan 1 00:00:00 1970 From: Christoffer Dall Subject: Re: [PATCH v3 7/8] ARM: KVM: Handle guest faults in KVM Date: Sat, 11 Jun 2011 12:37:01 +0200 Message-ID: References: <20110603150318.17011.82777.stgit@ubuntu> <20110603150414.17011.72525.stgit@ubuntu> <4DEB7B10.2070304@redhat.com> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: QUOTED-PRINTABLE Cc: catalin.marinas@arm.com, android-virt@lists.cs.columbia.edu, s.raho@virtualopensystems.com, a.motakis@virtualopensystems.com, kvm@vger.kernel.org, a.costa@virtualopensystems.com To: Avi Kivity Return-path: Received: from mail-gx0-f174.google.com ([209.85.161.174]:58485 "EHLO mail-gx0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751679Ab1FKKhD convert rfc822-to-8bit (ORCPT ); Sat, 11 Jun 2011 06:37:03 -0400 Received: by gxk21 with SMTP id 21so2211468gxk.19 for ; Sat, 11 Jun 2011 03:37:02 -0700 (PDT) In-Reply-To: <4DEB7B10.2070304@redhat.com> Sender: kvm-owner@vger.kernel.org List-ID: On Sun, Jun 5, 2011 at 2:48 PM, Avi Kivity wrote: > On 06/03/2011 06:04 PM, Christoffer Dall wrote: >> >> Handles the guest faults in KVM by mapping in corresponding user pag= es >> in the 2nd stage page tables. >> >> >> >> +static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_= ipa, >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 gfn_t gfn, struct = kvm_memory_slot *memslot) >> +{ >> + =A0 =A0 =A0 pfn_t pfn; >> + =A0 =A0 =A0 pgd_t *pgd; >> + =A0 =A0 =A0 pmd_t *pmd; >> + =A0 =A0 =A0 pte_t *pte, new_pte; >> + >> + =A0 =A0 =A0 pfn =3D gfn_to_pfn(vcpu->kvm, gfn); >> + >> + =A0 =A0 =A0 if (is_error_pfn(pfn)) { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 kvm_err(-EFAULT, "Guest gfn %u (0x%08l= x) does not have " >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "corre= sponding host mapping", >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 gfn, g= fn<< =A0PAGE_SHIFT); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -EFAULT; >> + =A0 =A0 =A0 } >> + >> + =A0 =A0 =A0 /* Create 2nd stage page table mapping - Level 1 */ >> + =A0 =A0 =A0 pgd =3D vcpu->kvm->arch.pgd + pgd_index(fault_ipa); >> + =A0 =A0 =A0 if (pgd_none(*pgd)) { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pmd =3D pmd_alloc_one(NULL, fault_ipa)= ; >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!pmd) { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 kvm_err(-ENOMEM, "Cann= ot allocate 2nd stage pmd"); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOMEM; >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 } >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pgd_populate(NULL, pgd, pmd); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pmd +=3D pmd_index(fault_ipa); >> + =A0 =A0 =A0 } else >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pmd =3D pmd_offset(pgd, fault_ipa); >> + >> + =A0 =A0 =A0 /* Create 2nd stage page table mapping - Level 2 */ >> + =A0 =A0 =A0 if (pmd_none(*pmd)) { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pte =3D pte_alloc_one_kernel(NULL, fau= lt_ipa); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!pte) { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 kvm_err(-ENOMEM, "Cann= ot allocate 2nd stage pte"); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOMEM; >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 } >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pmd_populate_kernel(NULL, pmd, pte); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pte +=3D pte_index(fault_ipa); >> + =A0 =A0 =A0 } else >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pte =3D pte_offset_kernel(pmd, fault_i= pa); >> + >> + =A0 =A0 =A0 /* Create 2nd stage page table mapping - Level 3 */ >> + =A0 =A0 =A0 new_pte =3D pfn_pte(pfn, PAGE_KVM_GUEST); >> + =A0 =A0 =A0 set_pte_ext(pte, new_pte, 0); >> + >> + =A0 =A0 =A0 return 0; >> +} >> + >> +#define HSR_ABT_FS =A0 =A0 (0x3f) >> +#define HPFAR_MASK =A0 =A0 (~0xf) >> =A0int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run = *run) >> =A0{ >> + =A0 =A0 =A0 unsigned long hsr_ec; >> + =A0 =A0 =A0 unsigned long fault_status; >> + =A0 =A0 =A0 phys_addr_t fault_ipa; >> + =A0 =A0 =A0 struct kvm_memory_slot *memslot =3D NULL; >> + =A0 =A0 =A0 bool is_iabt; >> + =A0 =A0 =A0 gfn_t gfn; >> + >> + =A0 =A0 =A0 hsr_ec =3D vcpu->arch.hsr>> =A0HSR_EC_SHIFT; >> + =A0 =A0 =A0 is_iabt =3D (hsr_ec =3D=3D HSR_EC_IABT); >> + >> + =A0 =A0 =A0 /* Check that the second stage fault is a translation = fault */ >> + =A0 =A0 =A0 fault_status =3D vcpu->arch.hsr& =A0HSR_ABT_FS; >> + =A0 =A0 =A0 if ((fault_status& =A00x3c) !=3D 0x4) { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 kvm_err(-EFAULT, "Unsupported fault st= atus: %x", >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 fault_= status& =A00x3c); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -EFAULT; >> + =A0 =A0 =A0 } >> + >> + =A0 =A0 =A0 fault_ipa =3D ((phys_addr_t)vcpu->arch.hpfar& =A0HPFAR= _MASK)<< =A08; >> + >> + =A0 =A0 =A0 gfn =3D fault_ipa>> =A0PAGE_SHIFT; >> + =A0 =A0 =A0 if (!kvm_is_visible_gfn(vcpu->kvm, gfn)) >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto io_mem_abort; >> + >> + =A0 =A0 =A0 memslot =3D gfn_to_memslot(vcpu->kvm, gfn); >> + =A0 =A0 =A0 if (memslot->user_alloc) >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return user_mem_abort(vcpu, fault_ipa,= gfn, memslot); > > Non-user_alloc should not exist for ARM (and are not supported for x8= 6 these > days, except for a few implementation internal slots). ok, I raise an error in when (!memslot->user_alloc) instead now. thanks= =2E > >> + >> +io_mem_abort: >> + =A0 =A0 =A0 if (is_iabt) { >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 kvm_err(-EFAULT, "Inst. abort on I/O a= ddress"); >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -EFAULT; >> + =A0 =A0 =A0 } >> + >> + =A0 =A0 =A0 kvm_msg("I/O address abort..."); >> =A0 =A0 =A0 =A0KVMARM_NOT_IMPLEMENTED(); >> =A0 =A0 =A0 =A0return -EINVAL; >> =A0} > > Okay, this is about a zillion times simpler than x86. =A0Congratulati= ons. Well, I need to handle the I/O aborts, but it's quite simple. What makes it much more complicated on x86? > > What are your thoughts about mmu notifier support? =46or what purpose? There is no swapping on ARM, so only case that jump= s to my mind is for KSM. And I'm not quite there yet :)