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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.