Module Name:    src
Committed By:   riastradh
Date:           Fri Nov 10 19:24:17 UTC 2017

Modified Files:
        src/sys/arch/xen/xen: evtchn.c

Log Message:
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


To generate a diff of this commit:
cvs rdiff -u -r1.74 -r1.75 src/sys/arch/xen/xen/evtchn.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/xen/xen/evtchn.c
diff -u src/sys/arch/xen/xen/evtchn.c:1.74 src/sys/arch/xen/xen/evtchn.c:1.75
--- src/sys/arch/xen/xen/evtchn.c:1.74	Sat Nov  4 10:26:14 2017
+++ src/sys/arch/xen/xen/evtchn.c	Fri Nov 10 19:24:17 2017
@@ -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_evtchn_delroute(struct pic *pic, str
 	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;
 
-	/* 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))
+	/* Mask it.  */
+	masked = xen_atomic_test_and_set_bit(&s->evtchn_mask[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;
 }
 

Reply via email to