summaryrefslogtreecommitdiffstats
path: root/sys/i386/include
diff options
context:
space:
mode:
authorups <ups@FreeBSD.org>2004-12-07 20:15:01 +0000
committerups <ups@FreeBSD.org>2004-12-07 20:15:01 +0000
commit0e900aeba092127fe706b8a59228a711b7bd683b (patch)
treea75fb9b20179ad2db0eb2556245efafc59a0bd82 /sys/i386/include
parente2f469b728b3ca90ab10d2794390412466d0c089 (diff)
downloadFreeBSD-src-0e900aeba092127fe706b8a59228a711b7bd683b.zip
FreeBSD-src-0e900aeba092127fe706b8a59228a711b7bd683b.tar.gz
Avoid more than two pending IPI interrupt vectors per local APIC
as this may cause deadlocks. This should fix kern/72123. Discussed with: jhb Tested by: Nik Azim Azam, Andy Farkas, Flack Man, Aykut KARA Izzet BESKARDES, Jens Binnewies, Karl Keusgen Approved by: sam (mentor)
Diffstat (limited to 'sys/i386/include')
-rw-r--r--sys/i386/include/apicvar.h51
-rw-r--r--sys/i386/include/smp.h7
2 files changed, 44 insertions, 14 deletions
diff --git a/sys/i386/include/apicvar.h b/sys/i386/include/apicvar.h
index cc46fda..a680b0d 100644
--- a/sys/i386/include/apicvar.h
+++ b/sys/i386/include/apicvar.h
@@ -81,22 +81,55 @@
#define APIC_IO_INTS (IDT_IO_INTS + 16)
#define APIC_NUM_IOINTS 192
+/*
+ ********************* !!! WARNING !!! ******************************
+ * Each local apic has an interrupt receive fifo that is two entries deep
+ * for each interrupt priority class (higher 4 bits of interrupt vector).
+ * Once the fifo is full the APIC can no longer receive interrupts for this
+ * class and sending IPIs from other CPUs will be blocked.
+ * To avoid deadlocks there should be no more than two IPI interrupts
+ * pending at the same time.
+ * Currently this is guaranteed by dividing the IPIs in two groups that have
+ * each at most one IPI interrupt pending. The first group is protected by the
+ * smp_ipi_mtx and waits for the completion of the IPI (Only one IPI user
+ * at a time) The second group uses a single interrupt and a bitmap to avoid
+ * redundant IPI interrupts.
+ *
+ * Right now IPI_STOP used by kdb shares the interrupt priority class with
+ * the two IPI groups mentioned above. As such IPI_STOP may cause a deadlock.
+ * Eventually IPI_STOP should use NMI IPIs - this would eliminate this and
+ * other deadlocks caused by IPI_STOP.
+ */
+
#define APIC_LOCAL_INTS 240
-#define APIC_TIMER_INT APIC_LOCAL_INTS
-#define APIC_ERROR_INT (APIC_LOCAL_INTS + 1)
-#define APIC_THERMAL_INT (APIC_LOCAL_INTS + 2)
-#define APIC_IPI_INTS (APIC_LOCAL_INTS + 3)
-#define IPI_AST APIC_IPI_INTS /* Generate software trap. */
+#if 0
+#define APIC_TIMER_INT (APIC_LOCAL_INTS + X)
+#define APIC_ERROR_INT (APIC_LOCAL_INTS + X)
+#define APIC_THERMAL_INT (APIC_LOCAL_INTS + X)
+#endif
+
+#define APIC_IPI_INTS (APIC_LOCAL_INTS + 0)
+#define IPI_RENDEZVOUS (APIC_IPI_INTS) /* Inter-CPU rendezvous. */
#define IPI_INVLTLB (APIC_IPI_INTS + 1) /* TLB Shootdown IPIs */
#define IPI_INVLPG (APIC_IPI_INTS + 2)
#define IPI_INVLRNG (APIC_IPI_INTS + 3)
#define IPI_LAZYPMAP (APIC_IPI_INTS + 4) /* Lazy pmap release. */
-#define IPI_HARDCLOCK (APIC_IPI_INTS + 8) /* Inter-CPU clock handling. */
-#define IPI_STATCLOCK (APIC_IPI_INTS + 9)
-#define IPI_RENDEZVOUS (APIC_IPI_INTS + 10) /* Inter-CPU rendezvous. */
-#define IPI_STOP (APIC_IPI_INTS + 11) /* Stop CPU until restarted. */
+/* Vector to handle bitmap based IPIs */
+#define IPI_BITMAP_VECTOR (APIC_IPI_INTS + 5)
+/* IPIs handled by IPI_BITMAPED_VECTOR (XXX ups is there a better place?) */
+#define IPI_AST 0 /* Generate software trap. */
+#define IPI_HARDCLOCK 1 /* Inter-CPU clock handling. */
+#define IPI_STATCLOCK 2
+#define IPI_BITMAP_LAST IPI_STATCLOCK
+#define IPI_IS_BITMAPED(x) ((x) <= IPI_BITMAP_LAST)
+
+#define IPI_STOP (APIC_IPI_INTS + 6) /* Stop CPU until restarted. */
+
+/* The spurious interrupt can share the priority class with the IPIs since
+ * it is not a normal interrupt. (Does not use the APIC's interrupt fifo)
+ */
#define APIC_SPURIOUS_INT 255
#define LVT_LINT0 0
diff --git a/sys/i386/include/smp.h b/sys/i386/include/smp.h
index fe87fdf..eb6a635 100644
--- a/sys/i386/include/smp.h
+++ b/sys/i386/include/smp.h
@@ -55,9 +55,7 @@ inthand_t
IDTVEC(invltlb), /* TLB shootdowns - global */
IDTVEC(invlpg), /* TLB shootdowns - 1 page */
IDTVEC(invlrng), /* TLB shootdowns - page range */
- IDTVEC(hardclock), /* Forward hardclock() */
- IDTVEC(statclock), /* Forward statclock() */
- IDTVEC(cpuast), /* Additional software trap on other cpu */
+ IDTVEC(ipi_intr_bitmap_handler), /* Bitmap based IPIs */
IDTVEC(cpustop), /* CPU stops & waits to be restarted */
IDTVEC(rendezvous), /* handle CPU rendezvous */
IDTVEC(lazypmap); /* handle lazy pmap release */
@@ -70,9 +68,8 @@ void ipi_all(u_int ipi);
void ipi_all_but_self(u_int ipi);
void ipi_self(u_int ipi);
void forward_statclock(void);
-void forwarded_statclock(struct clockframe frame);
void forward_hardclock(void);
-void forwarded_hardclock(struct clockframe frame);
+void ipi_bitmap_handler(struct clockframe frame);
u_int mp_bootaddress(u_int);
int mp_grab_cpu_hlt(void);
void mp_topology(void);
OpenPOWER on IntegriCloud