From d54b8204947bb8a83fa3d2c7f1b595e47f3802c2 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Mon, 19 Dec 2011 19:33:30 +0800 Subject: [PATCH 1/1] i386: Always set LINTEN for AMD CPUs if their family >= 0xF Since LINTEN will take effect when LAPIC is hardware enabled, so we defer the LINTEN turning on when we know LAPIC will be software enabled. This fixes the recent MI per-cpu interrupt information array support on AMD CPUs when IOAPIC is disabled on SMP system. --- sys/platform/pc32/apic/lapic.c | 35 ++++++++++++++++++++++++++++++++ sys/platform/pc32/i386/initcpu.c | 31 ---------------------------- 2 files changed, 35 insertions(+), 31 deletions(-) diff --git a/sys/platform/pc32/apic/lapic.c b/sys/platform/pc32/apic/lapic.c index 80ebd58fac..4c39d27c85 100644 --- a/sys/platform/pc32/apic/lapic.c +++ b/sys/platform/pc32/apic/lapic.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -110,6 +111,40 @@ lapic_init(boolean_t bsp) * only need to be installed once; we do it on BSP. */ if (bsp) { + if (cpu_vendor_id == CPU_VENDOR_AMD && + CPUID_TO_FAMILY(cpu_id) >= 0xf) { + uint32_t tcr; + + /* + * Set the LINTEN bit in the HyperTransport + * Transaction Control Register. + * + * This will cause EXTINT and NMI interrupts + * routed over the hypertransport bus to be + * fed into the LAPIC LINT0/LINT1. If the bit + * isn't set, the interrupts will go to the + * general cpu INTR/NMI pins. On a dual-core + * cpu the interrupt winds up going to BOTH cpus. + * The first cpu that does the interrupt ack + * cycle will get the correct interrupt. The + * second cpu that does it will get a spurious + * interrupt vector (typically IRQ 7). + */ + outl(0x0cf8, + (1 << 31) | /* enable */ + (0 << 16) | /* bus */ + (0x18 << 11) | /* dev (cpu + 0x18) */ + (0 << 8) | /* func */ + 0x68 /* reg */ + ); + tcr = inl(0xcfc); + if ((tcr & 0x00010000) == 0) { + kprintf("LAPIC: AMD LINTEN on\n"); + outl(0xcfc, tcr|0x00010000); + } + outl(0x0cf8, 0); + } + /* Install a 'Spurious INTerrupt' vector */ setidt(XSPURIOUSINT_OFFSET, Xspuriousint, SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); diff --git a/sys/platform/pc32/i386/initcpu.c b/sys/platform/pc32/i386/initcpu.c index 1ad772a409..8e7df828fb 100644 --- a/sys/platform/pc32/i386/initcpu.c +++ b/sys/platform/pc32/i386/initcpu.c @@ -619,37 +619,6 @@ init_686_amd(void) cpu_feature = regs[3]; } #endif -#ifdef CPU_AMD64X2_INTR_SPAM - /* - * Set the LINTEN bit in the HyperTransport Transaction - * Control Register. - * - * This will cause EXTINT and NMI interrupts routed over the - * hypertransport bus to be fed into the LAPIC LINT0/LINT1. If - * the bit isn't set, the interrupts will go to the general cpu - * INTR/NMI pins. On a dual-core cpu the interrupt winds up - * going to BOTH cpus. The first cpu that does the interrupt ack - * cycle will get the correct interrupt. The second cpu that does - * it will get a spurious interrupt vector (typically IRQ 7). - */ - if ((cpu_id & 0xff0) == 0xf30) { - int32_t tcr; - outl(0x0cf8, - (1 << 31) | /* enable */ - (0 << 16) | /* bus */ - (24 << 11) | /* dev (cpu + 24) */ - (0 << 8) | /* func */ - 0x68 /* reg */ - ); - tcr = inl(0xcfc); - if ((tcr & 0x00010000) == 0) { - outl(0xcfc, tcr|0x00010000); - additional_cpu_info("AMD: Rerouting HyperTransport " - "EXTINT/NMI to APIC"); - } - outl(0x0cf8, 0); - } -#endif } #endif /* I686_CPU */ -- 2.41.0