The mem_encrypt=on activates both SME and SEV. Add a new argument to disable the SEV and allow SME. The argument can be useful when SEV has issues and we want to disable it. early_detect_mem_encrypt() [cpu/amd.com] will need to know the state of the mem_encrypt= argument. Since early_detect_mem_encrypt() is not defined as __init hence we are not able to use the 'boot_command_line' variable to parse the cmdline argument. We introduce a new function me_cmdline_state() to get the cmdline state from mem_encrypt.c. Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx> Cc: Ingo Molnar <mingo@xxxxxxxxxx> Cc: "H. Peter Anvin" <hpa@xxxxxxxxx> Cc: Paolo Bonzini <pbonzini@xxxxxxxxxx> Cc: "Radim Krčmář" <rkrcmar@xxxxxxxxxx> Cc: Borislav Petkov <bp@xxxxxxx> Cc: kvm@xxxxxxxxxxxxxxx Cc: x86@xxxxxxxxxx Cc: linux-kernel@xxxxxxxxxxxxxxx Cc: Tom Lendacky <thomas.lendacky@xxxxxxx> Signed-off-by: Brijesh Singh <brijesh.singh@xxxxxxx> --- Boris, The patch depends on "x86/CPU/AMD: Add the SEV CPU feature" from Part2 [1]. [1] https://patchwork.kernel.org/patch/9960315/ Documentation/admin-guide/kernel-parameters.txt | 5 +++-- arch/x86/include/asm/mem_encrypt.h | 2 ++ arch/x86/kernel/cpu/amd.c | 10 +++++++++ arch/x86/mm/mem_encrypt.c | 27 +++++++++++++++++++++---- include/linux/mem_encrypt.h | 7 +++++++ 5 files changed, 45 insertions(+), 6 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 05496622b4ef..811e0aca1c0b 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -2238,8 +2238,9 @@ Default (depends on kernel configuration option): on (CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT=y) off (CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT=n) - mem_encrypt=on: Activate SME - mem_encrypt=off: Do not activate SME + mem_encrypt=on: Activate SME and SEV + mem_encrypt=off: Do not activate SME and SEV + mem_encrypt=sme: Activate SME only Refer to Documentation/x86/amd-memory-encryption.txt for details on when memory encryption can be activated. diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h index 3ba68c92be1b..0f012ff9691d 100644 --- a/arch/x86/include/asm/mem_encrypt.h +++ b/arch/x86/include/asm/mem_encrypt.h @@ -52,6 +52,7 @@ void swiotlb_set_mem_attributes(void *vaddr, unsigned long size); bool sme_active(void); bool sev_active(void); +unsigned int me_cmdline_state(void); #else /* !CONFIG_AMD_MEM_ENCRYPT */ @@ -72,6 +73,7 @@ static inline void __init sme_enable(struct boot_params *bp) { } static inline bool sme_active(void) { return false; } static inline bool sev_active(void) { return false; } +static inline unsigned int me_cmdline_state(void) { return ME_CMDLINE_OFF; } static inline int __init early_set_memory_decrypted(resource_size_t paddr, unsigned long size) { return 0; } diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index c1234aa0550c..10dfa7f1f34d 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -592,6 +592,16 @@ static void early_detect_mem_encrypt(struct cpuinfo_x86 *c) if (!(msr & MSR_K7_HWCR_SMMLOCK)) goto clear_sev; + /* Check for the mem_encrypt cmdline parameter and act accordingly. */ + switch (me_cmdline_state()) { + case ME_CMDLINE_OFF: + goto clear_all; + case ME_CMDLINE_SME: + goto clear_sev; + default: + break; + } + return; clear_all: diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c index 057417a3d9b4..183cd481a55f 100644 --- a/arch/x86/mm/mem_encrypt.c +++ b/arch/x86/mm/mem_encrypt.c @@ -33,6 +33,7 @@ static char sme_cmdline_arg[] __initdata = "mem_encrypt"; static char sme_cmdline_on[] __initdata = "on"; static char sme_cmdline_off[] __initdata = "off"; +static char sme_cmdline_sme[] __initdata = "sme"; /* * Since SME related variables are set early in the boot process they must @@ -45,6 +46,7 @@ DEFINE_STATIC_KEY_FALSE(__sev); EXPORT_SYMBOL_GPL(__sev); static bool sev_enabled __section(.data) = false; +static unsigned int cmdline_state __section(.data) = ME_CMDLINE_OFF; /* Buffer used for early in-place encryption by BSP, no locking needed */ static char sme_early_buffer[PAGE_SIZE] __aligned(PAGE_SIZE); @@ -403,6 +405,11 @@ bool sev_active(void) } EXPORT_SYMBOL_GPL(sev_active); +unsigned int me_cmdline_state(void) +{ + return cmdline_state; +} + static const struct dma_map_ops sev_dma_ops = { .alloc = sev_alloc, .free = sev_free, @@ -768,7 +775,7 @@ void __init sme_encrypt_kernel(void) void __init __nostackprotector sme_enable(struct boot_params *bp) { - const char *cmdline_ptr, *cmdline_arg, *cmdline_on, *cmdline_off; + const char *cmdline_ptr, *cmdline_arg, *cmdline_on, *cmdline_off, *cmdline_sme; unsigned int eax, ebx, ecx, edx; unsigned long feature_mask; bool active_by_default; @@ -842,6 +849,9 @@ void __init __nostackprotector sme_enable(struct boot_params *bp) asm ("lea sme_cmdline_off(%%rip), %0" : "=r" (cmdline_off) : "p" (sme_cmdline_off)); + asm ("lea sme_cmdline_sme(%%rip), %0" + : "=r" (cmdline_sme) + : "p" (sme_cmdline_sme)); if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT)) active_by_default = true; @@ -853,10 +863,19 @@ void __init __nostackprotector sme_enable(struct boot_params *bp) cmdline_find_option(cmdline_ptr, cmdline_arg, buffer, sizeof(buffer)); - if (!strncmp(buffer, cmdline_on, sizeof(buffer))) + if (!strncmp(buffer, cmdline_on, sizeof(buffer))) { sme_me_mask = me_mask; - else if (!strncmp(buffer, cmdline_off, sizeof(buffer))) + cmdline_state = ME_CMDLINE_ON; + } else if (!strncmp(buffer, cmdline_off, sizeof(buffer))) { sme_me_mask = 0; - else + cmdline_state = ME_CMDLINE_OFF; + } else if (!strncmp(buffer, cmdline_sme, sizeof(buffer))) { + sme_me_mask = me_mask; + cmdline_state = ME_CMDLINE_SME; + } else { sme_me_mask = active_by_default ? me_mask : 0; + if (active_by_default) + cmdline_state = ME_CMDLINE_ON; + } + } diff --git a/include/linux/mem_encrypt.h b/include/linux/mem_encrypt.h index b310a9c18113..7863cf2137e0 100644 --- a/include/linux/mem_encrypt.h +++ b/include/linux/mem_encrypt.h @@ -15,6 +15,12 @@ #ifndef __ASSEMBLY__ +enum { + ME_CMDLINE_OFF, + ME_CMDLINE_ON, + ME_CMDLINE_SME +}; + #ifdef CONFIG_ARCH_HAS_MEM_ENCRYPT #include <asm/mem_encrypt.h> @@ -25,6 +31,7 @@ static inline bool sme_active(void) { return false; } static inline bool sev_active(void) { return false; } +static unsigned int me_cmdline_state(void) { return ME_CMDLINE_OFF; } #endif /* CONFIG_ARCH_HAS_MEM_ENCRYPT */ -- 2.9.5