x86_64: Always set LINTEN for AMD CPUs if their family >= 0xF
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Mon, 19 Dec 2011 11:54:10 +0000 (19:54 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Mon, 19 Dec 2011 11:54:10 +0000 (19:54 +0800)
This merges d54b8204947bb8a83fa3d2c7f1b595e47f3802c2

sys/platform/pc64/apic/lapic.c
sys/platform/pc64/x86_64/initcpu.c

index 4ed8a6d..da6eada 100644 (file)
@@ -34,6 +34,7 @@
 #include <machine/smp.h>
 #include <machine/md_var.h>
 #include <machine/pmap.h>
+#include <machine/specialreg.h>
 #include <machine_base/apic/lapic.h>
 #include <machine_base/apic/ioapic.h>
 #include <machine_base/apic/ioapic_abi.h>
@@ -111,6 +112,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_global(XSPURIOUSINT_OFFSET, Xspuriousint,
                    SDT_SYSIGT, SEL_KPL, 0);
index 1755377..643342f 100644 (file)
@@ -145,35 +145,6 @@ initializecpu(void)
                load_cr4(rcr4() | CR4_FXSR | CR4_XMM);
                cpu_fxsr = hw_instruction_sse = 1;
        }
-#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 multi-core cpus the interrupt winds up
-        * going to ALL 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);
-           }
-           outl(0x0cf8, 0);
-       }
-#endif
 
        if ((amd_feature & AMDID_NX) != 0) {
                msr = rdmsr(MSR_EFER) | EFER_NXE;