kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/6] KVM: x86/xen: Add in-kernel Xen event channel delivery
@ 2021-11-01 19:03 David Woodhouse
  2021-11-01 19:03 ` [PATCH v2 1/6] KVM: x86/xen: Fix get_attr of KVM_XEN_ATTR_TYPE_SHARED_INFO David Woodhouse
                   ` (5 more replies)
  0 siblings, 6 replies; 12+ messages in thread
From: David Woodhouse @ 2021-11-01 19:03 UTC (permalink / raw)
  To: kvm
  Cc: Paolo Bonzini, Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li,
	Jim Mattson, Joerg Roedel, Joao Martins, Ankur Arora,
	KarimAllah Raslan

Implement 2-level event channel delivery based on the original code from
Joao and Ankur. For IPIs and timers we *really* want to have a completely
in-kernel code path instead of bouncing out to the VMM each time. That
will come next, but this is the basis for it. With this I can wire up
MSI of assigned devices to PIRQs in the guest.

v2: Actually solve the problem of mapping the shared_info page, instead
    of merely declaring that I've reduced it to a previously unsolved
    problem. And having fixed up the broken KVM steal time stuff in a
    separately posted patch.

David Woodhouse (6):
      KVM: x86/xen: Fix get_attr of KVM_XEN_ATTR_TYPE_SHARED_INFO
      KVM: selftests: Add event channel upcall support to xen_shinfo_test
      KVM: x86/xen: Use sizeof_field() instead of open-coding it
      KVM: Fix kvm_map_gfn()/kvm_unmap_gfn() to take a kvm as their names imply
      KVM: x86/xen: Maintain valid mapping of Xen shared_info page
      KVM: x86/xen: Add KVM_IRQ_ROUTING_XEN_EVTCHN and event channel delivery

 Documentation/virt/kvm/api.rst                       |  21 +++
 arch/x86/include/asm/kvm_host.h                      |   5 +
 arch/x86/kvm/irq_comm.c                              |  12 ++
 arch/x86/kvm/mmu/mmu.c                               |  23 ++++
 arch/x86/kvm/x86.c                                   |   3 +-
 arch/x86/kvm/xen.c                                   | 340 ++++++++++++++++++++++++++++++++++++++++++++----
 arch/x86/kvm/xen.h                                   |   9 ++
 include/linux/kvm_host.h                             |  37 ++----
 include/linux/kvm_types.h                            |  27 ++++
 include/uapi/linux/kvm.h                             |  11 ++
 tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c | 187 ++++++++++++++++++++++++--
 virt/kvm/kvm_main.c                                  |  11 +-
 12 files changed, 614 insertions(+), 72 deletions(-)




^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v2 1/6] KVM: x86/xen: Fix get_attr of KVM_XEN_ATTR_TYPE_SHARED_INFO
  2021-11-01 19:03 [PATCH v2 0/6] KVM: x86/xen: Add in-kernel Xen event channel delivery David Woodhouse
@ 2021-11-01 19:03 ` David Woodhouse
  2021-11-01 19:03 ` [PATCH v2 2/6] KVM: selftests: Add event channel upcall support to xen_shinfo_test David Woodhouse
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: David Woodhouse @ 2021-11-01 19:03 UTC (permalink / raw)
  To: kvm
  Cc: Paolo Bonzini, Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li,
	Jim Mattson, Joerg Roedel, Joao Martins, Ankur Arora,
	KarimAllah Raslan

From: David Woodhouse <dwmw@amazon.co.uk>

In commit 319afe68567b ("KVM: xen: do not use struct gfn_to_hva_cache") we
stopped storing this in-kernel as a GPA, and started storing it as a GFN.
Which means we probably should have stopped calling gpa_to_gfn() on it
when userspace asks for it back.

Cc: stable@vger.kernel.org
Fixes: 319afe68567b ("KVM: xen: do not use struct gfn_to_hva_cache")
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
 arch/x86/kvm/xen.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index 8f62baebd028..6dd3d687cf04 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -299,7 +299,7 @@ int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data)
 		break;
 
 	case KVM_XEN_ATTR_TYPE_SHARED_INFO:
-		data->u.shared_info.gfn = gpa_to_gfn(kvm->arch.xen.shinfo_gfn);
+		data->u.shared_info.gfn = kvm->arch.xen.shinfo_gfn;
 		r = 0;
 		break;
 
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 2/6] KVM: selftests: Add event channel upcall support to xen_shinfo_test
  2021-11-01 19:03 [PATCH v2 0/6] KVM: x86/xen: Add in-kernel Xen event channel delivery David Woodhouse
  2021-11-01 19:03 ` [PATCH v2 1/6] KVM: x86/xen: Fix get_attr of KVM_XEN_ATTR_TYPE_SHARED_INFO David Woodhouse
@ 2021-11-01 19:03 ` David Woodhouse
  2021-11-01 19:03 ` [PATCH v2 3/6] KVM: x86/xen: Use sizeof_field() instead of open-coding it David Woodhouse
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: David Woodhouse @ 2021-11-01 19:03 UTC (permalink / raw)
  To: kvm
  Cc: Paolo Bonzini, Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li,
	Jim Mattson, Joerg Roedel, Joao Martins, Ankur Arora,
	KarimAllah Raslan

From: David Woodhouse <dwmw@amazon.co.uk>

When I first looked at this, there was no support for guest exception
handling in the KVM selftests. In fact it was merged into 5.10 before
the Xen support got merged in 5.11, and I could have used it from the
start.

Hook it up now, to exercise the Xen upcall delivery. I'm about to make
things a bit more interesting by handling the full 2level event channel
stuff in-kernel on top of the basic vector injection that we already
have, and I'll want to build more tests on top.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
 .../selftests/kvm/x86_64/xen_shinfo_test.c    | 75 ++++++++++++++++---
 1 file changed, 66 insertions(+), 9 deletions(-)

diff --git a/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c b/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c
index eda0d2a51224..a0699f00b3d6 100644
--- a/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c
+++ b/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c
@@ -24,8 +24,12 @@
 
 #define PVTIME_ADDR	(SHINFO_REGION_GPA + PAGE_SIZE)
 #define RUNSTATE_ADDR	(SHINFO_REGION_GPA + PAGE_SIZE + 0x20)
+#define VCPU_INFO_ADDR	(SHINFO_REGION_GPA + 0x40)
 
 #define RUNSTATE_VADDR	(SHINFO_REGION_GVA + PAGE_SIZE + 0x20)
+#define VCPU_INFO_VADDR	(SHINFO_REGION_GVA + 0x40)
+
+#define EVTCHN_VECTOR	0x10
 
 static struct kvm_vm *vm;
 
@@ -56,15 +60,44 @@ struct vcpu_runstate_info {
     uint64_t time[4];
 };
 
+struct arch_vcpu_info {
+    unsigned long cr2;
+    unsigned long pad; /* sizeof(vcpu_info_t) == 64 */
+};
+
+struct vcpu_info {
+        uint8_t evtchn_upcall_pending;
+        uint8_t evtchn_upcall_mask;
+        unsigned long evtchn_pending_sel;
+        struct arch_vcpu_info arch;
+        struct pvclock_vcpu_time_info time;
+}; /* 64 bytes (x86) */
+
 #define RUNSTATE_running  0
 #define RUNSTATE_runnable 1
 #define RUNSTATE_blocked  2
 #define RUNSTATE_offline  3
 
+static void evtchn_handler(struct ex_regs *regs)
+{
+	struct vcpu_info *vi = (void *)VCPU_INFO_VADDR;
+	vi->evtchn_upcall_pending = 0;
+
+	GUEST_SYNC(0x20);
+}
+
 static void guest_code(void)
 {
 	struct vcpu_runstate_info *rs = (void *)RUNSTATE_VADDR;
 
+	__asm__ __volatile__(
+		"sti\n"
+		"nop\n"
+	);
+
+	/* Trigger an interrupt injection */
+	GUEST_SYNC(0);
+
 	/* Test having the host set runstates manually */
 	GUEST_SYNC(RUNSTATE_runnable);
 	GUEST_ASSERT(rs->time[RUNSTATE_runnable] != 0);
@@ -153,7 +186,7 @@ int main(int argc, char *argv[])
 
 	struct kvm_xen_vcpu_attr vi = {
 		.type = KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO,
-		.u.gpa = SHINFO_REGION_GPA + 0x40,
+		.u.gpa = VCPU_INFO_ADDR,
 	};
 	vcpu_ioctl(vm, VCPU_ID, KVM_XEN_VCPU_SET_ATTR, &vi);
 
@@ -163,6 +196,16 @@ int main(int argc, char *argv[])
 	};
 	vcpu_ioctl(vm, VCPU_ID, KVM_XEN_VCPU_SET_ATTR, &pvclock);
 
+	struct kvm_xen_hvm_attr vec = {
+		.type = KVM_XEN_ATTR_TYPE_UPCALL_VECTOR,
+		.u.vector = EVTCHN_VECTOR,
+	};
+	vm_ioctl(vm, KVM_XEN_HVM_SET_ATTR, &vec);
+
+	vm_init_descriptor_tables(vm);
+	vcpu_init_descriptor_tables(vm, VCPU_ID);
+	vm_install_exception_handler(vm, EVTCHN_VECTOR, evtchn_handler);
+
 	if (do_runstate_tests) {
 		struct kvm_xen_vcpu_attr st = {
 			.type = KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADDR,
@@ -171,9 +214,14 @@ int main(int argc, char *argv[])
 		vcpu_ioctl(vm, VCPU_ID, KVM_XEN_VCPU_SET_ATTR, &st);
 	}
 
+	struct vcpu_info *vinfo = addr_gpa2hva(vm, VCPU_INFO_VADDR);
+	vinfo->evtchn_upcall_pending = 0;
+
 	struct vcpu_runstate_info *rs = addr_gpa2hva(vm, RUNSTATE_ADDR);
 	rs->state = 0x5a;
 
+	bool evtchn_irq_expected = false;
+
 	for (;;) {
 		volatile struct kvm_run *run = vcpu_state(vm, VCPU_ID);
 		struct ucall uc;
@@ -193,16 +241,21 @@ int main(int argc, char *argv[])
 			struct kvm_xen_vcpu_attr rst;
 			long rundelay;
 
-			/* If no runstate support, bail out early */
-			if (!do_runstate_tests)
-				goto done;
-
-			TEST_ASSERT(rs->state_entry_time == rs->time[0] +
-				    rs->time[1] + rs->time[2] + rs->time[3],
-				    "runstate times don't add up");
+			if (do_runstate_tests)
+				TEST_ASSERT(rs->state_entry_time == rs->time[0] +
+					    rs->time[1] + rs->time[2] + rs->time[3],
+					    "runstate times don't add up");
 
 			switch (uc.args[1]) {
-			case RUNSTATE_running...RUNSTATE_offline:
+			case 0:
+				evtchn_irq_expected = true;
+				vinfo->evtchn_upcall_pending = 1;
+				break;
+
+			case RUNSTATE_runnable...RUNSTATE_offline:
+				TEST_ASSERT(!evtchn_irq_expected, "Event channel IRQ not seen");
+				if (!do_runstate_tests)
+					goto done;
 				rst.type = KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT;
 				rst.u.runstate.state = uc.args[1];
 				vcpu_ioctl(vm, VCPU_ID, KVM_XEN_VCPU_SET_ATTR, &rst);
@@ -236,6 +289,10 @@ int main(int argc, char *argv[])
 					sched_yield();
 				} while (get_run_delay() < rundelay);
 				break;
+			case 0x20:
+				TEST_ASSERT(evtchn_irq_expected, "Unexpected event channel IRQ");
+				evtchn_irq_expected = false;
+				break;
 			}
 			break;
 		}
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 3/6] KVM: x86/xen: Use sizeof_field() instead of open-coding it
  2021-11-01 19:03 [PATCH v2 0/6] KVM: x86/xen: Add in-kernel Xen event channel delivery David Woodhouse
  2021-11-01 19:03 ` [PATCH v2 1/6] KVM: x86/xen: Fix get_attr of KVM_XEN_ATTR_TYPE_SHARED_INFO David Woodhouse
  2021-11-01 19:03 ` [PATCH v2 2/6] KVM: selftests: Add event channel upcall support to xen_shinfo_test David Woodhouse
@ 2021-11-01 19:03 ` David Woodhouse
  2021-11-01 19:03 ` [PATCH v2 4/6] KVM: Fix kvm_map_gfn()/kvm_unmap_gfn() to take a kvm as their names imply David Woodhouse
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: David Woodhouse @ 2021-11-01 19:03 UTC (permalink / raw)
  To: kvm
  Cc: Paolo Bonzini, Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li,
	Jim Mattson, Joerg Roedel, Joao Martins, Ankur Arora,
	KarimAllah Raslan

From: David Woodhouse <dwmw@amazon.co.uk>

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
 arch/x86/kvm/xen.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index 6dd3d687cf04..565da9c3853b 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -127,9 +127,9 @@ void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, int state)
 	state_entry_time = vx->runstate_entry_time;
 	state_entry_time |= XEN_RUNSTATE_UPDATE;
 
-	BUILD_BUG_ON(sizeof(((struct vcpu_runstate_info *)0)->state_entry_time) !=
+	BUILD_BUG_ON(sizeof_field(struct vcpu_runstate_info, state_entry_time) !=
 		     sizeof(state_entry_time));
-	BUILD_BUG_ON(sizeof(((struct compat_vcpu_runstate_info *)0)->state_entry_time) !=
+	BUILD_BUG_ON(sizeof_field(struct compat_vcpu_runstate_info, state_entry_time) !=
 		     sizeof(state_entry_time));
 
 	if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache,
@@ -144,9 +144,9 @@ void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, int state)
 	 */
 	BUILD_BUG_ON(offsetof(struct vcpu_runstate_info, state) !=
 		     offsetof(struct compat_vcpu_runstate_info, state));
-	BUILD_BUG_ON(sizeof(((struct vcpu_runstate_info *)0)->state) !=
+	BUILD_BUG_ON(sizeof_field(struct vcpu_runstate_info, state) !=
 		     sizeof(vx->current_runstate));
-	BUILD_BUG_ON(sizeof(((struct compat_vcpu_runstate_info *)0)->state) !=
+	BUILD_BUG_ON(sizeof_field(struct compat_vcpu_runstate_info, state) !=
 		     sizeof(vx->current_runstate));
 
 	if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache,
@@ -163,9 +163,9 @@ void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, int state)
 		     offsetof(struct vcpu_runstate_info, time) - sizeof(u64));
 	BUILD_BUG_ON(offsetof(struct compat_vcpu_runstate_info, state_entry_time) !=
 		     offsetof(struct compat_vcpu_runstate_info, time) - sizeof(u64));
-	BUILD_BUG_ON(sizeof(((struct vcpu_runstate_info *)0)->time) !=
-		     sizeof(((struct compat_vcpu_runstate_info *)0)->time));
-	BUILD_BUG_ON(sizeof(((struct vcpu_runstate_info *)0)->time) !=
+	BUILD_BUG_ON(sizeof_field(struct vcpu_runstate_info, time) !=
+		     sizeof_field(struct compat_vcpu_runstate_info, time));
+	BUILD_BUG_ON(sizeof_field(struct vcpu_runstate_info, time) !=
 		     sizeof(vx->runstate_times));
 
 	if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache,
@@ -205,9 +205,9 @@ int __kvm_xen_has_interrupt(struct kvm_vcpu *v)
 	BUILD_BUG_ON(offsetof(struct vcpu_info, evtchn_upcall_pending) !=
 		     offsetof(struct compat_vcpu_info, evtchn_upcall_pending));
 	BUILD_BUG_ON(sizeof(rc) !=
-		     sizeof(((struct vcpu_info *)0)->evtchn_upcall_pending));
+		     sizeof_field(struct vcpu_info, evtchn_upcall_pending));
 	BUILD_BUG_ON(sizeof(rc) !=
-		     sizeof(((struct compat_vcpu_info *)0)->evtchn_upcall_pending));
+		     sizeof_field(struct compat_vcpu_info, evtchn_upcall_pending));
 
 	/*
 	 * For efficiency, this mirrors the checks for using the valid
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 4/6] KVM: Fix kvm_map_gfn()/kvm_unmap_gfn() to take a kvm as their names imply
  2021-11-01 19:03 [PATCH v2 0/6] KVM: x86/xen: Add in-kernel Xen event channel delivery David Woodhouse
                   ` (2 preceding siblings ...)
  2021-11-01 19:03 ` [PATCH v2 3/6] KVM: x86/xen: Use sizeof_field() instead of open-coding it David Woodhouse
@ 2021-11-01 19:03 ` David Woodhouse
  2021-11-02  3:12   ` kernel test robot
  2021-11-02 22:33   ` kernel test robot
  2021-11-01 19:03 ` [PATCH v2 5/6] KVM: x86/xen: Maintain valid mapping of Xen shared_info page David Woodhouse
  2021-11-01 19:03 ` [PATCH v2 6/6] KVM: x86/xen: Add KVM_IRQ_ROUTING_XEN_EVTCHN and event channel delivery David Woodhouse
  5 siblings, 2 replies; 12+ messages in thread
