[PATCH RFC 12/39] KVM: x86/xen: store virq when assigning evtchn

From: Joao Martins
Date: Wed Feb 20 2019 - 15:17:51 EST


Enable virq offload to the hypervisor. The primary user for this is
the timer virq.

Signed-off-by: Joao Martins <joao.m.martins@xxxxxxxxxx>
---
arch/x86/include/asm/kvm_host.h | 2 ++
arch/x86/kvm/xen.c | 23 ++++++++++++++++++++++-
2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index f31fcaf8fa7c..92b76127eb43 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -550,6 +550,8 @@ struct kvm_vcpu_xen {
gpa_t steal_time_addr;
struct vcpu_runstate_info *steal_time;
struct kvm_xen_callback cb;
+#define KVM_XEN_NR_VIRQS 24
+ unsigned int virq_to_port[KVM_XEN_NR_VIRQS];
};

struct kvm_vcpu_arch {
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index 1fbdfa7c4356..42c1fe01600d 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -101,6 +101,20 @@ static void kvm_xen_evtchnfd_upcall(struct kvm_vcpu *vcpu, struct evtchnfd *e)
kvm_xen_do_upcall(vcpu->kvm, e->vcpu, vx->cb.via, vx->cb.vector, 0);
}

+void kvm_xen_set_virq(struct kvm *kvm, struct evtchnfd *evt)
+{
+ int virq = evt->virq.type;
+ struct kvm_vcpu_xen *vcpu_xen;
+ struct kvm_vcpu *vcpu;
+
+ vcpu = kvm_get_vcpu(kvm, evt->vcpu);
+ if (!vcpu)
+ return;
+
+ vcpu_xen = vcpu_to_xen_vcpu(vcpu);
+ vcpu_xen->virq_to_port[virq] = evt->port;
+}
+
int kvm_xen_set_evtchn(struct kvm_kernel_irq_routing_entry *e,
struct kvm *kvm, int irq_source_id, int level,
bool line_status)
@@ -620,6 +634,10 @@ static int kvm_xen_eventfd_assign(struct kvm *kvm, struct idr *port_to_evt,
return PTR_ERR(eventfd);
}

+ if (args->type == XEN_EVTCHN_TYPE_VIRQ &&
+ args->virq.type >= KVM_XEN_NR_VIRQS)
+ return -EINVAL;
+
evtchnfd = kzalloc(sizeof(struct evtchnfd), GFP_KERNEL);
if (!evtchnfd)
return -ENOMEM;
@@ -636,8 +654,11 @@ static int kvm_xen_eventfd_assign(struct kvm *kvm, struct idr *port_to_evt,
GFP_KERNEL);
mutex_unlock(port_lock);

- if (ret >= 0)
+ if (ret >= 0) {
+ if (evtchnfd->type == XEN_EVTCHN_TYPE_VIRQ)
+ kvm_xen_set_virq(kvm, evtchnfd);
return 0;
+ }

if (ret == -ENOSPC)
ret = -EEXIST;
--
2.11.0