]> xenbits.xensource.com Git - people/iwj/xen.git/commitdiff
x86/upcall: inject a spurious event after setting upcall vector
authorRoger Pau Monné <roger.pau@citrix.com>
Fri, 12 Jan 2018 16:40:59 +0000 (16:40 +0000)
committerRoger Pau Monne <roger.pau@citrix.com>
Fri, 12 Jan 2018 16:40:59 +0000 (16:40 +0000)
In case the vCPU has pending events to inject. This fixes a bug that
happened if the guest mapped the vcpu info area using
VCPUOP_register_vcpu_info without having setup the event channel
upcall, and then setup the upcall vector.

In this scenario the guest would not receive any upcalls, because the
call to VCPUOP_register_vcpu_info would have marked the vCPU as having
pending events, but the vector could not be injected because it was
not yet setup.

This has not caused issues so far because all the consumers first
setup the vector callback and then map the vcpu info page, but there's
no limitation that prevents doing it in the inverse order.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
xen/arch/x86/hvm/hvm.c
xen/arch/x86/hvm/irq.c

index 53b99c36e614c6079aaf68a4e4f3c7658d34aac1..68b684bed0f2c5edbf7cffec0478d5f54b195cc0 100644 (file)
@@ -5078,6 +5078,7 @@ static int hvmop_set_evtchn_upcall_vector(
     printk(XENLOG_G_INFO "%pv: upcall vector %02x\n", v, op.vector);
 
     v->arch.hvm_vcpu.evtchn_upcall_vector = op.vector;
+    hvm_assert_evtchn_irq(v);
     return 0;
 }
 
index e59711467437f47889840707493304b6b11de1bc..34814a2525dc19e67efd053b6a44ec31cf143f70 100644 (file)
@@ -324,6 +324,7 @@ void hvm_set_callback_via(struct domain *d, uint64_t via)
     struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
     unsigned int gsi=0, pdev=0, pintx=0;
     uint8_t via_type;
+    struct vcpu *v;
 
     via_type = (uint8_t)MASK_EXTR(via, HVM_PARAM_CALLBACK_IRQ_TYPE_MASK) + 1;
     if ( ((via_type == HVMIRQ_callback_gsi) && (via == 0)) ||
@@ -386,6 +387,10 @@ void hvm_set_callback_via(struct domain *d, uint64_t via)
 
     spin_unlock(&d->arch.hvm_domain.irq_lock);
 
+    for_each_vcpu ( d, v )
+        if ( is_vcpu_online(v) )
+            hvm_assert_evtchn_irq(v);
+
 #ifndef NDEBUG
     printk(XENLOG_G_INFO "Dom%u callback via changed to ", d->domain_id);
     switch ( via_type )