From: Christoffer Dall <c.dall@virtualopensystems.com>
To: kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org
Subject: [PATCH v10 12/14] KVM: ARM: Handle guest faults in KVM
Date: Thu, 16 Aug 2012 11:30:19 -0400 [thread overview]
Message-ID: <20120816153019.21484.74222.stgit@ubuntu> (raw)
In-Reply-To: <20120816152637.21484.65421.stgit@ubuntu>
Handles the guest faults in KVM by mapping in corresponding user pages
in the 2nd stage page tables.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <c.dall@virtualopensystems.com>
---
arch/arm/include/asm/kvm_arm.h | 9 ++++
arch/arm/include/asm/kvm_asm.h | 2 +
arch/arm/kvm/mmu.c | 102 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 112 insertions(+), 1 deletion(-)
diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h
index ae586c1..4cff3b7 100644
--- a/arch/arm/include/asm/kvm_arm.h
+++ b/arch/arm/include/asm/kvm_arm.h
@@ -158,11 +158,20 @@
#define HSR_ISS (HSR_IL - 1)
#define HSR_ISV_SHIFT (24)
#define HSR_ISV (1U << HSR_ISV_SHIFT)
+#define HSR_FSC (0x3f)
+#define HSR_FSC_TYPE (0x3c)
+#define HSR_WNR (1 << 6)
#define HSR_CV_SHIFT (24)
#define HSR_CV (1U << HSR_CV_SHIFT)
#define HSR_COND_SHIFT (20)
#define HSR_COND (0xfU << HSR_COND_SHIFT)
+#define FSC_FAULT (0x04)
+#define FSC_PERM (0x0c)
+
+/* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */
+#define HPFAR_MASK (~0xf)
+
#define HSR_EC_UNKNOWN (0x00)
#define HSR_EC_WFI (0x01)
#define HSR_EC_CP15_32 (0x03)
diff --git a/arch/arm/include/asm/kvm_asm.h b/arch/arm/include/asm/kvm_asm.h
index 55b6446..85bd676 100644
--- a/arch/arm/include/asm/kvm_asm.h
+++ b/arch/arm/include/asm/kvm_asm.h
@@ -48,6 +48,8 @@ extern char __kvm_hyp_vector[];
extern char __kvm_hyp_code_start[];
extern char __kvm_hyp_code_end[];
+extern void __kvm_tlb_flush_vmid(struct kvm *kvm);
+
extern void __kvm_flush_vm_context(void);
extern void __kvm_tlb_flush_vmid(struct kvm *kvm);
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 6cb0e38..448fbd6 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -25,6 +25,7 @@
#include <asm/kvm_mmu.h>
#include <asm/kvm_asm.h>
#include <asm/mach/map.h>
+#include <asm/kvm_asm.h>
static DEFINE_MUTEX(kvm_hyp_pgd_mutex);
@@ -491,9 +492,108 @@ out:
return ret;
}
+static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
+ gfn_t gfn, struct kvm_memory_slot *memslot,
+ bool is_iabt)
+{
+ pte_t new_pte;
+ pfn_t pfn;
+ int ret;
+ bool write_fault, writable;
+ struct kvm_mmu_memory_cache *memcache = &vcpu->arch.mmu_page_cache;
+
+ /* TODO: Use instr. decoding for non-ISV to determine r/w fault */
+ if (is_iabt)
+ write_fault = false;
+ else if ((vcpu->arch.hsr & HSR_ISV) && !(vcpu->arch.hsr & HSR_WNR))
+ write_fault = false;
+ else
+ write_fault = true;
+
+ if ((vcpu->arch.hsr & HSR_FSC_TYPE) == FSC_PERM && !write_fault) {
+ kvm_err("Unexpected L2 read permission error\n");
+ return -EFAULT;
+ }
+
+ pfn = gfn_to_pfn_prot(vcpu->kvm, gfn, write_fault, &writable);
+
+ if (is_error_pfn(pfn)) {
+ put_page(pfn_to_page(pfn));
+ kvm_err("No host mapping: gfn %u (0x%08x)\n",
+ (unsigned int)gfn,
+ (unsigned int)gfn << PAGE_SHIFT);
+ return -EFAULT;
+ }
+
+ /* We need minimum second+third level pages */
+ ret = mmu_topup_memory_cache(memcache, 2, KVM_NR_MEM_OBJS);
+ if (ret)
+ return ret;
+ new_pte = pfn_pte(pfn, PAGE_KVM_GUEST);
+ if (writable)
+ new_pte |= L_PTE2_WRITE;
+ spin_lock(&vcpu->kvm->arch.pgd_lock);
+ stage2_set_pte(vcpu->kvm, memcache, fault_ipa, &new_pte);
+ spin_unlock(&vcpu->kvm->arch.pgd_lock);
+
+ return ret;
+}
+
+/**
+ * kvm_handle_guest_abort - handles all 2nd stage aborts
+ * @vcpu: the VCPU pointer
+ * @run: the kvm_run structure
+ *
+ * Any abort that gets to the host is almost guaranteed to be caused by a
+ * missing second stage translation table entry, which can mean that either the
+ * guest simply needs more memory and we must allocate an appropriate page or it
+ * can mean that the guest tried to access I/O memory, which is emulated by user
+ * space. The distinction is based on the IPA causing the fault and whether this
+ * memory region has been registered as standard RAM by user space.
+ */
int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
{
- return -EINVAL;
+ unsigned long hsr_ec;
+ unsigned long fault_status;
+ phys_addr_t fault_ipa;
+ struct kvm_memory_slot *memslot = NULL;
+ bool is_iabt;
+ gfn_t gfn;
+ int ret;
+
+ hsr_ec = vcpu->arch.hsr >> HSR_EC_SHIFT;
+ is_iabt = (hsr_ec == HSR_EC_IABT);
+
+ /* Check that the second stage fault is a translation fault */
+ fault_status = (vcpu->arch.hsr & HSR_FSC_TYPE);
+ if (fault_status != FSC_FAULT && fault_status != FSC_PERM) {
+ kvm_err("Unsupported fault status: EC=%#lx DFCS=%#lx\n",
+ hsr_ec, fault_status);
+ return -EFAULT;
+ }
+
+ fault_ipa = ((phys_addr_t)vcpu->arch.hpfar & HPFAR_MASK) << 8;
+
+ gfn = fault_ipa >> PAGE_SHIFT;
+ if (!kvm_is_visible_gfn(vcpu->kvm, gfn)) {
+ if (is_iabt) {
+ kvm_err("Inst. abort on I/O address %08lx\n",
+ (unsigned long)fault_ipa);
+ return -EFAULT;
+ }
+
+ kvm_pr_unimpl("I/O address abort...");
+ return 0;
+ }
+
+ memslot = gfn_to_memslot(vcpu->kvm, gfn);
+ if (!memslot->user_alloc) {
+ kvm_err("non user-alloc memslots not supported\n");
+ return -EINVAL;
+ }
+
+ ret = user_mem_abort(vcpu, fault_ipa, gfn, memslot, is_iabt);
+ return ret ? ret : 1;
}
static bool hva_to_gpa(struct kvm *kvm, unsigned long hva, gpa_t *gpa)
next prev parent reply other threads:[~2012-08-16 15:30 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-08-16 15:27 [PATCH v10 00/14] KVM/ARM Implementation Christoffer Dall
2012-08-16 15:28 ` [PATCH v10 01/14] ARM: add mem_type prot_pte accessor Christoffer Dall
2012-08-16 15:28 ` [PATCH v10 02/14] ARM: Add config option ARM_VIRT_EXT Christoffer Dall
2012-08-16 15:28 ` [PATCH v10 03/14] ARM: Section based HYP idmap Christoffer Dall
2012-08-16 15:28 ` [PATCH v10 04/14] ARM: Expose PMNC bitfields for KVM use Christoffer Dall
2012-08-16 15:28 ` [PATCH v10 05/14] KVM: ARM: Initial skeleton to compile KVM support Christoffer Dall
2012-08-16 15:29 ` [PATCH v10 06/14] KVM: ARM: Hypervisor inititalization Christoffer Dall
2012-08-23 15:08 ` [kvmarm] " Lei Wen
2012-08-23 15:27 ` Christoffer Dall
2012-08-24 8:04 ` Lei Wen
2012-08-24 13:38 ` Marc Zyngier
2012-08-24 14:34 ` Lei Wen
2012-08-16 15:29 ` [PATCH v10 07/14] KVM: ARM: Memory virtualization setup Christoffer Dall
2012-08-16 18:25 ` [kvmarm] " Alexander Graf
2012-08-19 4:34 ` Christoffer Dall
2012-08-19 9:38 ` Peter Maydell
2012-08-19 13:00 ` Avi Kivity
2012-08-19 20:00 ` Christoffer Dall
2012-08-23 8:12 ` Min-gyu Kim
2012-08-23 14:46 ` Christoffer Dall
2012-08-16 15:29 ` [PATCH v10 08/14] KVM: ARM: Inject IRQs and FIQs from userspace Christoffer Dall
2012-08-21 8:20 ` Jan Kiszka
2012-08-21 14:13 ` Christoffer Dall
2012-08-16 15:29 ` [PATCH v10 09/14] KVM: ARM: World-switch implementation Christoffer Dall
2012-08-16 15:29 ` [PATCH v10 10/14] KVM: ARM: Emulation framework and CP15 emulation Christoffer Dall
2012-08-16 15:30 ` [PATCH v10 11/14] KVM: ARM: User space API for getting/setting co-proc registers Christoffer Dall
2012-08-16 15:30 ` Christoffer Dall [this message]
2012-08-16 15:30 ` [PATCH v10 13/14] KVM: ARM: Handle I/O aborts Christoffer Dall
2012-08-16 15:30 ` [PATCH v10 14/14] KVM: ARM: Guest wait-for-interrupts (WFI) support Christoffer Dall
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20120816153019.21484.74222.stgit@ubuntu \
--to=c.dall@virtualopensystems.com \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.cs.columbia.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).