From: David Woodhouse @ 2021-11-01 19:03 UTC (permalink / raw)
  To: kvm
  Cc: Paolo Bonzini, Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li,
	Jim Mattson, Joerg Roedel, Joao Martins, Ankur Arora,
	KarimAllah Raslan

From: David Woodhouse <dwmw@amazon.co.uk>

These were somewhat misnamed, as they actually took a kvm_vcpu, even
though they didn't do anything with it except to find vcpu->kvm.

And more to the point I don't *have* a vcpu to give them, in an upcoming
use case...

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
 include/linux/kvm_host.h |  4 ++--
 virt/kvm/kvm_main.c      | 11 +++++------
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 0f18df7fe874..749cdc77fc4e 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -943,11 +943,11 @@ struct kvm_memory_slot *kvm_vcpu_gfn_to_memslot(struct kvm_vcpu *vcpu, gfn_t gfn
 kvm_pfn_t kvm_vcpu_gfn_to_pfn_atomic(struct kvm_vcpu *vcpu, gfn_t gfn);
 kvm_pfn_t kvm_vcpu_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn);
 int kvm_vcpu_map(struct kvm_vcpu *vcpu, gpa_t gpa, struct kvm_host_map *map);
-int kvm_map_gfn(struct kvm_vcpu *vcpu, gfn_t gfn, struct kvm_host_map *map,
+int kvm_map_gfn(struct kvm *kvm, gfn_t gfn, struct kvm_host_map *map,
 		struct gfn_to_pfn_cache *cache, bool atomic);
 struct page *kvm_vcpu_gfn_to_page(struct kvm_vcpu *vcpu, gfn_t gfn);
 void kvm_vcpu_unmap(struct kvm_vcpu *vcpu, struct kvm_host_map *map, bool dirty);
-int kvm_unmap_gfn(struct kvm_vcpu *vcpu, struct kvm_host_map *map,
+int kvm_unmap_gfn(struct kvm *kvm, struct kvm_host_map *map,
 		  struct gfn_to_pfn_cache *cache, bool dirty, bool atomic);
 unsigned long kvm_vcpu_gfn_to_hva(struct kvm_vcpu *vcpu, gfn_t gfn);
 unsigned long kvm_vcpu_gfn_to_hva_prot(struct kvm_vcpu *vcpu, gfn_t gfn, bool *writable);
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 7851f3a1b5f7..f3a2740660ae 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2620,11 +2620,10 @@ static int __kvm_map_gfn(struct kvm_memslots *slots, gfn_t gfn,
 	return 0;
 }
 
-int kvm_map_gfn(struct kvm_vcpu *vcpu, gfn_t gfn, struct kvm_host_map *map,
+int kvm_map_gfn(struct kvm *kvm, gfn_t gfn, struct kvm_host_map *map,
 		struct gfn_to_pfn_cache *cache, bool atomic)
 {
-	return __kvm_map_gfn(kvm_memslots(vcpu->kvm), gfn, map,
-			cache, atomic);
+	return __kvm_map_gfn(kvm_memslots(kvm), gfn, map, cache, atomic);
 }
 EXPORT_SYMBOL_GPL(kvm_map_gfn);
 
@@ -2672,11 +2671,11 @@ static void __kvm_unmap_gfn(struct kvm *kvm,
 	map->page = NULL;
 }
 
-int kvm_unmap_gfn(struct kvm_vcpu *vcpu, struct kvm_host_map *map, 
+int kvm_unmap_gfn(struct kvm *kvm, struct kvm_host_map *map,
 		  struct gfn_to_pfn_cache *cache, bool dirty, bool atomic)
 {
-	__kvm_unmap_gfn(vcpu->kvm, gfn_to_memslot(vcpu->kvm, map->gfn), map,
-			cache, dirty, atomic);
+	__kvm_unmap_gfn(kvm, gfn_to_memslot(kvm, map->gfn), map, cache, dirty,
+			atomic);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(kvm_unmap_gfn);
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 5/6] KVM: x86/xen: Maintain valid mapping of Xen shared_info page
  2021-11-01 19:03 [PATCH v2 0/6] KVM: x86/xen: Add in-kernel Xen event channel delivery David Woodhouse
                   ` (3 preceding siblings ...)
  2021-11-01 19:03 ` [PATCH v2 4/6] KVM: Fix kvm_map_gfn()/kvm_unmap_gfn() to take a kvm as their names imply David Woodhouse
@ 2021-11-01 19:03 ` David Woodhouse
  2021-11-02  1:23   ` kernel test robot
  2021-11-04 19:05   ` David Woodhouse
  2021-11-01 19:03 ` [PATCH v2 6/6] KVM: x86/xen: Add KVM_IRQ_ROUTING_XEN_EVTCHN and event channel delivery David Woodhouse
  5 siblings, 2 replies; 12+ messages in thread
From: David Woodhouse @ 2021-11-01 19:03 UTC (permalink / raw)
  To: kvm
  Cc: Paolo Bonzini, Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li,
	Jim Mattson, Joerg Roedel, Joao Martins, Ankur Arora,
	KarimAllah Raslan

From: David Woodhouse <dwmw@amazon.co.uk>

In order to allow for event channel delivery, we would like to have a
kernel mapping of the shared_info page which can be accessed in atomic
context in the common case.

The gfn_to_pfn_cache only automatically handles invalidation when the
KVM memslots change; it doesn't handle a change in the userspace HVA
to host PFN mappings. So hook into the MMU notifiers to invalidate the
shared_info pointer on demand.

The shared_info can be accessed while holding the shinfo_lock, with a
slow path which takes the kvm->lock mutex to refresh the mapping.
I'd like to use RCU for the invalidation but I don't think we can
always sleep in the invalidate_range notifier. Having a true kernel
mapping of the page means that our access to it can be atomic anyway,
so holding a spinlock is OK.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
 arch/x86/include/asm/kvm_host.h |  4 ++
 arch/x86/kvm/mmu/mmu.c          | 23 ++++++++++++
 arch/x86/kvm/xen.c              | 65 +++++++++++++++++++++++++++------
 include/linux/kvm_host.h        | 26 -------------
 include/linux/kvm_types.h       | 27 ++++++++++++++
 5 files changed, 107 insertions(+), 38 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 750f74da9793..ec58e41a69c2 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1017,6 +1017,10 @@ struct kvm_xen {
 	bool long_mode;
 	u8 upcall_vector;
 	gfn_t shinfo_gfn;
+	rwlock_t shinfo_lock;
+	void *shared_info;
+	struct kvm_host_map shinfo_map;
+	struct gfn_to_pfn_cache shinfo_cache;
 };
 
 enum kvm_irqchip_mode {
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index 0cc58901bf7a..429a4860d67a 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -25,6 +25,7 @@
 #include "kvm_emulate.h"
 #include "cpuid.h"
 #include "spte.h"
+#include "xen.h"
 
 #include <linux/kvm_host.h>
 #include <linux/types.h>
@@ -1588,6 +1589,28 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
 {
 	bool flush = false;
 
+	if (static_branch_unlikely(&kvm_xen_enabled.key)) {
+		write_lock(&kvm->arch.xen.shinfo_lock);
+
+		if (kvm->arch.xen.shared_info &&
+		    kvm->arch.xen.shinfo_gfn >= range->start &&
+		    kvm->arch.xen.shinfo_cache.gfn < range->end) {
+			/*
+			 * If kvm_xen_shared_info_init() had *finished* mapping the
+			 * page and assigned the pointer for real, then mark the page
+			 * dirty now instead of via the eventual cache teardown.
+			 */
+			if (kvm->arch.xen.shared_info != KVM_UNMAPPED_PAGE) {
+				kvm_set_pfn_dirty(kvm->arch.xen.shinfo_cache.pfn);
+				kvm->arch.xen.shinfo_cache.dirty = false;
+			}
+
+			kvm->arch.xen.shared_info = NULL;
+		}
+
+		write_unlock(&kvm->arch.xen.shinfo_lock);
+	}
+
 	if (kvm_memslots_have_rmaps(kvm))
 		flush = kvm_handle_gfn_range(kvm, range, kvm_unmap_rmapp);
 
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index 565da9c3853b..9d143bc7d769 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -21,18 +21,59 @@
 
 DEFINE_STATIC_KEY_DEFERRED_FALSE(kvm_xen_enabled, HZ);
 
-static int kvm_xen_shared_info_init(struct kvm *kvm, gfn_t gfn)
+static void kvm_xen_shared_info_unmap(struct kvm *kvm)
+{
+	bool was_valid = false;
+
+	write_lock(&kvm->arch.xen.shinfo_lock);
+	if (kvm->arch.xen.shared_info)
+		was_valid = true;
+	kvm->arch.xen.shared_info = NULL;
+	kvm->arch.xen.shinfo_gfn = GPA_INVALID;
+	write_unlock(&kvm->arch.xen.shinfo_lock);
+
+	if (kvm_vcpu_mapped(&kvm->arch.xen.shinfo_map)) {
+		kvm_unmap_gfn(kvm, &kvm->arch.xen.shinfo_map,
+			      &kvm->arch.xen.shinfo_cache, was_valid, false);
+
+		/* If the MMU notifier invalidated it, the gfn_to_pfn_cache
+		 * may be invalid. Force it to notice */
+		if (!was_valid)
+			kvm->arch.xen.shinfo_cache.generation = -1;
+	}
+}
+
+static int kvm_xen_shared_info_init(struct kvm *kvm, gfn_t gfn, bool update_clock)
 {
 	gpa_t gpa = gfn_to_gpa(gfn);
 	int wc_ofs, sec_hi_ofs;
 	int ret = 0;
 	int idx = srcu_read_lock(&kvm->srcu);
 
-	if (kvm_is_error_hva(gfn_to_hva(kvm, gfn))) {
-		ret = -EFAULT;
+	kvm_xen_shared_info_unmap(kvm);
+
+	if (gfn == GPA_INVALID)
 		goto out;
-	}
+
+	/* Let the MMU notifier know that we are in the process of mapping it */
+	write_lock(&kvm->arch.xen.shinfo_lock);
+	kvm->arch.xen.shared_info = KVM_UNMAPPED_PAGE;
 	kvm->arch.xen.shinfo_gfn = gfn;
+	write_unlock(&kvm->arch.xen.shinfo_lock);
+
+	ret = kvm_map_gfn(kvm, gfn, &kvm->arch.xen.shinfo_map,
+			  &kvm->arch.xen.shinfo_cache, false);
+	if (ret)
+		goto out;
+
+	write_lock(&kvm->arch.xen.shinfo_lock);
+	/* Unless the MMU notifier already invalidated it */
+	if (kvm->arch.xen.shared_info == KVM_UNMAPPED_PAGE)
+		kvm->arch.xen.shared_info = kvm->arch.xen.shinfo_map.hva;
+	write_unlock(&kvm->arch.xen.shinfo_lock);
+
+	if (!update_clock)
+		goto out;
 
 	/* Paranoia checks on the 32-bit struct layout */
 	BUILD_BUG_ON(offsetof(struct compat_shared_info, wc) != 0x900);
@@ -260,15 +301,9 @@ int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data)
 		break;
 
 	case KVM_XEN_ATTR_TYPE_SHARED_INFO:
-		if (data->u.shared_info.gfn == GPA_INVALID) {
-			kvm->arch.xen.shinfo_gfn = GPA_INVALID;
-			r = 0;
-			break;
-		}
-		r = kvm_xen_shared_info_init(kvm, data->u.shared_info.gfn);
+		r = kvm_xen_shared_info_init(kvm, data->u.shared_info.gfn, true);
 		break;
 
-
 	case KVM_XEN_ATTR_TYPE_UPCALL_VECTOR:
 		if (data->u.vector && data->u.vector < 0x10)
 			r = -EINVAL;
@@ -661,11 +696,17 @@ int kvm_xen_hvm_config(struct kvm *kvm, struct kvm_xen_hvm_config *xhc)
 
 void kvm_xen_init_vm(struct kvm *kvm)
 {
-	kvm->arch.xen.shinfo_gfn = GPA_INVALID;
+	rwlock_init(&kvm->arch.xen.shinfo_lock);
 }
 
 void kvm_xen_destroy_vm(struct kvm *kvm)
 {
+	struct gfn_to_pfn_cache *cache = &kvm->arch.xen.shinfo_cache;
+
+	kvm_xen_shared_info_unmap(kvm);
+
+	kvm_release_pfn(cache->pfn, cache->dirty, cache);
+
 	if (kvm->arch.xen_hvm_config.msr)
 		static_branch_slow_dec_deferred(&kvm_xen_enabled);
 }
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 749cdc77fc4e..f0012d128aa5 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -251,32 +251,6 @@ enum {
 	READING_SHADOW_PAGE_TABLES,
 };
 
-#define KVM_UNMAPPED_PAGE	((void *) 0x500 + POISON_POINTER_DELTA)
-
-struct kvm_host_map {
-	/*
-	 * Only valid if the 'pfn' is managed by the host kernel (i.e. There is
-	 * a 'struct page' for it. When using mem= kernel parameter some memory
-	 * can be used as guest memory but they are not managed by host
-	 * kernel).
-	 * If 'pfn' is not managed by the host kernel, this field is
-	 * initialized to KVM_UNMAPPED_PAGE.
-	 */
-	struct page *page;
-	void *hva;
-	kvm_pfn_t pfn;
-	kvm_pfn_t gfn;
-};
-
-/*
- * Used to check if the mapping is valid or not. Never use 'kvm_host_map'
- * directly to check for that.
- */
-static inline bool kvm_vcpu_mapped(struct kvm_host_map *map)
-{
-	return !!map->hva;
-}
-
 static inline bool kvm_vcpu_can_poll(ktime_t cur, ktime_t stop)
 {
 	return single_task_running() && !need_resched() && ktime_before(cur, stop);
diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h
index 2237abb93ccd..2092f4ca156b 100644
--- a/include/linux/kvm_types.h
+++ b/include/linux/kvm_types.h
@@ -60,6 +60,33 @@ struct gfn_to_pfn_cache {
 	bool dirty;
 };
 
+#define KVM_UNMAPPED_PAGE	((void *) 0x500 + POISON_POINTER_DELTA)
+
+struct kvm_host_map {
+	/*
+	 * Only valid if the 'pfn' is managed by the host kernel (i.e. There is
+	 * a 'struct page' for it. When using mem= kernel parameter some memory
+	 * can be used as guest memory but they are not managed by host
+	 * kernel).
+	 * If 'pfn' is not managed by the host kernel, this field is
+	 * initialized to KVM_UNMAPPED_PAGE.
+	 */
+	struct page *page;
+	void *hva;
+	kvm_pfn_t pfn;
+	kvm_pfn_t gfn;
+};
+
+/*
+ * Used to check if the mapping is valid or not. Never use 'kvm_host_map'
+ * directly to check for that.
+ */
+static inline bool kvm_vcpu_mapped(struct kvm_host_map *map)
+{
+	return !!map->hva;
+}
+
+
 #ifdef KVM_ARCH_NR_OBJS_PER_MEMORY_CACHE
 /*
  * Memory caches are used to preallocate memory ahead of various MMU flows,
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 6/6] KVM: x86/xen: Add KVM_IRQ_ROUTING_XEN_EVTCHN and event channel delivery
  2021-11-01 19:03 [PATCH v2 0/6] KVM: x86/xen: Add in-kernel Xen event channel delivery David Woodhouse
                   ` (4 preceding siblings ...)
  2021-11-01 19:03 ` [PATCH v2 5/6] KVM: x86/xen: Maintain valid mapping of Xen shared_info page David Woodhouse
@ 2021-11-01 19:03 ` David Woodhouse
  2021-11-02  0:25   ` David Woodhouse
  5 siblings, 1 reply; 12+ messages in thread
From: David Woodhouse @ 2021-11-01 19:03 UTC (permalink / raw)
  To: kvm
  Cc: Paolo Bonzini, Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li,
	Jim Mattson, Joerg Roedel, Joao Martins, Ankur Arora,
	KarimAllah Raslan

From: David Woodhouse <dwmw@amazon.co.uk>

This adds basic support for delivering 2 level event channels to a guest.

Initially, it only supports delivery via the IRQ routing table, triggered
by an eventfd. In order to do so, it has a kvm_xen_set_evtchn_fast()
function which will use the pre-mapped shared_info page if it already
exists and is still valid, while the slow path through the irqfd_inject
workqueue will remap the shared_info page if necessary.

It sets the bits in the shared_info page but not the vcpu_info; that is
deferred to __kvm_xen_has_interrupt() which raises the vector to the
appropriate vCPU.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
 Documentation/virt/kvm/api.rst                |  21 ++
 arch/x86/include/asm/kvm_host.h               |   1 +
 arch/x86/kvm/irq_comm.c                       |  12 +
 arch/x86/kvm/x86.c                            |   3 +-
 arch/x86/kvm/xen.c                            | 255 +++++++++++++++++-
 arch/x86/kvm/xen.h                            |   9 +
 include/linux/kvm_host.h                      |   7 +
 include/uapi/linux/kvm.h                      |  11 +
 .../selftests/kvm/x86_64/xen_shinfo_test.c    | 112 +++++++-
 9 files changed, 424 insertions(+), 7 deletions(-)

diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index a6729c8cf063..e11f9eb7f06e 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -1748,6 +1748,7 @@ No flags are specified so far, the corresponding field must be set to zero.
 		struct kvm_irq_routing_msi msi;
 		struct kvm_irq_routing_s390_adapter adapter;
 		struct kvm_irq_routing_hv_sint hv_sint;
+		struct kvm_irq_routing_xen_evtchn xen_evtchn;
 		__u32 pad[8];
 	} u;
   };
@@ -1757,6 +1758,7 @@ No flags are specified so far, the corresponding field must be set to zero.
   #define KVM_IRQ_ROUTING_MSI 2
   #define KVM_IRQ_ROUTING_S390_ADAPTER 3
   #define KVM_IRQ_ROUTING_HV_SINT 4
+  #define KVM_IRQ_ROUTING_XEN_EVTCHN 5
 
 flags:
 
@@ -1808,6 +1810,20 @@ address_hi must be zero.
 	__u32 sint;
   };
 
+  struct kvm_xen_evtchn {
+	__u32 port;
+	__u32 vcpu;
+	__u32 priority;
+  };
+
+
+When KVM_CAP_XEN_HVM includes the KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL bit
+in its indication of supported features, routing to Xen event channels
+is supported. Although the priority field is present, only the value
+KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL is supported, which means delivery by
+2 level event channels. FIFO event channel support may be added in
+the future.
+
 
 4.55 KVM_SET_TSC_KHZ
 --------------------
@@ -7182,6 +7198,7 @@ PVHVM guests. Valid flags are::
   #define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL	(1 << 1)
   #define KVM_XEN_HVM_CONFIG_SHARED_INFO	(1 << 2)
   #define KVM_XEN_HVM_CONFIG_RUNSTATE		(1 << 2)
+  #define KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL	(1 << 3)
 
 The KVM_XEN_HVM_CONFIG_HYPERCALL_MSR flag indicates that the KVM_XEN_HVM_CONFIG
 ioctl is available, for the guest to set its hypercall page.
@@ -7201,6 +7218,10 @@ The KVM_XEN_HVM_CONFIG_RUNSTATE flag indicates that the runstate-related
 features KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADDR/_CURRENT/_DATA/_ADJUST are
 supported by the KVM_XEN_VCPU_SET_ATTR/KVM_XEN_VCPU_GET_ATTR ioctls.
 
+The KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL flag indicates that IRQ routing entries
+of the type KVM_IRQ_ROUTING_XEN_EVTCHN are supported, with the priority
+field set to indicate 2 level event channel delivery.
+
 8.31 KVM_CAP_PPC_MULTITCE
 -------------------------
 
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index ec58e41a69c2..02ec330dbb4a 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -606,6 +606,7 @@ struct kvm_vcpu_xen {
 	u64 last_steal;
 	u64 runstate_entry_time;
 	u64 runstate_times[4];
+	unsigned long evtchn_pending_sel;
 };
 
 struct kvm_vcpu_arch {
diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c
index d5b72a08e566..afd2de84be60 100644
--- a/arch/x86/kvm/irq_comm.c
+++ b/arch/x86/kvm/irq_comm.c
@@ -24,6 +24,7 @@
 
 #include "hyperv.h"
 #include "x86.h"
+#include "xen.h"
 
 static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e,
 			   struct kvm *kvm, int irq_source_id, int level,
@@ -175,6 +176,13 @@ int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,
 			return r;
 		break;
 
+#ifdef CONFIG_KVM_XEN
+	case KVM_IRQ_ROUTING_XEN_EVTCHN:
+		if (!level)
+			return -1;
+
+		return kvm_xen_set_evtchn_fast(e, kvm);
+#endif
 	default:
 		break;
 	}
@@ -310,6 +318,10 @@ int kvm_set_routing_entry(struct kvm *kvm,
 		e->hv_sint.vcpu = ue->u.hv_sint.vcpu;
 		e->hv_sint.sint = ue->u.hv_sint.sint;
 		break;
+#ifdef CONFIG_KVM_XEN
+	case KVM_IRQ_ROUTING_XEN_EVTCHN:
+		return kvm_xen_setup_evtchn(kvm, e, ue);
+#endif
 	default:
 		return -EINVAL;
 	}
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 4d9ea4f43cf7..499c547cd1ce 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4082,7 +4082,8 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 	case KVM_CAP_XEN_HVM:
 		r = KVM_XEN_HVM_CONFIG_HYPERCALL_MSR |
 		    KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL |
-		    KVM_XEN_HVM_CONFIG_SHARED_INFO;
+		    KVM_XEN_HVM_CONFIG_SHARED_INFO |
+		    KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL;
 		if (sched_info_on())
 			r |= KVM_XEN_HVM_CONFIG_RUNSTATE;
 		break;
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index 9d143bc7d769..b66f4059f99c 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -16,6 +16,7 @@
 #include <trace/events/kvm.h>
 #include <xen/interface/xen.h>
 #include <xen/interface/vcpu.h>
+#include <xen/interface/event_channel.h>
 
 #include "trace.h"
 
@@ -231,6 +232,8 @@ void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, int state)
 
 int __kvm_xen_has_interrupt(struct kvm_vcpu *v)
 {
+	unsigned long evtchn_pending_sel = READ_ONCE(v->arch.xen.evtchn_pending_sel);
+	bool atomic = in_atomic() || !task_is_running(current);
 	int err;
 	u8 rc = 0;
 
@@ -240,6 +243,9 @@ int __kvm_xen_has_interrupt(struct kvm_vcpu *v)
 	 */
 	struct gfn_to_hva_cache *ghc = &v->arch.xen.vcpu_info_cache;
 	struct kvm_memslots *slots = kvm_memslots(v->kvm);
+	bool ghc_valid = slots->generation == ghc->generation &&
+		!kvm_is_error_hva(ghc->hva) && ghc->memslot;
+
 	unsigned int offset = offsetof(struct vcpu_info, evtchn_upcall_pending);
 
 	/* No need for compat handling here */
@@ -255,8 +261,7 @@ int __kvm_xen_has_interrupt(struct kvm_vcpu *v)
 	 * cache in kvm_read_guest_offset_cached(), but just uses
 	 * __get_user() instead. And falls back to the slow path.
 	 */
-	if (likely(slots->generation == ghc->generation &&
-		   !kvm_is_error_hva(ghc->hva) && ghc->memslot)) {
+	if (!evtchn_pending_sel && ghc_valid) {
 		/* Fast path */
 		pagefault_disable();
 		err = __get_user(rc, (u8 __user *)ghc->hva + offset);
@@ -275,11 +280,80 @@ int __kvm_xen_has_interrupt(struct kvm_vcpu *v)
 	 * and we'll end up getting called again from a context where we *can*
 	 * fault in the page and wait for it.
 	 */
-	if (in_atomic() || !task_is_running(current))
+	if (atomic)
 		return 1;
 
-	kvm_read_guest_offset_cached(v->kvm, ghc, &rc, offset,
-				     sizeof(rc));
+	if (!ghc_valid) {
+		err = kvm_gfn_to_hva_cache_init(v->kvm, ghc, ghc->gpa, ghc->len);
+		if (err && !ghc->memslot) {
+			/*
+			 * If this failed, userspace has screwed up the
+			 * vcpu_info mapping. No interrupts for you.
+			 */
+			return 0;
+		}
+	}
+
+	/*
+	 * Now we have a valid (protected by srcu) userspace HVA in
+	 * ghc->hva which points to the struct vcpu_info. If there
+	 * are any bits in the in-kernel evtchn_pending_sel then
+	 * we need to write those to the guest vcpu_info and set
+	 * its evtchn_upcall_pending flag. If there aren't any bits
+	 * to add, we only want to *check* evtchn_upcall_pending.
+	 */
+	if (evtchn_pending_sel) {
+		if (!user_access_begin((void *)ghc->hva, sizeof(struct vcpu_info)))
+			return 0;
+
+		if (IS_ENABLED(CONFIG_64BIT) && v->kvm->arch.xen.long_mode) {
+			struct vcpu_info __user *vi = (void *)ghc->hva;
+
+			/* Attempt to set the evtchn_pending_sel bits in the
+			 * guest, and if that succeeds then clear the same
+			 * bits in the in-kernel version. */
+			asm volatile("1:\t" LOCK_PREFIX "orq %0, %1\n"
+				     "\tnotq %0\n"
+				     "\t" LOCK_PREFIX "andq %0, %2\n"
+				     "2:\n"
+				     "\t.section .fixup,\"ax\"\n"
+				     "3:\tjmp\t2b\n"
+				     "\t.previous\n"
+				     _ASM_EXTABLE_UA(1b, 3b)
+				     : "=r" (evtchn_pending_sel)
+				     : "m" (vi->evtchn_pending_sel),
+				       "m" (v->arch.xen.evtchn_pending_sel),
+				       "0" (evtchn_pending_sel));
+		} else {
+			struct compat_vcpu_info __user *vi = (void *)ghc->hva;
+			u32 evtchn_pending_sel32 = evtchn_pending_sel;
+
+			/* Attempt to set the evtchn_pending_sel bits in the
+			 * guest, and if that succeeds then clear the same
+			 * bits in the in-kernel version. */
+			asm volatile("1:\t" LOCK_PREFIX "orl %0, %1\n"
+				     "\tnotl %0\n"
+				     "\t" LOCK_PREFIX "andl %0, %2\n"
+				     "2:\n"
+				     "\t.section .fixup,\"ax\"\n"
+				     "3:\tjmp\t2b\n"
+				     "\t.previous\n"
+				     _ASM_EXTABLE_UA(1b, 3b)
+				     : "=r" (evtchn_pending_sel32)
+				     : "m" (vi->evtchn_pending_sel),
+				       "m" (v->arch.xen.evtchn_pending_sel),
+				       "0" (evtchn_pending_sel32));
+		}
+		rc = 1;
+		unsafe_put_user(rc, (u8 __user *)ghc->hva + offset, err);
+
+	err:
+		user_access_end();
+
+		mark_page_dirty_in_slot(v->kvm, ghc->memslot, ghc->gpa >> PAGE_SHIFT);
+	} else {
+		__get_user(rc, (u8 __user *)ghc->hva + offset);
+	}
 
 	return rc;
 }
@@ -778,3 +852,174 @@ int kvm_xen_hypercall(struct kvm_vcpu *vcpu)
 
 	return 0;
 }
+
+static inline int max_evtchn_port(struct kvm *kvm)
+{
+	if (IS_ENABLED(CONFIG_64BIT) && kvm->arch.xen.long_mode)
+		return EVTCHN_2L_NR_CHANNELS;
+	else
+		return COMPAT_EVTCHN_2L_NR_CHANNELS;
+}
+
+int kvm_xen_set_evtchn_fast(struct kvm_kernel_irq_routing_entry *e,
+			    struct kvm *kvm)
+{
+	struct gfn_to_pfn_cache *gpc = &kvm->arch.xen.shinfo_cache;
+	struct kvm_memslots *slots;
+	struct kvm_vcpu *vcpu;
+	unsigned long *pending_bits, *mask_bits;
+	int port_word_bit;
+	bool kick_vcpu = false;
+	int idx;
+	int rc;
+
+	vcpu = kvm_get_vcpu_by_id(kvm, e->xen_evtchn.vcpu);
+	if (!vcpu)
+		return -EINVAL;
+
+	if (!vcpu->arch.xen.vcpu_info_set)
+		return -EINVAL;
+
+	if (e->xen_evtchn.port >= max_evtchn_port(kvm))
+		return -EINVAL;
+
+	rc = -EWOULDBLOCK;
+	read_lock(&kvm->arch.xen.shinfo_lock);
+
+	if (!kvm->arch.xen.shared_info ||
+	    kvm->arch.xen.shared_info == KVM_UNMAPPED_PAGE)
+		goto out_unlock;
+
+	idx = srcu_read_lock(&kvm->srcu);
+	slots = kvm_memslots(kvm);
+
+	/* The cache may only change while the shared_info pointer is NULL */
+	if (gpc->generation != slots->generation)
+		goto out_rcu;
+
+	if (IS_ENABLED(CONFIG_64BIT) && kvm->arch.xen.long_mode) {
+		struct shared_info *shinfo = kvm->arch.xen.shared_info;
+		pending_bits = (unsigned long *)&shinfo->evtchn_pending;
+		mask_bits = (unsigned long *)&shinfo->evtchn_mask;
+		port_word_bit = e->xen_evtchn.port / 64;
+	} else {
+		struct compat_shared_info *shinfo = kvm->arch.xen.shared_info;
+		pending_bits = (unsigned long *)&shinfo->evtchn_pending;
+		mask_bits = (unsigned long *)&shinfo->evtchn_mask;
+		port_word_bit = e->xen_evtchn.port / 32;
+	}
+
+	/*
+	 * If this port wasn't already set, and if it isn't masked, then
+	 * we try to set the corresponding bit in the in-kernel shadow of
+	 * evtchn_pending_sel for the target vCPU. And if *that* wasn't
+	 * already set, then we kick the vCPU in question to write to the
+	 * *real* evtchn_pending_sel in its own guest vcpu_info struct.
+	 */
+	if (!test_and_set_bit(e->xen_evtchn.port, pending_bits) &&
+	    !test_bit(e->xen_evtchn.port, mask_bits) &&
+	    !test_and_set_bit(port_word_bit, &vcpu->arch.xen.evtchn_pending_sel))
+		kick_vcpu = true;
+
+	rc = 0;
+
+ out_rcu:
+	srcu_read_unlock(&kvm->srcu, idx);
+ out_unlock:
+	read_unlock(&kvm->arch.xen.shinfo_lock);
+
+	if (kick_vcpu) {
+		kvm_make_request(KVM_REQ_EVENT, vcpu);
+		kvm_vcpu_kick(vcpu);
+	}
+
+	return rc;
+}
+
+/* This is the version called from kvm_set_irq() as the .set function */
+static int evtchn_set_fn(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm,
+			 int irq_source_id, int level, bool line_status)
+{
+	bool mm_borrowed = false;
+	int rc;
+
+	if (!level)
+		return -1;
+
+	rc = kvm_xen_set_evtchn_fast(e, kvm);
+	if (rc != -EWOULDBLOCK)
+		return rc;
+
+	if (current->mm != kvm->mm) {
+		/*
+		 * If not on a thread which already belongs to this KVM,
+		 * we'd better be in the irqfd workqueue.
+		 */
+		if (WARN_ON_ONCE(current->mm))
+			return -EINVAL;
+
+		kthread_use_mm(kvm->mm);
+		mm_borrowed = true;
+	}
+
+	/*
+	 * For the irqfd workqueue, using the main kvm->lock mutex is
+	 * fine since this function is invoked from kvm_set_irq() with
+	 * no other lock held, no srcu. In future if it will be called
+	 * directly from a vCPU thread (e.g. on hypercall for an IPI)
+	 * then it may need to switch to using a leaf-node mutex for
+	 * serializing the shared_info mapping.
+	 */
+	mutex_lock(&kvm->lock);
+
+	/*
+	 * It is theoretically possible for the page to be unmapped
+	 * and the MMU notifier to invalidate the shared_info before
+	 * we even get to use it. In that case, this looks like an
+	 * infinite loop. It was tempting to do it via the userspace
+	 * HVA instead... but that just *hides* the fact that it's
+	 * an infinite loop, because if a fault occurs and it waits
+	 * for the page to come back, it can *still* immediately
+	 * fault and have to wait again, repeatedly.
+	 *
+	 * Conversely, the page could also have been reinstated by
+	 * another thread before we even obtain the mutex above, so
+	 * check again *first* before remapping it.
+	 */
+	do {
+		rc = kvm_xen_set_evtchn_fast(e, kvm);
+		if (rc != -EWOULDBLOCK)
+			break;
+
+		rc = kvm_xen_shared_info_init(kvm,
+					      kvm->arch.xen.shinfo_cache.gfn,
+					      false);
+	} while(!rc);
+
+	mutex_unlock(&kvm->lock);
+
+	if (mm_borrowed)
+		kthread_unuse_mm(kvm->mm);
+
+	return rc;
+}
+
+int kvm_xen_setup_evtchn(struct kvm *kvm,
+			 struct kvm_kernel_irq_routing_entry *e,
+			 const struct kvm_irq_routing_entry *ue)
+
+{
+	if (ue->u.xen_evtchn.port >= max_evtchn_port(kvm))
+		return -EINVAL;
+
+	/* We only support 2 level event channels for now */
+	if (ue->u.xen_evtchn.priority != KVM_IRQ_ROUTING_XEN_EVTCHN_PRIO_2LEVEL)
+		return -EINVAL;
+
+	e->xen_evtchn.port = ue->u.xen_evtchn.port;
+	e->xen_evtchn.vcpu = ue->u.xen_evtchn.vcpu;
+	e->xen_evtchn.priority = ue->u.xen_evtchn.priority;
+	e->set = evtchn_set_fn;
+
+	return 0;
+}
diff --git a/arch/x86/kvm/xen.h b/arch/x86/kvm/xen.h
index cc0cf5f37450..adbcc9ed59db 100644
--- a/arch/x86/kvm/xen.h
+++ b/arch/x86/kvm/xen.h
@@ -24,6 +24,12 @@ int kvm_xen_hvm_config(struct kvm *kvm, struct kvm_xen_hvm_config *xhc);
 void kvm_xen_init_vm(struct kvm *kvm);
 void kvm_xen_destroy_vm(struct kvm *kvm);
 
+int kvm_xen_set_evtchn_fast(struct kvm_kernel_irq_routing_entry *e,
+			    struct kvm *kvm);
+int kvm_xen_setup_evtchn(struct kvm *kvm,
+			 struct kvm_kernel_irq_routing_entry *e,
+			 const struct kvm_irq_routing_entry *ue);
+
 static inline bool kvm_xen_msr_enabled(struct kvm *kvm)
 {
 	return static_branch_unlikely(&kvm_xen_enabled.key) &&
@@ -134,6 +140,9 @@ struct compat_shared_info {
 	struct compat_arch_shared_info arch;
 };
 
+#define COMPAT_EVTCHN_2L_NR_CHANNELS (8 *				\
+				      sizeof_field(struct compat_shared_info, \
+						   evtchn_pending))
 struct compat_vcpu_runstate_info {
     int state;
     uint64_t state_entry_time;
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index f0012d128aa5..7a0043734dbd 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -444,6 +444,12 @@ struct kvm_hv_sint {
 	u32 sint;
 };
 
+struct kvm_xen_evtchn {
+	u32 port;
+	u32 vcpu;
+	u32 priority;
+};
+
 struct kvm_kernel_irq_routing_entry {
 	u32 gsi;
 	u32 type;
@@ -464,6 +470,7 @@ struct kvm_kernel_irq_routing_entry {
 		} msi;
 		struct kvm_s390_adapter_int adapter;
 		struct kvm_hv_sint hv_sint;
+		struct kvm_xen_evtchn xen_evtchn;
 	};
 	struct hlist_node link;
 };
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index a067410ebea5..52ee8edfdbc3 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -1143,11 +1143,20 @@ struct kvm_irq_routing_hv_sint {
 	__u32 sint;
 };
 
+struct kvm_irq_routing_xen_evtchn {
+	__u32 port;
+	__u32 vcpu;
+	__u32 priority;
+};
+
+#define KVM_IRQ_ROUTING_XEN_EVTCHN_PRIO_2LEVEL ((__u32)(-1))
+
 /* gsi routing entry types */
 #define KVM_IRQ_ROUTING_IRQCHIP 1
 #define KVM_IRQ_ROUTING_MSI 2
 #define KVM_IRQ_ROUTING_S390_ADAPTER 3
 #define KVM_IRQ_ROUTING_HV_SINT 4
+#define KVM_IRQ_ROUTING_XEN_EVTCHN 5
 
 struct kvm_irq_routing_entry {
 	__u32 gsi;
@@ -1159,6 +1168,7 @@ struct kvm_irq_routing_entry {
 		struct kvm_irq_routing_msi msi;
 		struct kvm_irq_routing_s390_adapter adapter;
 		struct kvm_irq_routing_hv_sint hv_sint;
+		struct kvm_irq_routing_xen_evtchn xen_evtchn;
 		__u32 pad[8];
 	} u;
 };
@@ -1189,6 +1199,7 @@ struct kvm_x86_mce {
 #define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL	(1 << 1)
 #define KVM_XEN_HVM_CONFIG_SHARED_INFO		(1 << 2)
 #define KVM_XEN_HVM_CONFIG_RUNSTATE		(1 << 3)
+#define KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL	(1 << 4)
 
 struct kvm_xen_hvm_config {
 	__u32 flags;
diff --git a/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c b/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c
index a0699f00b3d6..a865e60a042c 100644
--- a/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c
+++ b/tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c
@@ -14,6 +14,9 @@
 #include <stdint.h>
 #include <time.h>
 #include <sched.h>
+#include <signal.h>
+
+#include <sys/eventfd.h>
 
 #define VCPU_ID		5
 
@@ -22,10 +25,12 @@
 #define SHINFO_REGION_SLOT	10
 #define PAGE_SIZE		4096
 
+#define SHINFO_ADDR	(SHINFO_REGION_GPA)
 #define PVTIME_ADDR	(SHINFO_REGION_GPA + PAGE_SIZE)
 #define RUNSTATE_ADDR	(SHINFO_REGION_GPA + PAGE_SIZE + 0x20)
 #define VCPU_INFO_ADDR	(SHINFO_REGION_GPA + 0x40)
 
+#define SHINFO_VADDR	(SHINFO_REGION_GVA)
 #define RUNSTATE_VADDR	(SHINFO_REGION_GVA + PAGE_SIZE + 0x20)
 #define VCPU_INFO_VADDR	(SHINFO_REGION_GVA + 0x40)
 
@@ -73,15 +78,30 @@ struct vcpu_info {
         struct pvclock_vcpu_time_info time;
 }; /* 64 bytes (x86) */
 
+struct shared_info {
+	struct vcpu_info vcpu_info[32];
+	unsigned long evtchn_pending[64];
+	unsigned long evtchn_mask[64];
+	struct pvclock_wall_clock wc;
+	uint32_t wc_sec_hi;
+	/* arch_shared_info here */
+};
+
 #define RUNSTATE_running  0
 #define RUNSTATE_runnable 1
 #define RUNSTATE_blocked  2
 #define RUNSTATE_offline  3
 
+struct {
+	struct kvm_irq_routing info;
+	struct kvm_irq_routing_entry entries[2];
+} irq_routes;
+
 static void evtchn_handler(struct ex_regs *regs)
 {
 	struct vcpu_info *vi = (void *)VCPU_INFO_VADDR;
 	vi->evtchn_upcall_pending = 0;
+	vi->evtchn_pending_sel = 0;
 
 	GUEST_SYNC(0x20);
 }
@@ -127,7 +147,19 @@ static void guest_code(void)
 	GUEST_SYNC(6);
 	GUEST_ASSERT(rs->time[RUNSTATE_runnable] >= MIN_STEAL_TIME);
 
-	GUEST_DONE();
+	/* Attempt to deliver a *masked* interrupt */
+	GUEST_SYNC(7);
+
+	/* Wait until we see the bit set */
+	struct shared_info *si = (void *)SHINFO_VADDR;
+	while (!si->evtchn_pending[0])
+		__asm__ __volatile__ ("rep nop" : : : "memory");
+
+	/* Now deliver an *unmasked* interrupt */
+	GUEST_SYNC(8);
+
+	for (;;)
+		__asm__ __volatile__ ("rep nop" : : : "memory");
 }
 
 static int cmp_timespec(struct timespec *a, struct timespec *b)
@@ -144,6 +176,11 @@ static int cmp_timespec(struct timespec *a, struct timespec *b)
 		return 0;
 }
 
+static void handle_alrm(int sig)
+{
+	TEST_FAIL("IRQ delivery timed out");
+}
+
 int main(int argc, char *argv[])
 {
 	struct timespec min_ts, max_ts, vm_ts;
@@ -155,6 +192,7 @@ int main(int argc, char *argv[])
 	}
 
 	bool do_runstate_tests = !!(xen_caps & KVM_XEN_HVM_CONFIG_RUNSTATE);
+	bool do_eventfd_tests = !!(xen_caps & KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL);
 
 	clock_gettime(CLOCK_REALTIME, &min_ts);
 
@@ -166,6 +204,11 @@ int main(int argc, char *argv[])
 				    SHINFO_REGION_GPA, SHINFO_REGION_SLOT, 2, 0);
 	virt_map(vm, SHINFO_REGION_GVA, SHINFO_REGION_GPA, 2);
 
+	struct shared_info *shinfo = addr_gpa2hva(vm, SHINFO_VADDR);
+
+	int zero_fd = open("/dev/zero", O_RDONLY);
+	TEST_ASSERT(zero_fd != -1, "Failed to open /dev/zero");
+
 	struct kvm_xen_hvm_config hvmc = {
 		.flags = KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL,
 		.msr = XEN_HYPERCALL_MSR,
@@ -184,6 +227,16 @@ int main(int argc, char *argv[])
 	};
 	vm_ioctl(vm, KVM_XEN_HVM_SET_ATTR, &ha);
 
+	/*
+	 * Test what happens when the HVA of the shinfo page is remapped after
+	 * the kernel has a reference to it. But make sure we copy the clock
+	 * info over since that's only set at setup time, and we test it later.
+	 */
+	struct pvclock_wall_clock wc_copy = shinfo->wc;
+	void *m = mmap(shinfo, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_PRIVATE, zero_fd, 0);
+	TEST_ASSERT(m == shinfo, "Failed to map /dev/zero over shared info");
+	shinfo->wc = wc_copy;
+
 	struct kvm_xen_vcpu_attr vi = {
 		.type = KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO,
 		.u.gpa = VCPU_INFO_ADDR,
@@ -214,6 +267,49 @@ int main(int argc, char *argv[])
 		vcpu_ioctl(vm, VCPU_ID, KVM_XEN_VCPU_SET_ATTR, &st);
 	}
 
+	int irq_fd[2] = { -1, -1 };
+
+	if (do_eventfd_tests) {
+		irq_fd[0] = eventfd(0, 0);
+		irq_fd[1] = eventfd(0, 0);
+
+		/* Unexpected, but not a KVM failure */
+		if (irq_fd[0] == -1 || irq_fd[1] == -1)
+			do_eventfd_tests = false;
+	}
+
+	if (do_eventfd_tests) {
+		irq_routes.info.nr = 2;
+
+		irq_routes.entries[0].gsi = 32;
+		irq_routes.entries[0].type = KVM_IRQ_ROUTING_XEN_EVTCHN;
+		irq_routes.entries[0].u.xen_evtchn.port = 15;
+		irq_routes.entries[0].u.xen_evtchn.vcpu = VCPU_ID;
+		irq_routes.entries[0].u.xen_evtchn.priority = KVM_IRQ_ROUTING_XEN_EVTCHN_PRIO_2LEVEL;
+
+		irq_routes.entries[1].gsi = 33;
+		irq_routes.entries[1].type = KVM_IRQ_ROUTING_XEN_EVTCHN;
+		irq_routes.entries[1].u.xen_evtchn.port = 66;
+		irq_routes.entries[1].u.xen_evtchn.vcpu = VCPU_ID;
+		irq_routes.entries[1].u.xen_evtchn.priority = KVM_IRQ_ROUTING_XEN_EVTCHN_PRIO_2LEVEL;
+
+		vm_ioctl(vm, KVM_SET_GSI_ROUTING, &irq_routes);
+
+		struct kvm_irqfd ifd = { };
+
+		ifd.fd = irq_fd[0];
+		ifd.gsi = 32;
+		vm_ioctl(vm, KVM_IRQFD, &ifd);
+
+		ifd.fd = irq_fd[1];
+		ifd.gsi = 33;
+		vm_ioctl(vm, KVM_IRQFD, &ifd);
+
+		struct sigaction sa = { };
+		sa.sa_handler = handle_alrm;
+		sigaction(SIGALRM, &sa, NULL);
+	}
+
 	struct vcpu_info *vinfo = addr_gpa2hva(vm, VCPU_INFO_VADDR);
 	vinfo->evtchn_upcall_pending = 0;
 
@@ -289,9 +385,23 @@ int main(int argc, char *argv[])
 					sched_yield();
 				} while (get_run_delay() < rundelay);
 				break;
+			case 7:
+				if (!do_eventfd_tests)
+					goto done;
+				shinfo->evtchn_mask[0] = 0x8000;
+				eventfd_write(irq_fd[0], 1UL);
+				alarm(1);
+				break;
+			case 8:
+				eventfd_write(irq_fd[1], 1UL);
+				evtchn_irq_expected = true;
+				break;
+
 			case 0x20:
 				TEST_ASSERT(evtchn_irq_expected, "Unexpected event channel IRQ");
 				evtchn_irq_expected = false;
+				if (shinfo->evtchn_pending[1])
+					goto done;
 				break;
 			}
 			break;
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 6/6] KVM: x86/xen: Add KVM_IRQ_ROUTING_XEN_EVTCHN and event channel delivery
  2021-11-01 19:03 ` [PATCH v2 6/6] KVM: x86/xen: Add KVM_IRQ_ROUTING_XEN_EVTCHN and event channel delivery David Woodhouse
@ 2021-11-02  0:25   ` David Woodhouse
  0 siblings, 0 replies; 12+ messages in thread
From: David Woodhouse @ 2021-11-02  0:25 UTC (permalink / raw)
  To: kvm
  Cc: Paolo Bonzini, Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li,
	Jim Mattson, Joerg Roedel, Joao Martins, Ankur Arora,
	KarimAllah Raslan

[-- Attachment #1: Type: text/plain, Size: 1461 bytes --]

On Mon, 2021-11-01 at 19:03 +0000, David Woodhouse wrote:
> +int kvm_xen_set_evtchn_fast(struct kvm_kernel_irq_routing_entry *e,
> +                           struct kvm *kvm)
> +{
> +       struct gfn_to_pfn_cache *gpc = &kvm->arch.xen.shinfo_cache;
> +       struct kvm_memslots *slots;
> +       struct kvm_vcpu *vcpu;
> +       unsigned long *pending_bits, *mask_bits;
> +       int port_word_bit;
> +       bool kick_vcpu = false;
> +       int idx;
> +       int rc;
> +
> +       vcpu = kvm_get_vcpu_by_id(kvm, e->xen_evtchn.vcpu);
> +       if (!vcpu)
> +               return -EINVAL;

Hm... am I allowed to do that kvm_get_vcpu_by_id() just once in
kvm_xen_setup_evtchn() and store the resulting vcpu pointer in
e->xen_evtchn.vcpu instead of its APIC ID? vCPUs can't go away until
the whole kvm is destroyed, can they?

> +       if (!vcpu->arch.xen.vcpu_info_set)
> +               return -EINVAL;
> +
> +       if (e->xen_evtchn.port >= max_evtchn_port(kvm))
> +               return -EINVAL;
> +
> +       rc = -EWOULDBLOCK;
> +       read_lock(&kvm->arch.xen.shinfo_lock);

Once I hooked that up to an actual VMM instead of just the self tests,
and this is being called from an actual IRQ handler (via
vfio_msihandler and eventfd_signal), lockdep reminded me that it needed
to be read_lock_irqsave() there, with similar changes in the previous
patch. Fixed in my tree and will be included in the next revision.

[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 5174 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 5/6] KVM: x86/xen: Maintain valid mapping of Xen shared_info page
  2021-11-01 19:03 ` [PATCH v2 5/6] KVM: x86/xen: Maintain valid mapping of Xen shared_info page David Woodhouse
@ 2021-11-02  1:23   ` kernel test robot
  2021-11-04 19:05   ` David Woodhouse
  1 sibling, 0 replies; 12+ messages in thread
From: kernel test robot @ 2021-11-02  1:23 UTC (permalink / raw)
  To: David Woodhouse, kvm
  Cc: kbuild-all, Paolo Bonzini, Sean Christopherson, Vitaly Kuznetsov,
	Wanpeng Li, Jim Mattson, Joerg Roedel, Joao Martins, Ankur Arora,
	KarimAllah Raslan

[-- Attachment #1: Type: text/plain, Size: 4205 bytes --]

Hi David,

I love your patch! Yet something to improve:

[auto build test ERROR on mst-vhost/linux-next]
[also build test ERROR on linus/master v5.15 next-20211101]
[cannot apply to kvm/queue]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/David-Woodhouse/KVM-x86-xen-Add-in-kernel-Xen-event-channel-delivery/20211102-035038
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git linux-next
config: i386-debian-10.3 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce (this is a W=1 build):
        # https://github.com/0day-ci/linux/commit/bba9531e42e9dd7a2ab056057a94d56f43643e24
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review David-Woodhouse/KVM-x86-xen-Add-in-kernel-Xen-event-channel-delivery/20211102-035038
        git checkout bba9531e42e9dd7a2ab056057a94d56f43643e24
        # save the attached .config to linux build tree
        mkdir build_dir
        make W=1 O=build_dir ARCH=i386 SHELL=/bin/bash arch/x86/kvm/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   In file included from include/linux/dynamic_debug.h:6,
                    from include/linux/printk.h:555,
                    from include/linux/kernel.h:19,
                    from include/linux/cpumask.h:10,
                    from include/linux/mm_types_task.h:14,
                    from include/linux/mm_types.h:5,
                    from arch/x86/kvm/irq.h:13,
                    from arch/x86/kvm/mmu/mmu.c:18:
   arch/x86/kvm/mmu/mmu.c: In function 'kvm_unmap_gfn_range':
>> arch/x86/kvm/mmu/mmu.c:1592:30: error: 'kvm_xen_enabled' undeclared (first use in this function); did you mean 'kvm_xen_msr_enabled'?
    1592 |  if (static_branch_unlikely(&kvm_xen_enabled.key)) {
         |                              ^~~~~~~~~~~~~~~
   include/linux/jump_label.h:496:43: note: in definition of macro 'static_branch_unlikely'
     496 |  if (__builtin_types_compatible_p(typeof(*x), struct static_key_true)) \
         |                                           ^
   arch/x86/kvm/mmu/mmu.c:1592:30: note: each undeclared identifier is reported only once for each function it appears in
    1592 |  if (static_branch_unlikely(&kvm_xen_enabled.key)) {
         |                              ^~~~~~~~~~~~~~~
   include/linux/jump_label.h:496:43: note: in definition of macro 'static_branch_unlikely'
     496 |  if (__builtin_types_compatible_p(typeof(*x), struct static_key_true)) \
         |                                           ^


vim +1592 arch/x86/kvm/mmu/mmu.c

  1587	
  1588	bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
  1589	{
  1590		bool flush = false;
  1591	
> 1592		if (static_branch_unlikely(&kvm_xen_enabled.key)) {
  1593			write_lock(&kvm->arch.xen.shinfo_lock);
  1594	
  1595			if (kvm->arch.xen.shared_info &&
  1596			    kvm->arch.xen.shinfo_gfn >= range->start &&
  1597			    kvm->arch.xen.shinfo_cache.gfn < range->end) {
  1598				/*
  1599				 * If kvm_xen_shared_info_init() had *finished* mapping the
  1600				 * page and assigned the pointer for real, then mark the page
  1601				 * dirty now instead of via the eventual cache teardown.
  1602				 */
  1603				if (kvm->arch.xen.shared_info != KVM_UNMAPPED_PAGE) {
  1604					kvm_set_pfn_dirty(kvm->arch.xen.shinfo_cache.pfn);
  1605					kvm->arch.xen.shinfo_cache.dirty = false;
  1606				}
  1607	
  1608				kvm->arch.xen.shared_info = NULL;
  1609			}
  1610	
  1611			write_unlock(&kvm->arch.xen.shinfo_lock);
  1612		}
  1613	
  1614		if (kvm_memslots_have_rmaps(kvm))
  1615			flush = kvm_handle_gfn_range(kvm, range, kvm_unmap_rmapp);
  1616	
  1617		if (is_tdp_mmu_enabled(kvm))
  1618			flush |= kvm_tdp_mmu_unmap_gfn_range(kvm, range, flush);
  1619	
  1620		return flush;
  1621	}
  1622	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 34096 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 4/6] KVM: Fix kvm_map_gfn()/kvm_unmap_gfn() to take a kvm as their names imply
  2021-11-01 19:03 ` [PATCH v2 4/6] KVM: Fix kvm_map_gfn()/kvm_unmap_gfn() to take a kvm as their names imply David Woodhouse
@ 2021-11-02  3:12   ` kernel test robot
  2021-11-02 22:33   ` kernel test robot
  1 sibling, 0 replies; 12+ messages in thread
From: kernel test robot @ 2021-11-02  3:12 UTC (permalink / raw)
  To: David Woodhouse, kvm
  Cc: llvm, kbuild-all, Paolo Bonzini, Sean Christopherson,
	Vitaly Kuznetsov, Wanpeng Li, Jim Mattson, Joerg Roedel,
	Joao Martins, Ankur Arora, KarimAllah Raslan

[-- Attachment #1: Type: text/plain, Size: 7712 bytes --]

Hi David,

I love your patch! Yet something to improve:

[auto build test ERROR on mst-vhost/linux-next]
[also build test ERROR on linus/master v5.15 next-20211101]
[cannot apply to kvm/queue]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/David-Woodhouse/KVM-x86-xen-Add-in-kernel-Xen-event-channel-delivery/20211102-035038
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git linux-next
config: x86_64-randconfig-a003-20211101 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 264d3b6d4e08401c5b50a85bd76e80b3461d77e6)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/e0d8e28314e04209c373131aa5ca6bf57c9f1857
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review David-Woodhouse/KVM-x86-xen-Add-in-kernel-Xen-event-channel-delivery/20211102-035038
        git checkout e0d8e28314e04209c373131aa5ca6bf57c9f1857
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> arch/x86/kvm/x86.c:3210:18: error: incompatible pointer types passing 'struct kvm_vcpu *' to parameter of type 'struct kvm *' [-Werror,-Wincompatible-pointer-types]
           if (kvm_map_gfn(vcpu, vcpu->arch.st.msr_val >> PAGE_SHIFT,
                           ^~~~
   include/linux/kvm_host.h:946:29: note: passing argument to parameter 'kvm' here
   int kvm_map_gfn(struct kvm *kvm, gfn_t gfn, struct kvm_host_map *map,
                               ^
   arch/x86/kvm/x86.c:3249:16: error: incompatible pointer types passing 'struct kvm_vcpu *' to parameter of type 'struct kvm *' [-Werror,-Wincompatible-pointer-types]
           kvm_unmap_gfn(vcpu, &map, &vcpu->arch.st.cache, true, false);
                         ^~~~
   include/linux/kvm_host.h:950:31: note: passing argument to parameter 'kvm' here
   int kvm_unmap_gfn(struct kvm *kvm, struct kvm_host_map *map,
                                 ^
   arch/x86/kvm/x86.c:4297:18: error: incompatible pointer types passing 'struct kvm_vcpu *' to parameter of type 'struct kvm *' [-Werror,-Wincompatible-pointer-types]
           if (kvm_map_gfn(vcpu, vcpu->arch.st.msr_val >> PAGE_SHIFT, &map,
                           ^~~~
   include/linux/kvm_host.h:946:29: note: passing argument to parameter 'kvm' here
   int kvm_map_gfn(struct kvm *kvm, gfn_t gfn, struct kvm_host_map *map,
                               ^
   arch/x86/kvm/x86.c:4306:16: error: incompatible pointer types passing 'struct kvm_vcpu *' to parameter of type 'struct kvm *' [-Werror,-Wincompatible-pointer-types]
           kvm_unmap_gfn(vcpu, &map, &vcpu->arch.st.cache, true, true);
                         ^~~~
   include/linux/kvm_host.h:950:31: note: passing argument to parameter 'kvm' here
   int kvm_unmap_gfn(struct kvm *kvm, struct kvm_host_map *map,
                                 ^
   4 errors generated.


vim +3210 arch/x86/kvm/x86.c

0baedd79271306 Vitaly Kuznetsov 2020-03-25  3195  
c9aaa8957f203b Glauber Costa    2011-07-11  3196  static void record_steal_time(struct kvm_vcpu *vcpu)
c9aaa8957f203b Glauber Costa    2011-07-11  3197  {
b043138246a410 Boris Ostrovsky  2019-12-05  3198  	struct kvm_host_map map;
b043138246a410 Boris Ostrovsky  2019-12-05  3199  	struct kvm_steal_time *st;
b043138246a410 Boris Ostrovsky  2019-12-05  3200  
30b5c851af7991 David Woodhouse  2021-03-01  3201  	if (kvm_xen_msr_enabled(vcpu->kvm)) {
30b5c851af7991 David Woodhouse  2021-03-01  3202  		kvm_xen_runstate_set_running(vcpu);
30b5c851af7991 David Woodhouse  2021-03-01  3203  		return;
30b5c851af7991 David Woodhouse  2021-03-01  3204  	}
30b5c851af7991 David Woodhouse  2021-03-01  3205  
c9aaa8957f203b Glauber Costa    2011-07-11  3206  	if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED))
c9aaa8957f203b Glauber Costa    2011-07-11  3207  		return;
c9aaa8957f203b Glauber Costa    2011-07-11  3208  
b043138246a410 Boris Ostrovsky  2019-12-05  3209  	/* -EAGAIN is returned in atomic context so we can just return. */
b043138246a410 Boris Ostrovsky  2019-12-05 @3210  	if (kvm_map_gfn(vcpu, vcpu->arch.st.msr_val >> PAGE_SHIFT,
b043138246a410 Boris Ostrovsky  2019-12-05  3211  			&map, &vcpu->arch.st.cache, false))
c9aaa8957f203b Glauber Costa    2011-07-11  3212  		return;
c9aaa8957f203b Glauber Costa    2011-07-11  3213  
b043138246a410 Boris Ostrovsky  2019-12-05  3214  	st = map.hva +
b043138246a410 Boris Ostrovsky  2019-12-05  3215  		offset_in_page(vcpu->arch.st.msr_val & KVM_STEAL_VALID_BITS);
b043138246a410 Boris Ostrovsky  2019-12-05  3216  
f38a7b75267f1f Wanpeng Li       2017-12-12  3217  	/*
f38a7b75267f1f Wanpeng Li       2017-12-12  3218  	 * Doing a TLB flush here, on the guest's behalf, can avoid
f38a7b75267f1f Wanpeng Li       2017-12-12  3219  	 * expensive IPIs.
f38a7b75267f1f Wanpeng Li       2017-12-12  3220  	 */
66570e966dd9cb Oliver Upton     2020-08-18  3221  	if (guest_pv_has(vcpu, KVM_FEATURE_PV_TLB_FLUSH)) {
af3511ff7fa210 Lai Jiangshan    2021-06-01  3222  		u8 st_preempted = xchg(&st->preempted, 0);
af3511ff7fa210 Lai Jiangshan    2021-06-01  3223  
b382f44e98506b Wanpeng Li       2019-08-05  3224  		trace_kvm_pv_tlb_flush(vcpu->vcpu_id,
af3511ff7fa210 Lai Jiangshan    2021-06-01  3225  				       st_preempted & KVM_VCPU_FLUSH_TLB);
af3511ff7fa210 Lai Jiangshan    2021-06-01  3226  		if (st_preempted & KVM_VCPU_FLUSH_TLB)
0baedd79271306 Vitaly Kuznetsov 2020-03-25  3227  			kvm_vcpu_flush_tlb_guest(vcpu);
1eff0ada88b48e Wanpeng Li       2021-05-18  3228  	} else {
1eff0ada88b48e Wanpeng Li       2021-05-18  3229  		st->preempted = 0;
66570e966dd9cb Oliver Upton     2020-08-18  3230  	}
0b9f6c4615c993 Pan Xinhui       2016-11-02  3231  
a6bd811f1209fe Boris Ostrovsky  2019-12-06  3232  	vcpu->arch.st.preempted = 0;
35f3fae1784979 Wanpeng Li       2016-05-03  3233  
b043138246a410 Boris Ostrovsky  2019-12-05  3234  	if (st->version & 1)
b043138246a410 Boris Ostrovsky  2019-12-05  3235  		st->version += 1;  /* first time write, random junk */
35f3fae1784979 Wanpeng Li       2016-05-03  3236  
b043138246a410 Boris Ostrovsky  2019-12-05  3237  	st->version += 1;
35f3fae1784979 Wanpeng Li       2016-05-03  3238  
35f3fae1784979 Wanpeng Li       2016-05-03  3239  	smp_wmb();
35f3fae1784979 Wanpeng Li       2016-05-03  3240  
b043138246a410 Boris Ostrovsky  2019-12-05  3241  	st->steal += current->sched_info.run_delay -
c54cdf141c40a5 Liang Chen       2016-03-16  3242  		vcpu->arch.st.last_steal;
c54cdf141c40a5 Liang Chen       2016-03-16  3243  	vcpu->arch.st.last_steal = current->sched_info.run_delay;
35f3fae1784979 Wanpeng Li       2016-05-03  3244  
35f3fae1784979 Wanpeng Li       2016-05-03  3245  	smp_wmb();
35f3fae1784979 Wanpeng Li       2016-05-03  3246  
b043138246a410 Boris Ostrovsky  2019-12-05  3247  	st->version += 1;
c9aaa8957f203b Glauber Costa    2011-07-11  3248  
b043138246a410 Boris Ostrovsky  2019-12-05  3249  	kvm_unmap_gfn(vcpu, &map, &vcpu->arch.st.cache, true, false);
c9aaa8957f203b Glauber Costa    2011-07-11  3250  }
c9aaa8957f203b Glauber Costa    2011-07-11  3251  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 31224 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 4/6] KVM: Fix kvm_map_gfn()/kvm_unmap_gfn() to take a kvm as their names imply
  2021-11-01 19:03 ` [PATCH v2 4/6] KVM: Fix kvm_map_gfn()/kvm_unmap_gfn() to take a kvm as their names imply David Woodhouse
  2021-11-02  3:12   ` kernel test robot
@ 2021-11-02 22:33   ` kernel test robot
  1 sibling, 0 replies; 12+ messages in thread
From: kernel test robot @ 2021-11-02 22:33 UTC (permalink / raw)
  To: David Woodhouse, kvm
  Cc: kbuild-all, Paolo Bonzini, Sean Christopherson, Vitaly Kuznetsov,
	Wanpeng Li, Jim Mattson, Joerg Roedel, Joao Martins, Ankur Arora,
	KarimAllah Raslan

[-- Attachment #1: Type: text/plain, Size: 8223 bytes --]

Hi David,

I love your patch! Yet something to improve:

[auto build test ERROR on mst-vhost/linux-next]
[also build test ERROR on linus/master v5.15 next-20211102]
[cannot apply to kvm/queue]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/David-Woodhouse/KVM-x86-xen-Add-in-kernel-Xen-event-channel-delivery/20211102-035038
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git linux-next
config: i386-allyesconfig (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce (this is a W=1 build):
        # https://github.com/0day-ci/linux/commit/e0d8e28314e04209c373131aa5ca6bf57c9f1857
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review David-Woodhouse/KVM-x86-xen-Add-in-kernel-Xen-event-channel-delivery/20211102-035038
        git checkout e0d8e28314e04209c373131aa5ca6bf57c9f1857
        # save the attached .config to linux build tree
        make W=1 ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   arch/x86/kvm/x86.c: In function 'record_steal_time':
>> arch/x86/kvm/x86.c:3210:18: error: passing argument 1 of 'kvm_map_gfn' from incompatible pointer type [-Werror=incompatible-pointer-types]
    3210 |  if (kvm_map_gfn(vcpu, vcpu->arch.st.msr_val >> PAGE_SHIFT,
         |                  ^~~~
         |                  |
         |                  struct kvm_vcpu *
   In file included from arch/x86/kvm/x86.c:19:
   include/linux/kvm_host.h:946:29: note: expected 'struct kvm *' but argument is of type 'struct kvm_vcpu *'
     946 | int kvm_map_gfn(struct kvm *kvm, gfn_t gfn, struct kvm_host_map *map,
         |                 ~~~~~~~~~~~~^~~
>> arch/x86/kvm/x86.c:3249:16: error: passing argument 1 of 'kvm_unmap_gfn' from incompatible pointer type [-Werror=incompatible-pointer-types]
    3249 |  kvm_unmap_gfn(vcpu, &map, &vcpu->arch.st.cache, true, false);
         |                ^~~~
         |                |
         |                struct kvm_vcpu *
   In file included from arch/x86/kvm/x86.c:19:
   include/linux/kvm_host.h:950:31: note: expected 'struct kvm *' but argument is of type 'struct kvm_vcpu *'
     950 | int kvm_unmap_gfn(struct kvm *kvm, struct kvm_host_map *map,
         |                   ~~~~~~~~~~~~^~~
   arch/x86/kvm/x86.c: In function 'kvm_steal_time_set_preempted':
   arch/x86/kvm/x86.c:4297:18: error: passing argument 1 of 'kvm_map_gfn' from incompatible pointer type [-Werror=incompatible-pointer-types]
    4297 |  if (kvm_map_gfn(vcpu, vcpu->arch.st.msr_val >> PAGE_SHIFT, &map,
         |                  ^~~~
         |                  |
         |                  struct kvm_vcpu *
   In file included from arch/x86/kvm/x86.c:19:
   include/linux/kvm_host.h:946:29: note: expected 'struct kvm *' but argument is of type 'struct kvm_vcpu *'
     946 | int kvm_map_gfn(struct kvm *kvm, gfn_t gfn, struct kvm_host_map *map,
         |                 ~~~~~~~~~~~~^~~
   arch/x86/kvm/x86.c:4306:16: error: passing argument 1 of 'kvm_unmap_gfn' from incompatible pointer type [-Werror=incompatible-pointer-types]
    4306 |  kvm_unmap_gfn(vcpu, &map, &vcpu->arch.st.cache, true, true);
         |                ^~~~
         |                |
         |                struct kvm_vcpu *
   In file included from arch/x86/kvm/x86.c:19:
   include/linux/kvm_host.h:950:31: note: expected 'struct kvm *' but argument is of type 'struct kvm_vcpu *'
     950 | int kvm_unmap_gfn(struct kvm *kvm, struct kvm_host_map *map,
         |                   ~~~~~~~~~~~~^~~
   cc1: all warnings being treated as errors


vim +/kvm_map_gfn +3210 arch/x86/kvm/x86.c

0baedd792713063 Vitaly Kuznetsov 2020-03-25  3195  
c9aaa8957f203bd Glauber Costa    2011-07-11  3196  static void record_steal_time(struct kvm_vcpu *vcpu)
c9aaa8957f203bd Glauber Costa    2011-07-11  3197  {
b043138246a4106 Boris Ostrovsky  2019-12-05  3198  	struct kvm_host_map map;
b043138246a4106 Boris Ostrovsky  2019-12-05  3199  	struct kvm_steal_time *st;
b043138246a4106 Boris Ostrovsky  2019-12-05  3200  
30b5c851af7991a David Woodhouse  2021-03-01  3201  	if (kvm_xen_msr_enabled(vcpu->kvm)) {
30b5c851af7991a David Woodhouse  2021-03-01  3202  		kvm_xen_runstate_set_running(vcpu);
30b5c851af7991a David Woodhouse  2021-03-01  3203  		return;
30b5c851af7991a David Woodhouse  2021-03-01  3204  	}
30b5c851af7991a David Woodhouse  2021-03-01  3205  
c9aaa8957f203bd Glauber Costa    2011-07-11  3206  	if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED))
c9aaa8957f203bd Glauber Costa    2011-07-11  3207  		return;
c9aaa8957f203bd Glauber Costa    2011-07-11  3208  
b043138246a4106 Boris Ostrovsky  2019-12-05  3209  	/* -EAGAIN is returned in atomic context so we can just return. */
b043138246a4106 Boris Ostrovsky  2019-12-05 @3210  	if (kvm_map_gfn(vcpu, vcpu->arch.st.msr_val >> PAGE_SHIFT,
b043138246a4106 Boris Ostrovsky  2019-12-05  3211  			&map, &vcpu->arch.st.cache, false))
c9aaa8957f203bd Glauber Costa    2011-07-11  3212  		return;
c9aaa8957f203bd Glauber Costa    2011-07-11  3213  
b043138246a4106 Boris Ostrovsky  2019-12-05  3214  	st = map.hva +
b043138246a4106 Boris Ostrovsky  2019-12-05  3215  		offset_in_page(vcpu->arch.st.msr_val & KVM_STEAL_VALID_BITS);
b043138246a4106 Boris Ostrovsky  2019-12-05  3216  
f38a7b75267f1fb Wanpeng Li       2017-12-12  3217  	/*
f38a7b75267f1fb Wanpeng Li       2017-12-12  3218  	 * Doing a TLB flush here, on the guest's behalf, can avoid
f38a7b75267f1fb Wanpeng Li       2017-12-12  3219  	 * expensive IPIs.
f38a7b75267f1fb Wanpeng Li       2017-12-12  3220  	 */
66570e966dd9cb4 Oliver Upton     2020-08-18  3221  	if (guest_pv_has(vcpu, KVM_FEATURE_PV_TLB_FLUSH)) {
af3511ff7fa2107 Lai Jiangshan    2021-06-01  3222  		u8 st_preempted = xchg(&st->preempted, 0);
af3511ff7fa2107 Lai Jiangshan    2021-06-01  3223  
b382f44e98506bc Wanpeng Li       2019-08-05  3224  		trace_kvm_pv_tlb_flush(vcpu->vcpu_id,
af3511ff7fa2107 Lai Jiangshan    2021-06-01  3225  				       st_preempted & KVM_VCPU_FLUSH_TLB);
af3511ff7fa2107 Lai Jiangshan    2021-06-01  3226  		if (st_preempted & KVM_VCPU_FLUSH_TLB)
0baedd792713063 Vitaly Kuznetsov 2020-03-25  3227  			kvm_vcpu_flush_tlb_guest(vcpu);
1eff0ada88b48e4 Wanpeng Li       2021-05-18  3228  	} else {
1eff0ada88b48e4 Wanpeng Li       2021-05-18  3229  		st->preempted = 0;
66570e966dd9cb4 Oliver Upton     2020-08-18  3230  	}
0b9f6c4615c993d Pan Xinhui       2016-11-02  3231  
a6bd811f1209fe1 Boris Ostrovsky  2019-12-06  3232  	vcpu->arch.st.preempted = 0;
35f3fae17849793 Wanpeng Li       2016-05-03  3233  
b043138246a4106 Boris Ostrovsky  2019-12-05  3234  	if (st->version & 1)
b043138246a4106 Boris Ostrovsky  2019-12-05  3235  		st->version += 1;  /* first time write, random junk */
35f3fae17849793 Wanpeng Li       2016-05-03  3236  
b043138246a4106 Boris Ostrovsky  2019-12-05  3237  	st->version += 1;
35f3fae17849793 Wanpeng Li       2016-05-03  3238  
35f3fae17849793 Wanpeng Li       2016-05-03  3239  	smp_wmb();
35f3fae17849793 Wanpeng Li       2016-05-03  3240  
b043138246a4106 Boris Ostrovsky  2019-12-05  3241  	st->steal += current->sched_info.run_delay -
c54cdf141c40a51 Liang Chen       2016-03-16  3242  		vcpu->arch.st.last_steal;
c54cdf141c40a51 Liang Chen       2016-03-16  3243  	vcpu->arch.st.last_steal = current->sched_info.run_delay;
35f3fae17849793 Wanpeng Li       2016-05-03  3244  
35f3fae17849793 Wanpeng Li       2016-05-03  3245  	smp_wmb();
35f3fae17849793 Wanpeng Li       2016-05-03  3246  
b043138246a4106 Boris Ostrovsky  2019-12-05  3247  	st->version += 1;
c9aaa8957f203bd Glauber Costa    2011-07-11  3248  
b043138246a4106 Boris Ostrovsky  2019-12-05 @3249  	kvm_unmap_gfn(vcpu, &map, &vcpu->arch.st.cache, true, false);
c9aaa8957f203bd Glauber Costa    2011-07-11  3250  }
c9aaa8957f203bd Glauber Costa    2011-07-11  3251  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 66021 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 5/6] KVM: x86/xen: Maintain valid mapping of Xen shared_info page
  2021-11-01 19:03 ` [PATCH v2 5/6] KVM: x86/xen: Maintain valid mapping of Xen shared_info page David Woodhouse
  2021-11-02  1:23   ` kernel test robot
@ 2021-11-04 19:05   ` David Woodhouse
  1 sibling, 0 replies; 12+ messages in thread
From: David Woodhouse @ 2021-11-04 19:05 UTC (permalink / raw)
  To: kvm
  Cc: Paolo Bonzini, Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li,
	Jim Mattson, Joerg Roedel, Joao Martins, Ankur Arora,
	KarimAllah Raslan

[-- Attachment #1: Type: text/plain, Size: 2007 bytes --]

On Mon, 2021-11-01 at 19:03 +0000, David Woodhouse wrote:
> @@ -1588,6 +1589,28 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
>  {
>         bool flush = false;
>  
> +       if (static_branch_unlikely(&kvm_xen_enabled.key)) {
> +               write_lock(&kvm->arch.xen.shinfo_lock);
> +
> +               if (kvm->arch.xen.shared_info &&
> +                   kvm->arch.xen.shinfo_gfn >= range->start &&
> +                   kvm->arch.xen.shinfo_cache.gfn < range->end) {
> +                       /*
> +                        * If kvm_xen_shared_info_init() had *finished* mapping the
> +                        * page and assigned the pointer for real, then mark the page
> +                        * dirty now instead of via the eventual cache teardown.
> +                        */
> +                       if (kvm->arch.xen.shared_info != KVM_UNMAPPED_PAGE) {
> +                               kvm_set_pfn_dirty(kvm->arch.xen.shinfo_cache.pfn);
> +                               kvm->arch.xen.shinfo_cache.dirty = false;
> +                       }
> +
> +                       kvm->arch.xen.shared_info = NULL;
> +               }
> +
> +               write_unlock(&kvm->arch.xen.shinfo_lock);
> +       }
> +
>         if (kvm_memslots_have_rmaps(kvm))
>                 flush = kvm_handle_gfn_range(kvm, range, kvm_unmap_rmapp);

If I could find a way to ditch that rwlock and use RCU for this, then
I'd be fairly much OK with making it a generic facility and using it
for other things like nesting and maybe even the steal time. 

But I don't think we *can* always sleep in the MMU notifier, so we
can't call synchronize_srcu(), and I can't see how to ditch that
rwlock.

Which means I'm slightly less happy about offering it as a generic
facility, and I think it needs to be a special case for Xen which
really *does* need to deliver interrupts to the guest shinfo page from
IRQ context without current->mm == kvm->mm.

[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 5174 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2021-11-04 19:06 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-01 19:03 [PATCH v2 0/6] KVM: x86/xen: Add in-kernel Xen event channel delivery David Woodhouse
2021-11-01 19:03 ` [PATCH v2 1/6] KVM: x86/xen: Fix get_attr of KVM_XEN_ATTR_TYPE_SHARED_INFO David Woodhouse
2021-11-01 19:03 ` [PATCH v2 2/6] KVM: selftests: Add event channel upcall support to xen_shinfo_test David Woodhouse
2021-11-01 19:03 ` [PATCH v2 3/6] KVM: x86/xen: Use sizeof_field() instead of open-coding it David Woodhouse
2021-11-01 19:03 ` [PATCH v2 4/6] KVM: Fix kvm_map_gfn()/kvm_unmap_gfn() to take a kvm as their names imply David Woodhouse
2021-11-02  3:12   ` kernel test robot
2021-11-02 22:33   ` kernel test robot
2021-11-01 19:03 ` [PATCH v2 5/6] KVM: x86/xen: Maintain valid mapping of Xen shared_info page David Woodhouse
2021-11-02  1:23   ` kernel test robot
2021-11-04 19:05   ` David Woodhouse
2021-11-01 19:03 ` [PATCH v2 6/6] KVM: x86/xen: Add KVM_IRQ_ROUTING_XEN_EVTCHN and event channel delivery David Woodhouse
2021-11-02  0:25   ` David Woodhouse

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