]> www.infradead.org Git - users/dwmw2/qemu.git/commitdiff
i386/xen: evtchn IPI support
authorJoao Martins <joao.m.martins@oracle.com>
Thu, 30 Aug 2018 18:46:38 +0000 (14:46 -0400)
committerJoao Martins <joao.m.martins@oracle.com>
Tue, 19 Feb 2019 14:00:57 +0000 (09:00 -0500)
IPI event channels are per cpu too and require an additional
hypercall to be implemented which is EVTCHNOP_send used when
a CPU wants to notify a target vcpu.

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

index 0c333d7d36aa2b5168ad18c61cc2f1c509a5d04d..d2aaafeba9944fba64ae593a14c120a9f7983390 100644 (file)
@@ -21,3 +21,4 @@ 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_send(int cpu, int dest, unsigned int port) "cpu %d notify_cpu %d port %u"
index 18adfe2ddd358b81032234caf77b88dd79a1af52..e8f21d5dd900493ee9cd618c0e054d4bc643c6ea 100644 (file)
@@ -22,6 +22,7 @@ typedef struct XenEvtChn {
   int port;
   int virq;
 #define XEN_EVTCHN_TYPE_VIRQ 0
+#define XEN_EVTCHN_TYPE_IPI  1
   int type;
 #define XEN_EVTCHN_STATE_FREE  0
 #define XEN_EVTCHN_STATE_INUSE 1
index 23fda5b1665717ad1ee0d4f8b1aef2a8d465d3ea..92a6a459da026ab22e37bc70a35bebf9791115b3 100644 (file)
@@ -533,6 +533,9 @@ static int kvm_xen_hcall_evtchn_op(struct kvm_xen_exit *exit, X86CPU *cpu,
     }
 
     switch (cmd) {
+    case EVTCHNOP_bind_ipi:
+        err = kvm_xen_evtchn_bind_ipi(cpu, eop);
+        break;
     case EVTCHNOP_bind_virq:
         err = kvm_xen_evtchn_bind_virq(cpu, eop);
         break;
@@ -545,6 +548,9 @@ static int kvm_xen_hcall_evtchn_op(struct kvm_xen_exit *exit, X86CPU *cpu,
     case EVTCHNOP_status:
         err = kvm_xen_evtchn_status(cpu, eop);
         break;
+    case EVTCHNOP_send:
+        err = kvm_xen_evtchn_send(cpu, eop);
+        break;
     /* FIFO ABI only */
     case EVTCHNOP_init_control:
     case EVTCHNOP_expand_array:
@@ -594,7 +600,7 @@ static int kvm_xen_hcall_sched_op(struct kvm_xen_exit *exit, X86CPU *cpu,
     }
 
     exit->u.hcall.result = err;
-    return err;
+    return err ? HCALL_ERR : 0;
 }
 
 static int __kvm_xen_handle_exit(X86CPU *cpu, struct kvm_xen_exit *exit)
index 12c6bd865004895fe0adbe3e1e85d8aaf220262f..4f3f5934d03925763cf60b0eb5d73d876bfe1865 100644 (file)
@@ -21,6 +21,7 @@
 #include "qom/cpu.h"
 #include "xen_evtchn.h"
 #include "xen.h"
+#include "trace.h"
 
 #ifndef __XEN_INTERFACE_VERSION__
 #define __XEN_INTERFACE_VERSION__ 0x00040400
@@ -231,6 +232,33 @@ static void xen_vcpu_set_evtchn(CPUState *cpu, run_on_cpu_data data)
     xen_vcpu->virq_to_evtchn[evtchn->virq] = evtchn;
 }
 
+int kvm_xen_evtchn_bind_ipi(X86CPU *cpu, void *arg)
+{
+    struct evtchn_bind_ipi *out = arg;
+    struct evtchn_bind_ipi bind_ipi;
+    struct XenEvtChn *evtchn;
+    CPUState *dest;
+
+    memcpy(&bind_ipi, arg, sizeof(bind_ipi));
+
+    dest = qemu_get_cpu(bind_ipi.vcpu);
+    if (!dest) {
+        return -EINVAL;
+    }
+
+    evtchn = alloc_evtchn(CPU(cpu)->xen_state);
+    if (!evtchn) {
+        return -ENOMEM;
+    }
+
+    evtchn->type = XEN_EVTCHN_TYPE_IPI;
+    evtchn->notify_vcpu_id = bind_ipi.vcpu;
+
+    out->port = evtchn->port;
+
+    return 0;
+}
+
 int kvm_xen_evtchn_bind_virq(X86CPU *cpu, void *arg)
 {
     XenCPUState *destxcpu;
@@ -325,6 +353,9 @@ int kvm_xen_evtchn_status(X86CPU *cpu, void *arg)
     status.vcpu = evtchn->notify_vcpu_id;
 
     switch (type) {
+    case XEN_EVTCHN_TYPE_IPI:
+        status.status = EVTCHNSTAT_ipi;
+        break;
     case XEN_EVTCHN_TYPE_VIRQ:
         status.status = EVTCHNSTAT_virq;
         status.u.virq = evtchn->virq;
@@ -338,6 +369,31 @@ int kvm_xen_evtchn_status(X86CPU *cpu, void *arg)
     return 0;
 }
 
+int kvm_xen_evtchn_send(X86CPU *cpu, void *arg)
+{
+    struct evtchn_send send;
+    struct XenEvtChn *evtchn;
+    CPUState *dest;
+
+    memcpy(&send, arg, sizeof(send));
+
+    evtchn = evtchn_from_port(send.port);
+    if (!evtchn) {
+        return -ENOENT;
+    }
+
+    dest = qemu_get_cpu(evtchn->notify_vcpu_id);
+    if (!dest) {
+        return -EINVAL;
+    }
+
+    evtchn_2l_set_pending(X86_CPU(dest), evtchn);
+
+    trace_kvm_xen_evtchn_send(CPU(cpu)->cpu_index, evtchn->notify_vcpu_id,
+                              send.port);
+    return 0;
+}
+
 int kvm_xen_evtchn_vcpu_init(X86CPU *cpu, struct vcpu_info *vcpu)
 {
     int i;
@@ -375,12 +431,18 @@ void hmp_xen_event_list(Monitor *mon, const QDict *qdict)
                 continue;
             }
 
-            monitor_printf(mon, "port %4u [%c/%c/%d] vcpu %d\n",
+            monitor_printf(mon, "port %4u [%c/%c/%d] vcpu %d type %d ",
                            evtchn->port,
                            evtchn_2l_is_pending(x86_cpu, evtchn) ? 'p' : ' ',
                            evtchn_2l_is_masked(x86_cpu, evtchn) ? 'm' : ' ',
                            evtchn_2l_state(x86_cpu, evtchn),
-                           evtchn->notify_vcpu_id);
+                           evtchn->notify_vcpu_id, evtchn->type);
+
+            if (evtchn->type == XEN_EVTCHN_TYPE_VIRQ) {
+                monitor_printf(mon, "virq %d ", evtchn->virq);
+            }
+
+            monitor_printf(mon, "\n");
         }
     }
 }
index 429dab5d7b916ba0eac8712e3237c5ea78f12dd3..72af31a18c3bb734c71c6649f224d551f4cca0b7 100644 (file)
 
 int kvm_xen_evtchn_init(XenState *xen_state);
 
+int kvm_xen_evtchn_bind_ipi(X86CPU *cpu, void *arg);
 int kvm_xen_evtchn_bind_virq(X86CPU *cpu, void *arg);
 int kvm_xen_evtchn_close(X86CPU *cpu, void *arg);
 int kvm_xen_evtchn_unmask(X86CPU *cpu, void *arg);
 int kvm_xen_evtchn_status(X86CPU *cpu, void *arg);
+int kvm_xen_evtchn_send(X86CPU *cpu, void *arg);
 int kvm_xen_evtchn_vcpu_init(X86CPU *cpu, struct vcpu_info *info);
 
 #endif