Commit aca20d54 authored by Tom Lendacky's avatar Tom Lendacky Committed by Ingo Molnar

x86/mm: Add support to make use of Secure Memory Encryption

Add support to check if SME has been enabled and if memory encryption
should be activated (checking of command line option based on the
configuration of the default state).  If memory encryption is to be
activated, then the encryption mask is set and the kernel is encrypted
"in place."
Signed-off-by: default avatarTom Lendacky <thomas.lendacky@amd.com>
Reviewed-by: default avatarThomas Gleixner <tglx@linutronix.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/5f0da2fd4cce63f556117549e2c89c170072209f.1500319216.git.thomas.lendacky@amd.comSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 7375ae3a
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#include <linux/init.h> #include <linux/init.h>
#include <asm/bootparam.h>
#ifdef CONFIG_AMD_MEM_ENCRYPT #ifdef CONFIG_AMD_MEM_ENCRYPT
extern unsigned long sme_me_mask; extern unsigned long sme_me_mask;
...@@ -38,7 +40,7 @@ void __init sme_unmap_bootdata(char *real_mode_data); ...@@ -38,7 +40,7 @@ void __init sme_unmap_bootdata(char *real_mode_data);
void __init sme_early_init(void); void __init sme_early_init(void);
void __init sme_encrypt_kernel(void); void __init sme_encrypt_kernel(void);
void __init sme_enable(void); void __init sme_enable(struct boot_params *bp);
/* Architecture __weak replacement functions */ /* Architecture __weak replacement functions */
void __init mem_encrypt_init(void); void __init mem_encrypt_init(void);
...@@ -60,7 +62,7 @@ static inline void __init sme_unmap_bootdata(char *real_mode_data) { } ...@@ -60,7 +62,7 @@ static inline void __init sme_unmap_bootdata(char *real_mode_data) { }
static inline void __init sme_early_init(void) { } static inline void __init sme_early_init(void) { }
static inline void __init sme_encrypt_kernel(void) { } static inline void __init sme_encrypt_kernel(void) { }
static inline void __init sme_enable(void) { } static inline void __init sme_enable(struct boot_params *bp) { }
#endif /* CONFIG_AMD_MEM_ENCRYPT */ #endif /* CONFIG_AMD_MEM_ENCRYPT */
......
...@@ -45,7 +45,8 @@ static void __head *fixup_pointer(void *ptr, unsigned long physaddr) ...@@ -45,7 +45,8 @@ static void __head *fixup_pointer(void *ptr, unsigned long physaddr)
return ptr - (void *)_text + (void *)physaddr; return ptr - (void *)_text + (void *)physaddr;
} }
unsigned long __head __startup_64(unsigned long physaddr) unsigned long __head __startup_64(unsigned long physaddr,
struct boot_params *bp)
{ {
unsigned long load_delta, *p; unsigned long load_delta, *p;
unsigned long pgtable_flags; unsigned long pgtable_flags;
...@@ -70,7 +71,7 @@ unsigned long __head __startup_64(unsigned long physaddr) ...@@ -70,7 +71,7 @@ unsigned long __head __startup_64(unsigned long physaddr)
for (;;); for (;;);
/* Activate Secure Memory Encryption (SME) if supported and enabled */ /* Activate Secure Memory Encryption (SME) if supported and enabled */
sme_enable(); sme_enable(bp);
/* Include the SME encryption mask in the fixup value */ /* Include the SME encryption mask in the fixup value */
load_delta += sme_get_me_mask(); load_delta += sme_get_me_mask();
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/swiotlb.h> #include <linux/swiotlb.h>
#include <linux/mem_encrypt.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/fixmap.h> #include <asm/fixmap.h>
...@@ -23,6 +24,13 @@ ...@@ -23,6 +24,13 @@
#include <asm/set_memory.h> #include <asm/set_memory.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/sections.h> #include <asm/sections.h>
#include <asm/processor-flags.h>
#include <asm/msr.h>
#include <asm/cmdline.h>
static char sme_cmdline_arg[] __initdata = "mem_encrypt";
static char sme_cmdline_on[] __initdata = "on";
static char sme_cmdline_off[] __initdata = "off";
/* /*
* Since SME related variables are set early in the boot process they must * Since SME related variables are set early in the boot process they must
...@@ -190,6 +198,8 @@ void __init mem_encrypt_init(void) ...@@ -190,6 +198,8 @@ void __init mem_encrypt_init(void)
/* Call into SWIOTLB to update the SWIOTLB DMA buffers */ /* Call into SWIOTLB to update the SWIOTLB DMA buffers */
swiotlb_update_mem_attributes(); swiotlb_update_mem_attributes();
pr_info("AMD Secure Memory Encryption (SME) active\n");
} }
void swiotlb_set_mem_attributes(void *vaddr, unsigned long size) void swiotlb_set_mem_attributes(void *vaddr, unsigned long size)
...@@ -513,6 +523,71 @@ void __init sme_encrypt_kernel(void) ...@@ -513,6 +523,71 @@ void __init sme_encrypt_kernel(void)
native_write_cr3(__native_read_cr3()); native_write_cr3(__native_read_cr3());
} }
void __init sme_enable(void) void __init __nostackprotector sme_enable(struct boot_params *bp)
{ {
const char *cmdline_ptr, *cmdline_arg, *cmdline_on, *cmdline_off;
unsigned int eax, ebx, ecx, edx;
bool active_by_default;
unsigned long me_mask;
char buffer[16];
u64 msr;
/* Check for the SME support leaf */
eax = 0x80000000;
ecx = 0;
native_cpuid(&eax, &ebx, &ecx, &edx);
if (eax < 0x8000001f)
return;
/*
* Check for the SME feature:
* CPUID Fn8000_001F[EAX] - Bit 0
* Secure Memory Encryption support
* CPUID Fn8000_001F[EBX] - Bits 5:0
* Pagetable bit position used to indicate encryption
*/
eax = 0x8000001f;
ecx = 0;
native_cpuid(&eax, &ebx, &ecx, &edx);
if (!(eax & 1))
return;
me_mask = 1UL << (ebx & 0x3f);
/* Check if SME is enabled */
msr = __rdmsr(MSR_K8_SYSCFG);
if (!(msr & MSR_K8_SYSCFG_MEM_ENCRYPT))
return;
/*
* Fixups have not been applied to phys_base yet and we're running
* identity mapped, so we must obtain the address to the SME command
* line argument data using rip-relative addressing.
*/
asm ("lea sme_cmdline_arg(%%rip), %0"
: "=r" (cmdline_arg)
: "p" (sme_cmdline_arg));
asm ("lea sme_cmdline_on(%%rip), %0"
: "=r" (cmdline_on)
: "p" (sme_cmdline_on));
asm ("lea sme_cmdline_off(%%rip), %0"
: "=r" (cmdline_off)
: "p" (sme_cmdline_off));
if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT))
active_by_default = true;
else
active_by_default = false;
cmdline_ptr = (const char *)((u64)bp->hdr.cmd_line_ptr |
((u64)bp->ext_cmd_line_ptr << 32));
cmdline_find_option(cmdline_ptr, cmdline_arg, buffer, sizeof(buffer));
if (!strncmp(buffer, cmdline_on, sizeof(buffer)))
sme_me_mask = me_mask;
else if (!strncmp(buffer, cmdline_off, sizeof(buffer)))
sme_me_mask = 0;
else
sme_me_mask = active_by_default ? me_mask : 0;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment