Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 12/14/21 6:14 PM, Venu Busireddy wrote:
On 2021-12-14 20:10:16 +0100, Borislav Petkov wrote:
On Tue, Dec 14, 2021 at 11:46:14AM -0600, Venu Busireddy wrote:
What I am suggesting should not have anything to do with the boot stage
of the kernel.

I know exactly what you're suggesting.

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://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FAMDESE%2Flinux.git&data=04%7C01%7Cthomas.lendacky%40amd.com%7Cbff83ee03b1147c39ea808d9bf5fe9d8%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637751240978266883%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&sdata=D8t%2FwXY%2FYIl8aJXN%2BU7%2Flubln8AbhtdgB0f4DCNWp4w%3D&reserved=0) 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)

I'm not a fan of this name. You are specifically returning the encryption bit position but using a very generic name of get_pagetable_bit_pos() in a very common header file. Maybe something more like get_me_bit() and move the function to an existing SEV header file.

Also, this can probably just return an unsigned int that will be either 0 or the bit position, right? Then the check above can be for a zero value, e.g.:

	me_bit = get_me_bit();
	if (!me_bit) {

	...

	sme_me_mask = BIT_ULL(me_bit);

That should work below, too, but you'll need to verify that.

+{
+	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;

This can then be:

		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 -1;

and this can be:

		return 0;

+
+	/*
+	 *   CPUID Fn8000_001F[EBX]
+	 *   - Bits 5:0 - Pagetable bit position used to indicate encryption
+	 */
+	*pt_bit_pos = (unsigned long)(ebx & 0x3f);

and this can be:

	return 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)
+

Maybe this is where that new static inline function should go...

  #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 */

unsigned int and me_bit or me_bit_pos.

Thanks,
Tom

  	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);




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux