From: Ankur Arora <ankur.a.arora@xxxxxxxxxx> Handle hypercall to unmasks event channel ports. A subtlety here is that we deliver an upcall if an actual unmask happened and the event channel was pending (and if the vcpu-wide evtchn_pending_sel was not already marked pending.) Co-developed-by: Joao Martins <joao.m.martins@xxxxxxxxxx> Signed-off-by: Ankur Arora <ankur.a.arora@xxxxxxxxxx> Signed-off-by: Joao Martins <joao.m.martins@xxxxxxxxxx> --- arch/x86/kvm/xen.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c index 420e3ebb66bc..1988ed3866bf 100644 --- a/arch/x86/kvm/xen.c +++ b/arch/x86/kvm/xen.c @@ -2102,6 +2102,29 @@ static int shim_hcall_evtchn_send(struct kvm_xen *dom0, struct evtchn_send *snd) return 0; } +static int shim_hcall_evtchn_unmask(struct kvm_xen *dom0, int port) +{ + struct shared_info *s = HYPERVISOR_shared_info; + struct evtchnfd *evtchnfd; + struct vcpu_info *v; + + evtchnfd = idr_find(&dom0->port_to_evt, port); + if (!evtchnfd) + return -ENOENT; + + v = per_cpu(xen_vcpu, evtchnfd->vcpu); + + if (test_and_clear_bit(port, (unsigned long *) s->evtchn_mask) && + test_bit(port, (unsigned long *) s->evtchn_pending) && + !test_and_set_bit(port / BITS_PER_EVTCHN_WORD, + (unsigned long *) &v->evtchn_pending_sel)) { + kvm_xen_evtchn_2l_vcpu_set_pending(v); + return kvm_xen_evtchn_call_function(evtchnfd); + } + + return 0; +} + static int shim_hcall_evtchn(int op, void *p) { int ret; @@ -2151,6 +2174,13 @@ static int shim_hcall_evtchn(int op, void *p) un->port = evt.port; break; } + case EVTCHNOP_unmask: { + struct evtchn_unmask *unmask; + + unmask = (struct evtchn_unmask *) p; + ret = shim_hcall_evtchn_unmask(xen_shim, unmask->port); + break; + } case EVTCHNOP_send: { struct evtchn_send *send; -- 2.11.0