diff options
author | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2017-11-28 09:53:50 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2018-01-14 06:14:51 -0500 |
commit | fc90ccfd286eabb05ec54521367df8663cf0bbbf (patch) | |
tree | 0300985a44c469db156e4f4fb2fd4b05a11a0f57 | |
parent | beacd6f7ed5e2915959442245b3b2480c2e37490 (diff) |
Revert "x86/apic: Remove init_bsp_APIC()"
This reverts commit b371ae0d4a194b178817b0edfb6a7395c7aec37a. It causes
boot hangs on old P3/P4 systems when the local APIC is enforced in UP mode.
Reported-by: Meelis Roos <mroos@linux.ee>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Dou Liyang <douly.fnst@cn.fujitsu.com>
Cc: yinghai@kernel.org
Cc: bhe@redhat.com
Link: https://lkml.kernel.org/r/20171128145350.21560-1-ville.syrjala@linux.intel.com
-rw-r--r-- | arch/x86/include/asm/apic.h | 1 | ||||
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 49 | ||||
-rw-r--r-- | arch/x86/kernel/irqinit.c | 3 |
3 files changed, 53 insertions, 0 deletions
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index a9e57f08bfa6..98722773391d 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h | |||
@@ -136,6 +136,7 @@ extern void disconnect_bsp_APIC(int virt_wire_setup); | |||
136 | extern void disable_local_APIC(void); | 136 | extern void disable_local_APIC(void); |
137 | extern void lapic_shutdown(void); | 137 | extern void lapic_shutdown(void); |
138 | extern void sync_Arb_IDs(void); | 138 | extern void sync_Arb_IDs(void); |
139 | extern void init_bsp_APIC(void); | ||
139 | extern void apic_intr_mode_init(void); | 140 | extern void apic_intr_mode_init(void); |
140 | extern void setup_local_APIC(void); | 141 | extern void setup_local_APIC(void); |
141 | extern void init_apic_mappings(void); | 142 | extern void init_apic_mappings(void); |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 880441f24146..25ddf02598d2 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -1286,6 +1286,55 @@ static int __init apic_intr_mode_select(void) | |||
1286 | return APIC_SYMMETRIC_IO; | 1286 | return APIC_SYMMETRIC_IO; |
1287 | } | 1287 | } |
1288 | 1288 | ||
1289 | /* | ||
1290 | * An initial setup of the virtual wire mode. | ||
1291 | */ | ||
1292 | void __init init_bsp_APIC(void) | ||
1293 | { | ||
1294 | unsigned int value; | ||
1295 | |||
1296 | /* | ||
1297 | * Don't do the setup now if we have a SMP BIOS as the | ||
1298 | * through-I/O-APIC virtual wire mode might be active. | ||
1299 | */ | ||
1300 | if (smp_found_config || !boot_cpu_has(X86_FEATURE_APIC)) | ||
1301 | return; | ||
1302 | |||
1303 | /* | ||
1304 | * Do not trust the local APIC being empty at bootup. | ||
1305 | */ | ||
1306 | clear_local_APIC(); | ||
1307 | |||
1308 | /* | ||
1309 | * Enable APIC. | ||
1310 | */ | ||
1311 | value = apic_read(APIC_SPIV); | ||
1312 | value &= ~APIC_VECTOR_MASK; | ||
1313 | value |= APIC_SPIV_APIC_ENABLED; | ||
1314 | |||
1315 | #ifdef CONFIG_X86_32 | ||
1316 | /* This bit is reserved on P4/Xeon and should be cleared */ | ||
1317 | if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && | ||
1318 | (boot_cpu_data.x86 == 15)) | ||
1319 | value &= ~APIC_SPIV_FOCUS_DISABLED; | ||
1320 | else | ||
1321 | #endif | ||
1322 | value |= APIC_SPIV_FOCUS_DISABLED; | ||
1323 | value |= SPURIOUS_APIC_VECTOR; | ||
1324 | apic_write(APIC_SPIV, value); | ||
1325 | |||
1326 | /* | ||
1327 | * Set up the virtual wire mode. | ||
1328 | */ | ||
1329 | apic_write(APIC_LVT0, APIC_DM_EXTINT); | ||
1330 | value = APIC_DM_NMI; | ||
1331 | if (!lapic_is_integrated()) /* 82489DX */ | ||
1332 | value |= APIC_LVT_LEVEL_TRIGGER; | ||
1333 | if (apic_extnmi == APIC_EXTNMI_NONE) | ||
1334 | value |= APIC_LVT_MASKED; | ||
1335 | apic_write(APIC_LVT1, value); | ||
1336 | } | ||
1337 | |||
1289 | /* Init the interrupt delivery mode for the BSP */ | 1338 | /* Init the interrupt delivery mode for the BSP */ |
1290 | void __init apic_intr_mode_init(void) | 1339 | void __init apic_intr_mode_init(void) |
1291 | { | 1340 | { |
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c index 8da3e909e967..a539410c4ea9 100644 --- a/arch/x86/kernel/irqinit.c +++ b/arch/x86/kernel/irqinit.c | |||
@@ -61,6 +61,9 @@ void __init init_ISA_irqs(void) | |||
61 | struct irq_chip *chip = legacy_pic->chip; | 61 | struct irq_chip *chip = legacy_pic->chip; |
62 | int i; | 62 | int i; |
63 | 63 | ||
64 | #if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC) | ||
65 | init_bsp_APIC(); | ||
66 | #endif | ||
64 | legacy_pic->init(0); | 67 | legacy_pic->init(0); |
65 | 68 | ||
66 | for (i = 0; i < nr_legacy_irqs(); i++) | 69 | for (i = 0; i < nr_legacy_irqs(); i++) |