linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: christoffer.dall@linaro.org (Christoffer Dall)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 02/27] arm/arm64: KVM: Support KVM_CAP_READONLY_MEM
Date: Fri, 26 Sep 2014 15:16:35 +0200	[thread overview]
Message-ID: <1411737420-9063-3-git-send-email-christoffer.dall@linaro.org> (raw)
In-Reply-To: <1411737420-9063-1-git-send-email-christoffer.dall@linaro.org>

When userspace loads code and data in a read-only memory regions, KVM
needs to be able to handle this on arm and arm64.  Specifically this is
used when running code directly from a read-only flash device; the
common scenario is a UEFI blob loaded with the -bios option in QEMU.

Note that the MMIO exit on writes to a read-only memory is ABI and can
be used to emulate block-erase style flash devices.

Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
---
 arch/arm/include/uapi/asm/kvm.h   |  1 +
 arch/arm/kvm/arm.c                |  1 +
 arch/arm/kvm/mmu.c                | 22 ++++++++--------------
 arch/arm64/include/uapi/asm/kvm.h |  1 +
 4 files changed, 11 insertions(+), 14 deletions(-)

diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index e6ebdd3..51257fd 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -25,6 +25,7 @@
 
 #define __KVM_HAVE_GUEST_DEBUG
 #define __KVM_HAVE_IRQ_LINE
+#define __KVM_HAVE_READONLY_MEM
 
 #define KVM_REG_SIZE(id)						\
 	(1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 9f788eb..ac306b4 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -188,6 +188,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 	case KVM_CAP_ONE_REG:
 	case KVM_CAP_ARM_PSCI:
 	case KVM_CAP_ARM_PSCI_0_2:
+	case KVM_CAP_READONLY_MEM:
 		r = 1;
 		break;
 	case KVM_CAP_COALESCED_MMIO:
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 16e7994..62f5642 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -747,14 +747,13 @@ static bool transparent_hugepage_adjust(pfn_t *pfnp, phys_addr_t *ipap)
 }
 
 static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
