[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[mini-os master] Mini-OS: call event handlers always with interrupts off



commit fbf15891cc38eb493c81b02964ba8c48f7ff6f63
Author:     Juergen Gross <jgross@xxxxxxxx>
AuthorDate: Wed Dec 13 10:49:40 2023 +0100
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Wed Dec 13 10:49:40 2023 +0100

    Mini-OS: call event handlers always with interrupts off
    
    When unmasking an event channel the associated event handler can be
    called with interrupts enabled when not running as a PV guest.
    
    This can result in hard to debug races in case e.g. a handler is
    registered for multiple events or when the handler is not using a lock
    as it assumes to have interrupts disabled.
    
    Instead of using the PV interrupt disabling points just before calling
    the handler, do the disabling once at the very start of
    force_evtchn_callback().
    
    Replace the evtchn_upcall_mask test in unmask_evtchn() with the more
    appropriate irqs_disabled() test.
    
    As a precaution add a test to do_hypervisor_callback() that interrupts
    are really disabled and crash in case this is not true.
    
    Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
    Reviewed-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxx>
---
 hypervisor.c | 26 +++++++++-----------------
 1 file changed, 9 insertions(+), 17 deletions(-)

diff --git a/hypervisor.c b/hypervisor.c
index f2cbbc1..5309daa 100644
--- a/hypervisor.c
+++ b/hypervisor.c
@@ -102,6 +102,8 @@ void do_hypervisor_callback(struct pt_regs *regs)
     shared_info_t *s = HYPERVISOR_shared_info;
     vcpu_info_t   *vcpu_info = &s->vcpu_info[cpu];
 
+    BUG_ON(!irqs_disabled());
+
     in_callback = 1;
    
     vcpu_info->evtchn_upcall_pending = 0;
@@ -131,27 +133,19 @@ void do_hypervisor_callback(struct pt_regs *regs)
 
 void force_evtchn_callback(void)
 {
-#ifdef XEN_HAVE_PV_UPCALL_MASK
-    int save;
-#endif
     vcpu_info_t *vcpu;
+    unsigned long flags;
+
+    local_irq_save(flags);
+
     vcpu = &HYPERVISOR_shared_info->vcpu_info[smp_processor_id()];
-#ifdef XEN_HAVE_PV_UPCALL_MASK
-    save = vcpu->evtchn_upcall_mask;
-#endif
 
     while (vcpu->evtchn_upcall_pending) {
-#ifdef XEN_HAVE_PV_UPCALL_MASK
-        vcpu->evtchn_upcall_mask = 1;
-#endif
-        barrier();
         do_hypervisor_callback(NULL);
         barrier();
-#ifdef XEN_HAVE_PV_UPCALL_MASK
-        vcpu->evtchn_upcall_mask = save;
-        barrier();
-#endif
     };
+
+    local_irq_restore(flags);
 }
 
 inline void mask_evtchn(uint32_t port)
@@ -177,9 +171,7 @@ inline void unmask_evtchn(uint32_t port)
               &vcpu_info->evtchn_pending_sel) )
     {
         vcpu_info->evtchn_upcall_pending = 1;
-#ifdef XEN_HAVE_PV_UPCALL_MASK
-        if ( !vcpu_info->evtchn_upcall_mask )
-#endif
+        if ( !irqs_disabled() )
             force_evtchn_callback();
     }
 }
--
generated by git-patchbot for /home/xen/git/mini-os.git#master



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.