Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
From: Venu Busireddy <hidden>
Date: 2021-12-15 00:15:39
Also in:
kvm, linux-coco, linux-mm, lkml, platform-driver-x86
Subsystem:
the rest, x86 architecture (32-bit and 64-bit), x86 mm · Maintainers:
Linus Torvalds, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, Andy Lutomirski, Peter Zijlstra
On 2021-12-14 20:10:16 +0100, Borislav Petkov wrote:
On Tue, Dec 14, 2021 at 11:46:14AM -0600, Venu Busireddy wrote:quoted
What I am suggesting should not have anything to do with the boot stage of the kernel.I know exactly what you're suggesting.quoted
For example, both these functions call native_cpuid(), which is declared as an inline function. I am merely suggesting to do something similar to avoid the code duplication.Try it yourself. If you can come up with something halfway readable and it builds, I'm willing to take a look.
Patch (to be applied on top of sev-snp-v8 branch of https://github.com/AMDESE/linux.git) is attached at the end. Here are a few things I did. 1. Moved all the common code that existed at the begining of sme_enable() and sev_enable() to an inline function named get_pagetable_bit_pos(). 2. sme_enable() was using AMD_SME_BIT and AMD_SEV_BIT, whereas sev_enable() was dealing with raw bits. Moved those definitions to sev.h, and changed sev_enable() to use those definitions. 3. Make consistent use of BIT_ULL. Venu
diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
index c2bf99522e5e..b44d6b37796e 100644
--- a/arch/x86/boot/compressed/sev.c
+++ b/arch/x86/boot/compressed/sev.c@@ -291,6 +291,7 @@ static void enforce_vmpl0(void) void sev_enable(struct boot_params *bp) { unsigned int eax, ebx, ecx, edx; + unsigned long pt_bit_pos; /* Pagetable bit position */ bool snp; /*
@@ -299,26 +300,8 @@ void sev_enable(struct boot_params *bp) */ snp = snp_init(bp); - /* Check for the SME/SEV support leaf */ - eax = 0x80000000; - ecx = 0; - native_cpuid(&eax, &ebx, &ecx, &edx); - if (eax < 0x8000001f) - return; - - /* - * Check for the SME/SEV feature: - * CPUID Fn8000_001F[EAX] - * - Bit 0 - Secure Memory Encryption support - * - Bit 1 - Secure Encrypted Virtualization 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); - /* Check whether SEV is supported */ - if (!(eax & BIT(1))) { + /* Get the pagetable bit position if SEV is supported */ + if ((get_pagetable_bit_pos(&pt_bit_pos, AMD_SEV_BIT)) < 0) { if (snp) error("SEV-SNP support indicated by CC blob, but not CPUID."); return;
@@ -350,7 +333,7 @@ void sev_enable(struct boot_params *bp) if (snp && !(sev_status & MSR_AMD64_SEV_SNP_ENABLED)) error("SEV-SNP supported indicated by CC blob, but not SEV status MSR."); - sme_me_mask = BIT_ULL(ebx & 0x3f); + sme_me_mask = BIT_ULL(pt_bit_pos); } /* Search for Confidential Computing blob in the EFI config table. */
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 2c5f12ae7d04..41b096f28d02 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h@@ -224,6 +224,43 @@ static inline void native_cpuid(unsigned int *eax, unsigned int *ebx, : "memory"); } +/* + * Returns the pagetable bit position in pt_bit_pos, + * iff the specified features are supported. + */ +static inline int get_pagetable_bit_pos(unsigned long *pt_bit_pos, + unsigned long features) +{ + unsigned int eax, ebx, ecx, edx; + + /* Check for the SME/SEV support leaf */ + eax = 0x80000000; + ecx = 0; + native_cpuid(&eax, &ebx, &ecx, &edx); + if (eax < 0x8000001f) + return -1; + + eax = 0x8000001f; + ecx = 0; + native_cpuid(&eax, &ebx, &ecx, &edx); + + /* Check whether the specified features are supported. + * SME/SEV features: + * CPUID Fn8000_001F[EAX] + * - Bit 0 - Secure Memory Encryption support + * - Bit 1 - Secure Encrypted Virtualization support + */ + if (!(eax & features)) + return -1; + + /* + * CPUID Fn8000_001F[EBX] + * - Bits 5:0 - Pagetable bit position used to indicate encryption + */ + *pt_bit_pos = (unsigned long)(ebx & 0x3f); + return 0; +} + #define native_cpuid_reg(reg) \ static inline unsigned int native_cpuid_##reg(unsigned int op) \ { \
diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index 7a5934af9d47..1a2344362ec6 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h@@ -17,6 +17,9 @@ #define GHCB_PROTOCOL_MAX 2ULL #define GHCB_DEFAULT_USAGE 0ULL +#define AMD_SME_BIT BIT(0) +#define AMD_SEV_BIT BIT(1) + #define VMGEXIT() { asm volatile("rep; vmmcall\n\r"); } enum es_result {
diff --git a/arch/x86/mm/mem_encrypt_identity.c b/arch/x86/mm/mem_encrypt_identity.c
index 2f723e106ed3..1ef50e969efd 100644
--- a/arch/x86/mm/mem_encrypt_identity.c
+++ b/arch/x86/mm/mem_encrypt_identity.c@@ -508,38 +508,18 @@ void __init sme_enable(struct boot_params *bp) unsigned long feature_mask; bool active_by_default; unsigned long me_mask; + unsigned long pt_bit_pos; /* Pagetable bit position */ char buffer[16]; bool snp; u64 msr; snp = snp_init(bp); - /* Check for the SME/SEV support leaf */ - eax = 0x80000000; - ecx = 0; - native_cpuid(&eax, &ebx, &ecx, &edx); - if (eax < 0x8000001f) + /* Get the pagetable bit position if SEV or SME are supported */ + if ((get_pagetable_bit_pos(&pt_bit_pos, AMD_SEV_BIT | AMD_SME_BIT)) < 0) return; -#define AMD_SME_BIT BIT(0) -#define AMD_SEV_BIT BIT(1) - - /* - * Check for the SME/SEV feature: - * CPUID Fn8000_001F[EAX] - * - Bit 0 - Secure Memory Encryption support - * - Bit 1 - Secure Encrypted Virtualization 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); - /* Check whether SEV or SME is supported */ - if (!(eax & (AMD_SEV_BIT | AMD_SME_BIT))) - return; - - me_mask = 1UL << (ebx & 0x3f); + me_mask = BIT_ULL(pt_bit_pos); /* Check the SEV MSR whether SEV or SME is enabled */ sev_status = __rdmsr(MSR_AMD64_SEV);