[RFC PATCH 5/6] KVM: ARM: implement kvm_*_incoherent_memory_regions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add the kvm_*_incoherent_memory_regions calls to arm's
kvm_arch_vcpu_ioctl_run and implement the corresponding
arch flush/invalidate functions.

Signed-off-by: Andrew Jones <drjones@xxxxxxxxxx>
---
 arch/arm/include/uapi/asm/kvm.h   |  1 +
 arch/arm/kvm/arm.c                |  4 +++
 arch/arm/kvm/mmu.c                | 54 +++++++++++++++++++++++++++++++++++++++
 arch/arm64/include/uapi/asm/kvm.h |  1 +
 4 files changed, 60 insertions(+)

diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index 09ee408c1a676..cb0898a995c4f 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -26,6 +26,7 @@
 #define __KVM_HAVE_GUEST_DEBUG
 #define __KVM_HAVE_IRQ_LINE
 #define __KVM_HAVE_READONLY_MEM
+#define __KVM_HAVE_INCOHERENT_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 c9e6ef1f7403a..789c03c84e7c0 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -486,6 +486,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
 			return ret;
 	}
 
+	kvm_flush_incoherent_memory_regions(vcpu->kvm);
+
 	if (vcpu->sigset_active)
 		sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
 
@@ -556,6 +558,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
 		ret = handle_exit(vcpu, run, ret);
 	}
 
+	kvm_invalidate_incoherent_memory_regions(vcpu->kvm);
+
 	if (vcpu->sigset_active)
 		sigprocmask(SIG_SETMASK, &sigsaved, NULL);
 	return ret;
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 2f3a6581b9200..2f45db9cd436a 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -1161,6 +1161,24 @@ static void coherent_cache_guest_page(struct kvm_vcpu *vcpu, pfn_t pfn,
 	__coherent_cache_guest_page(pfn, size, need_flush, false);
 }
 
+static void coherent_cache_memslot(struct kvm_memory_slot *slot, bool flush)
+{
+	gfn_t gfn, end = slot->base_gfn + slot->npages;
+	pfn_t pfn;
+
+	for (gfn = slot->base_gfn; gfn < end; ++gfn) {
+		pfn = gfn_to_pfn_memslot(slot, gfn);
+		if (is_error_pfn(pfn)) {
+			pr_err("%s: Bad pfn: gfn=%llx, pfn=%llx, "
+				"userspace_addr=%lx\n", __func__,
+				gfn, pfn, slot->userspace_addr);
+			continue;
+		}
+		__coherent_cache_guest_page(pfn, PAGE_SIZE, flush, !flush);
+		kvm_release_pfn_clean(pfn);
+	}
+}
+
 static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 			  struct kvm_memory_slot *memslot, unsigned long hva,
 			  unsigned long fault_status)
@@ -1802,6 +1820,42 @@ int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
 	return 0;
 }
 
+void kvm_arch_flush_incoherent(struct kvm *kvm, struct kvm_memory_slot *slot)
+{
+	if (slot->flags & KVM_MEM_READONLY) {
+		/*
+		 * Readonly memory shouldn't be changing, and we do a
+		 * clean+invalidate for KVM_MEM_INCOHERENT memory when
+		 * faulting it in. So, there's nothing to do now.
+		 */
+		return;
+	}
+
+	/*
+	 * Ideally, we would further filter out all pages not touched by
+	 * userspace on the last exit. No way to know those though, unless
+	 * we force userspace to fault on all pages in the incoherent
+	 * memory regions, but even then, I don't see any sane way for
+	 * do_wp_page to handle the faults without modification. So, sigh...
+	 */
+
+	coherent_cache_memslot(slot, true);
+}
+
+void kvm_arch_invalidate_incoherent(struct kvm *kvm, struct kvm_memory_slot *slot)
+{
+	if (slot->flags & KVM_MEM_LOG_DIRTY_PAGES) {
+		/*
+		 * We fault each write when logging is enabled, and do a
+		 * clean+invalidate on KVM_MEM_INCOHERENT memory while
+		 * handling the fault. So, there's nothing to do now.
+		 */
+		return;
+	}
+
+	coherent_cache_memslot(slot, false);
+}
+
 void kvm_arch_memslots_updated(struct kvm *kvm)
 {
 }
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index 8e38878c87c61..29ddf77958c2a 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -38,6 +38,7 @@
 #define __KVM_HAVE_GUEST_DEBUG
 #define __KVM_HAVE_IRQ_LINE
 #define __KVM_HAVE_READONLY_MEM
+#define __KVM_HAVE_INCOHERENT_MEM
 
 #define KVM_REG_SIZE(id)						\
 	(1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
-- 
1.8.3.1

_______________________________________________
kvmarm mailing list
kvmarm@xxxxxxxxxxxxxxxxxxxxx
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm




[Index of Archives]     [Linux KVM]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux