From: Bhavna Sarathy <bnagendr@redhat.com> Date: Mon, 9 Nov 2009 20:48:26 -0500 Subject: [x86] fix boot crash with < 8-core AMD Magny-cours system Message-id: <4AF8801A.8020508@redhat.com> Patchwork-id: 21336 O-Subject: Re: [RHEL5.5 PATCH] Fix boot crash with < 8-core Magny-cours system Bugzilla: 522215 RH-Acked-by: Prarit Bhargava <prarit@redhat.com> RH-Acked-by: Christopher Lalancette <clalance@redhat.com> BZ 522215 Detect use of extended APIC ID for AMD CPUs, and prevent kernel panic while booting an 8-core Magny-cours on 32-bit RHEL5.x. The reason is this: - the kernel cannot switch to "bigsmp" APIC driver mode, because in RH5.4 x86 that mode is used only if num_processors > 8. - so the kernel uses "0x0F" as the mask to get the APIC ID of the BSP. Therefore, if the BSP APIC ID happens to be 16, the kernel will incorrectly assign boot_cpu_physical_apicid to 0. Later, in the same smp_boot_cpus() function, the kernel will attempt to wake the boot CPU (which is already up and running), and "hang" Upstream links: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=42937e81a82 commit 2cb078603abb612e3bcd428fb8122c3d39e08832 Brew build: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=1993083 Testing: Patch tested on 2P Dinar system and HP Proliant G7 M-C system. diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c index 58f5e41..522c1a0 100644 --- a/arch/i386/kernel/cpu/amd.c +++ b/arch/i386/kernel/cpu/amd.c @@ -105,6 +105,15 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) } #endif +#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_PCI) + /* check CPU config space for extended APIC ID */ + if (cpu_has_apic && c->x86 >= 0xf) { + unsigned int val; + val = read_pci_config(0, 24, 0, 0x68); + if ((val & ((1 << 17) | (1 << 18))) == ((1 << 17) | (1 << 18))) + set_bit(X86_FEATURE_EXTD_APICID, c->x86_capability); + } +#endif /* * FIXME: We should handle the K5 here. Set up the write * range and also turn on MSR 83 bits 4 and 31 (write alloc, diff --git a/include/asm-i386/cpufeature.h b/include/asm-i386/cpufeature.h index 633cc2d..4a305ef 100644 --- a/include/asm-i386/cpufeature.h +++ b/include/asm-i386/cpufeature.h @@ -79,6 +79,7 @@ #define X86_FEATURE_TSC_RELIABLE (3*32+23) /* TSC is known to be reliable */ #define X86_FEATURE_NONSTOP_TSC (3*32+24) /* TSC does not stop in C states */ #define X86_FEATURE_ARAT (3*32+25) /* Always Running APIC Timer */ +#define X86_FEATURE_EXTD_APICID (3*32+26) /* has extended APICID (8 bits) */ #define X86_FEATURE_AMD_DCM (3*32+27) /* multi-node processor */ /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ diff --git a/include/asm-i386/mach-default/mach_apicdef.h b/include/asm-i386/mach-default/mach_apicdef.h index ae98413..c0f4a4a 100644 --- a/include/asm-i386/mach-default/mach_apicdef.h +++ b/include/asm-i386/mach-default/mach_apicdef.h @@ -8,7 +8,7 @@ static inline unsigned get_apic_id(unsigned long x) { unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR)); - if (APIC_XAPIC(ver)) + if (APIC_XAPIC(ver) || boot_cpu_has(X86_FEATURE_EXTD_APICID)) return (((x)>>24)&0xFF); else return (((x)>>24)&0xF);