Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86: Fix boot failures on older AMD CPU's

People with old AMD chips are getting hung boots, because commit
bcb80e53877c ("x86, microcode, AMD: Add microcode revision to
/proc/cpuinfo") moved the microcode detection too early into
"early_init_amd()".

At that point we are *so* early in the booth that the exception tables
haven't even been set up yet, so the whole

rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);

doesn't actually work: if the rdmsr does a GP fault (due to non-existant
MSR register on older CPU's), we can't fix it up yet, and the boot fails.

Fix it by simply moving the code to a slightly later point in the boot
(init_amd() instead of early_init_amd()), since the kernel itself
doesn't even really care about the microcode patchlevel at this point
(or really ever: it's made available to user space in /proc/cpuinfo, and
updated if you do a microcode load).

Reported-tested-and-bisected-by: Larry Finger <Larry.Finger@lwfinger.net>
Tested-by: Bob Tracy <rct@gherkin.frus.com>
Acked-by: Borislav Petkov <borislav.petkov@amd.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

+4 -4
+4 -4
arch/x86/kernel/cpu/amd.c
··· 442 442 443 443 static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) 444 444 { 445 - u32 dummy; 446 - 447 445 early_init_amd_mc(c); 448 446 449 447 /* ··· 471 473 set_cpu_cap(c, X86_FEATURE_EXTD_APICID); 472 474 } 473 475 #endif 474 - 475 - rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy); 476 476 } 477 477 478 478 static void __cpuinit init_amd(struct cpuinfo_x86 *c) 479 479 { 480 + u32 dummy; 481 + 480 482 #ifdef CONFIG_SMP 481 483 unsigned long long value; 482 484 ··· 655 657 checking_wrmsrl(MSR_AMD64_MCx_MASK(4), mask); 656 658 } 657 659 } 660 + 661 + rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy); 658 662 } 659 663 660 664 #ifdef CONFIG_X86_32