}
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;
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:
}
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)
#include "qom/cpu.h"
#include "xen_evtchn.h"
#include "xen.h"
+#include "trace.h"
#ifndef __XEN_INTERFACE_VERSION__
#define __XEN_INTERFACE_VERSION__ 0x00040400
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;
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;
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;
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");
}
}
}
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