On 2021-12-15 11:49:34 -0600, Michael Roth wrote: > > I think needing to pass in the SME/SEV CPUID bits to tell the helper when > to parse encryption bit and when not to is a little bit awkward though. > If there's some agreement that this will ultimately serve the purpose of > handling all (or most) of SME/SEV-related CPUID parsing, then the caller > shouldn't really need to be aware of any individual bit positions. > Maybe a bool could handle that instead, e.g.: > > int get_me_bit(bool sev_only, ...) > > or > > int sme_sev_parse_cpuid(bool sev_only, ...) > > where for boot/compressed sev_only=true, for kernel proper sev_only=false. Implemented using this suggestion, and the patch is at the end. I feel that passing of "true" or "false" to get_me_bit_pos() from sev_enable() and sme_enable() has become less clear now. It is not obvious what the "true" and "false" values mean. However, both implementations (Tom's suggestions and Tom's + Mike's suggestions) are available now. We can pick one of these, or I will redo this if we want a different implementation. Venu --- diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h index 7a5934af9d47..eb202096a1fc 100644 --- a/arch/x86/include/asm/sev.h +++ b/arch/x86/include/asm/sev.h @@ -17,6 +17,48 @@ #define GHCB_PROTOCOL_MAX 2ULL #define GHCB_DEFAULT_USAGE 0ULL +#define AMD_SME_BIT BIT(0) +#define AMD_SEV_BIT BIT(1) + +/* + * Returns the memory encryption bit position, + * if the specified features are supported. + * Returns 0, otherwise. + */ +static inline unsigned int get_me_bit_pos(bool sev_only) +{ + unsigned int eax, ebx, ecx, edx; + unsigned int features; + + features = AMD_SEV_BIT | (sev_only ? 0 : AMD_SME_BIT); + + /* Check for the SME/SEV support leaf */ + eax = 0x80000000; + ecx = 0; + native_cpuid(&eax, &ebx, &ecx, &edx); + if (eax < 0x8000001f) + return 0; + + 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 0; + + /* + * CPUID Fn8000_001F[EBX] + * - Bits 5:0 - Pagetable bit position used to indicate encryption + */ + return ebx & 0x3f; +} + #define VMGEXIT() { asm volatile("rep; vmmcall\n\r"); } enum es_result { diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c index c2bf99522e5e..9a8181893af7 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 int me_bit_pos; bool snp; /* @@ -299,26 +300,9 @@ 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 memory encryption bit position if SEV is supported */ + me_bit_pos = get_me_bit_pos(true); + if (!me_bit_pos) { if (snp) error("SEV-SNP support indicated by CC blob, but not CPUID."); return; @@ -350,7 +334,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(me_bit_pos); } /* Search for Confidential Computing blob in the EFI config table. */ diff --git a/arch/x86/mm/mem_encrypt_identity.c b/arch/x86/mm/mem_encrypt_identity.c index 2f723e106ed3..a4979f61ecc7 100644 --- a/arch/x86/mm/mem_encrypt_identity.c +++ b/arch/x86/mm/mem_encrypt_identity.c @@ -508,38 +508,19 @@ void __init sme_enable(struct boot_params *bp) unsigned long feature_mask; bool active_by_default; unsigned long me_mask; + unsigned int me_bit_pos; 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 memory encryption bit position if SEV or SME are supported */ + me_bit_pos = get_me_bit_pos(false); + if (!me_bit_pos) 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(me_bit_pos); /* Check the SEV MSR whether SEV or SME is enabled */ sev_status = __rdmsr(MSR_AMD64_SEV);