From: Joao Martins Date: Thu, 30 Aug 2018 18:46:38 +0000 (-0400) Subject: i386/xen: evtchn IPI support X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=7d0dfc6fba82f3ff5c5ba93b052c20a27f676134;p=users%2Fdwmw2%2Fqemu.git i386/xen: evtchn IPI support 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 --- diff --git a/target/i386/trace-events b/target/i386/trace-events index 0c333d7d36..d2aaafeba9 100644 --- a/target/i386/trace-events +++ b/target/i386/trace-events @@ -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" diff --git a/target/i386/xen-proto.h b/target/i386/xen-proto.h index 18adfe2ddd..e8f21d5dd9 100644 --- a/target/i386/xen-proto.h +++ b/target/i386/xen-proto.h @@ -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 diff --git a/target/i386/xen.c b/target/i386/xen.c index 23fda5b166..92a6a459da 100644 --- a/target/i386/xen.c +++ b/target/i386/xen.c @@ -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) diff --git a/target/i386/xen_evtchn.c b/target/i386/xen_evtchn.c index 12c6bd8650..4f3f5934d0 100644 --- a/target/i386/xen_evtchn.c +++ b/target/i386/xen_evtchn.c @@ -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"); } } } diff --git a/target/i386/xen_evtchn.h b/target/i386/xen_evtchn.h index 429dab5d7b..72af31a18c 100644 --- a/target/i386/xen_evtchn.h +++ b/target/i386/xen_evtchn.h @@ -17,10 +17,12 @@ 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