]> www.infradead.org Git - users/dwmw2/qemu.git/commitdiff
i386/xen: handle EVTCHNOP_alloc_unbound
authorJoao Martins <joao.m.martins@oracle.com>
Thu, 6 Sep 2018 10:54:33 +0000 (06:54 -0400)
committerJoao Martins <joao.m.martins@oracle.com>
Tue, 19 Feb 2019 14:00:57 +0000 (09:00 -0500)
Also add bounds check for event channel ports and also do not set a
eventfd for a Dom0 unbound port.

When running xenstored in Domain-0 we may have a remote domid of 0
(other than DOMID_SELF) which is the case when xenstored runs on
Domain-0. In such cases remote_dom being 0 is valid.

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

index 487525d15e0d9ea8dedad06a6e4cbadf3fda16fe..8409d197fb10d364e7b73ccffcfbd8b818806652 100644 (file)
@@ -1485,6 +1485,7 @@ struct kvm_xen_hvm_attr {
 #define XEN_EVTCHN_TYPE_VIRQ      0
 #define XEN_EVTCHN_TYPE_IPI       1
 #define XEN_EVTCHN_TYPE_INTERDOM  2
+#define XEN_EVTCHN_TYPE_UNBOUND   3
                        __u32 type;
                        __u32 port;
                        __u32 vcpu;
index d5b20abe2b0ae0b9b47855cb1f508baa6b932920..cf73f12ae6a638ddb21dec3fadc919e4decadd03 100644 (file)
@@ -26,9 +26,11 @@ typedef struct XenEvtChn {
 #define XEN_EVTCHN_TYPE_VIRQ      0
 #define XEN_EVTCHN_TYPE_IPI       1
 #define XEN_EVTCHN_TYPE_INTERDOM  2
+#define XEN_EVTCHN_TYPE_UNBOUND   3
   int type;
-#define XEN_EVTCHN_STATE_FREE  0
-#define XEN_EVTCHN_STATE_INUSE 1
+#define XEN_EVTCHN_STATE_FREE     0
+#define XEN_EVTCHN_STATE_INUSE    1
+#define XEN_EVTCHN_STATE_UNBOUND  2
   int state;
 } XenEvtChn;
 
index 10c94f2dd038410965bb08f968e1f22c27b4e385..8f523b58b873bd6f8bc6f4c029ece286a327c4aa 100644 (file)
@@ -745,6 +745,9 @@ static int kvm_xen_hcall_evtchn_op(struct kvm_xen_exit *exit, X86CPU *cpu,
     case EVTCHNOP_bind_virq:
         err = kvm_xen_evtchn_bind_virq(cpu, eop);
         break;
+    case EVTCHNOP_alloc_unbound:
+        err = kvm_xen_evtchn_alloc_unbound(cpu, eop);
+        break;
     case EVTCHNOP_close:
         err = kvm_xen_evtchn_close(cpu, eop);
         break;
index e95dee740e3734036450b952290de699012d01e6..4e19bbc554588de8b1f48a7fe8525e3aac880a13 100644 (file)
@@ -135,7 +135,8 @@ int kvm_xen_evtchn_init(XenState *xen_state)
 
 static struct XenEvtChn *evtchn_from_port(int port)
 {
-    if (port <= 0 || !group_from_port(port)) {
+    if (port <= 0 || (groupid_from_port(port) >= EVTCHN_MAX_GROUPS) ||
+        !group_from_port(port)) {
         return NULL;
     }
 
@@ -251,7 +252,8 @@ static int __kvm_set_xen_event(KVMState *s, XenEvtChn *e,
 
     if (e->type == XEN_EVTCHN_TYPE_VIRQ) {
         xenevfd.virq.type = e->virq;
-    } else if (e->type == XEN_EVTCHN_TYPE_INTERDOM) {
+    } else if ((e->type == XEN_EVTCHN_TYPE_INTERDOM) ||
+               (e->type == XEN_EVTCHN_TYPE_UNBOUND)) {
         xenevfd.remote.domid = e->remote_dom;
         xenevfd.remote.port = e->remote_port;
     }
@@ -384,6 +386,52 @@ int kvm_xen_evtchn_bind_virq(X86CPU *cpu, void *arg)
     return 0;
 }
 
+int kvm_xen_evtchn_alloc_unbound(X86CPU *cpu, void *arg)
+{
+    struct evtchn_alloc_unbound *out = arg;
+    struct evtchn_alloc_unbound alloc;
+    struct XenEvtChn *evtchn;
+    int default_vcpu = 0;
+    CPUState *dest;
+    int r;
+
+    memcpy(&alloc, arg, sizeof(alloc));
+
+    dest = qemu_get_cpu(default_vcpu);
+    if (!dest) {
+        return -EINVAL;
+    }
+
+    evtchn = alloc_evtchn(CPU(cpu)->xen_state);
+    if (!evtchn) {
+        return -ENOMEM;
+    }
+
+    if (alloc.remote_dom == DOMID_SELF) {
+        alloc.remote_dom = dest->xen_state->domid;
+    }
+    if (alloc.dom == DOMID_SELF) {
+        alloc.dom = dest->xen_state->domid;
+    }
+
+    evtchn->type = XEN_EVTCHN_TYPE_UNBOUND;
+    evtchn->remote_dom = alloc.remote_dom;
+    evtchn->notify_vcpu_id = default_vcpu;
+    evtchn->state = XEN_EVTCHN_STATE_UNBOUND;
+
+    if (evtchn->remote_dom >= 0) {
+        r = kvm_set_xen_event(dest->kvm_state, evtchn, NULL);
+        if (r) {
+            evtchn->state = XEN_EVTCHN_STATE_FREE;
+            return -EINVAL;
+        }
+    }
+
+    out->port = evtchn->port;
+
+    return 0;
+}
+
 int kvm_xen_evtchn_close(X86CPU *cpu, void *arg)
 {
     struct evtchn_close close;
@@ -481,6 +529,7 @@ int kvm_xen_evtchn_send(X86CPU *cpu, void *arg)
 
     trace_kvm_xen_evtchn_send(CPU(cpu)->cpu_index, evtchn->notify_vcpu_id,
                               send.port);
+
     return 0;
 }
 
index c6274f4f6805005d7fc4339ea54bc0df2cb68614..dce83d112e2d0aca73b9baa52de351d62783af29 100644 (file)
@@ -20,6 +20,7 @@ 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_bind_interdomain(X86CPU *cpu, void *arg);
+int kvm_xen_evtchn_alloc_unbound(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);