From ae8d2afc5f73beecb47675c043afc1f8608320b8 Mon Sep 17 00:00:00 2001 From: Joao Martins Date: Thu, 6 Sep 2018 06:54:33 -0400 Subject: [PATCH] i386/xen: handle EVTCHNOP_alloc_unbound 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 --- linux-headers/linux/kvm.h | 1 + target/i386/xen-proto.h | 6 +++-- target/i386/xen.c | 3 +++ target/i386/xen_evtchn.c | 53 +++++++++++++++++++++++++++++++++++++-- target/i386/xen_evtchn.h | 1 + 5 files changed, 60 insertions(+), 4 deletions(-) diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index 487525d15e..8409d197fb 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -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; diff --git a/target/i386/xen-proto.h b/target/i386/xen-proto.h index d5b20abe2b..cf73f12ae6 100644 --- a/target/i386/xen-proto.h +++ b/target/i386/xen-proto.h @@ -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; diff --git a/target/i386/xen.c b/target/i386/xen.c index 10c94f2dd0..8f523b58b8 100644 --- a/target/i386/xen.c +++ b/target/i386/xen.c @@ -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; diff --git a/target/i386/xen_evtchn.c b/target/i386/xen_evtchn.c index e95dee740e..4e19bbc554 100644 --- a/target/i386/xen_evtchn.c +++ b/target/i386/xen_evtchn.c @@ -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; } diff --git a/target/i386/xen_evtchn.h b/target/i386/xen_evtchn.h index c6274f4f68..dce83d112e 100644 --- a/target/i386/xen_evtchn.h +++ b/target/i386/xen_evtchn.h @@ -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); -- 2.50.1