#define KVM_CAP_MANUAL_DIRTY_LOG_PROTECT 166
#define KVM_CAP_HYPERV_CPUID 167
#define KVM_CAP_XEN_HVM_GUEST 168
+#define KVM_CAP_XEN_HVM_EVTCHN 169
#ifdef KVM_CAP_IRQ_ROUTING
__u32 vcpu;
__u64 gpa;
} vcpu_attr;
+ struct kvm_xen_eventfd {
+
+#define XEN_EVTCHN_TYPE_VIRQ 0
+#define XEN_EVTCHN_TYPE_IPI 1
+ __u32 type;
+ __u32 port;
+ __u32 vcpu;
+ __s32 fd;
+
+#define KVM_XEN_EVENTFD_DEASSIGN (1 << 0)
+#define KVM_XEN_EVENTFD_UPDATE (1 << 1)
+ __u32 flags;
+ union {
+ struct {
+ __u8 type;
+ } virq;
+ __u32 padding[2];
+ };
+ } evtchn;
} u;
};
#define KVM_XEN_ATTR_TYPE_VCPU_INFO 0x1
#define KVM_XEN_ATTR_TYPE_VCPU_TIME_INFO 0x2
#define KVM_XEN_ATTR_TYPE_VCPU_RUNSTATE 0x3
+/* Available with KVM_CAP_XEN_HVM_EVTCHN */
+#define KVM_XEN_ATTR_TYPE_EVTCHN 0x4
/* Secure Encrypted Virtualization command */
enum sev_cmd_id {
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_set(int flags, unsigned int port, int port_type) "flags 0x%x port %u port_type %d"
kvm_xen_evtchn_send(int cpu, int dest, unsigned int port) "cpu %d notify_cpu %d port %u"
xen_vcpu->virq_to_evtchn[evtchn->virq] = evtchn;
}
+static int __kvm_set_xen_event(KVMState *s, XenEvtChn *e,
+ EventNotifier *n, unsigned int flags)
+{
+ struct kvm_xen_eventfd xenevfd = {
+ .port = e->port,
+ .vcpu = e->notify_vcpu_id,
+ .type = e->type,
+ .fd = n ? event_notifier_get_fd(n) : -1,
+ .flags = flags,
+ };
+ struct kvm_xen_hvm_attr xha;
+ int r;
+
+ if (!kvm_check_extension(s, KVM_CAP_XEN_HVM_EVTCHN)) {
+ return -ENOSYS;
+ }
+
+ if (e->type == XEN_EVTCHN_TYPE_VIRQ) {
+ xenevfd.virq.type = e->virq;
+ }
+
+ xha.type = KVM_XEN_ATTR_TYPE_EVTCHN;
+ xha.u.evtchn = xenevfd;
+ r = kvm_vm_ioctl(s, KVM_XEN_HVM_SET_ATTR, &xha);
+ trace_kvm_xen_evtchn_set(flags, xenevfd.port, xenevfd.type);
+ return r;
+}
+
+static int kvm_set_xen_event(KVMState *s, XenEvtChn *e, EventNotifier *n)
+{
+ return __kvm_set_xen_event(s, e, n, 0);
+}
+
+static int kvm_clear_xen_event(KVMState *s, XenEvtChn *e)
+{
+ return __kvm_set_xen_event(s, e, NULL, KVM_XEN_EVENTFD_DEASSIGN);
+}
+
int kvm_xen_evtchn_bind_ipi(X86CPU *cpu, void *arg)
{
struct evtchn_bind_ipi *out = arg;
evtchn->type = XEN_EVTCHN_TYPE_IPI;
evtchn->notify_vcpu_id = bind_ipi.vcpu;
+ kvm_set_xen_event(dest->kvm_state, evtchn, NULL);
+
out->port = evtchn->port;
return 0;
}
evtchn_2l_clear_pending(cpu, evtchn);
+ kvm_clear_xen_event(CPU(cpu)->kvm_state, evtchn);
evtchn->state = XEN_EVTCHN_STATE_FREE;
evtchn->notify_vcpu_id = 0;