[RFC PATCH v3 20/20] x86: Add support to make use of Secure Memory Encryption

From: Tom Lendacky
Date: Wed Nov 09 2016 - 19:54:15 EST


This patch adds the support to check if SME has been enabled and if the
mem_encrypt=on command line option is set. If both of these conditions
are true, then the encryption mask is set and the kernel is encrypted
"in place."

Signed-off-by: Tom Lendacky <thomas.lendacky@xxxxxxx>
---
arch/x86/kernel/head_64.S | 1 +
arch/x86/kernel/mem_encrypt_init.c | 60 +++++++++++++++++++++++++++++++++++-
arch/x86/mm/mem_encrypt.c | 2 +
3 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index e8a7272..c225433 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -100,6 +100,7 @@ startup_64:
* to include it in the page table fixups.
*/
push %rsi
+ movq %rsi, %rdi
call sme_enable
pop %rsi
movq %rax, %r12
diff --git a/arch/x86/kernel/mem_encrypt_init.c b/arch/x86/kernel/mem_encrypt_init.c
index 7bdd159..c94ceb8 100644
--- a/arch/x86/kernel/mem_encrypt_init.c
+++ b/arch/x86/kernel/mem_encrypt_init.c
@@ -16,9 +16,14 @@
#include <linux/mm.h>

#include <asm/sections.h>
+#include <asm/processor-flags.h>
+#include <asm/msr.h>
+#include <asm/cmdline.h>

#ifdef CONFIG_AMD_MEM_ENCRYPT

+static char sme_cmdline_arg[] __initdata = "mem_encrypt=on";
+
extern void sme_encrypt_execute(unsigned long, unsigned long, unsigned long,
void *, pgd_t *);

@@ -219,7 +224,60 @@ unsigned long __init sme_get_me_mask(void)
return sme_me_mask;
}

-unsigned long __init sme_enable(void)
+unsigned long __init sme_enable(void *boot_data)
{
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+ struct boot_params *bp = boot_data;
+ unsigned int eax, ebx, ecx, edx;
+ u64 msr;
+ unsigned long cmdline_ptr;
+ void *cmdline_arg;
+
+ /* Check for an AMD processor */
+ eax = 0;
+ ecx = 0;
+ native_cpuid(&eax, &ebx, &ecx, &edx);
+ if ((ebx != 0x68747541) || (edx != 0x69746e65) || (ecx != 0x444d4163))
+ goto out;
+
+ /* Check for the SME support leaf */
+ eax = 0x80000000;
+ ecx = 0;
+ native_cpuid(&eax, &ebx, &ecx, &edx);
+ if (eax < 0x8000001f)
+ goto out;
+
+ /*
+ * 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))
+ goto out;
+
+ /* Check if SME is enabled */
+ msr = native_read_msr(MSR_K8_SYSCFG);
+ if (!(msr & MSR_K8_SYSCFG_MEM_ENCRYPT))
+ goto out;
+
+ /*
+ * Fixups have not been to applied phys_base yet, so we must obtain
+ * the address to the SME command line option in the following way.
+ */
+ asm ("lea sme_cmdline_arg(%%rip), %0"
+ : "=r" (cmdline_arg)
+ : "p" (sme_cmdline_arg));
+ cmdline_ptr = bp->hdr.cmd_line_ptr | ((u64)bp->ext_cmd_line_ptr << 32);
+ if (cmdline_find_option_bool((char *)cmdline_ptr, cmdline_arg))
+ sme_me_mask = 1UL << (ebx & 0x3f);
+
+out:
+#endif /* CONFIG_AMD_MEM_ENCRYPT */
+
return sme_me_mask;
}
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index e351003..d0bc3f5 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -251,6 +251,8 @@ void __init mem_encrypt_init(void)

/* Make SWIOTLB use an unencrypted DMA area */
swiotlb_clear_encryption();
+
+ pr_info("AMD Secure Memory Encryption active\n");
}

void swiotlb_set_mem_unenc(void *vaddr, unsigned long size)