summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwain Ainsworth <oga@cvs.openbsd.org>2009-01-27 15:34:00 +0000
committerOwain Ainsworth <oga@cvs.openbsd.org>2009-01-27 15:34:00 +0000
commit11466d531552c18807f1cc97f9472dad7f12992d (patch)
tree0b52928b3de9edf5ca28e95aaa55791a5be04db0
parentdb37bb7d79d37d659536a1dac53f5bab5c1ff67a (diff)
Switch the amd64 PCI_CONF_LOCK from being a simplelock and splhigh to a
mutex with ipl set to IPL_HIGH. While i'm here, unify the code with i386, by giving the same lock to the i386 code. This lock is mostly for MP, but could actually prevent a race where a process is doing pci_conf_{read,write}, and then an interrupt fire and also does pci_conf_{read,write}. Since this is a two stage process, the interrupt could race with the one, causing the value to the written to the wrong place, or the wrong value to be written. Tested by many. "go ahead" kettenis@.
-rw-r--r--sys/arch/amd64/pci/pci_machdep.c28
-rw-r--r--sys/arch/i386/pci/pci_machdep.c18
2 files changed, 27 insertions, 19 deletions
diff --git a/sys/arch/amd64/pci/pci_machdep.c b/sys/arch/amd64/pci/pci_machdep.c
index 85a4b1013b1..a11c8cd2ebe 100644
--- a/sys/arch/amd64/pci/pci_machdep.c
+++ b/sys/arch/amd64/pci/pci_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci_machdep.c,v 1.20 2008/12/28 18:26:53 kettenis Exp $ */
+/* $OpenBSD: pci_machdep.c,v 1.21 2009/01/27 15:33:59 oga Exp $ */
/* $NetBSD: pci_machdep.c,v 1.3 2003/05/07 21:33:58 fvdl Exp $ */
/*-
@@ -105,22 +105,16 @@
int pci_mode = -1;
-#if defined(MULTIPROCESSOR) && 0
-struct simplelock pci_conf_slock = SIMPLELOCK_INITIALIZER;
-#else
-struct simplelock pci_conf_slock = { 0 };
-#endif
+struct mutex pci_conf_lock = MUTEX_INITIALIZER(IPL_HIGH);
-#define PCI_CONF_LOCK(s) \
+#define PCI_CONF_LOCK() \
do { \
- (s) = splhigh(); \
- simple_lock(&pci_conf_slock); \
+ mtx_enter(&pci_conf_lock); \
} while (0)
-#define PCI_CONF_UNLOCK(s) \
+#define PCI_CONF_UNLOCK() \
do { \
- simple_unlock(&pci_conf_slock); \
- splx((s)); \
+ mtx_leave(&pci_conf_lock); \
} while (0)
#define PCI_MODE1_ENABLE 0x80000000UL
@@ -258,9 +252,8 @@ pcireg_t
pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
{
pcireg_t data;
- int s;
- PCI_CONF_LOCK(s);
+ PCI_CONF_LOCK();
switch (pci_mode) {
case 1:
outl(PCI_MODE1_ADDRESS_REG, tag.mode1 | reg);
@@ -276,7 +269,7 @@ pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
default:
panic("pci_conf_read: mode not configured");
}
- PCI_CONF_UNLOCK(s);
+ PCI_CONF_UNLOCK();
return data;
}
@@ -284,9 +277,8 @@ pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
void
pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data)
{
- int s;
- PCI_CONF_LOCK(s);
+ PCI_CONF_LOCK();
switch (pci_mode) {
case 1:
outl(PCI_MODE1_ADDRESS_REG, tag.mode1 | reg);
@@ -302,7 +294,7 @@ pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data)
default:
panic("pci_conf_write: mode not configured");
}
- PCI_CONF_UNLOCK(s);
+ PCI_CONF_UNLOCK();
}
int
diff --git a/sys/arch/i386/pci/pci_machdep.c b/sys/arch/i386/pci/pci_machdep.c
index 5954a8152b9..ebe9a4f9ad7 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.43 2008/12/28 18:26:53 kettenis Exp $ */
+/* $OpenBSD: pci_machdep.c,v 1.44 2009/01/27 15:33:59 oga Exp $ */
/* $NetBSD: pci_machdep.c,v 1.28 1997/06/06 23:29:17 thorpej Exp $ */
/*-
@@ -113,6 +113,18 @@ extern bios_pciinfo_t *bios_pciinfo;
int pci_mode = -1;
+struct mutex pci_conf_lock = MUTEX_INITIALIZER(IPL_HIGH);
+
+#define PCI_CONF_LOCK() \
+do { \
+ mtx_enter(&pci_conf_lock); \
+} while (0)
+
+#define PCI_CONF_UNLOCK() \
+do { \
+ mtx_leave(&pci_conf_lock); \
+} while (0)
+
#define PCI_MODE1_ENABLE 0x80000000UL
#define PCI_MODE1_ADDRESS_REG 0x0cf8
#define PCI_MODE1_DATA_REG 0x0cfc
@@ -252,6 +264,7 @@ pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
{
pcireg_t data;
+ PCI_CONF_LOCK();
switch (pci_mode) {
case 1:
outl(PCI_MODE1_ADDRESS_REG, tag.mode1 | reg);
@@ -267,6 +280,7 @@ pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
default:
panic("pci_conf_read: mode not configured");
}
+ PCI_CONF_UNLOCK();
return data;
}
@@ -275,6 +289,7 @@ void
pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data)
{
+ PCI_CONF_LOCK();
switch (pci_mode) {
case 1:
outl(PCI_MODE1_ADDRESS_REG, tag.mode1 | reg);
@@ -290,6 +305,7 @@ pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data)
default:
panic("pci_conf_write: mode not configured");
}
+ PCI_CONF_UNLOCK();
}
int