-			  struct kvm_memory_slot *memslot,
+			  struct kvm_memory_slot *memslot, unsigned long hva,
 			  unsigned long fault_status)
 {
 	int ret;
 	bool write_fault, writable, hugetlb = false, force_pte = false;
 	unsigned long mmu_seq;
 	gfn_t gfn = fault_ipa >> PAGE_SHIFT;
-	unsigned long hva = gfn_to_hva(vcpu->kvm, gfn);
 	struct kvm *kvm = vcpu->kvm;
 	struct kvm_mmu_memory_cache *memcache = &vcpu->arch.mmu_page_cache;
 	struct vm_area_struct *vma;
@@ -863,7 +862,8 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
 	unsigned long fault_status;
 	phys_addr_t fault_ipa;
 	struct kvm_memory_slot *memslot;
-	bool is_iabt;
+	unsigned long hva;
+	bool is_iabt, write_fault, writable;
 	gfn_t gfn;
 	int ret, idx;
 
@@ -884,7 +884,10 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
 	idx = srcu_read_lock(&vcpu->kvm->srcu);
 
 	gfn = fault_ipa >> PAGE_SHIFT;
-	if (!kvm_is_visible_gfn(vcpu->kvm, gfn)) {
+	memslot = gfn_to_memslot(vcpu->kvm, gfn);
+	hva = gfn_to_hva_memslot_prot(memslot, gfn, &writable);
+	write_fault = kvm_is_write_fault(kvm_vcpu_get_hsr(vcpu));
+	if (kvm_is_error_hva(hva) || (write_fault && !writable)) {
 		if (is_iabt) {
 			/* Prefetch Abort on I/O address */
 			kvm_inject_pabt(vcpu, kvm_vcpu_get_hfar(vcpu));
@@ -892,13 +895,6 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
 			goto out_unlock;
 		}
 
-		if (fault_status != FSC_FAULT) {
-			kvm_err("Unsupported fault status on io memory: %#lx\n",
-				fault_status);
-			ret = -EFAULT;
-			goto out_unlock;
-		}
-
 		/*
 		 * The IPA is reported as [MAX:12], so we need to
 		 * complement it with the bottom 12 bits from the
@@ -910,9 +906,7 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
 		goto out_unlock;
 	}
 
-	memslot = gfn_to_memslot(vcpu->kvm, gfn);
-
-	ret = user_mem_abort(vcpu, fault_ipa, memslot, fault_status);
+	ret = user_mem_abort(vcpu, fault_ipa, memslot, hva, fault_status);
 	if (ret == 0)
 		ret = 1;
 out_unlock:
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index e633ff8..f4ec5a6 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -37,6 +37,7 @@
 
 #define __KVM_HAVE_GUEST_DEBUG
 #define __KVM_HAVE_IRQ_LINE
+#define __KVM_HAVE_READONLY_MEM
 
 #define KVM_REG_SIZE(id)						\
 	(1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
-- 
2.0.0

  parent reply	other threads:[~2014-09-26 13:16 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-26 13:16 [PATCH 00/27] Changes for arm/arm64 KVM for 3.18 Christoffer Dall
2014-09-26 13:16 ` [PATCH 01/27] KVM: Introduce gfn_to_hva_memslot_prot Christoffer Dall
2014-09-26 13:16 ` Christoffer Dall [this message]
2014-09-26 13:16 ` [PATCH 03/27] KVM: ARM/arm64: fix non-const declaration of function returning const Christoffer Dall
2014-09-26 13:16 ` [PATCH 04/27] KVM: ARM/arm64: fix broken __percpu annotation Christoffer Dall
2014-09-26 13:16 ` [PATCH 05/27] KVM: ARM/arm64: avoid returning negative error code as bool Christoffer Dall
2014-09-26 13:16 ` [PATCH 06/27] KVM: ARM/arm64: return -EFAULT if copy_from_user fails in set_timer_reg Christoffer Dall
2014-09-26 13:16 ` [PATCH 07/27] KVM: vgic: return int instead of bool when checking I/O ranges Christoffer Dall
2014-09-26 13:16 ` [PATCH 08/27] KVM: vgic: declare probe function pointer as const Christoffer Dall
2014-09-26 13:16 ` [PATCH 09/27] ARM/arm64: KVM: fix use of WnR bit in kvm_is_write_fault() Christoffer Dall
2014-09-26 13:16 ` [PATCH 10/27] KVM: EVENTFD: remove inclusion of irq.h Christoffer Dall
2014-09-26 13:16 ` [PATCH 11/27] arm/arm64: KVM: Rename irq_state to irq_pending Christoffer Dall
2014-09-26 13:16 ` [PATCH 12/27] arm/arm64: KVM: Rename irq_active to irq_queued Christoffer Dall
2014-09-26 13:16 ` [PATCH 13/27] arm/arm64: KVM: vgic: Clear queued flags on unqueue Christoffer Dall
2014-09-26 13:16 ` [PATCH 14/27] arm/arm64: KVM: vgic: Improve handling of GICD_I{CS}PENDRn Christoffer Dall
2014-09-26 13:16 ` [PATCH 15/27] arm/arm64: KVM: vgic: Fix SGI writes to GICD_I{CS}PENDR0 Christoffer Dall
2014-09-26 13:16 ` [PATCH 16/27] arm/arm64: KVM: vgic: Clarify and correct vgic documentation Christoffer Dall
2014-09-26 13:16 ` [PATCH 17/27] KVM: ARM: vgic: plug irq injection race Christoffer Dall
2014-09-26 13:16 ` [PATCH 18/27] arm/arm64: KVM: vgic: switch to dynamic allocation Christoffer Dall
2014-09-26 13:16 ` [PATCH 19/27] arm/arm64: KVM: vgic: Parametrize VGIC_NR_SHARED_IRQS Christoffer Dall
2014-09-26 13:16 ` [PATCH 20/27] arm/arm64: KVM: vgic: kill VGIC_MAX_CPUS Christoffer Dall
2014-09-26 13:16 ` [PATCH 21/27] arm/arm64: KVM: vgic: handle out-of-range MMIO accesses Christoffer Dall
2014-09-26 13:16 ` [PATCH 22/27] arm/arm64: KVM: vgic: kill VGIC_NR_IRQS Christoffer Dall
2014-09-26 13:16 ` [PATCH 23/27] arm/arm64: KVM: vgic: delay vgic allocation until init time Christoffer Dall
2014-09-26 13:16 ` [PATCH 24/27] arm/arm64: KVM: vgic: make number of irqs a configurable attribute Christoffer Dall
2014-09-26 13:16 ` [PATCH 25/27] arm/arm64: KVM: Fix set_clear_sgi_pend_reg offset Christoffer Dall
2014-09-26 13:16 ` [PATCH 26/27] arm/arm64: KVM: Fix VTTBR_BADDR_MASK and pgd alloc Christoffer Dall
2014-09-26 13:17 ` [PATCH 27/27] arm/arm64: KVM: Report correct FSC for unsupported fault types Christoffer Dall
2014-09-27 19:33 ` [PATCH 00/27] Changes for arm/arm64 KVM for 3.18 Paolo Bonzini

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=1411737420-9063-3-git-send-email-christoffer.dall@linaro.org \
    --to=christoffer.dall@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    /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).