x86, realmode: Mask out EFER.LMA when saving trampoline EFER
authorH. Peter Anvin <hpa@linux.intel.com>
Wed, 16 May 2012 20:22:41 +0000 (13:22 -0700)
committerH. Peter Anvin <hpa@linux.intel.com>
Wed, 16 May 2012 20:22:41 +0000 (13:22 -0700)
Some AMD processors apparently #GP(0) if EFER.LMA is set in WRMSR,
rather than ignoring it.  Thus, we need to mask it out.

Reported-by: Ingo Molnar <mingo@kernel.org>
Tested-by: Borislav Petkov <bp@alien8.de>
Cc: Jarkko Sakkinen <jarkko.sakkinen@intel.com>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Link: http://lkml.kernel.org/r/1336501366-28617-24-git-send-email-jarkko.sakkinen@intel.com
arch/x86/kernel/realmode.c

index 66ac276..0992779 100644 (file)
@@ -22,6 +22,7 @@ void __init setup_real_mode(void)
        size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob);
 #ifdef CONFIG_X86_64
        u64 *trampoline_pgd;
+       u32 efer_low, efer_high;
 #endif
 
        /* Has to be in very low memory so we can execute real-mode AP code. */
@@ -65,9 +66,13 @@ void __init setup_real_mode(void)
        trampoline_header->gdt_limit = __BOOT_DS + 7;
        trampoline_header->gdt_base = __pa(boot_gdt);
 #else
-       if (rdmsr_safe(MSR_EFER, &trampoline_header->efer_low,
-                      &trampoline_header->efer_high))
-               BUG();
+       /*
+        * Some AMD processors will #GP(0) if EFER.LMA is set in WRMSR
+        * so we need to mask it out.
+        */
+       rdmsr(MSR_EFER, efer_low, efer_high);
+       trampoline_header->efer_low  = efer_low & ~EFER_LMA;
+       trampoline_header->efer_high = efer_high;
 
        trampoline_header->start = (u64) secondary_startup_64;
        trampoline_cr4_features = &trampoline_header->cr4;