x86/boot/realmode: Check for memory encryption on the APs
authorTom Lendacky <thomas.lendacky@amd.com>
Mon, 17 Jul 2017 21:10:25 +0000 (16:10 -0500)
committerIngo Molnar <mingo@kernel.org>
Tue, 18 Jul 2017 09:38:04 +0000 (11:38 +0200)
Add support to check if memory encryption is active in the kernel and that
it has been enabled on the AP. If memory encryption is active in the kernel
but has not been enabled on the AP, then set the memory encryption bit (bit
23) of MSR_K8_SYSCFG to enable memory encryption on that AP and allow the
AP to continue start up.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Borislav Petkov <bp@suse.de>
Cc: Alexander Potapenko <glider@google.com>
Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Dave Young <dyoung@redhat.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Larry Woodman <lwoodman@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Matt Fleming <matt@codeblueprint.co.uk>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Radim Krčmář <rkrcmar@redhat.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Toshimitsu Kani <toshi.kani@hpe.com>
Cc: kasan-dev@googlegroups.com
Cc: kvm@vger.kernel.org
Cc: linux-arch@vger.kernel.org
Cc: linux-doc@vger.kernel.org
Cc: linux-efi@vger.kernel.org
Cc: linux-mm@kvack.org
Link: http://lkml.kernel.org/r/37e29b99c395910f56ca9f8ecf7b0439b28827c8.1500319216.git.thomas.lendacky@amd.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
arch/x86/include/asm/realmode.h
arch/x86/realmode/init.c
arch/x86/realmode/rm/trampoline_64.S

index 230e1903acf07faa831c8d2496a4457aaae9b5ea..90d91520c13ab09b566ca0a599a6170353153e47 100644 (file)
@@ -1,6 +1,15 @@
 #ifndef _ARCH_X86_REALMODE_H
 #define _ARCH_X86_REALMODE_H
 
+/*
+ * Flag bit definitions for use with the flags field of the trampoline header
+ * in the CONFIG_X86_64 variant.
+ */
+#define TH_FLAGS_SME_ACTIVE_BIT                0
+#define TH_FLAGS_SME_ACTIVE            BIT(TH_FLAGS_SME_ACTIVE_BIT)
+
+#ifndef __ASSEMBLY__
+
 #include <linux/types.h>
 #include <asm/io.h>
 
@@ -38,6 +47,7 @@ struct trampoline_header {
        u64 start;
        u64 efer;
        u32 cr4;
+       u32 flags;
 #endif
 };
 
@@ -69,4 +79,6 @@ static inline size_t real_mode_size_needed(void)
 void set_real_mode_mem(phys_addr_t mem, size_t size);
 void reserve_real_mode(void);
 
+#endif /* __ASSEMBLY__ */
+
 #endif /* _ARCH_X86_REALMODE_H */
index d6ddc7e60884878c9004afd2dcd3b532c5a3d28d..1f71980fc5e0fa9983c1687aa4ff81f02eb0b989 100644 (file)
@@ -108,6 +108,10 @@ static void __init setup_real_mode(void)
        trampoline_cr4_features = &trampoline_header->cr4;
        *trampoline_cr4_features = mmu_cr4_features;
 
+       trampoline_header->flags = 0;
+       if (sme_active())
+               trampoline_header->flags |= TH_FLAGS_SME_ACTIVE;
+
        trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd);
        trampoline_pgd[0] = trampoline_pgd_entry.pgd;
        trampoline_pgd[511] = init_top_pgt[511].pgd;
index dac7b20d2f9de40f0244f623e8560c304394c178..614fd7064d0a21366c3f27721e610038fda1e9b0 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/msr.h>
 #include <asm/segment.h>
 #include <asm/processor-flags.h>
+#include <asm/realmode.h>
 #include "realmode.h"
 
        .text
@@ -92,6 +93,28 @@ ENTRY(startup_32)
        movl    %edx, %fs
        movl    %edx, %gs
 
+       /*
+        * Check for memory encryption support. This is a safety net in
+        * case BIOS hasn't done the necessary step of setting the bit in
+        * the MSR for this AP. If SME is active and we've gotten this far
+        * then it is safe for us to set the MSR bit and continue. If we
+        * don't we'll eventually crash trying to execute encrypted
+        * instructions.
+        */
+       bt      $TH_FLAGS_SME_ACTIVE_BIT, pa_tr_flags
+       jnc     .Ldone
+       movl    $MSR_K8_SYSCFG, %ecx
+       rdmsr
+       bts     $MSR_K8_SYSCFG_MEM_ENCRYPT_BIT, %eax
+       jc      .Ldone
+
+       /*
+        * Memory encryption is enabled but the SME enable bit for this
+        * CPU has has not been set.  It is safe to set it, so do so.
+        */
+       wrmsr
+.Ldone:
+
        movl    pa_tr_cr4, %eax
        movl    %eax, %cr4              # Enable PAE mode
 
@@ -147,6 +170,7 @@ GLOBAL(trampoline_header)
        tr_start:               .space  8
        GLOBAL(tr_efer)         .space  8
        GLOBAL(tr_cr4)          .space  4
+       GLOBAL(tr_flags)        .space  4
 END(trampoline_header)
 
 #include "trampoline_common.S"