Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/xen/xen Fix theoretical race in xen_evtchn_trymask.



details:   https://anonhg.NetBSD.org/src/rev/feceaa71fb72
branches:  trunk
changeset: 827736:feceaa71fb72
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Fri Nov 10 19:24:17 2017 +0000

description:
Fix theoretical race in xen_evtchn_trymask.

This now matches ioapic_trymask:

- Caller masks CPU interrupts while the PIC's interrupts are unmasked.
- Trymask masks the PIC's interrupts, and tests whether any were
  pending that we missed because the CPU interrupts are masked.

  ==> If there were any pending, trymask unmasks PIC's interrupts and
      returns false.

  ==> If not, interrupts are masked on the PIC and CPU and there were
      none pending and trymask returns true.

No functional change right now because cpu_intr_redistribute is
currently disabled on Xen.

ok cherry

diffstat:

 sys/arch/xen/xen/evtchn.c |  41 +++++++++++++++++++++++++++++------------
 1 files changed, 29 insertions(+), 12 deletions(-)

diffs (68 lines):

diff -r a0c4c12ac1e7 -r feceaa71fb72 sys/arch/xen/xen/evtchn.c
--- a/sys/arch/xen/xen/evtchn.c Fri Nov 10 18:08:11 2017 +0000
+++ b/sys/arch/xen/xen/evtchn.c Fri Nov 10 19:24:17 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: evtchn.c,v 1.74 2017/11/04 10:26:14 cherry Exp $       */
+/*     $NetBSD: evtchn.c,v 1.75 2017/11/10 19:24:17 riastradh Exp $    */
 
 /*
  * Copyright (c) 2006 Manuel Bouyer.
@@ -54,7 +54,7 @@
 
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.74 2017/11/04 10:26:14 cherry Exp $");
+__KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.75 2017/11/10 19:24:17 riastradh Exp $");
 
 #include "opt_xen.h"
 #include "isa.h"
@@ -505,22 +505,39 @@
        xen_atomic_clear_bit(&ci->ci_evtmask[0], evtchn);
 }
 
+/*
+ * xen_evtchn_trymask(pic, pin)
+ *
+ *     If there are interrupts pending on the bus-shared pic, return
+ *     false.  Otherwise, mask interrupts on the bus-shared pic and
+ *     return true.
+ */
 static bool
 xen_evtchn_trymask(struct pic *pic, int pin)
 {
-       volatile shared_info_t *s = HYPERVISOR_shared_info;
+       volatile struct shared_info *s = HYPERVISOR_shared_info;
+       unsigned long masked __diagused;
+
+       /* Mask it.  */
+       masked = xen_atomic_test_and_set_bit(&s->evtchn_mask[0], pin);
 
-       /* Already masked! */
-       if (xen_atomic_test_bit(&s->evtchn_mask[0], pin))
-               return true;
-       
-       /* Pending - bail! */
-       if (xen_atomic_test_bit(&s->evtchn_pending[0], pin))
+       /*
+        * Caller is responsible for calling trymask only when the
+        * interrupt pin is not masked, and for serializing calls to
+        * trymask.
+        */
+       KASSERT(!masked);
+
+       /*
+        * Check whether there were any interrupts pending when we
+        * masked it.  If there were, unmask and abort.
+        */
+       if (xen_atomic_test_bit(&s->evtchn_pending[0], pin)) {
+               xen_atomic_clear_bit(&s->evtchn_mask[0], pin);
                return false;
+       }
 
-       /* XXX: There's a race here - anything we can do about this ? */
-       /* Mask it */
-       xen_atomic_set_bit(&s->evtchn_mask[0], pin);
+       /* Success: masked, not pending.  */
        return true;
 }
 



Home | Main Index | Thread Index | Old Index