diff options
author | jhb <jhb@FreeBSD.org> | 2005-11-21 18:39:17 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2005-11-21 18:39:17 +0000 |
commit | f43bb7546346a694311becf1114bb2d99cb3739e (patch) | |
tree | a82283a0e20501a2111a6bf0073a58938c818b78 | |
parent | 92462f1576f9f0523af96b1f5b45af5a353a12f9 (diff) | |
download | FreeBSD-src-f43bb7546346a694311becf1114bb2d99cb3739e.zip FreeBSD-src-f43bb7546346a694311becf1114bb2d99cb3739e.tar.gz |
Expand the hack to mask the atpics if 'device atpic' is not in the kernel
during boot up. Now we do a full reset of the 8259As and setup a simple
interrupt handler (we actually borrow the apic one that just does an
immediate iret) to handle any spurious interrupts triggered by either chip.
This should fix some folks that were getting a Trap 30 during bootup of
certain SMP AMD systems. This might get pushed into the 6.0 branch as an
errata. For now a suitable workaround is to add 'device atpic' to your
kernel config.
Tested by: scottl
Helpful info from: dillon
MFC after: 1 week
-rw-r--r-- | sys/amd64/amd64/machdep.c | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index e336a31..0ee32f3 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -124,7 +124,9 @@ __FBSDID("$FreeBSD$"); #include <machine/smp.h> #endif +#include <dev/ic/i8259.h> #include <amd64/isa/icu.h> +#include <machine/apicvar.h> #include <isa/isareg.h> #include <isa/rtc.h> @@ -1125,14 +1127,6 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) u_int64_t msr; char *env; -#ifdef DEV_ISA - /* Preemptively mask the atpics and leave them shut down */ - outb(IO_ICU1 + ICU_IMR_OFFSET, 0xff); - outb(IO_ICU2 + ICU_IMR_OFFSET, 0xff); -#else -#error "have you forgotten the isa device?"; -#endif - thread0.td_kstack = physfree + KERNBASE; bzero((void *)thread0.td_kstack, KSTACK_PAGES * PAGE_SIZE); physfree += KSTACK_PAGES * PAGE_SIZE; @@ -1231,9 +1225,35 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) */ cninit(); +#ifdef DEV_ISA #ifdef DEV_ATPIC elcr_probe(); atpic_startup(); +#else + /* Reset and mask the atpics and leave them shut down. */ + outb(IO_ICU1, ICW1_RESET | ICW1_IC4); + outb(IO_ICU1 + ICU_IMR_OFFSET, IDT_IO_INTS); + outb(IO_ICU1 + ICU_IMR_OFFSET, 1 << 2); + outb(IO_ICU1 + ICU_IMR_OFFSET, ICW4_8086); + outb(IO_ICU1 + ICU_IMR_OFFSET, 0xff); + outb(IO_ICU1, OCW3_SEL | OCW3_RR); + + outb(IO_ICU2, ICW1_RESET | ICW1_IC4); + outb(IO_ICU2 + ICU_IMR_OFFSET, IDT_IO_INTS + 8); + outb(IO_ICU2 + ICU_IMR_OFFSET, 2); + outb(IO_ICU2 + ICU_IMR_OFFSET, ICW4_8086); + outb(IO_ICU2 + ICU_IMR_OFFSET, 0xff); + outb(IO_ICU2, OCW3_SEL | OCW3_RR); + + /* + * Point the ICU spurious interrupt vectors at the APIC spurious + * interrupt handler. + */ + setidt(IDT_IO_INTS + 7, IDTVEC(spuriousint), SDT_SYSIGT, SEL_KPL, 0); + setidt(IDT_IO_INTS + 15, IDTVEC(spuriousint), SDT_SYSIGT, SEL_KPL, 0); +#endif +#else +#error "have you forgotten the isa device?"; #endif kdb_init(); |