]> www.infradead.org Git - users/dwmw2/qemu.git/commitdiff
i386/xen: handle PV IPI in hypervisor
authorJoao Martins <joao.m.martins@oracle.com>
Mon, 3 Sep 2018 18:38:03 +0000 (14:38 -0400)
committerJoao Martins <joao.m.martins@oracle.com>
Tue, 19 Feb 2019 14:00:57 +0000 (09:00 -0500)
Uses XEN_EVENTFD ioctl to assign a eventfd to an ipi port and
therefore notify the guest. This allows offloading PV IPIs
to hypervisor instead of through Qemu.

Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
linux-headers/linux/kvm.h
target/i386/trace-events
target/i386/xen_evtchn.c

index 364a15b9da156295d853966301c51b87cf44331c..8a9a648c8c704ec42f1edde0278ec403e25ecba6 100644 (file)
@@ -1003,6 +1003,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_MANUAL_DIRTY_LOG_PROTECT 166
 #define KVM_CAP_HYPERV_CPUID 167
 #define KVM_CAP_XEN_HVM_GUEST 168
+#define KVM_CAP_XEN_HVM_EVTCHN 169
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1478,6 +1479,25 @@ struct kvm_xen_hvm_attr {
                        __u32 vcpu;
                        __u64 gpa;
                } vcpu_attr;
+               struct kvm_xen_eventfd {
+
+#define XEN_EVTCHN_TYPE_VIRQ 0
+#define XEN_EVTCHN_TYPE_IPI  1
+                       __u32 type;
+                       __u32 port;
+                       __u32 vcpu;
+                       __s32 fd;
+
+#define KVM_XEN_EVENTFD_DEASSIGN       (1 << 0)
+#define KVM_XEN_EVENTFD_UPDATE         (1 << 1)
+                       __u32 flags;
+                       union {
+                               struct {
+                                       __u8 type;
+                               } virq;
+                               __u32 padding[2];
+                       };
+               } evtchn;
        } u;
 };
 
@@ -1486,6 +1506,8 @@ struct kvm_xen_hvm_attr {
 #define KVM_XEN_ATTR_TYPE_VCPU_INFO         0x1
 #define KVM_XEN_ATTR_TYPE_VCPU_TIME_INFO    0x2
 #define KVM_XEN_ATTR_TYPE_VCPU_RUNSTATE     0x3
+/* Available with KVM_CAP_XEN_HVM_EVTCHN */
+#define KVM_XEN_ATTR_TYPE_EVTCHN            0x4
 
 /* Secure Encrypted Virtualization command */
 enum sev_cmd_id {
index d2aaafeba9944fba64ae593a14c120a9f7983390..f7c47790276221538689bff409077c69884d90b1 100644 (file)
@@ -21,4 +21,5 @@ kvm_xen_hypercall(int cpu, uint64_t input, uint64_t a0, uint64_t a1, uint64_t a2
 kvm_xen_set_shared_info(uint64_t gfn) "shared info at gfn 0x%" PRIx64
 kvm_xen_set_vcpu_attr(int cpu, int type, uint64_t gpa) "vcpu attr cpu %d type %d gpa 0x%" PRIu64
 kvm_xen_set_callback(int cpu, int virq, int vector, int via) "callback vcpu %d virq %d vector %d via %d"
+kvm_xen_evtchn_set(int flags, unsigned int port, int port_type) "flags 0x%x port %u port_type %d"
 kvm_xen_evtchn_send(int cpu, int dest, unsigned int port) "cpu %d notify_cpu %d port %u"
index 2187f38d7c6b55cefdf5b983934227ce69716c8e..e058a9aba2c0aeb32f7909d1e5474d1cf50659ed 100644 (file)
@@ -232,6 +232,44 @@ static void xen_vcpu_set_evtchn(CPUState *cpu, run_on_cpu_data data)
     xen_vcpu->virq_to_evtchn[evtchn->virq] = evtchn;
 }
 
+static int __kvm_set_xen_event(KVMState *s, XenEvtChn *e,
+                               EventNotifier *n, unsigned int flags)
+{
+    struct kvm_xen_eventfd xenevfd = {
+        .port = e->port,
+        .vcpu = e->notify_vcpu_id,
+        .type = e->type,
+        .fd = n ? event_notifier_get_fd(n) : -1,
+        .flags = flags,
+    };
+    struct kvm_xen_hvm_attr xha;
+    int r;
+
+    if (!kvm_check_extension(s, KVM_CAP_XEN_HVM_EVTCHN)) {
+        return -ENOSYS;
+    }
+
+    if (e->type == XEN_EVTCHN_TYPE_VIRQ) {
+        xenevfd.virq.type = e->virq;
+    }
+
+    xha.type = KVM_XEN_ATTR_TYPE_EVTCHN;
+    xha.u.evtchn = xenevfd;
+    r =  kvm_vm_ioctl(s, KVM_XEN_HVM_SET_ATTR, &xha);
+    trace_kvm_xen_evtchn_set(flags, xenevfd.port, xenevfd.type);
+    return r;
+}
+
+static int kvm_set_xen_event(KVMState *s, XenEvtChn *e, EventNotifier *n)
+{
+    return __kvm_set_xen_event(s, e, n, 0);
+}
+
+static int kvm_clear_xen_event(KVMState *s, XenEvtChn *e)
+{
+    return __kvm_set_xen_event(s, e, NULL, KVM_XEN_EVENTFD_DEASSIGN);
+}
+
 int kvm_xen_evtchn_bind_ipi(X86CPU *cpu, void *arg)
 {
     struct evtchn_bind_ipi *out = arg;
@@ -254,6 +292,8 @@ int kvm_xen_evtchn_bind_ipi(X86CPU *cpu, void *arg)
     evtchn->type = XEN_EVTCHN_TYPE_IPI;
     evtchn->notify_vcpu_id = bind_ipi.vcpu;
 
+    kvm_set_xen_event(dest->kvm_state, evtchn, NULL);
+
     out->port = evtchn->port;
 
     return 0;
@@ -308,6 +348,7 @@ int kvm_xen_evtchn_close(X86CPU *cpu, void *arg)
     }
 
     evtchn_2l_clear_pending(cpu, evtchn);
+    kvm_clear_xen_event(CPU(cpu)->kvm_state, evtchn);
 
     evtchn->state = XEN_EVTCHN_STATE_FREE;
     evtchn->notify_vcpu_id = 0;