diff options
author | dillon <dillon@FreeBSD.org> | 2002-03-27 05:39:23 +0000 |
---|---|---|
committer | dillon <dillon@FreeBSD.org> | 2002-03-27 05:39:23 +0000 |
commit | dc5aafeb94ddee4f835e390dffaecbb0eec5d5e2 (patch) | |
tree | 8233f61cf29e01829b91c6a5cf27defe60e6b8d8 /sys/pc98 | |
parent | 9b5143f94f573dc8954cb0913f3edb055e6caf0f (diff) | |
download | FreeBSD-src-dc5aafeb94ddee4f835e390dffaecbb0eec5d5e2.zip FreeBSD-src-dc5aafeb94ddee4f835e390dffaecbb0eec5d5e2.tar.gz |
Compromise for critical*()/cpu_critical*() recommit. Cleanup the interrupt
disablement assumptions in kern_fork.c by adding another API call,
cpu_critical_fork_exit(). Cleanup the td_savecrit field by moving it
from MI to MD. Temporarily move cpu_critical*() from <arch>/include/cpufunc.h
to <arch>/<arch>/critical.c (stage-2 will clean this up).
Implement interrupt deferral for i386 that allows interrupts to remain
enabled inside critical sections. This also fixes an IPI interlock bug,
and requires uses of icu_lock to be enclosed in a true interrupt disablement.
This is the stage-1 commit. Stage-2 will occur after stage-1 has stabilized,
and will move cpu_critical*() into its own header file(s) + other things.
This commit may break non-i386 architectures in trivial ways. This should
be temporary.
Reviewed by: core
Approved by: core
Diffstat (limited to 'sys/pc98')
-rw-r--r-- | sys/pc98/cbus/clock.c | 11 | ||||
-rw-r--r-- | sys/pc98/cbus/pcrtc.c | 11 | ||||
-rw-r--r-- | sys/pc98/i386/machdep.c | 14 | ||||
-rw-r--r-- | sys/pc98/pc98/clock.c | 11 | ||||
-rw-r--r-- | sys/pc98/pc98/machdep.c | 14 |
5 files changed, 51 insertions, 10 deletions
diff --git a/sys/pc98/cbus/clock.c b/sys/pc98/cbus/clock.c index b8b9e3f..b70465a 100644 --- a/sys/pc98/cbus/clock.c +++ b/sys/pc98/cbus/clock.c @@ -1331,6 +1331,7 @@ cpu_initclocks() int apic_8254_trial; void *clkdesc; #endif /* APIC_IO */ + register_t crit; #ifndef PC98 if (statclock_disable) { @@ -1367,9 +1368,11 @@ cpu_initclocks() inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, NULL, INTR_TYPE_CLK | INTR_FAST, &clkdesc); + crit = intr_disable(); mtx_lock_spin(&icu_lock); INTREN(1 << apic_8254_intr); mtx_unlock_spin(&icu_lock); + intr_restore(crit); #else /* APIC_IO */ @@ -1380,9 +1383,11 @@ cpu_initclocks() */ inthand_add("clk", 0, (driver_intr_t *)clkintr, NULL, INTR_TYPE_CLK | INTR_FAST, NULL); + crit = intr_disable(); mtx_lock_spin(&icu_lock); INTREN(IRQ0); mtx_unlock_spin(&icu_lock); + intr_restore(crit); #endif /* APIC_IO */ @@ -1408,6 +1413,7 @@ cpu_initclocks() inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL, INTR_TYPE_CLK | INTR_FAST, NULL); + crit = intr_disable(); mtx_lock_spin(&icu_lock); #ifdef APIC_IO INTREN(APIC_IRQ8); @@ -1415,6 +1421,7 @@ cpu_initclocks() INTREN(IRQ8); #endif /* APIC_IO */ mtx_unlock_spin(&icu_lock); + intr_restore(crit); writertc(RTC_STATUSB, rtc_statusb); #endif /* PC98 */ @@ -1432,9 +1439,11 @@ cpu_initclocks() * on the IO APIC. * Workaround: Limited variant of mixed mode. */ + crit = intr_disable(); mtx_lock_spin(&icu_lock); INTRDIS(1 << apic_8254_intr); mtx_unlock_spin(&icu_lock); + intr_restore(crit); inthand_remove(clkdesc); printf("APIC_IO: Broken MP table detected: " "8254 is not connected to " @@ -1457,9 +1466,11 @@ cpu_initclocks() inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, NULL, INTR_TYPE_CLK | INTR_FAST, NULL); + crit = intr_disable(); mtx_lock_spin(&icu_lock); INTREN(1 << apic_8254_intr); mtx_unlock_spin(&icu_lock); + intr_restore(crit); } } diff --git a/sys/pc98/cbus/pcrtc.c b/sys/pc98/cbus/pcrtc.c index b8b9e3f..b70465a 100644 --- a/sys/pc98/cbus/pcrtc.c +++ b/sys/pc98/cbus/pcrtc.c @@ -1331,6 +1331,7 @@ cpu_initclocks() int apic_8254_trial; void *clkdesc; #endif /* APIC_IO */ + register_t crit; #ifndef PC98 if (statclock_disable) { @@ -1367,9 +1368,11 @@ cpu_initclocks() inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, NULL, INTR_TYPE_CLK | INTR_FAST, &clkdesc); + crit = intr_disable(); mtx_lock_spin(&icu_lock); INTREN(1 << apic_8254_intr); mtx_unlock_spin(&icu_lock); + intr_restore(crit); #else /* APIC_IO */ @@ -1380,9 +1383,11 @@ cpu_initclocks() */ inthand_add("clk", 0, (driver_intr_t *)clkintr, NULL, INTR_TYPE_CLK | INTR_FAST, NULL); + crit = intr_disable(); mtx_lock_spin(&icu_lock); INTREN(IRQ0); mtx_unlock_spin(&icu_lock); + intr_restore(crit); #endif /* APIC_IO */ @@ -1408,6 +1413,7 @@ cpu_initclocks() inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL, INTR_TYPE_CLK | INTR_FAST, NULL); + crit = intr_disable(); mtx_lock_spin(&icu_lock); #ifdef APIC_IO INTREN(APIC_IRQ8); @@ -1415,6 +1421,7 @@ cpu_initclocks() INTREN(IRQ8); #endif /* APIC_IO */ mtx_unlock_spin(&icu_lock); + intr_restore(crit); writertc(RTC_STATUSB, rtc_statusb); #endif /* PC98 */ @@ -1432,9 +1439,11 @@ cpu_initclocks() * on the IO APIC. * Workaround: Limited variant of mixed mode. */ + crit = intr_disable(); mtx_lock_spin(&icu_lock); INTRDIS(1 << apic_8254_intr); mtx_unlock_spin(&icu_lock); + intr_restore(crit); inthand_remove(clkdesc); printf("APIC_IO: Broken MP table detected: " "8254 is not connected to " @@ -1457,9 +1466,11 @@ cpu_initclocks() inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, NULL, INTR_TYPE_CLK | INTR_FAST, NULL); + crit = intr_disable(); mtx_lock_spin(&icu_lock); INTREN(1 << apic_8254_intr); mtx_unlock_spin(&icu_lock); + intr_restore(crit); } } diff --git a/sys/pc98/i386/machdep.c b/sys/pc98/i386/machdep.c index 21a538f..e41899f 100644 --- a/sys/pc98/i386/machdep.c +++ b/sys/pc98/i386/machdep.c @@ -815,11 +815,10 @@ cpu_idle(void) #ifndef SMP if (cpu_idle_hlt) { disable_intr(); - if (procrunnable()) + if (procrunnable()) { enable_intr(); - else { - enable_intr(); - __asm __volatile("hlt"); + } else { + __asm __volatile("sti; hlt"); } } #endif @@ -1757,12 +1756,17 @@ init386(first) /* * Initialize mutexes. + * + * icu_lock: in order to allow an interrupt to occur in a critical + * section, to set pcpu->ipending (etc...) properly, we + * must be able to get the icu lock, so it can't be under + * witness. */ mtx_init(&Giant, "Giant", MTX_DEF | MTX_RECURSE); mtx_init(&sched_lock, "sched lock", MTX_SPIN | MTX_RECURSE); mtx_init(&proc0.p_mtx, "process lock", MTX_DEF); mtx_init(&clock_lock, "clk", MTX_SPIN | MTX_RECURSE); - mtx_init(&icu_lock, "icu", MTX_SPIN); + mtx_init(&icu_lock, "icu", MTX_SPIN | MTX_NOWITNESS); mtx_lock(&Giant); /* make ldt memory segments */ diff --git a/sys/pc98/pc98/clock.c b/sys/pc98/pc98/clock.c index b8b9e3f..b70465a 100644 --- a/sys/pc98/pc98/clock.c +++ b/sys/pc98/pc98/clock.c @@ -1331,6 +1331,7 @@ cpu_initclocks() int apic_8254_trial; void *clkdesc; #endif /* APIC_IO */ + register_t crit; #ifndef PC98 if (statclock_disable) { @@ -1367,9 +1368,11 @@ cpu_initclocks() inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, NULL, INTR_TYPE_CLK | INTR_FAST, &clkdesc); + crit = intr_disable(); mtx_lock_spin(&icu_lock); INTREN(1 << apic_8254_intr); mtx_unlock_spin(&icu_lock); + intr_restore(crit); #else /* APIC_IO */ @@ -1380,9 +1383,11 @@ cpu_initclocks() */ inthand_add("clk", 0, (driver_intr_t *)clkintr, NULL, INTR_TYPE_CLK | INTR_FAST, NULL); + crit = intr_disable(); mtx_lock_spin(&icu_lock); INTREN(IRQ0); mtx_unlock_spin(&icu_lock); + intr_restore(crit); #endif /* APIC_IO */ @@ -1408,6 +1413,7 @@ cpu_initclocks() inthand_add("rtc", 8, (driver_intr_t *)rtcintr, NULL, INTR_TYPE_CLK | INTR_FAST, NULL); + crit = intr_disable(); mtx_lock_spin(&icu_lock); #ifdef APIC_IO INTREN(APIC_IRQ8); @@ -1415,6 +1421,7 @@ cpu_initclocks() INTREN(IRQ8); #endif /* APIC_IO */ mtx_unlock_spin(&icu_lock); + intr_restore(crit); writertc(RTC_STATUSB, rtc_statusb); #endif /* PC98 */ @@ -1432,9 +1439,11 @@ cpu_initclocks() * on the IO APIC. * Workaround: Limited variant of mixed mode. */ + crit = intr_disable(); mtx_lock_spin(&icu_lock); INTRDIS(1 << apic_8254_intr); mtx_unlock_spin(&icu_lock); + intr_restore(crit); inthand_remove(clkdesc); printf("APIC_IO: Broken MP table detected: " "8254 is not connected to " @@ -1457,9 +1466,11 @@ cpu_initclocks() inthand_add("clk", apic_8254_intr, (driver_intr_t *)clkintr, NULL, INTR_TYPE_CLK | INTR_FAST, NULL); + crit = intr_disable(); mtx_lock_spin(&icu_lock); INTREN(1 << apic_8254_intr); mtx_unlock_spin(&icu_lock); + intr_restore(crit); } } diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c index 21a538f..e41899f 100644 --- a/sys/pc98/pc98/machdep.c +++ b/sys/pc98/pc98/machdep.c @@ -815,11 +815,10 @@ cpu_idle(void) #ifndef SMP if (cpu_idle_hlt) { disable_intr(); - if (procrunnable()) + if (procrunnable()) { enable_intr(); - else { - enable_intr(); - __asm __volatile("hlt"); + } else { + __asm __volatile("sti; hlt"); } } #endif @@ -1757,12 +1756,17 @@ init386(first) /* * Initialize mutexes. + * + * icu_lock: in order to allow an interrupt to occur in a critical + * section, to set pcpu->ipending (etc...) properly, we + * must be able to get the icu lock, so it can't be under + * witness. */ mtx_init(&Giant, "Giant", MTX_DEF | MTX_RECURSE); mtx_init(&sched_lock, "sched lock", MTX_SPIN | MTX_RECURSE); mtx_init(&proc0.p_mtx, "process lock", MTX_DEF); mtx_init(&clock_lock, "clk", MTX_SPIN | MTX_RECURSE); - mtx_init(&icu_lock, "icu", MTX_SPIN); + mtx_init(&icu_lock, "icu", MTX_SPIN | MTX_NOWITNESS); mtx_lock(&Giant); /* make ldt memory segments */ |