summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2013-07-10 21:31:13 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2013-07-10 21:31:13 +0000
commita9e152251b8b18a9e73ec90b80e224e11e85e994 (patch)
treebafac4709f790afafcec9aa7e6ad58ce59a33c88
parent21a444a3bc99c444bb3030efbf902340551c2716 (diff)
To prevent lock ordering problems with the kernel lock, we need to make sure
we block all interrupts that can grab the kernel lock. The simplest way to achieve this is to make sure mutexes always raise the ipl to the highest level that has interrupts that grab the kernel lock. This will allow us to have "mpsafe" interrupt handlers at lower priority levels. No change for non-MULTIPROCESSOR kernels. ok matthew@
-rw-r--r--sys/arch/i386/i386/ioapic.c4
-rw-r--r--sys/arch/i386/i386/mutex.S4
-rw-r--r--sys/arch/i386/include/mutex.h21
-rw-r--r--sys/arch/i386/isa/isa_machdep.c4
-rw-r--r--sys/arch/i386/pci/pci_machdep.c4
5 files changed, 30 insertions, 7 deletions
diff --git a/sys/arch/i386/i386/ioapic.c b/sys/arch/i386/i386/ioapic.c
index 0b0c6b880b3..89863102702 100644
--- a/sys/arch/i386/i386/ioapic.c
+++ b/sys/arch/i386/i386/ioapic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ioapic.c,v 1.28 2013/05/16 19:26:04 kettenis Exp $ */
+/* $OpenBSD: ioapic.c,v 1.29 2013/07/10 21:31:11 kettenis Exp $ */
/* $NetBSD: ioapic.c,v 1.7 2003/07/14 22:32:40 lukem Exp $ */
/*-
@@ -677,6 +677,8 @@ apic_intr_establish(int irq, int type, int level, int (*ih_fun)(void *),
flags = level & IPL_MPSAFE;
level &= ~IPL_MPSAFE;
+ KASSERT(level <= IPL_TTY || flags & IPL_MPSAFE);
+
if (sc == NULL)
panic("apic_intr_establish: unknown ioapic %d", ioapic);
diff --git a/sys/arch/i386/i386/mutex.S b/sys/arch/i386/i386/mutex.S
index 313da9eb01a..b4352c3b8d7 100644
--- a/sys/arch/i386/i386/mutex.S
+++ b/sys/arch/i386/i386/mutex.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: mutex.S,v 1.8 2010/09/24 13:21:30 matthew Exp $ */
+/* $OpenBSD: mutex.S,v 1.9 2013/07/10 21:31:11 kettenis Exp $ */
/*
* Copyright (c) 2004 Artur Grabowski <art@openbsd.org>
@@ -30,7 +30,7 @@
* Yeah, we don't really need to implement mtx_init here, but let's keep
* all the functions in the same place.
*/
-ENTRY(mtx_init)
+ENTRY(__mtx_init)
pushl %ebp
movl %esp, %ebp
movl 8(%esp), %eax
diff --git a/sys/arch/i386/include/mutex.h b/sys/arch/i386/include/mutex.h
index de340320e57..b2fb16802bb 100644
--- a/sys/arch/i386/include/mutex.h
+++ b/sys/arch/i386/include/mutex.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mutex.h,v 1.4 2011/03/23 16:54:35 pirofti Exp $ */
+/* $OpenBSD: mutex.h,v 1.5 2013/07/10 21:31:12 kettenis Exp $ */
/*
* Copyright (c) 2004 Artur Grabowski <art@openbsd.org>
@@ -38,7 +38,24 @@ struct mutex {
void *mtx_owner;
};
-#define MUTEX_INITIALIZER(IPL) { 0, (IPL), 0, NULL }
+/*
+ * To prevent lock ordering problems with the kernel lock, we need to
+ * make sure we block all interrupts that can grab the kernel lock.
+ * The simplest way to achieve this is to make sure mutexes always
+ * raise the interrupt priority level to the highest level that has
+ * interrupts that grab the kernel lock.
+ */
+#ifdef MULTIPROCESSOR
+#define __MUTEX_IPL(ipl) \
+ (((ipl) > IPL_NONE && (ipl) < IPL_VM) ? IPL_VM : (ipl))
+#else
+#define __MUTEX_IPL(ipl) (ipl)
+#endif
+
+#define MUTEX_INITIALIZER(ipl) { 0, __MUTEX_IPL((ipl)), 0, NULL }
+
+void __mtx_init(struct mutex *, int);
+#define mtx_init(mtx, ipl) __mtx_init((mtx), __MUTEX_IPL((ipl)))
#define MUTEX_ASSERT_LOCKED(mtx) do { \
if ((mtx)->mtx_lock != 1 || \
diff --git a/sys/arch/i386/isa/isa_machdep.c b/sys/arch/i386/isa/isa_machdep.c
index ad2b74f6796..d596af6d7a6 100644
--- a/sys/arch/i386/isa/isa_machdep.c
+++ b/sys/arch/i386/isa/isa_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: isa_machdep.c,v 1.73 2013/05/16 19:26:04 kettenis Exp $ */
+/* $OpenBSD: isa_machdep.c,v 1.74 2013/07/10 21:31:12 kettenis Exp $ */
/* $NetBSD: isa_machdep.c,v 1.22 1997/06/12 23:57:32 thorpej Exp $ */
/*-
@@ -501,6 +501,8 @@ isa_intr_establish(isa_chipset_tag_t ic, int irq, int type, int level,
flags = level & IPL_MPSAFE;
level &= ~IPL_MPSAFE;
+ KASSERT(level <= IPL_VM || level >= IPL_CLOCK || flags & IPL_MPSAFE);
+
/* no point in sleeping unless someone can free memory. */
ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
if (ih == NULL) {
diff --git a/sys/arch/i386/pci/pci_machdep.c b/sys/arch/i386/pci/pci_machdep.c
index 4eeeb6b88fb..374a7373842 100644
--- a/sys/arch/i386/pci/pci_machdep.c
+++ b/sys/arch/i386/pci/pci_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci_machdep.c,v 1.75 2013/05/30 16:19:25 deraadt Exp $ */
+/* $OpenBSD: pci_machdep.c,v 1.76 2013/07/10 21:31:12 kettenis Exp $ */
/* $NetBSD: pci_machdep.c,v 1.28 1997/06/06 23:29:17 thorpej Exp $ */
/*-
@@ -787,6 +787,8 @@ pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level,
flags = level & IPL_MPSAFE;
level &= ~IPL_MPSAFE;
+ KASSERT(level <= IPL_TTY || flags & IPL_MPSAFE);
+
if (pci_get_capability(pc, tag, PCI_CAP_MSI, &off, &reg) == 0)
panic("%s: no msi capability", __func__);