kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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)


  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).