* [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2021-12-10 15:42 [PATCH v8 00/40] Add AMD Secure Nested Paging (SEV-SNP) Guest Support Brijesh Singh
@ 2021-12-10 15:42 ` Brijesh Singh
2021-12-10 18:47 ` Dave Hansen
` (2 more replies)
2021-12-10 15:42 ` [PATCH v8 02/40] x86/sev: " Brijesh Singh
` (39 subsequent siblings)
40 siblings, 3 replies; 183+ messages in thread
From: Brijesh Singh @ 2021-12-10 15:42 UTC (permalink / raw)
To: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm
Cc: Thomas Gleixner, Ingo Molnar, Joerg Roedel, Tom Lendacky,
H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy, Brijesh Singh
From: Michael Roth <michael.roth@amd.com>
With upcoming SEV-SNP support, SEV-related features need to be
initialized earlier in boot, at the same point the initial #VC handler
is set up, so that the SEV-SNP CPUID table can be utilized during the
initial feature checks. Also, SEV-SNP feature detection will rely on
EFI helper functions to scan the EFI config table for the Confidential
Computing blob, and so would need to be implemented at least partially
in C.
Currently set_sev_encryption_mask() is used to initialize the
sev_status and sme_me_mask globals that advertise what SEV/SME features
are available in a guest. Rename it to sev_enable() to better reflect
that (SME is only enabled in the case of SEV guests in the
boot/compressed kernel), and move it to just after the stage1 #VC
handler is set up so that it can be used to initialize SEV-SNP as well
in future patches.
While at it, re-implement it as C code so that all SEV feature
detection can be better consolidated with upcoming SEV-SNP feature
detection, which will also be in C.
The 32-bit entry path remains unchanged, as it never relied on the
set_sev_encryption_mask() initialization to begin with, possibly due to
the normal rva() helper for accessing globals only being usable by code
in .head.text. Either way, 32-bit entry for SEV-SNP would likely only
be supported for non-EFI boot paths, and so wouldn't rely on existing
EFI helper functions, and so could be handled by a separate/simpler
32-bit initializer in the future if needed.
Signed-off-by: Michael Roth <michael.roth@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
arch/x86/boot/compressed/head_64.S | 32 ++++++++++--------
arch/x86/boot/compressed/mem_encrypt.S | 36 ---------------------
arch/x86/boot/compressed/misc.h | 4 +--
arch/x86/boot/compressed/sev.c | 45 ++++++++++++++++++++++++++
4 files changed, 66 insertions(+), 51 deletions(-)
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index 572c535cf45b..20b174adca51 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -191,9 +191,8 @@ SYM_FUNC_START(startup_32)
/*
* Mark SEV as active in sev_status so that startup32_check_sev_cbit()
* will do a check. The sev_status memory will be fully initialized
- * with the contents of MSR_AMD_SEV_STATUS later in
- * set_sev_encryption_mask(). For now it is sufficient to know that SEV
- * is active.
+ * with the contents of MSR_AMD_SEV_STATUS later via sev_enable(). For
+ * now it is sufficient to know that SEV is active.
*/
movl $1, rva(sev_status)(%ebp)
1:
@@ -447,6 +446,23 @@ SYM_CODE_START(startup_64)
call load_stage1_idt
popq %rsi
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+ /*
+ * Now that the stage1 interrupt handlers are set up, #VC exceptions from
+ * CPUID instructions can be properly handled for SEV-ES guests.
+ *
+ * For SEV-SNP, the CPUID table also needs to be set up in advance of any
+ * CPUID instructions being issued, so go ahead and do that now via
+ * sev_enable(), which will also handle the rest of the SEV-related
+ * detection/setup to ensure that has been done in advance of any dependent
+ * code.
+ */
+ pushq %rsi
+ movq %rsi, %rdi /* real mode address */
+ call sev_enable
+ popq %rsi
+#endif
+
/*
* paging_prepare() sets up the trampoline and checks if we need to
* enable 5-level paging.
@@ -559,17 +575,7 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
shrq $3, %rcx
rep stosq
-/*
- * If running as an SEV guest, the encryption mask is required in the
- * page-table setup code below. When the guest also has SEV-ES enabled
- * set_sev_encryption_mask() will cause #VC exceptions, but the stage2
- * handler can't map its GHCB because the page-table is not set up yet.
- * So set up the encryption mask here while still on the stage1 #VC
- * handler. Then load stage2 IDT and switch to the kernel's own
- * page-table.
- */
pushq %rsi
- call set_sev_encryption_mask
call load_stage2_idt
/* Pass boot_params to initialize_identity_maps() */
diff --git a/arch/x86/boot/compressed/mem_encrypt.S b/arch/x86/boot/compressed/mem_encrypt.S
index c1e81a848b2a..311d40f35a4b 100644
--- a/arch/x86/boot/compressed/mem_encrypt.S
+++ b/arch/x86/boot/compressed/mem_encrypt.S
@@ -187,42 +187,6 @@ SYM_CODE_END(startup32_vc_handler)
.code64
#include "../../kernel/sev_verify_cbit.S"
-SYM_FUNC_START(set_sev_encryption_mask)
-#ifdef CONFIG_AMD_MEM_ENCRYPT
- push %rbp
- push %rdx
-
- movq %rsp, %rbp /* Save current stack pointer */
-
- call get_sev_encryption_bit /* Get the encryption bit position */
- testl %eax, %eax
- jz .Lno_sev_mask
-
- bts %rax, sme_me_mask(%rip) /* Create the encryption mask */
-
- /*
- * Read MSR_AMD64_SEV again and store it to sev_status. Can't do this in
- * get_sev_encryption_bit() because this function is 32-bit code and
- * shared between 64-bit and 32-bit boot path.
- */
- movl $MSR_AMD64_SEV, %ecx /* Read the SEV MSR */
- rdmsr
-
- /* Store MSR value in sev_status */
- shlq $32, %rdx
- orq %rdx, %rax
- movq %rax, sev_status(%rip)
-
-.Lno_sev_mask:
- movq %rbp, %rsp /* Restore original stack pointer */
-
- pop %rdx
- pop %rbp
-#endif
-
- xor %rax, %rax
- ret
-SYM_FUNC_END(set_sev_encryption_mask)
.data
diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
index 16ed360b6692..23e0e395084a 100644
--- a/arch/x86/boot/compressed/misc.h
+++ b/arch/x86/boot/compressed/misc.h
@@ -120,12 +120,12 @@ static inline void console_init(void)
{ }
#endif
-void set_sev_encryption_mask(void);
-
#ifdef CONFIG_AMD_MEM_ENCRYPT
+void sev_enable(struct boot_params *bp);
void sev_es_shutdown_ghcb(void);
extern bool sev_es_check_ghcb_fault(unsigned long address);
#else
+static inline void sev_enable(struct boot_params *bp) { }
static inline void sev_es_shutdown_ghcb(void) { }
static inline bool sev_es_check_ghcb_fault(unsigned long address)
{
diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
index 28bcf04c022e..8eebdf589a90 100644
--- a/arch/x86/boot/compressed/sev.c
+++ b/arch/x86/boot/compressed/sev.c
@@ -204,3 +204,48 @@ void do_boot_stage2_vc(struct pt_regs *regs, unsigned long exit_code)
else if (result != ES_RETRY)
sev_es_terminate(GHCB_SEV_ES_GEN_REQ);
}
+
+static inline u64 rd_sev_status_msr(void)
+{
+ unsigned long low, high;
+
+ asm volatile("rdmsr" : "=a" (low), "=d" (high) :
+ "c" (MSR_AMD64_SEV));
+
+ return ((high << 32) | low);
+}
+
+void sev_enable(struct boot_params *bp)
+{
+ 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;
+
+ /*
+ * 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)))
+ return;
+
+ /* Set the SME mask if this is an SEV guest. */
+ sev_status = rd_sev_status_msr();
+
+ if (!(sev_status & MSR_AMD64_SEV_ENABLED))
+ return;
+
+ sme_me_mask = BIT_ULL(ebx & 0x3f);
+}
--
2.25.1
^ permalink raw reply related [flat|nested] 183+ messages in thread* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2021-12-10 15:42 ` [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot Brijesh Singh
@ 2021-12-10 18:47 ` Dave Hansen
2021-12-10 19:12 ` Borislav Petkov
2021-12-13 19:09 ` Venu Busireddy
2 siblings, 0 replies; 183+ messages in thread
From: Dave Hansen @ 2021-12-10 18:47 UTC (permalink / raw)
To: Brijesh Singh, x86, linux-kernel, kvm, linux-efi,
platform-driver-x86, linux-coco, linux-mm
Cc: Thomas Gleixner, Ingo Molnar, Joerg Roedel, Tom Lendacky,
H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 12/10/21 7:42 AM, Brijesh Singh wrote:
> + /* Set the SME mask if this is an SEV guest. */
> + sev_status = rd_sev_status_msr();
Nit: there's some weird extra whitespace there. Might be some some old
attempts at vertical alignment.
^ permalink raw reply [flat|nested] 183+ messages in thread
* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2021-12-10 15:42 ` [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot Brijesh Singh
2021-12-10 18:47 ` Dave Hansen
@ 2021-12-10 19:12 ` Borislav Petkov
2021-12-10 19:23 ` Dave Hansen
2021-12-13 19:09 ` Venu Busireddy
2 siblings, 1 reply; 183+ messages in thread
From: Borislav Petkov @ 2021-12-10 19:12 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Michael Roth, Vlastimil Babka,
Kirill A . Shutemov, Andi Kleen, Dr . David Alan Gilbert,
tony.luck, marcorr, sathyanarayanan.kuppuswamy
On Fri, Dec 10, 2021 at 09:42:53AM -0600, Brijesh Singh wrote:
> @@ -447,6 +446,23 @@ SYM_CODE_START(startup_64)
> call load_stage1_idt
> popq %rsi
>
> +#ifdef CONFIG_AMD_MEM_ENCRYPT
I guess that ifdeffery is not needed.
> + /*
> + * Now that the stage1 interrupt handlers are set up, #VC exceptions from
> + * CPUID instructions can be properly handled for SEV-ES guests.
> + *
> + * For SEV-SNP, the CPUID table also needs to be set up in advance of any
> + * CPUID instructions being issued, so go ahead and do that now via
> + * sev_enable(), which will also handle the rest of the SEV-related
> + * detection/setup to ensure that has been done in advance of any dependent
> + * code.
> + */
> + pushq %rsi
> + movq %rsi, %rdi /* real mode address */
> + call sev_enable
> + popq %rsi
> +#endif
> +
> /*
> * paging_prepare() sets up the trampoline and checks if we need to
> * enable 5-level paging.
...
> +void sev_enable(struct boot_params *bp)
> +{
> + 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;
> +
> + /*
> + * 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)))
> + return;
> +
> + /* Set the SME mask if this is an SEV guest. */
> + sev_status = rd_sev_status_msr();
> +
^ Superfluous newline.
> + if (!(sev_status & MSR_AMD64_SEV_ENABLED))
> + return;
> +
> + sme_me_mask = BIT_ULL(ebx & 0x3f);
> +}
> --
Thx.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2021-12-10 19:12 ` Borislav Petkov
@ 2021-12-10 19:23 ` Dave Hansen
2021-12-10 19:33 ` Borislav Petkov
0 siblings, 1 reply; 183+ messages in thread
From: Dave Hansen @ 2021-12-10 19:23 UTC (permalink / raw)
To: Borislav Petkov, Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Michael Roth, Vlastimil Babka,
Kirill A . Shutemov, Andi Kleen, Dr . David Alan Gilbert,
tony.luck, marcorr, sathyanarayanan.kuppuswamy
On 12/10/21 11:12 AM, Borislav Petkov wrote:
> On Fri, Dec 10, 2021 at 09:42:53AM -0600, Brijesh Singh wrote:
>> @@ -447,6 +446,23 @@ SYM_CODE_START(startup_64)
>> call load_stage1_idt
>> popq %rsi
>>
>> +#ifdef CONFIG_AMD_MEM_ENCRYPT
>
> I guess that ifdeffery is not needed.
I think sev_enable() is only defined in arch/x86/boot/compressed/sev.c,
which is compiled via:
vmlinux-objs-$(CONFIG_AMD_MEM_ENCRYPT) += $(obj)/sev.o
So I think we either need the #ifdef or a stub for sev_enable()
somewhere else.
>> + /*
>> + * Now that the stage1 interrupt handlers are set up, #VC exceptions from
>> + * CPUID instructions can be properly handled for SEV-ES guests.
>> + *
>> + * For SEV-SNP, the CPUID table also needs to be set up in advance of any
>> + * CPUID instructions being issued, so go ahead and do that now via
>> + * sev_enable(), which will also handle the rest of the SEV-related
>> + * detection/setup to ensure that has been done in advance of any dependent
>> + * code.
>> + */
>> + pushq %rsi
>> + movq %rsi, %rdi /* real mode address */
>> + call sev_enable
>> + popq %rsi
>> +#endif
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2021-12-10 19:23 ` Dave Hansen
@ 2021-12-10 19:33 ` Borislav Petkov
0 siblings, 0 replies; 183+ messages in thread
From: Borislav Petkov @ 2021-12-10 19:33 UTC (permalink / raw)
To: Dave Hansen
Cc: Brijesh Singh, x86, linux-kernel, kvm, linux-efi,
platform-driver-x86, linux-coco, linux-mm, Thomas Gleixner,
Ingo Molnar, Joerg Roedel, Tom Lendacky, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On Fri, Dec 10, 2021 at 11:23:24AM -0800, Dave Hansen wrote:
> So I think we either need the #ifdef or a stub for sev_enable()
> somewhere else.
Yeah, there's a stub but in the C header so that won't work for asm
files. Forget what I said.
Thx.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 183+ messages in thread
* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2021-12-10 15:42 ` [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot Brijesh Singh
2021-12-10 18:47 ` Dave Hansen
2021-12-10 19:12 ` Borislav Petkov
@ 2021-12-13 19:09 ` Venu Busireddy
2021-12-13 19:17 ` Borislav Petkov
2 siblings, 1 reply; 183+ messages in thread
From: Venu Busireddy @ 2021-12-13 19:09 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2021-12-10 09:42:53 -0600, Brijesh Singh wrote:
> From: Michael Roth <michael.roth@amd.com>
>
> With upcoming SEV-SNP support, SEV-related features need to be
> initialized earlier in boot, at the same point the initial #VC handler
> is set up, so that the SEV-SNP CPUID table can be utilized during the
> initial feature checks. Also, SEV-SNP feature detection will rely on
> EFI helper functions to scan the EFI config table for the Confidential
> Computing blob, and so would need to be implemented at least partially
> in C.
>
> Currently set_sev_encryption_mask() is used to initialize the
> sev_status and sme_me_mask globals that advertise what SEV/SME features
> are available in a guest. Rename it to sev_enable() to better reflect
> that (SME is only enabled in the case of SEV guests in the
> boot/compressed kernel), and move it to just after the stage1 #VC
> handler is set up so that it can be used to initialize SEV-SNP as well
> in future patches.
>
> While at it, re-implement it as C code so that all SEV feature
> detection can be better consolidated with upcoming SEV-SNP feature
> detection, which will also be in C.
>
> The 32-bit entry path remains unchanged, as it never relied on the
> set_sev_encryption_mask() initialization to begin with, possibly due to
> the normal rva() helper for accessing globals only being usable by code
> in .head.text. Either way, 32-bit entry for SEV-SNP would likely only
> be supported for non-EFI boot paths, and so wouldn't rely on existing
> EFI helper functions, and so could be handled by a separate/simpler
> 32-bit initializer in the future if needed.
>
> Signed-off-by: Michael Roth <michael.roth@amd.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
> arch/x86/boot/compressed/head_64.S | 32 ++++++++++--------
> arch/x86/boot/compressed/mem_encrypt.S | 36 ---------------------
> arch/x86/boot/compressed/misc.h | 4 +--
> arch/x86/boot/compressed/sev.c | 45 ++++++++++++++++++++++++++
> 4 files changed, 66 insertions(+), 51 deletions(-)
>
> diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
> index 572c535cf45b..20b174adca51 100644
> --- a/arch/x86/boot/compressed/head_64.S
> +++ b/arch/x86/boot/compressed/head_64.S
> @@ -191,9 +191,8 @@ SYM_FUNC_START(startup_32)
> /*
> * Mark SEV as active in sev_status so that startup32_check_sev_cbit()
> * will do a check. The sev_status memory will be fully initialized
> - * with the contents of MSR_AMD_SEV_STATUS later in
> - * set_sev_encryption_mask(). For now it is sufficient to know that SEV
> - * is active.
> + * with the contents of MSR_AMD_SEV_STATUS later via sev_enable(). For
> + * now it is sufficient to know that SEV is active.
> */
> movl $1, rva(sev_status)(%ebp)
> 1:
> @@ -447,6 +446,23 @@ SYM_CODE_START(startup_64)
> call load_stage1_idt
> popq %rsi
>
> +#ifdef CONFIG_AMD_MEM_ENCRYPT
> + /*
> + * Now that the stage1 interrupt handlers are set up, #VC exceptions from
> + * CPUID instructions can be properly handled for SEV-ES guests.
> + *
> + * For SEV-SNP, the CPUID table also needs to be set up in advance of any
> + * CPUID instructions being issued, so go ahead and do that now via
> + * sev_enable(), which will also handle the rest of the SEV-related
> + * detection/setup to ensure that has been done in advance of any dependent
> + * code.
> + */
> + pushq %rsi
> + movq %rsi, %rdi /* real mode address */
> + call sev_enable
> + popq %rsi
> +#endif
> +
> /*
> * paging_prepare() sets up the trampoline and checks if we need to
> * enable 5-level paging.
> @@ -559,17 +575,7 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
> shrq $3, %rcx
> rep stosq
>
> -/*
> - * If running as an SEV guest, the encryption mask is required in the
> - * page-table setup code below. When the guest also has SEV-ES enabled
> - * set_sev_encryption_mask() will cause #VC exceptions, but the stage2
> - * handler can't map its GHCB because the page-table is not set up yet.
> - * So set up the encryption mask here while still on the stage1 #VC
> - * handler. Then load stage2 IDT and switch to the kernel's own
> - * page-table.
> - */
> pushq %rsi
> - call set_sev_encryption_mask
> call load_stage2_idt
>
> /* Pass boot_params to initialize_identity_maps() */
> diff --git a/arch/x86/boot/compressed/mem_encrypt.S b/arch/x86/boot/compressed/mem_encrypt.S
> index c1e81a848b2a..311d40f35a4b 100644
> --- a/arch/x86/boot/compressed/mem_encrypt.S
> +++ b/arch/x86/boot/compressed/mem_encrypt.S
> @@ -187,42 +187,6 @@ SYM_CODE_END(startup32_vc_handler)
> .code64
>
> #include "../../kernel/sev_verify_cbit.S"
> -SYM_FUNC_START(set_sev_encryption_mask)
> -#ifdef CONFIG_AMD_MEM_ENCRYPT
> - push %rbp
> - push %rdx
> -
> - movq %rsp, %rbp /* Save current stack pointer */
> -
> - call get_sev_encryption_bit /* Get the encryption bit position */
> - testl %eax, %eax
> - jz .Lno_sev_mask
> -
> - bts %rax, sme_me_mask(%rip) /* Create the encryption mask */
> -
> - /*
> - * Read MSR_AMD64_SEV again and store it to sev_status. Can't do this in
> - * get_sev_encryption_bit() because this function is 32-bit code and
> - * shared between 64-bit and 32-bit boot path.
> - */
> - movl $MSR_AMD64_SEV, %ecx /* Read the SEV MSR */
> - rdmsr
> -
> - /* Store MSR value in sev_status */
> - shlq $32, %rdx
> - orq %rdx, %rax
> - movq %rax, sev_status(%rip)
> -
> -.Lno_sev_mask:
> - movq %rbp, %rsp /* Restore original stack pointer */
> -
> - pop %rdx
> - pop %rbp
> -#endif
> -
> - xor %rax, %rax
> - ret
> -SYM_FUNC_END(set_sev_encryption_mask)
>
> .data
>
> diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
> index 16ed360b6692..23e0e395084a 100644
> --- a/arch/x86/boot/compressed/misc.h
> +++ b/arch/x86/boot/compressed/misc.h
> @@ -120,12 +120,12 @@ static inline void console_init(void)
> { }
> #endif
>
> -void set_sev_encryption_mask(void);
> -
> #ifdef CONFIG_AMD_MEM_ENCRYPT
> +void sev_enable(struct boot_params *bp);
> void sev_es_shutdown_ghcb(void);
> extern bool sev_es_check_ghcb_fault(unsigned long address);
> #else
> +static inline void sev_enable(struct boot_params *bp) { }
> static inline void sev_es_shutdown_ghcb(void) { }
> static inline bool sev_es_check_ghcb_fault(unsigned long address)
> {
> diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
> index 28bcf04c022e..8eebdf589a90 100644
> --- a/arch/x86/boot/compressed/sev.c
> +++ b/arch/x86/boot/compressed/sev.c
> @@ -204,3 +204,48 @@ void do_boot_stage2_vc(struct pt_regs *regs, unsigned long exit_code)
> else if (result != ES_RETRY)
> sev_es_terminate(GHCB_SEV_ES_GEN_REQ);
> }
> +
> +static inline u64 rd_sev_status_msr(void)
> +{
> + unsigned long low, high;
> +
> + asm volatile("rdmsr" : "=a" (low), "=d" (high) :
> + "c" (MSR_AMD64_SEV));
> +
> + return ((high << 32) | low);
> +}
> +
> +void sev_enable(struct boot_params *bp)
> +{
> + 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;
> +
> + /*
> + * 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)))
> + return;
> +
> + /* Set the SME mask if this is an SEV guest. */
> + sev_status = rd_sev_status_msr();
> +
> + if (!(sev_status & MSR_AMD64_SEV_ENABLED))
> + return;
> +
> + sme_me_mask = BIT_ULL(ebx & 0x3f);
I made this suggestion while reviewing v7 too, but it appears that it
fell through the cracks. Most of the code in sev_enable() is duplicated
from sme_enable(). Wouldn't it be better to put all that common code
in a different function, and call that function from sme_enable()
and sev_enable()?
Venu
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2021-12-13 19:09 ` Venu Busireddy
@ 2021-12-13 19:17 ` Borislav Petkov
2021-12-14 17:46 ` Venu Busireddy
0 siblings, 1 reply; 183+ messages in thread
From: Borislav Petkov @ 2021-12-13 19:17 UTC (permalink / raw)
To: Venu Busireddy
Cc: Brijesh Singh, x86, linux-kernel, kvm, linux-efi,
platform-driver-x86, linux-coco, linux-mm, Thomas Gleixner,
Ingo Molnar, Joerg Roedel, Tom Lendacky, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On Mon, Dec 13, 2021 at 01:09:19PM -0600, Venu Busireddy wrote:
> I made this suggestion while reviewing v7 too, but it appears that it
> fell through the cracks. Most of the code in sev_enable() is duplicated
> from sme_enable(). Wouldn't it be better to put all that common code
> in a different function, and call that function from sme_enable()
> and sev_enable()?
How about you look where both functions are defined? Which kernel stages?
And please trim your mails when you reply.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2021-12-13 19:17 ` Borislav Petkov
@ 2021-12-14 17:46 ` Venu Busireddy
2021-12-14 19:10 ` Borislav Petkov
0 siblings, 1 reply; 183+ messages in thread
From: Venu Busireddy @ 2021-12-14 17:46 UTC (permalink / raw)
To: Borislav Petkov
Cc: Brijesh Singh, x86, linux-kernel, kvm, linux-efi,
platform-driver-x86, linux-coco, linux-mm, Thomas Gleixner,
Ingo Molnar, Joerg Roedel, Tom Lendacky, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2021-12-13 20:17:31 +0100, Borislav Petkov wrote:
> On Mon, Dec 13, 2021 at 01:09:19PM -0600, Venu Busireddy wrote:
> > I made this suggestion while reviewing v7 too, but it appears that it
> > fell through the cracks. Most of the code in sev_enable() is duplicated
> > from sme_enable(). Wouldn't it be better to put all that common code
> > in a different function, and call that function from sme_enable()
> > and sev_enable()?
>
> How about you look where both functions are defined? Which kernel stages?
What I am suggesting should not have anything to do with the boot stage
of the kernel.
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.
Venu
^ permalink raw reply [flat|nested] 183+ messages in thread
* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2021-12-14 17:46 ` Venu Busireddy
@ 2021-12-14 19:10 ` Borislav Petkov
2021-12-15 0:14 ` Venu Busireddy
0 siblings, 1 reply; 183+ messages in thread
From: Borislav Petkov @ 2021-12-14 19:10 UTC (permalink / raw)
To: Venu Busireddy
Cc: Brijesh Singh, x86, linux-kernel, kvm, linux-efi,
platform-driver-x86, linux-coco, linux-mm, Thomas Gleixner,
Ingo Molnar, Joerg Roedel, Tom Lendacky, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
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.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2021-12-14 19:10 ` Borislav Petkov
@ 2021-12-15 0:14 ` Venu Busireddy
2021-12-15 11:57 ` Borislav Petkov
` (2 more replies)
0 siblings, 3 replies; 183+ messages in thread
From: Venu Busireddy @ 2021-12-15 0:14 UTC (permalink / raw)
To: Borislav Petkov
Cc: Brijesh Singh, x86, linux-kernel, kvm, linux-efi,
platform-driver-x86, linux-coco, linux-mm, Thomas Gleixner,
Ingo Molnar, Joerg Roedel, Tom Lendacky, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
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://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);
^ permalink raw reply related [flat|nested] 183+ messages in thread* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2021-12-15 0:14 ` Venu Busireddy
@ 2021-12-15 11:57 ` Borislav Petkov
2021-12-15 14:43 ` Tom Lendacky
2021-12-15 17:51 ` Michael Roth
2 siblings, 0 replies; 183+ messages in thread
From: Borislav Petkov @ 2021-12-15 11:57 UTC (permalink / raw)
To: Venu Busireddy
Cc: Brijesh Singh, x86, linux-kernel, kvm, linux-efi,
platform-driver-x86, linux-coco, linux-mm, Thomas Gleixner,
Ingo Molnar, Joerg Roedel, Tom Lendacky, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On Tue, Dec 14, 2021 at 06:14:34PM -0600, Venu Busireddy wrote:
> 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)
You can simply return pt_bit_pos:
static inline unsigned int get_pagetable_bit_pos(unsigned long features)
and return a negative value on error.
Also, the only duplication this is saving is visual - that function will
get inlined at the call sites.
Also, I'd love to separate the compressed kernel headers from the
kernel proper ones but I'm afraid that ship has sailed. But if I could,
that would have to be in a special header that gets included by both
stages...
So I don't mind this but I'd let Brijesh and Tom have a look at it too.
Thx.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2021-12-15 0:14 ` Venu Busireddy
2021-12-15 11:57 ` Borislav Petkov
@ 2021-12-15 14:43 ` Tom Lendacky
2021-12-15 17:49 ` Michael Roth
2021-12-15 18:58 ` Venu Busireddy
2021-12-15 17:51 ` Michael Roth
2 siblings, 2 replies; 183+ messages in thread
From: Tom Lendacky @ 2021-12-15 14:43 UTC (permalink / raw)
To: Venu Busireddy, Borislav Petkov
Cc: Brijesh Singh, x86, linux-kernel, kvm, linux-efi,
platform-driver-x86, linux-coco, linux-mm, Thomas Gleixner,
Ingo Molnar, Joerg Roedel, H. Peter Anvin, Ard Biesheuvel,
Paolo Bonzini, Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Michael Roth, Vlastimil Babka,
Kirill A . Shutemov, Andi Kleen, Dr . David Alan Gilbert,
tony.luck, marcorr, sathyanarayanan.kuppuswamy
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);
>
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2021-12-15 14:43 ` Tom Lendacky
@ 2021-12-15 17:49 ` Michael Roth
2021-12-15 18:17 ` Venu Busireddy
2021-12-15 19:54 ` Venu Busireddy
2021-12-15 18:58 ` Venu Busireddy
1 sibling, 2 replies; 183+ messages in thread
From: Michael Roth @ 2021-12-15 17:49 UTC (permalink / raw)
To: Tom Lendacky
Cc: Venu Busireddy, Borislav Petkov, Brijesh Singh, x86, linux-kernel,
kvm, linux-efi, platform-driver-x86, linux-coco, linux-mm,
Thomas Gleixner, Ingo Molnar, Joerg Roedel, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On Wed, Dec 15, 2021 at 08:43:23AM -0600, Tom Lendacky wrote:
> 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.
I think in the greater context of consolidating all the SME/SEV setup
and re-using code, this helper stands a high chance of eventually becoming
something more along the lines of sme_sev_parse_cpuid(), since otherwise
we'd end up re-introducing multiple helpers to parse the same 0x8000001F
fields if we ever need to process any of the other fields advertised in
there. Given that, it makes sense to reserve the return value as an
indication that either SEV or SME are enabled, and then have a
pass-by-pointer parameters list to collect the individual feature
bits/encryption mask for cases where SEV/SME are enabled, which are only
treated as valid if sme_sev_parse_cpuid() returns 0.
So Venu's original approach of passing the encryption mask by pointer
seems a little closer toward that end, but I also agree Tom's approach
is cleaner for the current code base, so I'm fine either way, just
figured I'd mention this.
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.
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2021-12-15 17:49 ` Michael Roth
@ 2021-12-15 18:17 ` Venu Busireddy
2021-12-15 18:33 ` Borislav Petkov
2021-12-15 20:43 ` Michael Roth
2021-12-15 19:54 ` Venu Busireddy
1 sibling, 2 replies; 183+ messages in thread
From: Venu Busireddy @ 2021-12-15 18:17 UTC (permalink / raw)
To: Michael Roth
Cc: Tom Lendacky, Borislav Petkov, Brijesh Singh, x86, linux-kernel,
kvm, linux-efi, platform-driver-x86, linux-coco, linux-mm,
Thomas Gleixner, Ingo Molnar, Joerg Roedel, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2021-12-15 11:49:34 -0600, Michael Roth wrote:
>
> I think in the greater context of consolidating all the SME/SEV setup
> and re-using code, this helper stands a high chance of eventually becoming
> something more along the lines of sme_sev_parse_cpuid(), since otherwise
> we'd end up re-introducing multiple helpers to parse the same 0x8000001F
> fields if we ever need to process any of the other fields advertised in
> there. Given that, it makes sense to reserve the return value as an
> indication that either SEV or SME are enabled, and then have a
> pass-by-pointer parameters list to collect the individual feature
> bits/encryption mask for cases where SEV/SME are enabled, which are only
> treated as valid if sme_sev_parse_cpuid() returns 0.
>
> So Venu's original approach of passing the encryption mask by pointer
> seems a little closer toward that end, but I also agree Tom's approach
> is cleaner for the current code base, so I'm fine either way, just
> figured I'd mention this.
>
> 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.
I can implement it this way too. But I am wondering if having a
boolean argument limits us from handling any future additions to the
bit positions.
Boris & Tom, which implementation would you prefer?
Venu
^ permalink raw reply [flat|nested] 183+ messages in thread
* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2021-12-15 18:17 ` Venu Busireddy
@ 2021-12-15 18:33 ` Borislav Petkov
2021-12-15 20:17 ` Michael Roth
2021-12-15 20:43 ` Michael Roth
1 sibling, 1 reply; 183+ messages in thread
From: Borislav Petkov @ 2021-12-15 18:33 UTC (permalink / raw)
To: Venu Busireddy
Cc: Michael Roth, Tom Lendacky, Brijesh Singh, x86, linux-kernel, kvm,
linux-efi, platform-driver-x86, linux-coco, linux-mm,
Thomas Gleixner, Ingo Molnar, Joerg Roedel, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On Wed, Dec 15, 2021 at 12:17:44PM -0600, Venu Busireddy wrote:
> Boris & Tom, which implementation would you prefer?
I'd like to see how that sme_sev_parse_cpuid() would look like. And that
function should be called sev_parse_cpuid(), btw.
Because if that function turns out to be a subset of your suggestion,
functionality-wise, then we should save us the churn and simply do one
generic helper.
Btw 2, that helper should be in arch/x86/kernel/sev-shared.c so that it
gets shared by both kernel stages instead having an inline function in
some random header.
Btw 3, I'm not crazy about the feature testing with the @features param
either. Maybe that function should return the eYx register directly,
like the cpuid_eYx() variants in the kernel do, where Y in { a, b, c, d
}.
The caller can than do its own testing:
eax = sev_parse_cpuid(RET_EAX, ...)
if (eax > 0) {
if (eax & BIT(1))
...
Something along those lines, for example.
But I'd have to see a concrete diff from Michael to get a better idea
how that CPUID parsing from the CPUID page is going to look like.
Thx.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2021-12-15 18:33 ` Borislav Petkov
@ 2021-12-15 20:17 ` Michael Roth
2021-12-15 20:38 ` Borislav Petkov
0 siblings, 1 reply; 183+ messages in thread
From: Michael Roth @ 2021-12-15 20:17 UTC (permalink / raw)
To: Borislav Petkov
Cc: Venu Busireddy, Tom Lendacky, Brijesh Singh, x86, linux-kernel,
kvm, linux-efi, platform-driver-x86, linux-coco, linux-mm,
Thomas Gleixner, Ingo Molnar, Joerg Roedel, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On Wed, Dec 15, 2021 at 07:33:47PM +0100, Borislav Petkov wrote:
> On Wed, Dec 15, 2021 at 12:17:44PM -0600, Venu Busireddy wrote:
> > Boris & Tom, which implementation would you prefer?
>
> I'd like to see how that sme_sev_parse_cpuid() would look like. And that
> function should be called sev_parse_cpuid(), btw.
>
> Because if that function turns out to be a subset of your suggestion,
> functionality-wise, then we should save us the churn and simply do one
> generic helper.
I was actually thinking this proposed sev_parse_cpuid() helper would be
a superset of what Venu currently has implemented. E.g. Venu's most recent
patch does:
sev_enable():
unsigned int me_bit_pos;
me_bit_pos = get_me_bit(AMD_SEV_BIT)
if (!me_bit_pos)
return;
...
Let's say in the future there's need to also grab say, the VTE bit. We
could introduce a new helper, get_vte_bit() that re-does all the
0x80000000-0x8000001F range checks, some sanity checks that SEV is set if
VTE bit is set, and then now have a nice single-purpose helper that
duplicates similar checks in get_me_bit(), or we could avoid the
duplication by expanding get_me_bit() so it could be used something like:
me_bit_pos = get_me_bit(AMD_SEV_BIT, &vte_enabled)
at which point it makes more sense to just have it be a more generic
helper, called via:
ret = sev_parse_cpuid(AMD_SEV_BIT, &me_bit_pos, &vte_enabled)
i.e. Venu's original patch basically, but with the helper function
renamed.
and if fields are added in the future:
sev_parse_cpuid(AMD_SEV_BIT, &me_bit_pos, &vte_enabled, &new_feature_enabled, etc..)
or if that eventually becomes unwieldly it could later be changed to return
a feature mask.
>
> Btw 2, that helper should be in arch/x86/kernel/sev-shared.c so that it
> gets shared by both kernel stages instead having an inline function in
> some random header.
>
> Btw 3, I'm not crazy about the feature testing with the @features param
> either. Maybe that function should return the eYx register directly,
> like the cpuid_eYx() variants in the kernel do, where Y in { a, b, c, d
> }.
>
> The caller can than do its own testing:
>
> eax = sev_parse_cpuid(RET_EAX, ...)
> if (eax > 0) {
> if (eax & BIT(1))
> ...
>
> Something along those lines, for example.
I think having sev_parse_cpuid() using a more "human-readable" format
for reporting features/fields will make it easier to abstract away the
nitty-gritty details and reduce that chances for more duplication
between boot/compressed and kernel proper in the future. That
"human-readable" format could be in the form of a boolean/int
parameter list that gets expanded over time as needed (like the above
examples), or a higher-level construct like a struct/bitmask/etc. But
either way it would be nice to only have to think about specific CPUID
bits when looking at sev_parse_cpuid(), and have callers instead rely
purely on the sev_parse_cpuid() function prototype/documentation to
know what's going on.
>
> But I'd have to see a concrete diff from Michael to get a better idea
> how that CPUID parsing from the CPUID page is going to look like.
It should look the same with/without CPUID page, since the CPUID page
will have already been set up early in sev_enable()/sme_enable() based
on the presence of the CC blob via snp_init(), introduced in:
[PATCH v8 31/40] x86/compressed: add SEV-SNP feature detection/setup
Thanks,
Mike
>
> Thx.
>
> --
> Regards/Gruss,
> Boris.
>
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpeople.kernel.org%2Ftglx%2Fnotes-about-netiquette&data=04%7C01%7Cmichael.roth%40amd.com%7C6a28b961ef1441ed08f908d9bff970ea%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637751900351173552%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&sdata=nnCrpsw9%2FYlmhK1Xbx5y5vUScVsEOQeU%2F%2FTCmBMQ3v4%3D&reserved=0
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2021-12-15 20:17 ` Michael Roth
@ 2021-12-15 20:38 ` Borislav Petkov
2021-12-15 21:22 ` Michael Roth
0 siblings, 1 reply; 183+ messages in thread
From: Borislav Petkov @ 2021-12-15 20:38 UTC (permalink / raw)
To: Michael Roth
Cc: Venu Busireddy, Tom Lendacky, Brijesh Singh, x86, linux-kernel,
kvm, linux-efi, platform-driver-x86, linux-coco, linux-mm,
Thomas Gleixner, Ingo Molnar, Joerg Roedel, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On Wed, Dec 15, 2021 at 02:17:34PM -0600, Michael Roth wrote:
> and if fields are added in the future:
>
> sev_parse_cpuid(AMD_SEV_BIT, &me_bit_pos, &vte_enabled, &new_feature_enabled, etc..)
And that will end up being a vararg function because of who knows what
other feature bits will have to get passed in? You have even added the
ellipsis in there.
Nope. Definitely not.
> or if that eventually becomes unwieldly
The above example is already unwieldy.
> it could later be changed to return a feature mask.
Yes, that. Clean and simple.
But it is hard to discuss anything without patches so we can continue
the topic with concrete patches. But this unification is not
super-pressing so it can go ontop of the SNP pile.
Thx.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2021-12-15 20:38 ` Borislav Petkov
@ 2021-12-15 21:22 ` Michael Roth
2022-01-03 19:10 ` Venu Busireddy
0 siblings, 1 reply; 183+ messages in thread
From: Michael Roth @ 2021-12-15 21:22 UTC (permalink / raw)
To: Borislav Petkov
Cc: Venu Busireddy, Tom Lendacky, Brijesh Singh, x86, linux-kernel,
kvm, linux-efi, platform-driver-x86, linux-coco, linux-mm,
Thomas Gleixner, Ingo Molnar, Joerg Roedel, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On Wed, Dec 15, 2021 at 09:38:55PM +0100, Borislav Petkov wrote:
> On Wed, Dec 15, 2021 at 02:17:34PM -0600, Michael Roth wrote:
> > and if fields are added in the future:
> >
> > sev_parse_cpuid(AMD_SEV_BIT, &me_bit_pos, &vte_enabled, &new_feature_enabled, etc..)
>
> And that will end up being a vararg function because of who knows what
> other feature bits will have to get passed in? You have even added the
> ellipsis in there.
Well, not varargs, just sort of anticipating how the function prototype
might change over time as it's modified to parse for new features.
>
> Nope. Definitely not.
>
> > or if that eventually becomes unwieldly
>
> The above example is already unwieldy.
>
> > it could later be changed to return a feature mask.
>
> Yes, that. Clean and simple.
>
> But it is hard to discuss anything without patches so we can continue
> the topic with concrete patches. But this unification is not
> super-pressing so it can go ontop of the SNP pile.
Yah, it's all theoretical at this point. Didn't mean to derail things
though. I mainly brought it up to suggest that Venu's original approach of
returning the encryption bit via a pointer argument might make it easier to
expand it for other purposes in the future, and that naming it for that
future purpose might encourage future developers to focus their efforts
there instead of potentially re-introducing duplicate code.
But either way it's simple enough to rework things when we actually
cross that bridge. So totally fine with saving all of this as a future
follow-up, or picking up either of Venu's patches for now if you'd still
prefer.
Thanks,
Mike
>
> Thx.
>
> --
> Regards/Gruss,
> Boris.
>
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpeople.kernel.org%2Ftglx%2Fnotes-about-netiquette&data=04%7C01%7Cmichael.roth%40amd.com%7C10261dab334649b4b81408d9c00aec95%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637751975466658716%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&sdata=E3prWlptt32G%2FsgFg9wU8cMKec2cHywgNm1pPL3jzcI%3D&reserved=0
^ permalink raw reply [flat|nested] 183+ messages in thread
* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2021-12-15 21:22 ` Michael Roth
@ 2022-01-03 19:10 ` Venu Busireddy
2022-01-05 19:34 ` Brijesh Singh
0 siblings, 1 reply; 183+ messages in thread
From: Venu Busireddy @ 2022-01-03 19:10 UTC (permalink / raw)
To: Michael Roth
Cc: Borislav Petkov, Tom Lendacky, Brijesh Singh, x86, linux-kernel,
kvm, linux-efi, platform-driver-x86, linux-coco, linux-mm,
Thomas Gleixner, Ingo Molnar, Joerg Roedel, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2021-12-15 15:22:57 -0600, Michael Roth wrote:
> On Wed, Dec 15, 2021 at 09:38:55PM +0100, Borislav Petkov wrote:
> >
> > But it is hard to discuss anything without patches so we can continue
> > the topic with concrete patches. But this unification is not
> > super-pressing so it can go ontop of the SNP pile.
>
> Yah, it's all theoretical at this point. Didn't mean to derail things
> though. I mainly brought it up to suggest that Venu's original approach of
> returning the encryption bit via a pointer argument might make it easier to
> expand it for other purposes in the future, and that naming it for that
> future purpose might encourage future developers to focus their efforts
> there instead of potentially re-introducing duplicate code.
>
> But either way it's simple enough to rework things when we actually
> cross that bridge. So totally fine with saving all of this as a future
> follow-up, or picking up either of Venu's patches for now if you'd still
> prefer.
So, what is the consensus? Do you want me to submit a patch after the
SNP changes go upstream? Or, do you want to roll in one of the patches
that I posted earlier?
Venu
>
^ permalink raw reply [flat|nested] 183+ messages in thread
* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2022-01-03 19:10 ` Venu Busireddy
@ 2022-01-05 19:34 ` Brijesh Singh
2022-01-10 20:46 ` Brijesh Singh
0 siblings, 1 reply; 183+ messages in thread
From: Brijesh Singh @ 2022-01-05 19:34 UTC (permalink / raw)
To: Venu Busireddy, Michael Roth
Cc: brijesh.singh, Borislav Petkov, Tom Lendacky, x86, linux-kernel,
kvm, linux-efi, platform-driver-x86, linux-coco, linux-mm,
Thomas Gleixner, Ingo Molnar, Joerg Roedel, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 1/3/22 1:10 PM, Venu Busireddy wrote:
> On 2021-12-15 15:22:57 -0600, Michael Roth wrote:
>> On Wed, Dec 15, 2021 at 09:38:55PM +0100, Borislav Petkov wrote:
>>>
>>> But it is hard to discuss anything without patches so we can continue
>>> the topic with concrete patches. But this unification is not
>>> super-pressing so it can go ontop of the SNP pile.
>>
>> Yah, it's all theoretical at this point. Didn't mean to derail things
>> though. I mainly brought it up to suggest that Venu's original approach of
>> returning the encryption bit via a pointer argument might make it easier to
>> expand it for other purposes in the future, and that naming it for that
>> future purpose might encourage future developers to focus their efforts
>> there instead of potentially re-introducing duplicate code.
>>
>> But either way it's simple enough to rework things when we actually
>> cross that bridge. So totally fine with saving all of this as a future
>> follow-up, or picking up either of Venu's patches for now if you'd still
>> prefer.
>
> So, what is the consensus? Do you want me to submit a patch after the
> SNP changes go upstream? Or, do you want to roll in one of the patches
> that I posted earlier?
>
Will incorporate your changes in v9. And will see what others say about it.
-Brijesh
^ permalink raw reply [flat|nested] 183+ messages in thread
* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2022-01-05 19:34 ` Brijesh Singh
@ 2022-01-10 20:46 ` Brijesh Singh
2022-01-10 21:17 ` Venu Busireddy
0 siblings, 1 reply; 183+ messages in thread
From: Brijesh Singh @ 2022-01-10 20:46 UTC (permalink / raw)
To: Venu Busireddy, Michael Roth
Cc: brijesh.singh, Borislav Petkov, Tom Lendacky, x86, linux-kernel,
kvm, linux-efi, platform-driver-x86, linux-coco, linux-mm,
Thomas Gleixner, Ingo Molnar, Joerg Roedel, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
Hi Venu,
On 1/5/22 1:34 PM, Brijesh Singh wrote:
>
>
> On 1/3/22 1:10 PM, Venu Busireddy wrote:
>> On 2021-12-15 15:22:57 -0600, Michael Roth wrote:
>>> On Wed, Dec 15, 2021 at 09:38:55PM +0100, Borislav Petkov wrote:
>>>>
>>>> But it is hard to discuss anything without patches so we can continue
>>>> the topic with concrete patches. But this unification is not
>>>> super-pressing so it can go ontop of the SNP pile.
>>>
>>> Yah, it's all theoretical at this point. Didn't mean to derail things
>>> though. I mainly brought it up to suggest that Venu's original
>>> approach of
>>> returning the encryption bit via a pointer argument might make it
>>> easier to
>>> expand it for other purposes in the future, and that naming it for that
>>> future purpose might encourage future developers to focus their efforts
>>> there instead of potentially re-introducing duplicate code.
>>>
>>> But either way it's simple enough to rework things when we actually
>>> cross that bridge. So totally fine with saving all of this as a future
>>> follow-up, or picking up either of Venu's patches for now if you'd still
>>> prefer.
>>
>> So, what is the consensus? Do you want me to submit a patch after the
>> SNP changes go upstream? Or, do you want to roll in one of the patches
>> that I posted earlier?
>>
>
> Will incorporate your changes in v9. And will see what others say about it.
>
Now that I am incorporating the feedback in my wip branch, at this time
I am dropping your cleanup mainly because some of recommendation may
require more rework down the line; you can submit your recommendation as
cleanup after the patches are in. I hope this is okay with you.
thanks
^ permalink raw reply [flat|nested] 183+ messages in thread
* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2022-01-10 20:46 ` Brijesh Singh
@ 2022-01-10 21:17 ` Venu Busireddy
2022-01-10 21:38 ` Borislav Petkov
0 siblings, 1 reply; 183+ messages in thread
From: Venu Busireddy @ 2022-01-10 21:17 UTC (permalink / raw)
To: Brijesh Singh
Cc: Michael Roth, Borislav Petkov, Tom Lendacky, x86, linux-kernel,
kvm, linux-efi, platform-driver-x86, linux-coco, linux-mm,
Thomas Gleixner, Ingo Molnar, Joerg Roedel, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2022-01-10 14:46:27 -0600, Brijesh Singh wrote:
> Hi Venu,
>
> On 1/5/22 1:34 PM, Brijesh Singh wrote:
> >
> >
> > On 1/3/22 1:10 PM, Venu Busireddy wrote:
> > > On 2021-12-15 15:22:57 -0600, Michael Roth wrote:
> > > > On Wed, Dec 15, 2021 at 09:38:55PM +0100, Borislav Petkov wrote:
> > > > >
> > > > > But it is hard to discuss anything without patches so we can continue
> > > > > the topic with concrete patches. But this unification is not
> > > > > super-pressing so it can go ontop of the SNP pile.
> > > >
> > > > Yah, it's all theoretical at this point. Didn't mean to derail things
> > > > though. I mainly brought it up to suggest that Venu's original
> > > > approach of
> > > > returning the encryption bit via a pointer argument might make
> > > > it easier to
> > > > expand it for other purposes in the future, and that naming it for that
> > > > future purpose might encourage future developers to focus their efforts
> > > > there instead of potentially re-introducing duplicate code.
> > > >
> > > > But either way it's simple enough to rework things when we actually
> > > > cross that bridge. So totally fine with saving all of this as a future
> > > > follow-up, or picking up either of Venu's patches for now if you'd still
> > > > prefer.
> > >
> > > So, what is the consensus? Do you want me to submit a patch after the
> > > SNP changes go upstream? Or, do you want to roll in one of the patches
> > > that I posted earlier?
> > >
> >
> > Will incorporate your changes in v9. And will see what others say about it.
> >
>
> Now that I am incorporating the feedback in my wip branch, at this time I am
> dropping your cleanup mainly because some of recommendation may require more
> rework down the line; you can submit your recommendation as cleanup after
> the patches are in. I hope this is okay with you.
Can't we do that rework (if any) as and when it is needed? I am worried
that we will never get this in!
Venu
^ permalink raw reply [flat|nested] 183+ messages in thread
* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2022-01-10 21:17 ` Venu Busireddy
@ 2022-01-10 21:38 ` Borislav Petkov
0 siblings, 0 replies; 183+ messages in thread
From: Borislav Petkov @ 2022-01-10 21:38 UTC (permalink / raw)
To: Venu Busireddy
Cc: Brijesh Singh, Michael Roth, Tom Lendacky, x86, linux-kernel, kvm,
linux-efi, platform-driver-x86, linux-coco, linux-mm,
Thomas Gleixner, Ingo Molnar, Joerg Roedel, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On Mon, Jan 10, 2022 at 03:17:56PM -0600, Venu Busireddy wrote:
> Can't we do that rework (if any) as and when it is needed? I am worried
> that we will never get this in!
In case you've missed it from a previous mail on that same thread:
"But this unification is not super-pressing so it can go ontop of the
SNP pile."
So such cleanups go ontop, when the dust settles and when we realize
that there really are parts which can be unified. Right now, everything
is moving so first things first.
Thx.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 183+ messages in thread
* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2021-12-15 18:17 ` Venu Busireddy
2021-12-15 18:33 ` Borislav Petkov
@ 2021-12-15 20:43 ` Michael Roth
1 sibling, 0 replies; 183+ messages in thread
From: Michael Roth @ 2021-12-15 20:43 UTC (permalink / raw)
To: Venu Busireddy
Cc: Tom Lendacky, Borislav Petkov, Brijesh Singh, x86, linux-kernel,
kvm, linux-efi, platform-driver-x86, linux-coco, linux-mm,
Thomas Gleixner, Ingo Molnar, Joerg Roedel, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On Wed, Dec 15, 2021 at 12:17:44PM -0600, Venu Busireddy wrote:
> On 2021-12-15 11:49:34 -0600, Michael Roth wrote:
> >
> > I think in the greater context of consolidating all the SME/SEV setup
> > and re-using code, this helper stands a high chance of eventually becoming
> > something more along the lines of sme_sev_parse_cpuid(), since otherwise
> > we'd end up re-introducing multiple helpers to parse the same 0x8000001F
> > fields if we ever need to process any of the other fields advertised in
> > there. Given that, it makes sense to reserve the return value as an
> > indication that either SEV or SME are enabled, and then have a
> > pass-by-pointer parameters list to collect the individual feature
> > bits/encryption mask for cases where SEV/SME are enabled, which are only
> > treated as valid if sme_sev_parse_cpuid() returns 0.
> >
> > So Venu's original approach of passing the encryption mask by pointer
> > seems a little closer toward that end, but I also agree Tom's approach
> > is cleaner for the current code base, so I'm fine either way, just
> > figured I'd mention this.
> >
> > 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.
>
> I can implement it this way too. But I am wondering if having a
> boolean argument limits us from handling any future additions to the
> bit positions.
That's the thing, we'll pretty much always want to parse cpuid in
boot/compressed if SEV is enabled, and in kernel proper if either SEV or
SME are enabled, because they both require, at a minimum, the c-bit
position. Extensions to either SEV/SME likely won't change this, but by
using CPUID feature masks to handle this it gives the impression that
this helper relies on individual features being present in the mask in
order for the corresponding fields to be parsed, when in reality it
boils down more to SEV features needing to be enabled earlier because
they don't trust the host during early boot.
I agree the boolean flag makes things a bit less readable without
checking the function prototype though. I was going to suggest 2
separate functions that use a common helper and hide away the
boolean, e.g:
sev_parse_cpuid() //sev-only
and
sme_parse_cpuid() //sev or sme
but the latter maybe is a bit misleading and I couldn't think of a
better name. It's really more like sev_sme_parse_cpuid(), but I'm
not sure that will fly. Maybe sme_parse_cpuid() is fine.
You could also just have it take an enum as the first arg though:
enum sev_parse_cpuid {
SEV_PARSE_CPUID_SEV_ONLY = 0
SEV_PARSE_CPUID_SME_ONLY //unused
SEV_PARSE_CPUID_BOTH
}
Personally I still prefer the boolean but just some alternatives
you could consider otherwise.
>
> Boris & Tom, which implementation would you prefer?
>
> Venu
>
>
^ permalink raw reply [flat|nested] 183+ messages in thread
* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2021-12-15 17:49 ` Michael Roth
2021-12-15 18:17 ` Venu Busireddy
@ 2021-12-15 19:54 ` Venu Busireddy
1 sibling, 0 replies; 183+ messages in thread
From: Venu Busireddy @ 2021-12-15 19:54 UTC (permalink / raw)
To: Michael Roth
Cc: Tom Lendacky, Borislav Petkov, Brijesh Singh, x86, linux-kernel,
kvm, linux-efi, platform-driver-x86, linux-coco, linux-mm,
Thomas Gleixner, Ingo Molnar, Joerg Roedel, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
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);
^ permalink raw reply related [flat|nested] 183+ messages in thread
* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2021-12-15 14:43 ` Tom Lendacky
2021-12-15 17:49 ` Michael Roth
@ 2021-12-15 18:58 ` Venu Busireddy
1 sibling, 0 replies; 183+ messages in thread
From: Venu Busireddy @ 2021-12-15 18:58 UTC (permalink / raw)
To: Tom Lendacky
Cc: Borislav Petkov, Brijesh Singh, x86, linux-kernel, kvm, linux-efi,
platform-driver-x86, linux-coco, linux-mm, Thomas Gleixner,
Ingo Molnar, Joerg Roedel, H. Peter Anvin, Ard Biesheuvel,
Paolo Bonzini, Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Michael Roth, Vlastimil Babka,
Kirill A . Shutemov, Andi Kleen, Dr . David Alan Gilbert,
tony.luck, marcorr, sathyanarayanan.kuppuswamy
On 2021-12-15 08:43:23 -0600, Tom Lendacky wrote:
>
> 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.
>
Implemented the changes as you suggested. Patch attached below. Will
submit another if we reach a different consensus.
Venu
---
diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index 7a5934af9d47..f0d5a00e490d 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h
@@ -17,6 +17,45 @@
#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(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 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..838c383f102b 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(AMD_SEV_BIT);
+ 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..57bc77382288 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(AMD_SEV_BIT | AMD_SME_BIT);
+ 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);
^ permalink raw reply related [flat|nested] 183+ messages in thread
* Re: [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot
2021-12-15 0:14 ` Venu Busireddy
2021-12-15 11:57 ` Borislav Petkov
2021-12-15 14:43 ` Tom Lendacky
@ 2021-12-15 17:51 ` Michael Roth
2 siblings, 0 replies; 183+ messages in thread
From: Michael Roth @ 2021-12-15 17:51 UTC (permalink / raw)
To: Venu Busireddy
Cc: Borislav Petkov, Brijesh Singh, x86, linux-kernel, kvm, linux-efi,
platform-driver-x86, linux-coco, linux-mm, Thomas Gleixner,
Ingo Molnar, Joerg Roedel, Tom Lendacky, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On Tue, Dec 14, 2021 at 06:14:34PM -0600, 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%7Cmichael.roth%40amd.com%7Cbff83ee03b1147c39ea808d9bf5fe9d8%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637751240979543818%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&sdata=DZpgEtthswLhhfWqZlLkHHd5nJW2jb%2FVFuTssAFJ6Uo%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.
Hi Venu,
I know there's still comments floating around, but once there's consensus feel
free to respond with a separate precursor patch against tip which moves
sme_enable() cpuid code into your helper function, along with your S-o-B, and I
can include it directly in the next version. Otherwise, I can incorporate your
suggestions into the next spin, just let me know if it's okay to add:
Co-authored-by: Venu Busireddy <venu.busireddy@oracle.com>
Signed-off-by: Venu Busireddy <venu.busireddy@oracle.com>
to the relevant commits.
Thank you (and Boris/Tom) for the suggestions!
-Mike
>
> Venu
>
^ permalink raw reply [flat|nested] 183+ messages in thread
* [PATCH v8 02/40] x86/sev: detect/setup SEV/SME features earlier in boot
2021-12-10 15:42 [PATCH v8 00/40] Add AMD Secure Nested Paging (SEV-SNP) Guest Support Brijesh Singh
2021-12-10 15:42 ` [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot Brijesh Singh
@ 2021-12-10 15:42 ` Brijesh Singh
2021-12-13 22:36 ` Venu Busireddy
2021-12-10 15:42 ` [PATCH v8 03/40] x86/mm: Extend cc_attr to include AMD SEV-SNP Brijesh Singh
` (38 subsequent siblings)
40 siblings, 1 reply; 183+ messages in thread
From: Brijesh Singh @ 2021-12-10 15:42 UTC (permalink / raw)
To: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm
Cc: Thomas Gleixner, Ingo Molnar, Joerg Roedel, Tom Lendacky,
H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy, Brijesh Singh
From: Michael Roth <michael.roth@amd.com>
sme_enable() handles feature detection for both SEV and SME. Future
patches will also use it for SEV-SNP feature detection/setup, which
will need to be done immediately after the first #VC handler is set up.
Move it now in preparation.
Signed-off-by: Michael Roth <michael.roth@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
arch/x86/kernel/head64.c | 3 ---
arch/x86/kernel/head_64.S | 13 +++++++++++++
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 3be9dd213dad..b01f64e8389b 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -192,9 +192,6 @@ unsigned long __head __startup_64(unsigned long physaddr,
if (load_delta & ~PMD_PAGE_MASK)
for (;;);
- /* Activate Secure Memory Encryption (SME) if supported and enabled */
- sme_enable(bp);
-
/* Include the SME encryption mask in the fixup value */
load_delta += sme_get_me_mask();
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index d8b3ebd2bb85..99de8fd461e8 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -69,6 +69,19 @@ SYM_CODE_START_NOALIGN(startup_64)
call startup_64_setup_env
popq %rsi
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+ /*
+ * Activate SEV/SME memory encryption if supported/enabled. This needs to
+ * be done now, since this also includes setup of the SEV-SNP CPUID table,
+ * which needs to be done before any CPUID instructions are executed in
+ * subsequent code.
+ */
+ movq %rsi, %rdi
+ pushq %rsi
+ call sme_enable
+ popq %rsi
+#endif
+
/* Now switch to __KERNEL_CS so IRET works reliably */
pushq $__KERNEL_CS
leaq .Lon_kernel_cs(%rip), %rax
--
2.25.1
^ permalink raw reply related [flat|nested] 183+ messages in thread* Re: [PATCH v8 02/40] x86/sev: detect/setup SEV/SME features earlier in boot
2021-12-10 15:42 ` [PATCH v8 02/40] x86/sev: " Brijesh Singh
@ 2021-12-13 22:36 ` Venu Busireddy
0 siblings, 0 replies; 183+ messages in thread
From: Venu Busireddy @ 2021-12-13 22:36 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2021-12-10 09:42:54 -0600, Brijesh Singh wrote:
> From: Michael Roth <michael.roth@amd.com>
>
> sme_enable() handles feature detection for both SEV and SME. Future
> patches will also use it for SEV-SNP feature detection/setup, which
> will need to be done immediately after the first #VC handler is set up.
> Move it now in preparation.
>
> Signed-off-by: Michael Roth <michael.roth@amd.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Venu Busireddy <venu.busireddy@oracle.com>
> ---
> arch/x86/kernel/head64.c | 3 ---
> arch/x86/kernel/head_64.S | 13 +++++++++++++
> 2 files changed, 13 insertions(+), 3 deletions(-)
>
> diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
> index 3be9dd213dad..b01f64e8389b 100644
> --- a/arch/x86/kernel/head64.c
> +++ b/arch/x86/kernel/head64.c
> @@ -192,9 +192,6 @@ unsigned long __head __startup_64(unsigned long physaddr,
> if (load_delta & ~PMD_PAGE_MASK)
> for (;;);
>
> - /* Activate Secure Memory Encryption (SME) if supported and enabled */
> - sme_enable(bp);
> -
> /* Include the SME encryption mask in the fixup value */
> load_delta += sme_get_me_mask();
>
> diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
> index d8b3ebd2bb85..99de8fd461e8 100644
> --- a/arch/x86/kernel/head_64.S
> +++ b/arch/x86/kernel/head_64.S
> @@ -69,6 +69,19 @@ SYM_CODE_START_NOALIGN(startup_64)
> call startup_64_setup_env
> popq %rsi
>
> +#ifdef CONFIG_AMD_MEM_ENCRYPT
> + /*
> + * Activate SEV/SME memory encryption if supported/enabled. This needs to
> + * be done now, since this also includes setup of the SEV-SNP CPUID table,
> + * which needs to be done before any CPUID instructions are executed in
> + * subsequent code.
> + */
> + movq %rsi, %rdi
> + pushq %rsi
> + call sme_enable
> + popq %rsi
> +#endif
> +
> /* Now switch to __KERNEL_CS so IRET works reliably */
> pushq $__KERNEL_CS
> leaq .Lon_kernel_cs(%rip), %rax
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 183+ messages in thread
* [PATCH v8 03/40] x86/mm: Extend cc_attr to include AMD SEV-SNP
2021-12-10 15:42 [PATCH v8 00/40] Add AMD Secure Nested Paging (SEV-SNP) Guest Support Brijesh Singh
2021-12-10 15:42 ` [PATCH v8 01/40] x86/compressed/64: detect/setup SEV/SME features earlier in boot Brijesh Singh
2021-12-10 15:42 ` [PATCH v8 02/40] x86/sev: " Brijesh Singh
@ 2021-12-10 15:42 ` Brijesh Singh
2021-12-13 22:47 ` Venu Busireddy
2021-12-14 15:53 ` Borislav Petkov
2021-12-10 15:42 ` [PATCH v8 04/40] x86/sev: Define the Linux specific guest termination reasons Brijesh Singh
` (37 subsequent siblings)
40 siblings, 2 replies; 183+ messages in thread
From: Brijesh Singh @ 2021-12-10 15:42 UTC (permalink / raw)
To: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm
Cc: Thomas Gleixner, Ingo Molnar, Joerg Roedel, Tom Lendacky,
H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy, Brijesh Singh
The CC_ATTR_SEV_SNP can be used by the guest to query whether the SNP -
Secure Nested Paging feature is active.
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
arch/x86/include/asm/msr-index.h | 2 ++
arch/x86/kernel/cc_platform.c | 2 ++
arch/x86/mm/mem_encrypt.c | 4 ++++
include/linux/cc_platform.h | 8 ++++++++
4 files changed, 16 insertions(+)
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 01e2650b9585..98a64b230447 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -481,8 +481,10 @@
#define MSR_AMD64_SEV 0xc0010131
#define MSR_AMD64_SEV_ENABLED_BIT 0
#define MSR_AMD64_SEV_ES_ENABLED_BIT 1
+#define MSR_AMD64_SEV_SNP_ENABLED_BIT 2
#define MSR_AMD64_SEV_ENABLED BIT_ULL(MSR_AMD64_SEV_ENABLED_BIT)
#define MSR_AMD64_SEV_ES_ENABLED BIT_ULL(MSR_AMD64_SEV_ES_ENABLED_BIT)
+#define MSR_AMD64_SEV_SNP_ENABLED BIT_ULL(MSR_AMD64_SEV_SNP_ENABLED_BIT)
#define MSR_AMD64_VIRT_SPEC_CTRL 0xc001011f
diff --git a/arch/x86/kernel/cc_platform.c b/arch/x86/kernel/cc_platform.c
index 03bb2f343ddb..e05310f5ec2f 100644
--- a/arch/x86/kernel/cc_platform.c
+++ b/arch/x86/kernel/cc_platform.c
@@ -50,6 +50,8 @@ static bool amd_cc_platform_has(enum cc_attr attr)
case CC_ATTR_GUEST_STATE_ENCRYPT:
return sev_status & MSR_AMD64_SEV_ES_ENABLED;
+ case CC_ATTR_SEV_SNP:
+ return sev_status & MSR_AMD64_SEV_SNP_ENABLED;
default:
return false;
}
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 35487305d8af..3ba801ff6afc 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -487,6 +487,10 @@ static void print_mem_encrypt_feature_info(void)
if (cc_platform_has(CC_ATTR_GUEST_STATE_ENCRYPT))
pr_cont(" SEV-ES");
+ /* Secure Nested Paging */
+ if (cc_platform_has(CC_ATTR_SEV_SNP))
+ pr_cont(" SEV-SNP");
+
pr_cont("\n");
}
diff --git a/include/linux/cc_platform.h b/include/linux/cc_platform.h
index a075b70b9a70..ef5e2209c9b8 100644
--- a/include/linux/cc_platform.h
+++ b/include/linux/cc_platform.h
@@ -61,6 +61,14 @@ enum cc_attr {
* Examples include SEV-ES.
*/
CC_ATTR_GUEST_STATE_ENCRYPT,
+
+ /**
+ * @CC_ATTR_SEV_SNP: Guest SNP is active.
+ *
+ * The platform/OS is running as a guest/virtual machine and actively
+ * using AMD SEV-SNP features.
+ */
+ CC_ATTR_SEV_SNP = 0x100,
};
#ifdef CONFIG_ARCH_HAS_CC_PLATFORM
--
2.25.1
^ permalink raw reply related [flat|nested] 183+ messages in thread* Re: [PATCH v8 03/40] x86/mm: Extend cc_attr to include AMD SEV-SNP
2021-12-10 15:42 ` [PATCH v8 03/40] x86/mm: Extend cc_attr to include AMD SEV-SNP Brijesh Singh
@ 2021-12-13 22:47 ` Venu Busireddy
2021-12-14 15:53 ` Borislav Petkov
1 sibling, 0 replies; 183+ messages in thread
From: Venu Busireddy @ 2021-12-13 22:47 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2021-12-10 09:42:55 -0600, Brijesh Singh wrote:
> The CC_ATTR_SEV_SNP can be used by the guest to query whether the SNP -
> Secure Nested Paging feature is active.
>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
> +
> + /**
> + * @CC_ATTR_SEV_SNP: Guest SNP is active.
> + *
> + * The platform/OS is running as a guest/virtual machine and actively
> + * using AMD SEV-SNP features.
> + */
> + CC_ATTR_SEV_SNP = 0x100,
Perhaps add a note on why this is being set to 0x100?
With that...
Reviewed-by: Venu Busireddy <venu.busireddy@oracle.com>
^ permalink raw reply [flat|nested] 183+ messages in thread
* Re: [PATCH v8 03/40] x86/mm: Extend cc_attr to include AMD SEV-SNP
2021-12-10 15:42 ` [PATCH v8 03/40] x86/mm: Extend cc_attr to include AMD SEV-SNP Brijesh Singh
2021-12-13 22:47 ` Venu Busireddy
@ 2021-12-14 15:53 ` Borislav Petkov
1 sibling, 0 replies; 183+ messages in thread
From: Borislav Petkov @ 2021-12-14 15:53 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Michael Roth, Vlastimil Babka,
Kirill A . Shutemov, Andi Kleen, Dr . David Alan Gilbert,
tony.luck, marcorr, sathyanarayanan.kuppuswamy
On Fri, Dec 10, 2021 at 09:42:55AM -0600, Brijesh Singh wrote:
> diff --git a/include/linux/cc_platform.h b/include/linux/cc_platform.h
> index a075b70b9a70..ef5e2209c9b8 100644
> --- a/include/linux/cc_platform.h
> +++ b/include/linux/cc_platform.h
> @@ -61,6 +61,14 @@ enum cc_attr {
> * Examples include SEV-ES.
> */
> CC_ATTR_GUEST_STATE_ENCRYPT,
> +
> + /**
> + * @CC_ATTR_SEV_SNP: Guest SNP is active.
> + *
> + * The platform/OS is running as a guest/virtual machine and actively
> + * using AMD SEV-SNP features.
> + */
> + CC_ATTR_SEV_SNP = 0x100,
I guess CC_ATTR_GUEST_SEV_SNP. The Intel is called CC_ATTR_GUEST_TDX so
at least they all say it is a guest thing, this way.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 183+ messages in thread
* [PATCH v8 04/40] x86/sev: Define the Linux specific guest termination reasons
2021-12-10 15:42 [PATCH v8 00/40] Add AMD Secure Nested Paging (SEV-SNP) Guest Support Brijesh Singh
` (2 preceding siblings ...)
2021-12-10 15:42 ` [PATCH v8 03/40] x86/mm: Extend cc_attr to include AMD SEV-SNP Brijesh Singh
@ 2021-12-10 15:42 ` Brijesh Singh
2021-12-14 0:13 ` Venu Busireddy
2021-12-14 22:22 ` Borislav Petkov
2021-12-10 15:42 ` [PATCH v8 05/40] x86/sev: Save the negotiated GHCB version Brijesh Singh
` (36 subsequent siblings)
40 siblings, 2 replies; 183+ messages in thread
From: Brijesh Singh @ 2021-12-10 15:42 UTC (permalink / raw)
To: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm
Cc: Thomas Gleixner, Ingo Molnar, Joerg Roedel, Tom Lendacky,
H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy, Brijesh Singh
GHCB specification defines the reason code for reason set 0. The reason
codes defined in the set 0 do not cover all possible causes for a guest
to request termination.
The reason set 1 to 255 is reserved for the vendor-specific codes.
Reseve the reason set 1 for the Linux guest. Define an error codes for
reason set 1.
While at it, change the sev_es_terminate() to accept the reason set
parameter.
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
arch/x86/boot/compressed/sev.c | 6 +++---
arch/x86/include/asm/sev-common.h | 8 ++++++++
arch/x86/kernel/sev-shared.c | 11 ++++-------
arch/x86/kernel/sev.c | 4 ++--
4 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
index 8eebdf589a90..0b6cc6402ac1 100644
--- a/arch/x86/boot/compressed/sev.c
+++ b/arch/x86/boot/compressed/sev.c
@@ -122,7 +122,7 @@ static enum es_result vc_read_mem(struct es_em_ctxt *ctxt,
static bool early_setup_sev_es(void)
{
if (!sev_es_negotiate_protocol())
- sev_es_terminate(GHCB_SEV_ES_PROT_UNSUPPORTED);
+ sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_PROT_UNSUPPORTED);
if (set_page_decrypted((unsigned long)&boot_ghcb_page))
return false;
@@ -175,7 +175,7 @@ void do_boot_stage2_vc(struct pt_regs *regs, unsigned long exit_code)
enum es_result result;
if (!boot_ghcb && !early_setup_sev_es())
- sev_es_terminate(GHCB_SEV_ES_GEN_REQ);
+ sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_GEN_REQ);
vc_ghcb_invalidate(boot_ghcb);
result = vc_init_em_ctxt(&ctxt, regs, exit_code);
@@ -202,7 +202,7 @@ void do_boot_stage2_vc(struct pt_regs *regs, unsigned long exit_code)
if (result == ES_OK)
vc_finish_insn(&ctxt);
else if (result != ES_RETRY)
- sev_es_terminate(GHCB_SEV_ES_GEN_REQ);
+ sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_GEN_REQ);
}
static inline u64 rd_sev_status_msr(void)
diff --git a/arch/x86/include/asm/sev-common.h b/arch/x86/include/asm/sev-common.h
index 1b2fd32b42fe..94f0ea574049 100644
--- a/arch/x86/include/asm/sev-common.h
+++ b/arch/x86/include/asm/sev-common.h
@@ -73,9 +73,17 @@
/* GHCBData[23:16] */ \
((((u64)reason_val) & 0xff) << 16))
+/* Error codes from reason set 0 */
+#define SEV_TERM_SET_GEN 0
#define GHCB_SEV_ES_GEN_REQ 0
#define GHCB_SEV_ES_PROT_UNSUPPORTED 1
+/* Linux-specific reason codes (used with reason set 1) */
+#define SEV_TERM_SET_LINUX 1
+#define GHCB_TERM_REGISTER 0 /* GHCB GPA registration failure */
+#define GHCB_TERM_PSC 1 /* Page State Change failure */
+#define GHCB_TERM_PVALIDATE 2 /* Pvalidate failure */
+
#define GHCB_RESP_CODE(v) ((v) & GHCB_MSR_INFO_MASK)
/*
diff --git a/arch/x86/kernel/sev-shared.c b/arch/x86/kernel/sev-shared.c
index ce987688bbc0..2abf8a7d75e5 100644
--- a/arch/x86/kernel/sev-shared.c
+++ b/arch/x86/kernel/sev-shared.c
@@ -24,15 +24,12 @@ static bool __init sev_es_check_cpu_features(void)
return true;
}
-static void __noreturn sev_es_terminate(unsigned int reason)
+static void __noreturn sev_es_terminate(unsigned int set, unsigned int reason)
{
u64 val = GHCB_MSR_TERM_REQ;
- /*
- * Tell the hypervisor what went wrong - only reason-set 0 is
- * currently supported.
- */
- val |= GHCB_SEV_TERM_REASON(0, reason);
+ /* Tell the hypervisor what went wrong. */
+ val |= GHCB_SEV_TERM_REASON(set, reason);
/* Request Guest Termination from Hypvervisor */
sev_es_wr_ghcb_msr(val);
@@ -221,7 +218,7 @@ void __init do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code)
fail:
/* Terminate the guest */
- sev_es_terminate(GHCB_SEV_ES_GEN_REQ);
+ sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_GEN_REQ);
}
static enum es_result vc_insn_string_read(struct es_em_ctxt *ctxt,
diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c
index e6d316a01fdd..19ad09712902 100644
--- a/arch/x86/kernel/sev.c
+++ b/arch/x86/kernel/sev.c
@@ -1337,7 +1337,7 @@ DEFINE_IDTENTRY_VC_KERNEL(exc_vmm_communication)
show_regs(regs);
/* Ask hypervisor to sev_es_terminate */
- sev_es_terminate(GHCB_SEV_ES_GEN_REQ);
+ sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_GEN_REQ);
/* If that fails and we get here - just panic */
panic("Returned from Terminate-Request to Hypervisor\n");
@@ -1385,7 +1385,7 @@ bool __init handle_vc_boot_ghcb(struct pt_regs *regs)
/* Do initial setup or terminate the guest */
if (unlikely(boot_ghcb == NULL && !sev_es_setup_ghcb()))
- sev_es_terminate(GHCB_SEV_ES_GEN_REQ);
+ sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_GEN_REQ);
vc_ghcb_invalidate(boot_ghcb);
--
2.25.1
^ permalink raw reply related [flat|nested] 183+ messages in thread* Re: [PATCH v8 04/40] x86/sev: Define the Linux specific guest termination reasons
2021-12-10 15:42 ` [PATCH v8 04/40] x86/sev: Define the Linux specific guest termination reasons Brijesh Singh
@ 2021-12-14 0:13 ` Venu Busireddy
2021-12-14 22:22 ` Borislav Petkov
1 sibling, 0 replies; 183+ messages in thread
From: Venu Busireddy @ 2021-12-14 0:13 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2021-12-10 09:42:56 -0600, Brijesh Singh wrote:
> GHCB specification defines the reason code for reason set 0. The reason
> codes defined in the set 0 do not cover all possible causes for a guest
> to request termination.
>
> The reason set 1 to 255 is reserved for the vendor-specific codes.
s/set 1 to 255 is/sets 1 to 255 are/
> Reseve the reason set 1 for the Linux guest. Define an error codes for
s/Define an/Define the/
> reason set 1.
>
> While at it, change the sev_es_terminate() to accept the reason set
> parameter.
>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
With that...
Reviewed-by: Venu Busireddy <venu.busireddy@oracle.com>
> ---
> arch/x86/boot/compressed/sev.c | 6 +++---
> arch/x86/include/asm/sev-common.h | 8 ++++++++
> arch/x86/kernel/sev-shared.c | 11 ++++-------
> arch/x86/kernel/sev.c | 4 ++--
> 4 files changed, 17 insertions(+), 12 deletions(-)
^ permalink raw reply [flat|nested] 183+ messages in thread
* Re: [PATCH v8 04/40] x86/sev: Define the Linux specific guest termination reasons
2021-12-10 15:42 ` [PATCH v8 04/40] x86/sev: Define the Linux specific guest termination reasons Brijesh Singh
2021-12-14 0:13 ` Venu Busireddy
@ 2021-12-14 22:22 ` Borislav Petkov
1 sibling, 0 replies; 183+ messages in thread
From: Borislav Petkov @ 2021-12-14 22:22 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Michael Roth, Vlastimil Babka,
Kirill A . Shutemov, Andi Kleen, Dr . David Alan Gilbert,
tony.luck, marcorr, sathyanarayanan.kuppuswamy
On Fri, Dec 10, 2021 at 09:42:56AM -0600, Brijesh Singh wrote:
> GHCB specification defines the reason code for reason set 0. The reason
> codes defined in the set 0 do not cover all possible causes for a guest
> to request termination.
>
> The reason set 1 to 255 is reserved for the vendor-specific codes.
> Reseve the reason set 1 for the Linux guest. Define an error codes for
Yah, your spellchecker is still broken:
Reseve the reason set 1 for the Linux guest. Define an error codes for
Unknown word [Reseve] in commit message, suggestions:
['Reeves', 'Reeve', 'Reserve', 'Res eve', 'Res-eve', 'Severe', 'Reverse', 'Sevres', 'Revers']
> reason set 1.
"... and use them in the Linux guest so that one can have meaningful
termination reasons and thus better guest failure diagnosis."
The *why* is very important.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 183+ messages in thread
* [PATCH v8 05/40] x86/sev: Save the negotiated GHCB version
2021-12-10 15:42 [PATCH v8 00/40] Add AMD Secure Nested Paging (SEV-SNP) Guest Support Brijesh Singh
` (3 preceding siblings ...)
2021-12-10 15:42 ` [PATCH v8 04/40] x86/sev: Define the Linux specific guest termination reasons Brijesh Singh
@ 2021-12-10 15:42 ` Brijesh Singh
2021-12-14 0:32 ` Venu Busireddy
2021-12-10 15:42 ` [PATCH v8 06/40] x86/sev: Check SEV-SNP features support Brijesh Singh
` (35 subsequent siblings)
40 siblings, 1 reply; 183+ messages in thread
From: Brijesh Singh @ 2021-12-10 15:42 UTC (permalink / raw)
To: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm
Cc: Thomas Gleixner, Ingo Molnar, Joerg Roedel, Tom Lendacky,
H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy, Brijesh Singh
The SEV-ES guest calls the sev_es_negotiate_protocol() to negotiate the
GHCB protocol version before establishing the GHCB. Cache the negotiated
GHCB version so that it can be used later.
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
arch/x86/include/asm/sev.h | 2 +-
arch/x86/kernel/sev-shared.c | 17 ++++++++++++++---
2 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index ec060c433589..9b9c190e8c3b 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h
@@ -12,7 +12,7 @@
#include <asm/insn.h>
#include <asm/sev-common.h>
-#define GHCB_PROTO_OUR 0x0001UL
+#define GHCB_PROTOCOL_MIN 1ULL
#define GHCB_PROTOCOL_MAX 1ULL
#define GHCB_DEFAULT_USAGE 0ULL
diff --git a/arch/x86/kernel/sev-shared.c b/arch/x86/kernel/sev-shared.c
index 2abf8a7d75e5..91105f5a02a8 100644
--- a/arch/x86/kernel/sev-shared.c
+++ b/arch/x86/kernel/sev-shared.c
@@ -14,6 +14,15 @@
#define has_cpuflag(f) boot_cpu_has(f)
#endif
+/*
+ * Since feature negotiation related variables are set early in the boot
+ * process they must reside in the .data section so as not to be zeroed
+ * out when the .bss section is later cleared.
+ *
+ * GHCB protocol version negotiated with the hypervisor.
+ */
+static u16 ghcb_version __ro_after_init;
+
static bool __init sev_es_check_cpu_features(void)
{
if (!has_cpuflag(X86_FEATURE_RDRAND)) {
@@ -51,10 +60,12 @@ static bool sev_es_negotiate_protocol(void)
if (GHCB_MSR_INFO(val) != GHCB_MSR_SEV_INFO_RESP)
return false;
- if (GHCB_MSR_PROTO_MAX(val) < GHCB_PROTO_OUR ||
- GHCB_MSR_PROTO_MIN(val) > GHCB_PROTO_OUR)
+ if (GHCB_MSR_PROTO_MAX(val) < GHCB_PROTOCOL_MIN ||
+ GHCB_MSR_PROTO_MIN(val) > GHCB_PROTOCOL_MAX)
return false;
+ ghcb_version = min_t(size_t, GHCB_MSR_PROTO_MAX(val), GHCB_PROTOCOL_MAX);
+
return true;
}
@@ -127,7 +138,7 @@ enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb, bool set_ghcb_msr,
u64 exit_info_1, u64 exit_info_2)
{
/* Fill in protocol and format specifiers */
- ghcb->protocol_version = GHCB_PROTOCOL_MAX;
+ ghcb->protocol_version = ghcb_version;
ghcb->ghcb_usage = GHCB_DEFAULT_USAGE;
ghcb_set_sw_exit_code(ghcb, exit_code);
--
2.25.1
^ permalink raw reply related [flat|nested] 183+ messages in thread* Re: [PATCH v8 05/40] x86/sev: Save the negotiated GHCB version
2021-12-10 15:42 ` [PATCH v8 05/40] x86/sev: Save the negotiated GHCB version Brijesh Singh
@ 2021-12-14 0:32 ` Venu Busireddy
0 siblings, 0 replies; 183+ messages in thread
From: Venu Busireddy @ 2021-12-14 0:32 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2021-12-10 09:42:57 -0600, Brijesh Singh wrote:
> The SEV-ES guest calls the sev_es_negotiate_protocol() to negotiate the
> GHCB protocol version before establishing the GHCB. Cache the negotiated
> GHCB version so that it can be used later.
>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Venu Busireddy <venu.busireddy@oracle.com>
> ---
> arch/x86/include/asm/sev.h | 2 +-
> arch/x86/kernel/sev-shared.c | 17 ++++++++++++++---
> 2 files changed, 15 insertions(+), 4 deletions(-)
^ permalink raw reply [flat|nested] 183+ messages in thread
* [PATCH v8 06/40] x86/sev: Check SEV-SNP features support
2021-12-10 15:42 [PATCH v8 00/40] Add AMD Secure Nested Paging (SEV-SNP) Guest Support Brijesh Singh
` (4 preceding siblings ...)
2021-12-10 15:42 ` [PATCH v8 05/40] x86/sev: Save the negotiated GHCB version Brijesh Singh
@ 2021-12-10 15:42 ` Brijesh Singh
2021-12-16 15:47 ` Borislav Petkov
2021-12-16 19:01 ` Venu Busireddy
2021-12-10 15:42 ` [PATCH v8 07/40] x86/sev: Add a helper for the PVALIDATE instruction Brijesh Singh
` (34 subsequent siblings)
40 siblings, 2 replies; 183+ messages in thread
From: Brijesh Singh @ 2021-12-10 15:42 UTC (permalink / raw)
To: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm
Cc: Thomas Gleixner, Ingo Molnar, Joerg Roedel, Tom Lendacky,
H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy, Brijesh Singh
Version 2 of the GHCB specification added the advertisement of features
that are supported by the hypervisor. If hypervisor supports the SEV-SNP
then it must set the SEV-SNP features bit to indicate that the base
SEV-SNP is supported.
Check the SEV-SNP feature while establishing the GHCB, if failed,
terminate the guest.
Version 2 of GHCB specification adds several new NAEs, most of them are
optional except the hypervisor feature. Now that hypervisor feature NAE
is implemented, so bump the GHCB maximum support protocol version.
While at it, move the GHCB protocol negotitation check from VC exception
handler to sev_enable() so that all feature detection happens before
the first VC exception.
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
arch/x86/boot/compressed/sev.c | 21 ++++++++++++++++-----
arch/x86/include/asm/sev-common.h | 6 ++++++
arch/x86/include/asm/sev.h | 2 +-
arch/x86/include/uapi/asm/svm.h | 2 ++
arch/x86/kernel/sev-shared.c | 20 ++++++++++++++++++++
arch/x86/kernel/sev.c | 16 ++++++++++++++++
6 files changed, 61 insertions(+), 6 deletions(-)
diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
index 0b6cc6402ac1..a0708f359a46 100644
--- a/arch/x86/boot/compressed/sev.c
+++ b/arch/x86/boot/compressed/sev.c
@@ -119,11 +119,8 @@ static enum es_result vc_read_mem(struct es_em_ctxt *ctxt,
/* Include code for early handlers */
#include "../../kernel/sev-shared.c"
-static bool early_setup_sev_es(void)
+static bool early_setup_ghcb(void)
{
- if (!sev_es_negotiate_protocol())
- sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_PROT_UNSUPPORTED);
-
if (set_page_decrypted((unsigned long)&boot_ghcb_page))
return false;
@@ -174,7 +171,7 @@ void do_boot_stage2_vc(struct pt_regs *regs, unsigned long exit_code)
struct es_em_ctxt ctxt;
enum es_result result;
- if (!boot_ghcb && !early_setup_sev_es())
+ if (!boot_ghcb && !early_setup_ghcb())
sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_GEN_REQ);
vc_ghcb_invalidate(boot_ghcb);
@@ -247,5 +244,19 @@ void sev_enable(struct boot_params *bp)
if (!(sev_status & MSR_AMD64_SEV_ENABLED))
return;
+ /* Negotiate the GHCB protocol version */
+ if (sev_status & MSR_AMD64_SEV_ES_ENABLED)
+ if (!sev_es_negotiate_protocol())
+ sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_PROT_UNSUPPORTED);
+
+ /*
+ * SNP is supported in v2 of the GHCB spec which mandates support for HV
+ * features. If SEV-SNP is enabled, then check if the hypervisor supports
+ * the SEV-SNP features.
+ */
+ if (sev_status & MSR_AMD64_SEV_SNP_ENABLED && !(get_hv_features() & GHCB_HV_FT_SNP))
+ sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
+
+
sme_me_mask = BIT_ULL(ebx & 0x3f);
}
diff --git a/arch/x86/include/asm/sev-common.h b/arch/x86/include/asm/sev-common.h
index 94f0ea574049..6f037c29a46e 100644
--- a/arch/x86/include/asm/sev-common.h
+++ b/arch/x86/include/asm/sev-common.h
@@ -60,6 +60,11 @@
/* GHCB Hypervisor Feature Request/Response */
#define GHCB_MSR_HV_FT_REQ 0x080
#define GHCB_MSR_HV_FT_RESP 0x081
+#define GHCB_MSR_HV_FT_RESP_VAL(v) \
+ /* GHCBData[63:12] */ \
+ (((u64)(v) & GENMASK_ULL(63, 12)) >> 12)
+
+#define GHCB_HV_FT_SNP BIT_ULL(0)
#define GHCB_MSR_TERM_REQ 0x100
#define GHCB_MSR_TERM_REASON_SET_POS 12
@@ -77,6 +82,7 @@
#define SEV_TERM_SET_GEN 0
#define GHCB_SEV_ES_GEN_REQ 0
#define GHCB_SEV_ES_PROT_UNSUPPORTED 1
+#define GHCB_SNP_UNSUPPORTED 2
/* Linux-specific reason codes (used with reason set 1) */
#define SEV_TERM_SET_LINUX 1
diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index 9b9c190e8c3b..17b75f6ee11a 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h
@@ -13,7 +13,7 @@
#include <asm/sev-common.h>
#define GHCB_PROTOCOL_MIN 1ULL
-#define GHCB_PROTOCOL_MAX 1ULL
+#define GHCB_PROTOCOL_MAX 2ULL
#define GHCB_DEFAULT_USAGE 0ULL
#define VMGEXIT() { asm volatile("rep; vmmcall\n\r"); }
diff --git a/arch/x86/include/uapi/asm/svm.h b/arch/x86/include/uapi/asm/svm.h
index efa969325ede..b0ad00f4c1e1 100644
--- a/arch/x86/include/uapi/asm/svm.h
+++ b/arch/x86/include/uapi/asm/svm.h
@@ -108,6 +108,7 @@
#define SVM_VMGEXIT_AP_JUMP_TABLE 0x80000005
#define SVM_VMGEXIT_SET_AP_JUMP_TABLE 0
#define SVM_VMGEXIT_GET_AP_JUMP_TABLE 1
+#define SVM_VMGEXIT_HV_FEATURES 0x8000fffd
#define SVM_VMGEXIT_UNSUPPORTED_EVENT 0x8000ffff
/* Exit code reserved for hypervisor/software use */
@@ -218,6 +219,7 @@
{ SVM_VMGEXIT_NMI_COMPLETE, "vmgexit_nmi_complete" }, \
{ SVM_VMGEXIT_AP_HLT_LOOP, "vmgexit_ap_hlt_loop" }, \
{ SVM_VMGEXIT_AP_JUMP_TABLE, "vmgexit_ap_jump_table" }, \
+ { SVM_VMGEXIT_HV_FEATURES, "vmgexit_hypervisor_feature" }, \
{ SVM_EXIT_ERR, "invalid_guest_state" }
diff --git a/arch/x86/kernel/sev-shared.c b/arch/x86/kernel/sev-shared.c
index 91105f5a02a8..4a876e684f67 100644
--- a/arch/x86/kernel/sev-shared.c
+++ b/arch/x86/kernel/sev-shared.c
@@ -48,6 +48,26 @@ static void __noreturn sev_es_terminate(unsigned int set, unsigned int reason)
asm volatile("hlt\n" : : : "memory");
}
+/*
+ * The hypervisor features are available from GHCB version 2 onward.
+ */
+static u64 get_hv_features(void)
+{
+ u64 val;
+
+ if (ghcb_version < 2)
+ return 0;
+
+ sev_es_wr_ghcb_msr(GHCB_MSR_HV_FT_REQ);
+ VMGEXIT();
+
+ val = sev_es_rd_ghcb_msr();
+ if (GHCB_RESP_CODE(val) != GHCB_MSR_HV_FT_RESP)
+ return 0;
+
+ return GHCB_MSR_HV_FT_RESP_VAL(val);
+}
+
static bool sev_es_negotiate_protocol(void)
{
u64 val;
diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c
index 19ad09712902..a0cada8398a4 100644
--- a/arch/x86/kernel/sev.c
+++ b/arch/x86/kernel/sev.c
@@ -43,6 +43,10 @@ static struct ghcb boot_ghcb_page __bss_decrypted __aligned(PAGE_SIZE);
*/
static struct ghcb __initdata *boot_ghcb;
+/* Bitmap of SEV features supported by the hypervisor */
+static u64 sev_hv_features;
+
+
/* #VC handler runtime per-CPU data */
struct sev_es_runtime_data {
struct ghcb ghcb_page;
@@ -766,6 +770,18 @@ void __init sev_es_init_vc_handling(void)
if (!sev_es_check_cpu_features())
panic("SEV-ES CPU Features missing");
+ /*
+ * SNP is supported in v2 of the GHCB spec which mandates support for HV
+ * features. If SEV-SNP is enabled, then check if the hypervisor supports
+ * the SEV-SNP features.
+ */
+ if (cc_platform_has(CC_ATTR_SEV_SNP)) {
+ sev_hv_features = get_hv_features();
+
+ if (!(sev_hv_features & GHCB_HV_FT_SNP))
+ sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
+ }
+
/* Enable SEV-ES special handling */
static_branch_enable(&sev_es_enable_key);
--
2.25.1
^ permalink raw reply related [flat|nested] 183+ messages in thread* Re: [PATCH v8 06/40] x86/sev: Check SEV-SNP features support
2021-12-10 15:42 ` [PATCH v8 06/40] x86/sev: Check SEV-SNP features support Brijesh Singh
@ 2021-12-16 15:47 ` Borislav Petkov
2021-12-16 16:28 ` Brijesh Singh
2021-12-16 19:01 ` Venu Busireddy
1 sibling, 1 reply; 183+ messages in thread
From: Borislav Petkov @ 2021-12-16 15:47 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Michael Roth, Vlastimil Babka,
Kirill A . Shutemov, Andi Kleen, Dr . David Alan Gilbert,
tony.luck, marcorr, sathyanarayanan.kuppuswamy
On Fri, Dec 10, 2021 at 09:42:58AM -0600, Brijesh Singh wrote:
> Version 2 of the GHCB specification added the advertisement of features
> that are supported by the hypervisor. If hypervisor supports the SEV-SNP
> then it must set the SEV-SNP features bit to indicate that the base
> SEV-SNP is supported.
>
> Check the SEV-SNP feature while establishing the GHCB, if failed,
> terminate the guest.
>
> Version 2 of GHCB specification adds several new NAEs, most of them are
> optional except the hypervisor feature. Now that hypervisor feature NAE
> is implemented, so bump the GHCB maximum support protocol version.
>
> While at it, move the GHCB protocol negotitation check from VC exception
Unknown word [negotitation] in commit message, suggestions:
['negotiation', 'negotiator', 'negotiate', 'abnegation', 'vegetation']
> handler to sev_enable() so that all feature detection happens before
> the first VC exception.
>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
> arch/x86/boot/compressed/sev.c | 21 ++++++++++++++++-----
> arch/x86/include/asm/sev-common.h | 6 ++++++
> arch/x86/include/asm/sev.h | 2 +-
> arch/x86/include/uapi/asm/svm.h | 2 ++
> arch/x86/kernel/sev-shared.c | 20 ++++++++++++++++++++
> arch/x86/kernel/sev.c | 16 ++++++++++++++++
> 6 files changed, 61 insertions(+), 6 deletions(-)
>
> diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
> index 0b6cc6402ac1..a0708f359a46 100644
> --- a/arch/x86/boot/compressed/sev.c
> +++ b/arch/x86/boot/compressed/sev.c
> @@ -119,11 +119,8 @@ static enum es_result vc_read_mem(struct es_em_ctxt *ctxt,
> /* Include code for early handlers */
> #include "../../kernel/sev-shared.c"
>
> -static bool early_setup_sev_es(void)
> +static bool early_setup_ghcb(void)
> {
> - if (!sev_es_negotiate_protocol())
> - sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_PROT_UNSUPPORTED);
> -
> if (set_page_decrypted((unsigned long)&boot_ghcb_page))
> return false;
>
> @@ -174,7 +171,7 @@ void do_boot_stage2_vc(struct pt_regs *regs, unsigned long exit_code)
> struct es_em_ctxt ctxt;
> enum es_result result;
>
> - if (!boot_ghcb && !early_setup_sev_es())
> + if (!boot_ghcb && !early_setup_ghcb())
> sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_GEN_REQ);
Can you setup the GHCB in sev_enable() too, after the protocol version
negotiation succeeds?
> vc_ghcb_invalidate(boot_ghcb);
> @@ -247,5 +244,19 @@ void sev_enable(struct boot_params *bp)
> if (!(sev_status & MSR_AMD64_SEV_ENABLED))
> return;
>
> + /* Negotiate the GHCB protocol version */
> + if (sev_status & MSR_AMD64_SEV_ES_ENABLED)
> + if (!sev_es_negotiate_protocol())
> + sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_PROT_UNSUPPORTED);
> +
> + /*
> + * SNP is supported in v2 of the GHCB spec which mandates support for HV
> + * features. If SEV-SNP is enabled, then check if the hypervisor supports
> + * the SEV-SNP features.
> + */
> + if (sev_status & MSR_AMD64_SEV_SNP_ENABLED && !(get_hv_features() & GHCB_HV_FT_SNP))
> + sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
> +
> +
^ Superfluous newline.
> sme_me_mask = BIT_ULL(ebx & 0x3f);
...
> diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c
> index 19ad09712902..a0cada8398a4 100644
> --- a/arch/x86/kernel/sev.c
> +++ b/arch/x86/kernel/sev.c
> @@ -43,6 +43,10 @@ static struct ghcb boot_ghcb_page __bss_decrypted __aligned(PAGE_SIZE);
> */
> static struct ghcb __initdata *boot_ghcb;
>
> +/* Bitmap of SEV features supported by the hypervisor */
> +static u64 sev_hv_features;
__ro_after_init
> +
> +
> /* #VC handler runtime per-CPU data */
> struct sev_es_runtime_data {
> struct ghcb ghcb_page;
> @@ -766,6 +770,18 @@ void __init sev_es_init_vc_handling(void)
> if (!sev_es_check_cpu_features())
> panic("SEV-ES CPU Features missing");
>
> + /*
> + * SNP is supported in v2 of the GHCB spec which mandates support for HV
> + * features. If SEV-SNP is enabled, then check if the hypervisor supports
s/SEV-SNP/SNP/g
And please do that everywhere in sev-specific files.
This file is called sev.c and there's way too many acronyms flying
around so the simpler the better.
Thx.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 06/40] x86/sev: Check SEV-SNP features support
2021-12-16 15:47 ` Borislav Petkov
@ 2021-12-16 16:28 ` Brijesh Singh
2021-12-16 16:58 ` Borislav Petkov
0 siblings, 1 reply; 183+ messages in thread
From: Brijesh Singh @ 2021-12-16 16:28 UTC (permalink / raw)
To: Borislav Petkov
Cc: brijesh.singh, x86, linux-kernel, kvm, linux-efi,
platform-driver-x86, linux-coco, linux-mm, Thomas Gleixner,
Ingo Molnar, Joerg Roedel, Tom Lendacky, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 12/16/21 9:47 AM, Borislav Petkov wrote:
>>
>> - if (!boot_ghcb && !early_setup_sev_es())
>> + if (!boot_ghcb && !early_setup_ghcb())
>> sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_GEN_REQ);
>
> Can you setup the GHCB in sev_enable() too, after the protocol version
> negotiation succeeds?
A good question; the GHCB page is needed only at the time of #VC. If
the second stage VC handler is not called after the sev_enable() during
the decompression stage, setting up the GHC page in sev_enable() is a
waste. But in practice, the second stage VC handler will be called
during decompression. It also brings a similar question for the kernel
proper, should we do the same over there?
Jorge did the initial ES support and may have other reasons he chose to
set up GHCB page in the handler. I was trying to avoid the flow change.
We can do this as a pre or post-SNP patch; let me know your thoughts?
>> + * SNP is supported in v2 of the GHCB spec which mandates support for HV
>> + * features. If SEV-SNP is enabled, then check if the hypervisor supports
>
> s/SEV-SNP/SNP/g
>
> And please do that everywhere in sev-specific files.
>
> This file is called sev.c and there's way too many acronyms flying
> around so the simpler the better.
>
Noted.
thanks
^ permalink raw reply [flat|nested] 183+ messages in thread
* Re: [PATCH v8 06/40] x86/sev: Check SEV-SNP features support
2021-12-16 16:28 ` Brijesh Singh
@ 2021-12-16 16:58 ` Borislav Petkov
0 siblings, 0 replies; 183+ messages in thread
From: Borislav Petkov @ 2021-12-16 16:58 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Michael Roth, Vlastimil Babka,
Kirill A . Shutemov, Andi Kleen, Dr . David Alan Gilbert,
tony.luck, marcorr, sathyanarayanan.kuppuswamy
On Thu, Dec 16, 2021 at 10:28:45AM -0600, Brijesh Singh wrote:
> A good question; the GHCB page is needed only at the time of #VC. If the
> second stage VC handler is not called after the sev_enable() during the
> decompression stage, setting up the GHC page in sev_enable() is a waste.
It would be a waste if no #VC would fire. But we set up a #VC handler so
we might just as well set up the GHCB for it too.
> But in practice, the second stage VC handler will be called during
> decompression. It also brings a similar question for the kernel
> proper, should we do the same over there?
I'd think so, yes.
> Jorge did the initial ES support and may have other reasons he chose to set
> up GHCB page in the handler. I was trying to avoid the flow change. We can
> do this as a pre or post-SNP patch; let me know your thoughts?
You can do a separate patch only with that change and if it causes
trouble, we can always debug/delay it.
Thx.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 183+ messages in thread
* Re: [PATCH v8 06/40] x86/sev: Check SEV-SNP features support
2021-12-10 15:42 ` [PATCH v8 06/40] x86/sev: Check SEV-SNP features support Brijesh Singh
2021-12-16 15:47 ` Borislav Petkov
@ 2021-12-16 19:01 ` Venu Busireddy
1 sibling, 0 replies; 183+ messages in thread
From: Venu Busireddy @ 2021-12-16 19:01 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2021-12-10 09:42:58 -0600, Brijesh Singh wrote:
> Version 2 of the GHCB specification added the advertisement of features
> that are supported by the hypervisor. If hypervisor supports the SEV-SNP
> then it must set the SEV-SNP features bit to indicate that the base
> SEV-SNP is supported.
>
> Check the SEV-SNP feature while establishing the GHCB, if failed,
> terminate the guest.
>
> Version 2 of GHCB specification adds several new NAEs, most of them are
> optional except the hypervisor feature. Now that hypervisor feature NAE
> is implemented, so bump the GHCB maximum support protocol version.
>
> While at it, move the GHCB protocol negotitation check from VC exception
> handler to sev_enable() so that all feature detection happens before
> the first VC exception.
>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
> arch/x86/boot/compressed/sev.c | 21 ++++++++++++++++-----
> arch/x86/include/asm/sev-common.h | 6 ++++++
> arch/x86/include/asm/sev.h | 2 +-
> arch/x86/include/uapi/asm/svm.h | 2 ++
> arch/x86/kernel/sev-shared.c | 20 ++++++++++++++++++++
> arch/x86/kernel/sev.c | 16 ++++++++++++++++
> 6 files changed, 61 insertions(+), 6 deletions(-)
>
> diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
> index 0b6cc6402ac1..a0708f359a46 100644
> --- a/arch/x86/boot/compressed/sev.c
> +++ b/arch/x86/boot/compressed/sev.c
> @@ -119,11 +119,8 @@ static enum es_result vc_read_mem(struct es_em_ctxt *ctxt,
> /* Include code for early handlers */
> #include "../../kernel/sev-shared.c"
>
> -static bool early_setup_sev_es(void)
> +static bool early_setup_ghcb(void)
> {
> - if (!sev_es_negotiate_protocol())
> - sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_PROT_UNSUPPORTED);
Should the name sev_es_terminate() be changed to a more generic
name, as we are simply terminating the guest, not SEV or ES as the
name implies?
Other than that...
Reviewed-by: Venu Busireddy <venu.busireddy@oracle.com>
^ permalink raw reply [flat|nested] 183+ messages in thread
* [PATCH v8 07/40] x86/sev: Add a helper for the PVALIDATE instruction
2021-12-10 15:42 [PATCH v8 00/40] Add AMD Secure Nested Paging (SEV-SNP) Guest Support Brijesh Singh
` (5 preceding siblings ...)
2021-12-10 15:42 ` [PATCH v8 06/40] x86/sev: Check SEV-SNP features support Brijesh Singh
@ 2021-12-10 15:42 ` Brijesh Singh
2021-12-16 20:20 ` Venu Busireddy
2021-12-10 15:43 ` [PATCH v8 08/40] x86/sev: Check the vmpl level Brijesh Singh
` (33 subsequent siblings)
40 siblings, 1 reply; 183+ messages in thread
From: Brijesh Singh @ 2021-12-10 15:42 UTC (permalink / raw)
To: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm
Cc: Thomas Gleixner, Ingo Molnar, Joerg Roedel, Tom Lendacky,
H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy, Brijesh Singh
An SNP-active guest uses the PVALIDATE instruction to validate or
rescind the validation of a guest page’s RMP entry. Upon completion,
a return code is stored in EAX and rFLAGS bits are set based on the
return code. If the instruction completed successfully, the CF
indicates if the content of the RMP were changed or not.
See AMD APM Volume 3 for additional details.
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
arch/x86/include/asm/sev.h | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index 17b75f6ee11a..4ee98976aed8 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h
@@ -60,6 +60,9 @@ extern void vc_no_ghcb(void);
extern void vc_boot_ghcb(void);
extern bool handle_vc_boot_ghcb(struct pt_regs *regs);
+/* Software defined (when rFlags.CF = 1) */
+#define PVALIDATE_FAIL_NOUPDATE 255
+
#ifdef CONFIG_AMD_MEM_ENCRYPT
extern struct static_key_false sev_es_enable_key;
extern void __sev_es_ist_enter(struct pt_regs *regs);
@@ -87,12 +90,30 @@ extern enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb,
struct es_em_ctxt *ctxt,
u64 exit_code, u64 exit_info_1,
u64 exit_info_2);
+static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate)
+{
+ bool no_rmpupdate;
+ int rc;
+
+ /* "pvalidate" mnemonic support in binutils 2.36 and newer */
+ asm volatile(".byte 0xF2, 0x0F, 0x01, 0xFF\n\t"
+ CC_SET(c)
+ : CC_OUT(c) (no_rmpupdate), "=a"(rc)
+ : "a"(vaddr), "c"(rmp_psize), "d"(validate)
+ : "memory", "cc");
+
+ if (no_rmpupdate)
+ return PVALIDATE_FAIL_NOUPDATE;
+
+ return rc;
+}
#else
static inline void sev_es_ist_enter(struct pt_regs *regs) { }
static inline void sev_es_ist_exit(void) { }
static inline int sev_es_setup_ap_jump_table(struct real_mode_header *rmh) { return 0; }
static inline void sev_es_nmi_complete(void) { }
static inline int sev_es_efi_map_ghcbs(pgd_t *pgd) { return 0; }
+static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate) { return 0; }
#endif
#endif
--
2.25.1
^ permalink raw reply related [flat|nested] 183+ messages in thread* Re: [PATCH v8 07/40] x86/sev: Add a helper for the PVALIDATE instruction
2021-12-10 15:42 ` [PATCH v8 07/40] x86/sev: Add a helper for the PVALIDATE instruction Brijesh Singh
@ 2021-12-16 20:20 ` Venu Busireddy
0 siblings, 0 replies; 183+ messages in thread
From: Venu Busireddy @ 2021-12-16 20:20 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2021-12-10 09:42:59 -0600, Brijesh Singh wrote:
> An SNP-active guest uses the PVALIDATE instruction to validate or
> rescind the validation of a guest page’s RMP entry. Upon completion,
> a return code is stored in EAX and rFLAGS bits are set based on the
> return code. If the instruction completed successfully, the CF
> indicates if the content of the RMP were changed or not.
>
> See AMD APM Volume 3 for additional details.
>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Venu Busireddy <venu.busireddy@oracle.com>
^ permalink raw reply [flat|nested] 183+ messages in thread
* [PATCH v8 08/40] x86/sev: Check the vmpl level
2021-12-10 15:42 [PATCH v8 00/40] Add AMD Secure Nested Paging (SEV-SNP) Guest Support Brijesh Singh
` (6 preceding siblings ...)
2021-12-10 15:42 ` [PATCH v8 07/40] x86/sev: Add a helper for the PVALIDATE instruction Brijesh Singh
@ 2021-12-10 15:43 ` Brijesh Singh
2021-12-16 20:24 ` Venu Busireddy
2021-12-10 15:43 ` [PATCH v8 09/40] x86/compressed: Add helper for validating pages in the decompression stage Brijesh Singh
` (32 subsequent siblings)
40 siblings, 1 reply; 183+ messages in thread
From: Brijesh Singh @ 2021-12-10 15:43 UTC (permalink / raw)
To: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm
Cc: Thomas Gleixner, Ingo Molnar, Joerg Roedel, Tom Lendacky,
H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy, Brijesh Singh
Virtual Machine Privilege Level (VMPL) feature in the SEV-SNP architecture
allows a guest VM to divide its address space into four levels. The level
can be used to provide the hardware isolated abstraction layers with a VM.
The VMPL0 is the highest privilege, and VMPL3 is the least privilege.
Certain operations must be done by the VMPL0 software, such as:
* Validate or invalidate memory range (PVALIDATE instruction)
* Allocate VMSA page (RMPADJUST instruction when VMSA=1)
The initial SEV-SNP support requires that the guest kernel is running on
VMPL0. Add a check to make sure that kernel is running at VMPL0 before
continuing the boot. There is no easy method to query the current VMPL
level, so use the RMPADJUST instruction to determine whether the guest is
running at the VMPL0.
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
arch/x86/boot/compressed/sev.c | 34 ++++++++++++++++++++++++++++---
arch/x86/include/asm/sev-common.h | 1 +
arch/x86/include/asm/sev.h | 16 +++++++++++++++
3 files changed, 48 insertions(+), 3 deletions(-)
diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
index a0708f359a46..9be369f72299 100644
--- a/arch/x86/boot/compressed/sev.c
+++ b/arch/x86/boot/compressed/sev.c
@@ -212,6 +212,31 @@ static inline u64 rd_sev_status_msr(void)
return ((high << 32) | low);
}
+static void enforce_vmpl0(void)
+{
+ u64 attrs;
+ int err;
+
+ /*
+ * There is no straightforward way to query the current VMPL level. The
+ * simplest method is to use the RMPADJUST instruction to change a page
+ * permission to a VMPL level-1, and if the guest kernel is launched at
+ * a level <= 1, then RMPADJUST instruction will return an error.
+ */
+ attrs = 1;
+
+ /*
+ * Any page-aligned virtual address is sufficient to test the VMPL level.
+ * The boot_ghcb_page is page aligned memory, so use for the test.
+ *
+ * The RMPADJUST operation below clears the permission for the boot_ghcb_page
+ * on VMPL1. If the guest is booted at the VMPL0, then there is no need to
+ * restore the permissions because VMPL1 permission will be all zero.
+ */
+ if (rmpadjust((unsigned long)&boot_ghcb_page, RMP_PG_SIZE_4K, attrs))
+ sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_NOT_VMPL0);
+}
+
void sev_enable(struct boot_params *bp)
{
unsigned int eax, ebx, ecx, edx;
@@ -252,11 +277,14 @@ void sev_enable(struct boot_params *bp)
/*
* SNP is supported in v2 of the GHCB spec which mandates support for HV
* features. If SEV-SNP is enabled, then check if the hypervisor supports
- * the SEV-SNP features.
+ * the SEV-SNP features and is launched at VMPL0 level.
*/
- if (sev_status & MSR_AMD64_SEV_SNP_ENABLED && !(get_hv_features() & GHCB_HV_FT_SNP))
- sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
+ if (sev_status & MSR_AMD64_SEV_SNP_ENABLED) {
+ if (!(get_hv_features() & GHCB_HV_FT_SNP))
+ sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
+ enforce_vmpl0();
+ }
sme_me_mask = BIT_ULL(ebx & 0x3f);
}
diff --git a/arch/x86/include/asm/sev-common.h b/arch/x86/include/asm/sev-common.h
index 6f037c29a46e..7ac5842e32b6 100644
--- a/arch/x86/include/asm/sev-common.h
+++ b/arch/x86/include/asm/sev-common.h
@@ -89,6 +89,7 @@
#define GHCB_TERM_REGISTER 0 /* GHCB GPA registration failure */
#define GHCB_TERM_PSC 1 /* Page State Change failure */
#define GHCB_TERM_PVALIDATE 2 /* Pvalidate failure */
+#define GHCB_TERM_NOT_VMPL0 3 /* SNP guest is not running at VMPL-0 */
#define GHCB_RESP_CODE(v) ((v) & GHCB_MSR_INFO_MASK)
diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index 4ee98976aed8..e37451849165 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h
@@ -63,6 +63,9 @@ extern bool handle_vc_boot_ghcb(struct pt_regs *regs);
/* Software defined (when rFlags.CF = 1) */
#define PVALIDATE_FAIL_NOUPDATE 255
+/* RMP page size */
+#define RMP_PG_SIZE_4K 0
+
#ifdef CONFIG_AMD_MEM_ENCRYPT
extern struct static_key_false sev_es_enable_key;
extern void __sev_es_ist_enter(struct pt_regs *regs);
@@ -90,6 +93,18 @@ extern enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb,
struct es_em_ctxt *ctxt,
u64 exit_code, u64 exit_info_1,
u64 exit_info_2);
+static inline int rmpadjust(unsigned long vaddr, bool rmp_psize, unsigned long attrs)
+{
+ int rc;
+
+ /* "rmpadjust" mnemonic support in binutils 2.36 and newer */
+ asm volatile(".byte 0xF3,0x0F,0x01,0xFE\n\t"
+ : "=a"(rc)
+ : "a"(vaddr), "c"(rmp_psize), "d"(attrs)
+ : "memory", "cc");
+
+ return rc;
+}
static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate)
{
bool no_rmpupdate;
@@ -114,6 +129,7 @@ static inline int sev_es_setup_ap_jump_table(struct real_mode_header *rmh) { ret
static inline void sev_es_nmi_complete(void) { }
static inline int sev_es_efi_map_ghcbs(pgd_t *pgd) { return 0; }
static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate) { return 0; }
+static inline int rmpadjust(unsigned long vaddr, bool rmp_psize, unsigned long attrs) { return 0; }
#endif
#endif
--
2.25.1
^ permalink raw reply related [flat|nested] 183+ messages in thread* Re: [PATCH v8 08/40] x86/sev: Check the vmpl level
2021-12-10 15:43 ` [PATCH v8 08/40] x86/sev: Check the vmpl level Brijesh Singh
@ 2021-12-16 20:24 ` Venu Busireddy
2021-12-16 23:39 ` Mikolaj Lisik
0 siblings, 1 reply; 183+ messages in thread
From: Venu Busireddy @ 2021-12-16 20:24 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2021-12-10 09:43:00 -0600, Brijesh Singh wrote:
> Virtual Machine Privilege Level (VMPL) feature in the SEV-SNP architecture
> allows a guest VM to divide its address space into four levels. The level
> can be used to provide the hardware isolated abstraction layers with a VM.
> The VMPL0 is the highest privilege, and VMPL3 is the least privilege.
> Certain operations must be done by the VMPL0 software, such as:
>
> * Validate or invalidate memory range (PVALIDATE instruction)
> * Allocate VMSA page (RMPADJUST instruction when VMSA=1)
>
> The initial SEV-SNP support requires that the guest kernel is running on
> VMPL0. Add a check to make sure that kernel is running at VMPL0 before
> continuing the boot. There is no easy method to query the current VMPL
> level, so use the RMPADJUST instruction to determine whether the guest is
> running at the VMPL0.
>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
> arch/x86/boot/compressed/sev.c | 34 ++++++++++++++++++++++++++++---
> arch/x86/include/asm/sev-common.h | 1 +
> arch/x86/include/asm/sev.h | 16 +++++++++++++++
> 3 files changed, 48 insertions(+), 3 deletions(-)
>
> diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
> index a0708f359a46..9be369f72299 100644
> --- a/arch/x86/boot/compressed/sev.c
> +++ b/arch/x86/boot/compressed/sev.c
> @@ -212,6 +212,31 @@ static inline u64 rd_sev_status_msr(void)
> return ((high << 32) | low);
> }
>
> +static void enforce_vmpl0(void)
> +{
> + u64 attrs;
> + int err;
> +
> + /*
> + * There is no straightforward way to query the current VMPL level. The
> + * simplest method is to use the RMPADJUST instruction to change a page
> + * permission to a VMPL level-1, and if the guest kernel is launched at
> + * a level <= 1, then RMPADJUST instruction will return an error.
Perhaps a nit. When you say "level <= 1", do you mean a level lower than or
equal to 1 semantically, or numerically?
Venu
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 08/40] x86/sev: Check the vmpl level
2021-12-16 20:24 ` Venu Busireddy
@ 2021-12-16 23:39 ` Mikolaj Lisik
2021-12-17 22:19 ` Brijesh Singh
0 siblings, 1 reply; 183+ messages in thread
From: Mikolaj Lisik @ 2021-12-16 23:39 UTC (permalink / raw)
To: Venu Busireddy
Cc: Brijesh Singh, x86, linux-kernel, kvm, linux-efi,
platform-driver-x86, linux-coco, linux-mm, Thomas Gleixner,
Ingo Molnar, Joerg Roedel, Tom Lendacky, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum,
Borislav Petkov, Michael Roth, Vlastimil Babka,
Kirill A . Shutemov, Andi Kleen, Dr . David Alan Gilbert,
tony.luck, marcorr, sathyanarayanan.kuppuswamy
On Thu, Dec 16, 2021 at 12:24 PM Venu Busireddy
<venu.busireddy@oracle.com> wrote:
>
> On 2021-12-10 09:43:00 -0600, Brijesh Singh wrote:
> > Virtual Machine Privilege Level (VMPL) feature in the SEV-SNP architecture
> > allows a guest VM to divide its address space into four levels. The level
> > can be used to provide the hardware isolated abstraction layers with a VM.
> > The VMPL0 is the highest privilege, and VMPL3 is the least privilege.
> > Certain operations must be done by the VMPL0 software, such as:
> >
> > * Validate or invalidate memory range (PVALIDATE instruction)
> > * Allocate VMSA page (RMPADJUST instruction when VMSA=1)
> >
> > The initial SEV-SNP support requires that the guest kernel is running on
> > VMPL0. Add a check to make sure that kernel is running at VMPL0 before
> > continuing the boot. There is no easy method to query the current VMPL
> > level, so use the RMPADJUST instruction to determine whether the guest is
> > running at the VMPL0.
> >
> > Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> > ---
> > arch/x86/boot/compressed/sev.c | 34 ++++++++++++++++++++++++++++---
> > arch/x86/include/asm/sev-common.h | 1 +
> > arch/x86/include/asm/sev.h | 16 +++++++++++++++
> > 3 files changed, 48 insertions(+), 3 deletions(-)
> >
> > diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
> > index a0708f359a46..9be369f72299 100644
> > --- a/arch/x86/boot/compressed/sev.c
> > +++ b/arch/x86/boot/compressed/sev.c
> > @@ -212,6 +212,31 @@ static inline u64 rd_sev_status_msr(void)
> > return ((high << 32) | low);
> > }
> >
> > +static void enforce_vmpl0(void)
> > +{
> > + u64 attrs;
> > + int err;
> > +
> > + /*
> > + * There is no straightforward way to query the current VMPL level. The
> > + * simplest method is to use the RMPADJUST instruction to change a page
> > + * permission to a VMPL level-1, and if the guest kernel is launched at
> > + * a level <= 1, then RMPADJUST instruction will return an error.
>
> Perhaps a nit. When you say "level <= 1", do you mean a level lower than or
> equal to 1 semantically, or numerically?
>
+1 to this. Additionally I found the "level-1" confusing which I
interpreted as "level minus one".
Perhaps phrasing it as "level one", or "level=1" would be more explicit?
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 08/40] x86/sev: Check the vmpl level
2021-12-16 23:39 ` Mikolaj Lisik
@ 2021-12-17 22:19 ` Brijesh Singh
2021-12-17 22:33 ` Tom Lendacky
0 siblings, 1 reply; 183+ messages in thread
From: Brijesh Singh @ 2021-12-17 22:19 UTC (permalink / raw)
To: Mikolaj Lisik, Venu Busireddy
Cc: brijesh.singh, x86, linux-kernel, kvm, linux-efi,
platform-driver-x86, linux-coco, linux-mm, Thomas Gleixner,
Ingo Molnar, Joerg Roedel, Tom Lendacky, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum,
Borislav Petkov, Michael Roth, Vlastimil Babka,
Kirill A . Shutemov, Andi Kleen, Dr . David Alan Gilbert,
tony.luck, marcorr, sathyanarayanan.kuppuswamy
On 12/16/21 5:39 PM, Mikolaj Lisik wrote:
> On Thu, Dec 16, 2021 at 12:24 PM Venu Busireddy
> <venu.busireddy@oracle.com> wrote:
>> On 2021-12-10 09:43:00 -0600, Brijesh Singh wrote:
>>> Virtual Machine Privilege Level (VMPL) feature in the SEV-SNP architecture
>>> allows a guest VM to divide its address space into four levels. The level
>>> can be used to provide the hardware isolated abstraction layers with a VM.
>>> The VMPL0 is the highest privilege, and VMPL3 is the least privilege.
>>> Certain operations must be done by the VMPL0 software, such as:
>>>
>>> * Validate or invalidate memory range (PVALIDATE instruction)
>>> * Allocate VMSA page (RMPADJUST instruction when VMSA=1)
>>>
>>> The initial SEV-SNP support requires that the guest kernel is running on
>>> VMPL0. Add a check to make sure that kernel is running at VMPL0 before
>>> continuing the boot. There is no easy method to query the current VMPL
>>> level, so use the RMPADJUST instruction to determine whether the guest is
>>> running at the VMPL0.
>>>
>>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>>> ---
>>> arch/x86/boot/compressed/sev.c | 34 ++++++++++++++++++++++++++++---
>>> arch/x86/include/asm/sev-common.h | 1 +
>>> arch/x86/include/asm/sev.h | 16 +++++++++++++++
>>> 3 files changed, 48 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
>>> index a0708f359a46..9be369f72299 100644
>>> --- a/arch/x86/boot/compressed/sev.c
>>> +++ b/arch/x86/boot/compressed/sev.c
>>> @@ -212,6 +212,31 @@ static inline u64 rd_sev_status_msr(void)
>>> return ((high << 32) | low);
>>> }
>>>
>>> +static void enforce_vmpl0(void)
>>> +{
>>> + u64 attrs;
>>> + int err;
>>> +
>>> + /*
>>> + * There is no straightforward way to query the current VMPL level. The
>>> + * simplest method is to use the RMPADJUST instruction to change a page
>>> + * permission to a VMPL level-1, and if the guest kernel is launched at
>>> + * a level <= 1, then RMPADJUST instruction will return an error.
>> Perhaps a nit. When you say "level <= 1", do you mean a level lower than or
>> equal to 1 semantically, or numerically?
Its numerically, please see the AMD APM vol 3.
Here is the snippet from the APM RMPAJUST.
IF (TARGET_VMPL <= CURRENT_VMPL) // Only permissions for numerically
EAX = FAIL_PERMISSION // higher VMPL can be modified
EXIT
> +1 to this. Additionally I found the "level-1" confusing which I
> interpreted as "level minus one".
>
> Perhaps phrasing it as "level one", or "level=1" would be more explicit?
>
Sure, I will make it clear that its target vmpl level 1 and not (target
level - 1).
thanks
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 08/40] x86/sev: Check the vmpl level
2021-12-17 22:19 ` Brijesh Singh
@ 2021-12-17 22:33 ` Tom Lendacky
2021-12-20 18:10 ` Borislav Petkov
0 siblings, 1 reply; 183+ messages in thread
From: Tom Lendacky @ 2021-12-17 22:33 UTC (permalink / raw)
To: Brijesh Singh, Mikolaj Lisik, Venu Busireddy
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 12/17/21 4:19 PM, Brijesh Singh wrote:
>
> On 12/16/21 5:39 PM, Mikolaj Lisik wrote:
>> On Thu, Dec 16, 2021 at 12:24 PM Venu Busireddy
>> <venu.busireddy@oracle.com> wrote:
>>> On 2021-12-10 09:43:00 -0600, Brijesh Singh wrote:
>>>> Virtual Machine Privilege Level (VMPL) feature in the SEV-SNP architecture
>>>> allows a guest VM to divide its address space into four levels. The level
>>>> can be used to provide the hardware isolated abstraction layers with a VM.
>>>> The VMPL0 is the highest privilege, and VMPL3 is the least privilege.
>>>> Certain operations must be done by the VMPL0 software, such as:
>>>>
>>>> * Validate or invalidate memory range (PVALIDATE instruction)
>>>> * Allocate VMSA page (RMPADJUST instruction when VMSA=1)
>>>>
>>>> The initial SEV-SNP support requires that the guest kernel is running on
>>>> VMPL0. Add a check to make sure that kernel is running at VMPL0 before
>>>> continuing the boot. There is no easy method to query the current VMPL
>>>> level, so use the RMPADJUST instruction to determine whether the guest is
>>>> running at the VMPL0.
>>>>
>>>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>>>> ---
>>>> arch/x86/boot/compressed/sev.c | 34 ++++++++++++++++++++++++++++---
>>>> arch/x86/include/asm/sev-common.h | 1 +
>>>> arch/x86/include/asm/sev.h | 16 +++++++++++++++
>>>> 3 files changed, 48 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
>>>> index a0708f359a46..9be369f72299 100644
>>>> --- a/arch/x86/boot/compressed/sev.c
>>>> +++ b/arch/x86/boot/compressed/sev.c
>>>> @@ -212,6 +212,31 @@ static inline u64 rd_sev_status_msr(void)
>>>> return ((high << 32) | low);
>>>> }
>>>>
>>>> +static void enforce_vmpl0(void)
>>>> +{
>>>> + u64 attrs;
>>>> + int err;
>>>> +
>>>> + /*
>>>> + * There is no straightforward way to query the current VMPL level. The
>>>> + * simplest method is to use the RMPADJUST instruction to change a page
>>>> + * permission to a VMPL level-1, and if the guest kernel is launched at
>>>> + * a level <= 1, then RMPADJUST instruction will return an error.
>>> Perhaps a nit. When you say "level <= 1", do you mean a level lower than or
>>> equal to 1 semantically, or numerically?
>
> Its numerically, please see the AMD APM vol 3.
Actually it is not numerically... if it was numerically, then 0 <= 1
would return an error, but VMPL0 is the highest permission level.
>
> Here is the snippet from the APM RMPAJUST.
>
> IF (TARGET_VMPL <= CURRENT_VMPL) // Only permissions for numerically
Notice, that the target VMPL is checked against the current VMPL. So if
the target VMPL is numerically less than or equal to the current VMPL
(e.g. you are trying to modify permissions for VMPL1 when you are running
at VMPL2), that is a permission error. So similar to CPL, 0 is the highest
permission followed by 1 then 2 then 3.
Thanks,
Tom
>
> EAX = FAIL_PERMISSION // higher VMPL can be modified
>
> EXIT
>
>
>> +1 to this. Additionally I found the "level-1" confusing which I
>> interpreted as "level minus one".
>>
>> Perhaps phrasing it as "level one", or "level=1" would be more explicit?
>>
> Sure, I will make it clear that its target vmpl level 1 and not (target
> level - 1).
>
> thanks
>
>
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 08/40] x86/sev: Check the vmpl level
2021-12-17 22:33 ` Tom Lendacky
@ 2021-12-20 18:10 ` Borislav Petkov
2022-01-04 15:23 ` Brijesh Singh
0 siblings, 1 reply; 183+ messages in thread
From: Borislav Petkov @ 2021-12-20 18:10 UTC (permalink / raw)
To: Tom Lendacky
Cc: Brijesh Singh, Mikolaj Lisik, Venu Busireddy, x86, linux-kernel,
kvm, linux-efi, platform-driver-x86, linux-coco, linux-mm,
Thomas Gleixner, Ingo Molnar, Joerg Roedel, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On Fri, Dec 17, 2021 at 04:33:02PM -0600, Tom Lendacky wrote:
> > > > > + * There is no straightforward way to query the current VMPL level. The
> > > > > + * simplest method is to use the RMPADJUST instruction to change a page
> > > > > + * permission to a VMPL level-1, and if the guest kernel is launched at
> > > > > + * a level <= 1, then RMPADJUST instruction will return an error.
> > > > Perhaps a nit. When you say "level <= 1", do you mean a level lower than or
> > > > equal to 1 semantically, or numerically?
> >
> > Its numerically, please see the AMD APM vol 3.
>
> Actually it is not numerically... if it was numerically, then 0 <= 1 would
> return an error, but VMPL0 is the highest permission level.
Just write in that comment exactly what this function does:
"RMPADJUST modifies RMP permissions of a lesser-privileged (numerically
higher) privilege level. Here, clear the VMPL1 permission mask of the
GHCB page. If the guest is not running at VMPL0, this will fail.
If the guest is running at VMP0, it will succeed. Even if that operation
modifies permission bits, it is still ok to do currently because Linux
SNP guests are supported only on VMPL0 so VMPL1 or higher permission
masks changing is a don't-care."
and then everything is clear wrt numbering, privilege, etc.
Ok?
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 08/40] x86/sev: Check the vmpl level
2021-12-20 18:10 ` Borislav Petkov
@ 2022-01-04 15:23 ` Brijesh Singh
0 siblings, 0 replies; 183+ messages in thread
From: Brijesh Singh @ 2022-01-04 15:23 UTC (permalink / raw)
To: Borislav Petkov, Tom Lendacky
Cc: brijesh.singh, Mikolaj Lisik, Venu Busireddy, x86, linux-kernel,
kvm, linux-efi, platform-driver-x86, linux-coco, linux-mm,
Thomas Gleixner, Ingo Molnar, Joerg Roedel, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 12/20/21 12:10 PM, Borislav Petkov wrote:
> On Fri, Dec 17, 2021 at 04:33:02PM -0600, Tom Lendacky wrote:
>>>>>> + * There is no straightforward way to query the current VMPL level. The
>>>>>> + * simplest method is to use the RMPADJUST instruction to change a page
>>>>>> + * permission to a VMPL level-1, and if the guest kernel is launched at
>>>>>> + * a level <= 1, then RMPADJUST instruction will return an error.
>>>>> Perhaps a nit. When you say "level <= 1", do you mean a level lower than or
>>>>> equal to 1 semantically, or numerically?
>>>
>>> Its numerically, please see the AMD APM vol 3.
>>
>> Actually it is not numerically... if it was numerically, then 0 <= 1 would
>> return an error, but VMPL0 is the highest permission level.
>
> Just write in that comment exactly what this function does:
>
> "RMPADJUST modifies RMP permissions of a lesser-privileged (numerically
> higher) privilege level. Here, clear the VMPL1 permission mask of the
> GHCB page. If the guest is not running at VMPL0, this will fail.
>
> If the guest is running at VMP0, it will succeed. Even if that operation
> modifies permission bits, it is still ok to do currently because Linux
> SNP guests are supported only on VMPL0 so VMPL1 or higher permission
> masks changing is a don't-care."
>
> and then everything is clear wrt numbering, privilege, etc.
>
> Ok?
>
Noted.
thanks
^ permalink raw reply [flat|nested] 183+ messages in thread
* [PATCH v8 09/40] x86/compressed: Add helper for validating pages in the decompression stage
2021-12-10 15:42 [PATCH v8 00/40] Add AMD Secure Nested Paging (SEV-SNP) Guest Support Brijesh Singh
` (7 preceding siblings ...)
2021-12-10 15:43 ` [PATCH v8 08/40] x86/sev: Check the vmpl level Brijesh Singh
@ 2021-12-10 15:43 ` Brijesh Singh
2021-12-17 20:47 ` Venu Busireddy
2021-12-21 13:01 ` Borislav Petkov
2021-12-10 15:43 ` [PATCH v8 10/40] x86/compressed: Register GHCB memory when SEV-SNP is active Brijesh Singh
` (31 subsequent siblings)
40 siblings, 2 replies; 183+ messages in thread
From: Brijesh Singh @ 2021-12-10 15:43 UTC (permalink / raw)
To: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm
Cc: Thomas Gleixner, Ingo Molnar, Joerg Roedel, Tom Lendacky,
H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy, Brijesh Singh
Many of the integrity guarantees of SEV-SNP are enforced through the
Reverse Map Table (RMP). Each RMP entry contains the GPA at which a
particular page of DRAM should be mapped. The VMs can request the
hypervisor to add pages in the RMP table via the Page State Change VMGEXIT
defined in the GHCB specification. Inside each RMP entry is a Validated
flag; this flag is automatically cleared to 0 by the CPU hardware when a
new RMP entry is created for a guest. Each VM page can be either
validated or invalidated, as indicated by the Validated flag in the RMP
entry. Memory access to a private page that is not validated generates
a #VC. A VM must use PVALIDATE instruction to validate the private page
before using it.
To maintain the security guarantee of SEV-SNP guests, when transitioning
pages from private to shared, the guest must invalidate the pages before
asking the hypervisor to change the page state to shared in the RMP table.
After the pages are mapped private in the page table, the guest must issue
a page state change VMGEXIT to make the pages private in the RMP table and
validate it.
On boot, BIOS should have validated the entire system memory. During
the kernel decompression stage, the VC handler uses the
set_memory_decrypted() to make the GHCB page shared (i.e clear encryption
attribute). And while exiting from the decompression, it calls the
set_page_encrypted() to make the page private.
Add sev_snp_set_page_{private,shared}() helper that is used by the
set_memory_{decrypt,encrypt}() to change the page state in the RMP table.
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
arch/x86/boot/compressed/ident_map_64.c | 18 +++++++++-
arch/x86/boot/compressed/misc.h | 4 +++
arch/x86/boot/compressed/sev.c | 46 +++++++++++++++++++++++++
arch/x86/include/asm/sev-common.h | 26 ++++++++++++++
4 files changed, 93 insertions(+), 1 deletion(-)
diff --git a/arch/x86/boot/compressed/ident_map_64.c b/arch/x86/boot/compressed/ident_map_64.c
index f7213d0943b8..ef77453cc629 100644
--- a/arch/x86/boot/compressed/ident_map_64.c
+++ b/arch/x86/boot/compressed/ident_map_64.c
@@ -275,15 +275,31 @@ static int set_clr_page_flags(struct x86_mapping_info *info,
* Changing encryption attributes of a page requires to flush it from
* the caches.
*/
- if ((set | clr) & _PAGE_ENC)
+ if ((set | clr) & _PAGE_ENC) {
clflush_page(address);
+ /*
+ * If the encryption attribute is being cleared, then change
+ * the page state to shared in the RMP table.
+ */
+ if (clr)
+ snp_set_page_shared(pte_pfn(*ptep) << PAGE_SHIFT);
+ }
+
/* Update PTE */
pte = *ptep;
pte = pte_set_flags(pte, set);
pte = pte_clear_flags(pte, clr);
set_pte(ptep, pte);
+ /*
+ * If the encryption attribute is being set, then change the page state to
+ * private in the RMP entry. The page state must be done after the PTE
+ * is updated.
+ */
+ if (set & _PAGE_ENC)
+ snp_set_page_private(__pa(address & PAGE_MASK));
+
/* Flush TLB after changing encryption attribute */
write_cr3(top_level_pgt);
diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
index 23e0e395084a..01cc13c12059 100644
--- a/arch/x86/boot/compressed/misc.h
+++ b/arch/x86/boot/compressed/misc.h
@@ -124,6 +124,8 @@ static inline void console_init(void)
void sev_enable(struct boot_params *bp);
void sev_es_shutdown_ghcb(void);
extern bool sev_es_check_ghcb_fault(unsigned long address);
+void snp_set_page_private(unsigned long paddr);
+void snp_set_page_shared(unsigned long paddr);
#else
static inline void sev_enable(struct boot_params *bp) { }
static inline void sev_es_shutdown_ghcb(void) { }
@@ -131,6 +133,8 @@ static inline bool sev_es_check_ghcb_fault(unsigned long address)
{
return false;
}
+static inline void snp_set_page_private(unsigned long paddr) { }
+static inline void snp_set_page_shared(unsigned long paddr) { }
#endif
/* acpi.c */
diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
index 9be369f72299..12a93acc94ba 100644
--- a/arch/x86/boot/compressed/sev.c
+++ b/arch/x86/boot/compressed/sev.c
@@ -119,6 +119,52 @@ static enum es_result vc_read_mem(struct es_em_ctxt *ctxt,
/* Include code for early handlers */
#include "../../kernel/sev-shared.c"
+static inline bool sev_snp_enabled(void)
+{
+ return sev_status & MSR_AMD64_SEV_SNP_ENABLED;
+}
+
+static void __page_state_change(unsigned long paddr, enum psc_op op)
+{
+ u64 val;
+
+ if (!sev_snp_enabled())
+ return;
+
+ /*
+ * If private -> shared then invalidate the page before requesting the
+ * state change in the RMP table.
+ */
+ if (op == SNP_PAGE_STATE_SHARED && pvalidate(paddr, RMP_PG_SIZE_4K, 0))
+ sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PVALIDATE);
+
+ /* Issue VMGEXIT to change the page state in RMP table. */
+ sev_es_wr_ghcb_msr(GHCB_MSR_PSC_REQ_GFN(paddr >> PAGE_SHIFT, op));
+ VMGEXIT();
+
+ /* Read the response of the VMGEXIT. */
+ val = sev_es_rd_ghcb_msr();
+ if ((GHCB_RESP_CODE(val) != GHCB_MSR_PSC_RESP) || GHCB_MSR_PSC_RESP_VAL(val))
+ sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PSC);
+
+ /*
+ * Now that page is added in the RMP table, validate it so that it is
+ * consistent with the RMP entry.
+ */
+ if (op == SNP_PAGE_STATE_PRIVATE && pvalidate(paddr, RMP_PG_SIZE_4K, 1))
+ sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PVALIDATE);
+}
+
+void snp_set_page_private(unsigned long paddr)
+{
+ __page_state_change(paddr, SNP_PAGE_STATE_PRIVATE);
+}
+
+void snp_set_page_shared(unsigned long paddr)
+{
+ __page_state_change(paddr, SNP_PAGE_STATE_SHARED);
+}
+
static bool early_setup_ghcb(void)
{
if (set_page_decrypted((unsigned long)&boot_ghcb_page))
diff --git a/arch/x86/include/asm/sev-common.h b/arch/x86/include/asm/sev-common.h
index 7ac5842e32b6..a2f956cfafba 100644
--- a/arch/x86/include/asm/sev-common.h
+++ b/arch/x86/include/asm/sev-common.h
@@ -57,6 +57,32 @@
#define GHCB_MSR_AP_RESET_HOLD_REQ 0x006
#define GHCB_MSR_AP_RESET_HOLD_RESP 0x007
+/*
+ * SNP Page State Change Operation
+ *
+ * GHCBData[55:52] - Page operation:
+ * 0x0001 – Page assignment, Private
+ * 0x0002 – Page assignment, Shared
+ */
+enum psc_op {
+ SNP_PAGE_STATE_PRIVATE = 1,
+ SNP_PAGE_STATE_SHARED,
+};
+
+#define GHCB_MSR_PSC_REQ 0x014
+#define GHCB_MSR_PSC_REQ_GFN(gfn, op) \
+ /* GHCBData[55:52] */ \
+ (((u64)((op) & 0xf) << 52) | \
+ /* GHCBData[51:12] */ \
+ ((u64)((gfn) & GENMASK_ULL(39, 0)) << 12) | \
+ /* GHCBData[11:0] */ \
+ GHCB_MSR_PSC_REQ)
+
+#define GHCB_MSR_PSC_RESP 0x015
+#define GHCB_MSR_PSC_RESP_VAL(val) \
+ /* GHCBData[63:32] */ \
+ (((u64)(val) & GENMASK_ULL(63, 32)) >> 32)
+
/* GHCB Hypervisor Feature Request/Response */
#define GHCB_MSR_HV_FT_REQ 0x080
#define GHCB_MSR_HV_FT_RESP 0x081
--
2.25.1
^ permalink raw reply related [flat|nested] 183+ messages in thread* Re: [PATCH v8 09/40] x86/compressed: Add helper for validating pages in the decompression stage
2021-12-10 15:43 ` [PATCH v8 09/40] x86/compressed: Add helper for validating pages in the decompression stage Brijesh Singh
@ 2021-12-17 20:47 ` Venu Busireddy
2021-12-17 23:24 ` Brijesh Singh
2021-12-21 13:01 ` Borislav Petkov
1 sibling, 1 reply; 183+ messages in thread
From: Venu Busireddy @ 2021-12-17 20:47 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2021-12-10 09:43:01 -0600, Brijesh Singh wrote:
> Many of the integrity guarantees of SEV-SNP are enforced through the
> Reverse Map Table (RMP). Each RMP entry contains the GPA at which a
> particular page of DRAM should be mapped. The VMs can request the
> hypervisor to add pages in the RMP table via the Page State Change VMGEXIT
> defined in the GHCB specification. Inside each RMP entry is a Validated
> flag; this flag is automatically cleared to 0 by the CPU hardware when a
> new RMP entry is created for a guest. Each VM page can be either
> validated or invalidated, as indicated by the Validated flag in the RMP
> entry. Memory access to a private page that is not validated generates
> a #VC. A VM must use PVALIDATE instruction to validate the private page
> before using it.
>
> To maintain the security guarantee of SEV-SNP guests, when transitioning
> pages from private to shared, the guest must invalidate the pages before
> asking the hypervisor to change the page state to shared in the RMP table.
>
> After the pages are mapped private in the page table, the guest must issue
> a page state change VMGEXIT to make the pages private in the RMP table and
> validate it.
>
> On boot, BIOS should have validated the entire system memory. During
> the kernel decompression stage, the VC handler uses the
> set_memory_decrypted() to make the GHCB page shared (i.e clear encryption
> attribute). And while exiting from the decompression, it calls the
> set_page_encrypted() to make the page private.
>
> Add sev_snp_set_page_{private,shared}() helper that is used by the
Since the functions being added are snp_set_page_{private,shared}(),
s/sev_snp_set_page_/snp_set_page_/
Also, s/helper that is/helpers that are/
> set_memory_{decrypt,encrypt}() to change the page state in the RMP table.
s/decrypt,encrypt/decrypted,encrypted/
>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
> arch/x86/boot/compressed/ident_map_64.c | 18 +++++++++-
> arch/x86/boot/compressed/misc.h | 4 +++
> arch/x86/boot/compressed/sev.c | 46 +++++++++++++++++++++++++
> arch/x86/include/asm/sev-common.h | 26 ++++++++++++++
> 4 files changed, 93 insertions(+), 1 deletion(-)
>
> diff --git a/arch/x86/boot/compressed/ident_map_64.c b/arch/x86/boot/compressed/ident_map_64.c
> index f7213d0943b8..ef77453cc629 100644
> --- a/arch/x86/boot/compressed/ident_map_64.c
> +++ b/arch/x86/boot/compressed/ident_map_64.c
> @@ -275,15 +275,31 @@ static int set_clr_page_flags(struct x86_mapping_info *info,
> * Changing encryption attributes of a page requires to flush it from
> * the caches.
> */
> - if ((set | clr) & _PAGE_ENC)
> + if ((set | clr) & _PAGE_ENC) {
> clflush_page(address);
>
> + /*
> + * If the encryption attribute is being cleared, then change
> + * the page state to shared in the RMP table.
> + */
> + if (clr)
This function is also called by set_page_non_present() with clr set to
_PAGE_PRESENT. Do we want to change the page state to shared even when
the page is not present? If not, shouldn't the check be (clr & _PAGE_ENC)?
> + snp_set_page_shared(pte_pfn(*ptep) << PAGE_SHIFT);
> + }
> +
> /* Update PTE */
> pte = *ptep;
> pte = pte_set_flags(pte, set);
> pte = pte_clear_flags(pte, clr);
> set_pte(ptep, pte);
>
> + /*
> + * If the encryption attribute is being set, then change the page state to
> + * private in the RMP entry. The page state must be done after the PTE
> + * is updated.
> + */
> + if (set & _PAGE_ENC)
> + snp_set_page_private(__pa(address & PAGE_MASK));
> +
> /* Flush TLB after changing encryption attribute */
> write_cr3(top_level_pgt);
>
> diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
> index 23e0e395084a..01cc13c12059 100644
> --- a/arch/x86/boot/compressed/misc.h
> +++ b/arch/x86/boot/compressed/misc.h
> @@ -124,6 +124,8 @@ static inline void console_init(void)
> void sev_enable(struct boot_params *bp);
> void sev_es_shutdown_ghcb(void);
> extern bool sev_es_check_ghcb_fault(unsigned long address);
> +void snp_set_page_private(unsigned long paddr);
> +void snp_set_page_shared(unsigned long paddr);
> #else
> static inline void sev_enable(struct boot_params *bp) { }
> static inline void sev_es_shutdown_ghcb(void) { }
> @@ -131,6 +133,8 @@ static inline bool sev_es_check_ghcb_fault(unsigned long address)
> {
> return false;
> }
> +static inline void snp_set_page_private(unsigned long paddr) { }
> +static inline void snp_set_page_shared(unsigned long paddr) { }
> #endif
>
> /* acpi.c */
> diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
> index 9be369f72299..12a93acc94ba 100644
> --- a/arch/x86/boot/compressed/sev.c
> +++ b/arch/x86/boot/compressed/sev.c
> @@ -119,6 +119,52 @@ static enum es_result vc_read_mem(struct es_em_ctxt *ctxt,
> /* Include code for early handlers */
> #include "../../kernel/sev-shared.c"
>
> +static inline bool sev_snp_enabled(void)
> +{
> + return sev_status & MSR_AMD64_SEV_SNP_ENABLED;
> +}
> +
> +static void __page_state_change(unsigned long paddr, enum psc_op op)
> +{
> + u64 val;
> +
> + if (!sev_snp_enabled())
> + return;
> +
> + /*
> + * If private -> shared then invalidate the page before requesting the
This comment is confusing. We don't know what the present state is,
right? If we don't, shouldn't we just say:
If the operation is SNP_PAGE_STATE_SHARED, invalidate the page before
requesting the state change in the RMP table.
> + * state change in the RMP table.
> + */
> + if (op == SNP_PAGE_STATE_SHARED && pvalidate(paddr, RMP_PG_SIZE_4K, 0))
> + sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PVALIDATE);
> +
> + /* Issue VMGEXIT to change the page state in RMP table. */
> + sev_es_wr_ghcb_msr(GHCB_MSR_PSC_REQ_GFN(paddr >> PAGE_SHIFT, op));
> + VMGEXIT();
> +
> + /* Read the response of the VMGEXIT. */
> + val = sev_es_rd_ghcb_msr();
> + if ((GHCB_RESP_CODE(val) != GHCB_MSR_PSC_RESP) || GHCB_MSR_PSC_RESP_VAL(val))
> + sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PSC);
> +
> + /*
> + * Now that page is added in the RMP table, validate it so that it is
> + * consistent with the RMP entry.
The page is not "added", right? Shouldn't we just say:
Validate the page so that it is consistent with the RMP entry.
Venu
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 09/40] x86/compressed: Add helper for validating pages in the decompression stage
2021-12-17 20:47 ` Venu Busireddy
@ 2021-12-17 23:24 ` Brijesh Singh
2022-01-03 18:43 ` Venu Busireddy
0 siblings, 1 reply; 183+ messages in thread
From: Brijesh Singh @ 2021-12-17 23:24 UTC (permalink / raw)
To: Venu Busireddy
Cc: brijesh.singh, x86, linux-kernel, kvm, linux-efi,
platform-driver-x86, linux-coco, linux-mm, Thomas Gleixner,
Ingo Molnar, Joerg Roedel, Tom Lendacky, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum,
Borislav Petkov, Michael Roth, Vlastimil Babka,
Kirill A . Shutemov, Andi Kleen, Dr . David Alan Gilbert,
tony.luck, marcorr, sathyanarayanan.kuppuswamy
On 12/17/21 2:47 PM, Venu Busireddy wrote:
>> * the caches.
>> */
>> - if ((set | clr) & _PAGE_ENC)
>> + if ((set | clr) & _PAGE_ENC) {
>> clflush_page(address);
>>
>> + /*
>> + * If the encryption attribute is being cleared, then change
>> + * the page state to shared in the RMP table.
>> + */
>> + if (clr)
> This function is also called by set_page_non_present() with clr set to
> _PAGE_PRESENT. Do we want to change the page state to shared even when
> the page is not present? If not, shouldn't the check be (clr & _PAGE_ENC)?
I am not able to follow your comment. Here we only pay attention to the
encryption attribute, if encryption attribute is getting cleared then
make PSC. In the case ov set_page_non_present(), the outer if() block
will return false. Am I missing something ?
>> + /*
>> + * If private -> shared then invalidate the page before requesting the
> This comment is confusing. We don't know what the present state is,
> right? If we don't, shouldn't we just say:
>
> If the operation is SNP_PAGE_STATE_SHARED, invalidate the page before
> requesting the state change in the RMP table.
>
By default all the pages are private, so I don't see any issue with
saying "private -> shared".
>> + * state change in the RMP table.
>> + */
>> + if (op == SNP_PAGE_STATE_SHARED && pvalidate(paddr, RMP_PG_SIZE_4K, 0))
>> + sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PVALIDATE);
>> +
>> + /* Issue VMGEXIT to change the page state in RMP table. */
>> + sev_es_wr_ghcb_msr(GHCB_MSR_PSC_REQ_GFN(paddr >> PAGE_SHIFT, op));
>> + VMGEXIT();
>> +
>> + /* Read the response of the VMGEXIT. */
>> + val = sev_es_rd_ghcb_msr();
>> + if ((GHCB_RESP_CODE(val) != GHCB_MSR_PSC_RESP) || GHCB_MSR_PSC_RESP_VAL(val))
>> + sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PSC);
>> +
>> + /*
>> + * Now that page is added in the RMP table, validate it so that it is
>> + * consistent with the RMP entry.
> The page is not "added", right? Shouldn't we just say:
Technically, PSC modifies the RMP entry, so I should use that instead
of calling "added".
> Validate the page so that it is consistent with the RMP entry.
Yes, I am okay with it.
> Venu
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 09/40] x86/compressed: Add helper for validating pages in the decompression stage
2021-12-17 23:24 ` Brijesh Singh
@ 2022-01-03 18:43 ` Venu Busireddy
0 siblings, 0 replies; 183+ messages in thread
From: Venu Busireddy @ 2022-01-03 18:43 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2021-12-17 17:24:43 -0600, Brijesh Singh wrote:
>
> On 12/17/21 2:47 PM, Venu Busireddy wrote:
>
> >> * the caches.
> >> */
> >> - if ((set | clr) & _PAGE_ENC)
> >> + if ((set | clr) & _PAGE_ENC) {
> >> clflush_page(address);
> >>
> >> + /*
> >> + * If the encryption attribute is being cleared, then change
> >> + * the page state to shared in the RMP table.
> >> + */
> >> + if (clr)
> > This function is also called by set_page_non_present() with clr set to
> > _PAGE_PRESENT. Do we want to change the page state to shared even when
> > the page is not present? If not, shouldn't the check be (clr & _PAGE_ENC)?
>
> I am not able to follow your comment. Here we only pay attention to the
> encryption attribute, if encryption attribute is getting cleared then
> make PSC. In the case ov set_page_non_present(), the outer if() block
> will return false. Am I missing something ?
You are right. I missed the outer check.
> > The page is not "added", right? Shouldn't we just say:
>
> Technically, PSC modifies the RMP entry, so I should use that instead
> of calling "added".
>
>
> > Validate the page so that it is consistent with the RMP entry.
>
> Yes, I am okay with it.
Thanks,
Venu
^ permalink raw reply [flat|nested] 183+ messages in thread
* Re: [PATCH v8 09/40] x86/compressed: Add helper for validating pages in the decompression stage
2021-12-10 15:43 ` [PATCH v8 09/40] x86/compressed: Add helper for validating pages in the decompression stage Brijesh Singh
2021-12-17 20:47 ` Venu Busireddy
@ 2021-12-21 13:01 ` Borislav Petkov
1 sibling, 0 replies; 183+ messages in thread
From: Borislav Petkov @ 2021-12-21 13:01 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Michael Roth, Vlastimil Babka,
Kirill A . Shutemov, Andi Kleen, Dr . David Alan Gilbert,
tony.luck, marcorr, sathyanarayanan.kuppuswamy
On Fri, Dec 10, 2021 at 09:43:01AM -0600, Brijesh Singh wrote:
> diff --git a/arch/x86/boot/compressed/ident_map_64.c b/arch/x86/boot/compressed/ident_map_64.c
> index f7213d0943b8..ef77453cc629 100644
> --- a/arch/x86/boot/compressed/ident_map_64.c
> +++ b/arch/x86/boot/compressed/ident_map_64.c
> @@ -275,15 +275,31 @@ static int set_clr_page_flags(struct x86_mapping_info *info,
> * Changing encryption attributes of a page requires to flush it from
> * the caches.
> */
> - if ((set | clr) & _PAGE_ENC)
> + if ((set | clr) & _PAGE_ENC) {
> clflush_page(address);
>
> + /*
> + * If the encryption attribute is being cleared, then change
> + * the page state to shared in the RMP table.
> + */
> + if (clr)
> + snp_set_page_shared(pte_pfn(*ptep) << PAGE_SHIFT);
You forgot to change that one.
> + }
> +
> /* Update PTE */
> pte = *ptep;
> pte = pte_set_flags(pte, set);
> pte = pte_clear_flags(pte, clr);
> set_pte(ptep, pte);
>
> + /*
> + * If the encryption attribute is being set, then change the page state to
> + * private in the RMP entry. The page state must be done after the PTE
^
change
Geez, tell me, why should I be even bothering to review stuff if I have
to go look at the previous review I did and find that you haven't really
addressed it?!
> diff --git a/arch/x86/include/asm/sev-common.h b/arch/x86/include/asm/sev-common.h
> index 7ac5842e32b6..a2f956cfafba 100644
> --- a/arch/x86/include/asm/sev-common.h
> +++ b/arch/x86/include/asm/sev-common.h
> @@ -57,6 +57,32 @@
> #define GHCB_MSR_AP_RESET_HOLD_REQ 0x006
> #define GHCB_MSR_AP_RESET_HOLD_RESP 0x007
>
> +/*
> + * SNP Page State Change Operation
> + *
> + * GHCBData[55:52] - Page operation:
> + * 0x0001 – Page assignment, Private
> + * 0x0002 – Page assignment, Shared
I wonder how you've achieved that:
massage_diff: Warning: Unicode char [–] (0x2013) in line: + * 0x0001 – Page assignment, Private
massage_diff: Warning: Unicode char [–] (0x2013) in line: + * 0x0002 – Page assignment, Shared
See https://trojansource.codes/ for some background.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 183+ messages in thread
* [PATCH v8 10/40] x86/compressed: Register GHCB memory when SEV-SNP is active
2021-12-10 15:42 [PATCH v8 00/40] Add AMD Secure Nested Paging (SEV-SNP) Guest Support Brijesh Singh
` (8 preceding siblings ...)
2021-12-10 15:43 ` [PATCH v8 09/40] x86/compressed: Add helper for validating pages in the decompression stage Brijesh Singh
@ 2021-12-10 15:43 ` Brijesh Singh
2022-01-03 19:54 ` Venu Busireddy
2021-12-10 15:43 ` [PATCH v8 11/40] x86/sev: " Brijesh Singh
` (30 subsequent siblings)
40 siblings, 1 reply; 183+ messages in thread
From: Brijesh Singh @ 2021-12-10 15:43 UTC (permalink / raw)
To: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm
Cc: Thomas Gleixner, Ingo Molnar, Joerg Roedel, Tom Lendacky,
H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy, Brijesh Singh
The SEV-SNP guest is required by the GHCB spec to register the GHCB's
Guest Physical Address (GPA). This is because the hypervisor may prefer
that a guest use a consistent and/or specific GPA for the GHCB associated
with a vCPU. For more information, see the GHCB specification section
"GHCB GPA Registration".
If hypervisor can not work with the guest provided GPA then terminate the
guest boot.
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
arch/x86/boot/compressed/sev.c | 4 ++++
arch/x86/include/asm/sev-common.h | 13 +++++++++++++
arch/x86/kernel/sev-shared.c | 16 ++++++++++++++++
3 files changed, 33 insertions(+)
diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
index 12a93acc94ba..348f7711c3ea 100644
--- a/arch/x86/boot/compressed/sev.c
+++ b/arch/x86/boot/compressed/sev.c
@@ -178,6 +178,10 @@ static bool early_setup_ghcb(void)
/* Initialize lookup tables for the instruction decoder */
inat_init_tables();
+ /* SEV-SNP guest requires the GHCB GPA must be registered */
+ if (sev_snp_enabled())
+ snp_register_ghcb_early(__pa(&boot_ghcb_page));
+
return true;
}
diff --git a/arch/x86/include/asm/sev-common.h b/arch/x86/include/asm/sev-common.h
index a2f956cfafba..6dc27963690e 100644
--- a/arch/x86/include/asm/sev-common.h
+++ b/arch/x86/include/asm/sev-common.h
@@ -57,6 +57,19 @@
#define GHCB_MSR_AP_RESET_HOLD_REQ 0x006
#define GHCB_MSR_AP_RESET_HOLD_RESP 0x007
+/* GHCB GPA Register */
+#define GHCB_MSR_REG_GPA_REQ 0x012
+#define GHCB_MSR_REG_GPA_REQ_VAL(v) \
+ /* GHCBData[63:12] */ \
+ (((u64)((v) & GENMASK_ULL(51, 0)) << 12) | \
+ /* GHCBData[11:0] */ \
+ GHCB_MSR_REG_GPA_REQ)
+
+#define GHCB_MSR_REG_GPA_RESP 0x013
+#define GHCB_MSR_REG_GPA_RESP_VAL(v) \
+ /* GHCBData[63:12] */ \
+ (((u64)(v) & GENMASK_ULL(63, 12)) >> 12)
+
/*
* SNP Page State Change Operation
*
diff --git a/arch/x86/kernel/sev-shared.c b/arch/x86/kernel/sev-shared.c
index 4a876e684f67..e9ff13cd90b0 100644
--- a/arch/x86/kernel/sev-shared.c
+++ b/arch/x86/kernel/sev-shared.c
@@ -68,6 +68,22 @@ static u64 get_hv_features(void)
return GHCB_MSR_HV_FT_RESP_VAL(val);
}
+static void __maybe_unused snp_register_ghcb_early(unsigned long paddr)
+{
+ unsigned long pfn = paddr >> PAGE_SHIFT;
+ u64 val;
+
+ sev_es_wr_ghcb_msr(GHCB_MSR_REG_GPA_REQ_VAL(pfn));
+ VMGEXIT();
+
+ val = sev_es_rd_ghcb_msr();
+
+ /* If the response GPA is not ours then abort the guest */
+ if ((GHCB_RESP_CODE(val) != GHCB_MSR_REG_GPA_RESP) ||
+ (GHCB_MSR_REG_GPA_RESP_VAL(val) != pfn))
+ sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_REGISTER);
+}
+
static bool sev_es_negotiate_protocol(void)
{
u64 val;
--
2.25.1
^ permalink raw reply related [flat|nested] 183+ messages in thread* Re: [PATCH v8 10/40] x86/compressed: Register GHCB memory when SEV-SNP is active
2021-12-10 15:43 ` [PATCH v8 10/40] x86/compressed: Register GHCB memory when SEV-SNP is active Brijesh Singh
@ 2022-01-03 19:54 ` Venu Busireddy
0 siblings, 0 replies; 183+ messages in thread
From: Venu Busireddy @ 2022-01-03 19:54 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2021-12-10 09:43:02 -0600, Brijesh Singh wrote:
> The SEV-SNP guest is required by the GHCB spec to register the GHCB's
> Guest Physical Address (GPA). This is because the hypervisor may prefer
> that a guest use a consistent and/or specific GPA for the GHCB associated
> with a vCPU. For more information, see the GHCB specification section
> "GHCB GPA Registration".
>
> If hypervisor can not work with the guest provided GPA then terminate the
> guest boot.
>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Venu Busireddy <venu.busireddy@oracle.com>
> ---
> arch/x86/boot/compressed/sev.c | 4 ++++
> arch/x86/include/asm/sev-common.h | 13 +++++++++++++
> arch/x86/kernel/sev-shared.c | 16 ++++++++++++++++
> 3 files changed, 33 insertions(+)
>
^ permalink raw reply [flat|nested] 183+ messages in thread
* [PATCH v8 11/40] x86/sev: Register GHCB memory when SEV-SNP is active
2021-12-10 15:42 [PATCH v8 00/40] Add AMD Secure Nested Paging (SEV-SNP) Guest Support Brijesh Singh
` (9 preceding siblings ...)
2021-12-10 15:43 ` [PATCH v8 10/40] x86/compressed: Register GHCB memory when SEV-SNP is active Brijesh Singh
@ 2021-12-10 15:43 ` Brijesh Singh
2021-12-22 13:16 ` Borislav Petkov
2022-01-03 22:47 ` Venu Busireddy
2021-12-10 15:43 ` [PATCH v8 12/40] x86/sev: Add helper for validating pages in early enc attribute changes Brijesh Singh
` (29 subsequent siblings)
40 siblings, 2 replies; 183+ messages in thread
From: Brijesh Singh @ 2021-12-10 15:43 UTC (permalink / raw)
To: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm
Cc: Thomas Gleixner, Ingo Molnar, Joerg Roedel, Tom Lendacky,
H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy, Brijesh Singh
The SEV-SNP guest is required by the GHCB spec to register the GHCB's
Guest Physical Address (GPA). This is because the hypervisor may prefer
that a guest use a consistent and/or specific GPA for the GHCB associated
with a vCPU. For more information, see the GHCB specification section
"GHCB GPA Registration".
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
arch/x86/include/asm/sev.h | 2 +
arch/x86/kernel/cpu/common.c | 4 ++
arch/x86/kernel/head64.c | 1 +
arch/x86/kernel/sev-shared.c | 2 +-
arch/x86/kernel/sev.c | 120 ++++++++++++++++++++---------------
5 files changed, 77 insertions(+), 52 deletions(-)
diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index e37451849165..0df508374a35 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h
@@ -122,6 +122,7 @@ static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate)
return rc;
}
+void sev_snp_register_ghcb(void);
#else
static inline void sev_es_ist_enter(struct pt_regs *regs) { }
static inline void sev_es_ist_exit(void) { }
@@ -130,6 +131,7 @@ static inline void sev_es_nmi_complete(void) { }
static inline int sev_es_efi_map_ghcbs(pgd_t *pgd) { return 0; }
static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate) { return 0; }
static inline int rmpadjust(unsigned long vaddr, bool rmp_psize, unsigned long attrs) { return 0; }
+static inline void sev_snp_register_ghcb(void) { }
#endif
#endif
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 0663642d6199..1146e8920b03 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -59,6 +59,7 @@
#include <asm/cpu_device_id.h>
#include <asm/uv/uv.h>
#include <asm/sigframe.h>
+#include <asm/sev.h>
#include "cpu.h"
@@ -1988,6 +1989,9 @@ void cpu_init_exception_handling(void)
load_TR_desc();
+ /* Register the GHCB before taking any VC exception */
+ sev_snp_register_ghcb();
+
/* Finally load the IDT */
load_current_idt();
}
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index b01f64e8389b..fa02402dcb9b 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -588,6 +588,7 @@ void early_setup_idt(void)
bringup_idt_descr.address = (unsigned long)bringup_idt_table;
native_load_idt(&bringup_idt_descr);
+ sev_snp_register_ghcb();
}
/*
diff --git a/arch/x86/kernel/sev-shared.c b/arch/x86/kernel/sev-shared.c
index e9ff13cd90b0..3aaef1a18ffe 100644
--- a/arch/x86/kernel/sev-shared.c
+++ b/arch/x86/kernel/sev-shared.c
@@ -68,7 +68,7 @@ static u64 get_hv_features(void)
return GHCB_MSR_HV_FT_RESP_VAL(val);
}
-static void __maybe_unused snp_register_ghcb_early(unsigned long paddr)
+static void snp_register_ghcb_early(unsigned long paddr)
{
unsigned long pfn = paddr >> PAGE_SHIFT;
u64 val;
diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c
index a0cada8398a4..17ad603f62da 100644
--- a/arch/x86/kernel/sev.c
+++ b/arch/x86/kernel/sev.c
@@ -162,55 +162,6 @@ void noinstr __sev_es_ist_exit(void)
this_cpu_write(cpu_tss_rw.x86_tss.ist[IST_INDEX_VC], *(unsigned long *)ist);
}
-/*
- * Nothing shall interrupt this code path while holding the per-CPU
- * GHCB. The backup GHCB is only for NMIs interrupting this path.
- *
- * Callers must disable local interrupts around it.
- */
-static noinstr struct ghcb *__sev_get_ghcb(struct ghcb_state *state)
-{
- struct sev_es_runtime_data *data;
- struct ghcb *ghcb;
-
- WARN_ON(!irqs_disabled());
-
- data = this_cpu_read(runtime_data);
- ghcb = &data->ghcb_page;
-
- if (unlikely(data->ghcb_active)) {
- /* GHCB is already in use - save its contents */
-
- if (unlikely(data->backup_ghcb_active)) {
- /*
- * Backup-GHCB is also already in use. There is no way
- * to continue here so just kill the machine. To make
- * panic() work, mark GHCBs inactive so that messages
- * can be printed out.
- */
- data->ghcb_active = false;
- data->backup_ghcb_active = false;
-
- instrumentation_begin();
- panic("Unable to handle #VC exception! GHCB and Backup GHCB are already in use");
- instrumentation_end();
- }
-
- /* Mark backup_ghcb active before writing to it */
- data->backup_ghcb_active = true;
-
- state->ghcb = &data->backup_ghcb;
-
- /* Backup GHCB content */
- *state->ghcb = *ghcb;
- } else {
- state->ghcb = NULL;
- data->ghcb_active = true;
- }
-
- return ghcb;
-}
-
static inline u64 sev_es_rd_ghcb_msr(void)
{
return __rdmsr(MSR_AMD64_SEV_ES_GHCB);
@@ -484,6 +435,55 @@ static enum es_result vc_slow_virt_to_phys(struct ghcb *ghcb, struct es_em_ctxt
/* Include code shared with pre-decompression boot stage */
#include "sev-shared.c"
+/*
+ * Nothing shall interrupt this code path while holding the per-CPU
+ * GHCB. The backup GHCB is only for NMIs interrupting this path.
+ *
+ * Callers must disable local interrupts around it.
+ */
+static noinstr struct ghcb *__sev_get_ghcb(struct ghcb_state *state)
+{
+ struct sev_es_runtime_data *data;
+ struct ghcb *ghcb;
+
+ WARN_ON(!irqs_disabled());
+
+ data = this_cpu_read(runtime_data);
+ ghcb = &data->ghcb_page;
+
+ if (unlikely(data->ghcb_active)) {
+ /* GHCB is already in use - save its contents */
+
+ if (unlikely(data->backup_ghcb_active)) {
+ /*
+ * Backup-GHCB is also already in use. There is no way
+ * to continue here so just kill the machine. To make
+ * panic() work, mark GHCBs inactive so that messages
+ * can be printed out.
+ */
+ data->ghcb_active = false;
+ data->backup_ghcb_active = false;
+
+ instrumentation_begin();
+ panic("Unable to handle #VC exception! GHCB and Backup GHCB are already in use");
+ instrumentation_end();
+ }
+
+ /* Mark backup_ghcb active before writing to it */
+ data->backup_ghcb_active = true;
+
+ state->ghcb = &data->backup_ghcb;
+
+ /* Backup GHCB content */
+ *state->ghcb = *ghcb;
+ } else {
+ state->ghcb = NULL;
+ data->ghcb_active = true;
+ }
+
+ return ghcb;
+}
+
static noinstr void __sev_put_ghcb(struct ghcb_state *state)
{
struct sev_es_runtime_data *data;
@@ -652,7 +652,7 @@ static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
* This function runs on the first #VC exception after the kernel
* switched to virtual addresses.
*/
-static bool __init sev_es_setup_ghcb(void)
+static bool __init setup_ghcb(void)
{
/* First make sure the hypervisor talks a supported protocol. */
if (!sev_es_negotiate_protocol())
@@ -667,6 +667,10 @@ static bool __init sev_es_setup_ghcb(void)
/* Alright - Make the boot-ghcb public */
boot_ghcb = &boot_ghcb_page;
+ /* SEV-SNP guest requires that GHCB GPA must be registered. */
+ if (cc_platform_has(CC_ATTR_SEV_SNP))
+ snp_register_ghcb_early(__pa(&boot_ghcb_page));
+
return true;
}
@@ -758,6 +762,20 @@ static void __init init_ghcb(int cpu)
data->backup_ghcb_active = false;
}
+void sev_snp_register_ghcb(void)
+{
+ struct sev_es_runtime_data *data;
+ struct ghcb *ghcb;
+
+ if (!cc_platform_has(CC_ATTR_SEV_SNP))
+ return;
+
+ data = this_cpu_read(runtime_data);
+ ghcb = &data->ghcb_page;
+
+ snp_register_ghcb_early(__pa(ghcb));
+}
+
void __init sev_es_init_vc_handling(void)
{
int cpu;
@@ -1400,7 +1418,7 @@ bool __init handle_vc_boot_ghcb(struct pt_regs *regs)
enum es_result result;
/* Do initial setup or terminate the guest */
- if (unlikely(boot_ghcb == NULL && !sev_es_setup_ghcb()))
+ if (unlikely(boot_ghcb == NULL && !setup_ghcb()))
sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_GEN_REQ);
vc_ghcb_invalidate(boot_ghcb);
--
2.25.1
^ permalink raw reply related [flat|nested] 183+ messages in thread* Re: [PATCH v8 11/40] x86/sev: Register GHCB memory when SEV-SNP is active
2021-12-10 15:43 ` [PATCH v8 11/40] x86/sev: " Brijesh Singh
@ 2021-12-22 13:16 ` Borislav Petkov
2021-12-22 15:16 ` Brijesh Singh
2022-01-03 22:47 ` Venu Busireddy
1 sibling, 1 reply; 183+ messages in thread
From: Borislav Petkov @ 2021-12-22 13:16 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Michael Roth, Vlastimil Babka,
Kirill A . Shutemov, Andi Kleen, Dr . David Alan Gilbert,
tony.luck, marcorr, sathyanarayanan.kuppuswamy
On Fri, Dec 10, 2021 at 09:43:03AM -0600, Brijesh Singh wrote:
> @@ -652,7 +652,7 @@ static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
> * This function runs on the first #VC exception after the kernel
> * switched to virtual addresses.
> */
> -static bool __init sev_es_setup_ghcb(void)
> +static bool __init setup_ghcb(void)
> {
> /* First make sure the hypervisor talks a supported protocol. */
> if (!sev_es_negotiate_protocol())
Ok, let me stare at this for a while:
This gets called by handle_vc_boot_ghcb() which gets set at build time:
arch/x86/kernel/head_64.S:372:SYM_DATA(initial_vc_handler, .quad handle_vc_boot_ghcb)
initial_vc_handler() gets called by vc_boot_ghcb() which gets set in
early_setup_idt()
and that function already does sev_snp_register_ghcb().
So why don't you concentrate the work setup_ghcb() does before the first
#VC and call it in early_setup_idt(), before the IDT is set?
And then you get rid of yet another setup-at-first-use case?
Thx.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 11/40] x86/sev: Register GHCB memory when SEV-SNP is active
2021-12-22 13:16 ` Borislav Petkov
@ 2021-12-22 15:16 ` Brijesh Singh
0 siblings, 0 replies; 183+ messages in thread
From: Brijesh Singh @ 2021-12-22 15:16 UTC (permalink / raw)
To: Borislav Petkov
Cc: brijesh.singh, x86, linux-kernel, kvm, linux-efi,
platform-driver-x86, linux-coco, linux-mm, Thomas Gleixner,
Ingo Molnar, Joerg Roedel, Tom Lendacky, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 12/22/21 7:16 AM, Borislav Petkov wrote:
> On Fri, Dec 10, 2021 at 09:43:03AM -0600, Brijesh Singh wrote:
>> @@ -652,7 +652,7 @@ static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
>> * This function runs on the first #VC exception after the kernel
>> * switched to virtual addresses.
>> */
>> -static bool __init sev_es_setup_ghcb(void)
>> +static bool __init setup_ghcb(void)
>> {
>> /* First make sure the hypervisor talks a supported protocol. */
>> if (!sev_es_negotiate_protocol())
>
> Ok, let me stare at this for a while:
>
> This gets called by handle_vc_boot_ghcb() which gets set at build time:
>
> arch/x86/kernel/head_64.S:372:SYM_DATA(initial_vc_handler, .quad handle_vc_boot_ghcb)
>
> initial_vc_handler() gets called by vc_boot_ghcb() which gets set in
>
> early_setup_idt()
>
> and that function already does sev_snp_register_ghcb().
>
> So why don't you concentrate the work setup_ghcb() does before the first
> #VC and call it in early_setup_idt(), before the IDT is set?
>
> And then you get rid of yet another setup-at-first-use case?
>
I was following the existing SEV-ES implementation in which GHCB is
setup on first #VC. But recently you recommended to move the setup
outside of the VC handler for the decompression path and I was going to
do the same for the kernel proper. I have tried moving the GHCB setup
outside and it seems to be working okay with me (a limited testing so
far). I will check Jorge to see if there was any reason for doing the
GHCB setup inside the VC for the SEV-ES case.
^ permalink raw reply [flat|nested] 183+ messages in thread
* Re: [PATCH v8 11/40] x86/sev: Register GHCB memory when SEV-SNP is active
2021-12-10 15:43 ` [PATCH v8 11/40] x86/sev: " Brijesh Singh
2021-12-22 13:16 ` Borislav Petkov
@ 2022-01-03 22:47 ` Venu Busireddy
1 sibling, 0 replies; 183+ messages in thread
From: Venu Busireddy @ 2022-01-03 22:47 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2021-12-10 09:43:03 -0600, Brijesh Singh wrote:
> The SEV-SNP guest is required by the GHCB spec to register the GHCB's
> Guest Physical Address (GPA). This is because the hypervisor may prefer
> that a guest use a consistent and/or specific GPA for the GHCB associated
> with a vCPU. For more information, see the GHCB specification section
> "GHCB GPA Registration".
>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Venu Busireddy <venu.busireddy@oracle.com>
> ---
> arch/x86/include/asm/sev.h | 2 +
> arch/x86/kernel/cpu/common.c | 4 ++
> arch/x86/kernel/head64.c | 1 +
> arch/x86/kernel/sev-shared.c | 2 +-
> arch/x86/kernel/sev.c | 120 ++++++++++++++++++++---------------
> 5 files changed, 77 insertions(+), 52 deletions(-)
>
^ permalink raw reply [flat|nested] 183+ messages in thread
* [PATCH v8 12/40] x86/sev: Add helper for validating pages in early enc attribute changes
2021-12-10 15:42 [PATCH v8 00/40] Add AMD Secure Nested Paging (SEV-SNP) Guest Support Brijesh Singh
` (10 preceding siblings ...)
2021-12-10 15:43 ` [PATCH v8 11/40] x86/sev: " Brijesh Singh
@ 2021-12-10 15:43 ` Brijesh Singh
2021-12-23 11:50 ` Borislav Petkov
2022-01-03 23:28 ` Venu Busireddy
2021-12-10 15:43 ` [PATCH v8 13/40] x86/kernel: Make the bss.decrypted section shared in RMP table Brijesh Singh
` (28 subsequent siblings)
40 siblings, 2 replies; 183+ messages in thread
From: Brijesh Singh @ 2021-12-10 15:43 UTC (permalink / raw)
To: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm
Cc: Thomas Gleixner, Ingo Molnar, Joerg Roedel, Tom Lendacky,
H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy, Brijesh Singh
The early_set_memory_{encrypt,decrypt}() are used for changing the
page from decrypted (shared) to encrypted (private) and vice versa.
When SEV-SNP is active, the page state transition needs to go through
additional steps.
If the page is transitioned from shared to private, then perform the
following after the encryption attribute is set in the page table:
1. Issue the page state change VMGEXIT to add the page as a private
in the RMP table.
2. Validate the page after its successfully added in the RMP table.
To maintain the security guarantees, if the page is transitioned from
private to shared, then perform the following before clearing the
encryption attribute from the page table.
1. Invalidate the page.
2. Issue the page state change VMGEXIT to make the page shared in the
RMP table.
The early_set_memory_{encrypt,decrypt} can be called before the GHCB
is setup, use the SNP page state MSR protocol VMGEXIT defined in the GHCB
specification to request the page state change in the RMP table.
While at it, add a helper snp_prep_memory() that can be used outside
the sev specific files to change the page state for a specified memory
range.
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
arch/x86/include/asm/sev.h | 10 ++++
arch/x86/kernel/sev.c | 102 +++++++++++++++++++++++++++++++++++++
arch/x86/mm/mem_encrypt.c | 51 +++++++++++++++++--
3 files changed, 159 insertions(+), 4 deletions(-)
diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index 0df508374a35..eec2e1b9d557 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h
@@ -123,6 +123,11 @@ static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate)
return rc;
}
void sev_snp_register_ghcb(void);
+void __init early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr,
+ unsigned int npages);
+void __init early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr,
+ unsigned int npages);
+void __init snp_prep_memory(unsigned long paddr, unsigned int sz, enum psc_op op);
#else
static inline void sev_es_ist_enter(struct pt_regs *regs) { }
static inline void sev_es_ist_exit(void) { }
@@ -132,6 +137,11 @@ static inline int sev_es_efi_map_ghcbs(pgd_t *pgd) { return 0; }
static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate) { return 0; }
static inline int rmpadjust(unsigned long vaddr, bool rmp_psize, unsigned long attrs) { return 0; }
static inline void sev_snp_register_ghcb(void) { }
+static inline void __init
+early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr, unsigned int npages) { }
+static inline void __init
+early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr, unsigned int npages) { }
+static inline void __init snp_prep_memory(unsigned long paddr, unsigned int sz, enum psc_op op) { }
#endif
#endif
diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c
index 17ad603f62da..2971aa280ce6 100644
--- a/arch/x86/kernel/sev.c
+++ b/arch/x86/kernel/sev.c
@@ -557,6 +557,108 @@ static u64 get_jump_table_addr(void)
return ret;
}
+static void pvalidate_pages(unsigned long vaddr, unsigned int npages, bool validate)
+{
+ unsigned long vaddr_end;
+ int rc;
+
+ vaddr = vaddr & PAGE_MASK;
+ vaddr_end = vaddr + (npages << PAGE_SHIFT);
+
+ while (vaddr < vaddr_end) {
+ rc = pvalidate(vaddr, RMP_PG_SIZE_4K, validate);
+ if (WARN(rc, "Failed to validate address 0x%lx ret %d", vaddr, rc))
+ sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PVALIDATE);
+
+ vaddr = vaddr + PAGE_SIZE;
+ }
+}
+
+static void __init early_set_page_state(unsigned long paddr, unsigned int npages, enum psc_op op)
+{
+ unsigned long paddr_end;
+ u64 val;
+
+ paddr = paddr & PAGE_MASK;
+ paddr_end = paddr + (npages << PAGE_SHIFT);
+
+ while (paddr < paddr_end) {
+ /*
+ * Use the MSR protocol because this function can be called before the GHCB
+ * is established.
+ */
+ sev_es_wr_ghcb_msr(GHCB_MSR_PSC_REQ_GFN(paddr >> PAGE_SHIFT, op));
+ VMGEXIT();
+
+ val = sev_es_rd_ghcb_msr();
+
+ if (WARN(GHCB_RESP_CODE(val) != GHCB_MSR_PSC_RESP,
+ "Wrong PSC response code: 0x%x\n",
+ (unsigned int)GHCB_RESP_CODE(val)))
+ goto e_term;
+
+ if (WARN(GHCB_MSR_PSC_RESP_VAL(val),
+ "Failed to change page state to '%s' paddr 0x%lx error 0x%llx\n",
+ op == SNP_PAGE_STATE_PRIVATE ? "private" : "shared",
+ paddr, GHCB_MSR_PSC_RESP_VAL(val)))
+ goto e_term;
+
+ paddr = paddr + PAGE_SIZE;
+ }
+
+ return;
+
+e_term:
+ sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PSC);
+}
+
+void __init early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr,
+ unsigned int npages)
+{
+ if (!cc_platform_has(CC_ATTR_SEV_SNP))
+ return;
+
+ /*
+ * Ask the hypervisor to mark the memory pages as private in the RMP
+ * table.
+ */
+ early_set_page_state(paddr, npages, SNP_PAGE_STATE_PRIVATE);
+
+ /* Validate the memory pages after they've been added in the RMP table. */
+ pvalidate_pages(vaddr, npages, 1);
+}
+
+void __init early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr,
+ unsigned int npages)
+{
+ if (!cc_platform_has(CC_ATTR_SEV_SNP))
+ return;
+
+ /*
+ * Invalidate the memory pages before they are marked shared in the
+ * RMP table.
+ */
+ pvalidate_pages(vaddr, npages, 0);
+
+ /* Ask hypervisor to mark the memory pages shared in the RMP table. */
+ early_set_page_state(paddr, npages, SNP_PAGE_STATE_SHARED);
+}
+
+void __init snp_prep_memory(unsigned long paddr, unsigned int sz, enum psc_op op)
+{
+ unsigned long vaddr, npages;
+
+ vaddr = (unsigned long)__va(paddr);
+ npages = PAGE_ALIGN(sz) >> PAGE_SHIFT;
+
+ if (op == SNP_PAGE_STATE_PRIVATE)
+ early_snp_set_memory_private(vaddr, paddr, npages);
+ else if (op == SNP_PAGE_STATE_SHARED)
+ early_snp_set_memory_shared(vaddr, paddr, npages);
+ else
+ WARN(1, "invalid memory op %d\n", op);
+}
+
int sev_es_setup_ap_jump_table(struct real_mode_header *rmh)
{
u16 startup_cs, startup_ip;
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 3ba801ff6afc..5d19aad06670 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -31,6 +31,7 @@
#include <asm/processor-flags.h>
#include <asm/msr.h>
#include <asm/cmdline.h>
+#include <asm/sev.h>
#include "mm_internal.h"
@@ -49,6 +50,34 @@ EXPORT_SYMBOL_GPL(sev_enable_key);
/* Buffer used for early in-place encryption by BSP, no locking needed */
static char sme_early_buffer[PAGE_SIZE] __initdata __aligned(PAGE_SIZE);
+/*
+ * When SNP is active, change the page state from private to shared before
+ * copying the data from the source to destination and restore after the copy.
+ * This is required because the source address is mapped as decrypted by the
+ * caller of the routine.
+ */
+static inline void __init snp_memcpy(void *dst, void *src, size_t sz,
+ unsigned long paddr, bool decrypt)
+{
+ unsigned long npages = PAGE_ALIGN(sz) >> PAGE_SHIFT;
+
+ if (!cc_platform_has(CC_ATTR_SEV_SNP) || !decrypt) {
+ memcpy(dst, src, sz);
+ return;
+ }
+
+ /*
+ * With SNP, the paddr needs to be accessed decrypted, mark the page
+ * shared in the RMP table before copying it.
+ */
+ early_snp_set_memory_shared((unsigned long)__va(paddr), paddr, npages);
+
+ memcpy(dst, src, sz);
+
+ /* Restore the page state after the memcpy. */
+ early_snp_set_memory_private((unsigned long)__va(paddr), paddr, npages);
+}
+
/*
* This routine does not change the underlying encryption setting of the
* page(s) that map this memory. It assumes that eventually the memory is
@@ -97,8 +126,8 @@ static void __init __sme_early_enc_dec(resource_size_t paddr,
* Use a temporary buffer, of cache-line multiple size, to
* avoid data corruption as documented in the APM.
*/
- memcpy(sme_early_buffer, src, len);
- memcpy(dst, sme_early_buffer, len);
+ snp_memcpy(sme_early_buffer, src, len, paddr, enc);
+ snp_memcpy(dst, sme_early_buffer, len, paddr, !enc);
early_memunmap(dst, len);
early_memunmap(src, len);
@@ -320,14 +349,28 @@ static void __init __set_clr_pte_enc(pte_t *kpte, int level, bool enc)
clflush_cache_range(__va(pa), size);
/* Encrypt/decrypt the contents in-place */
- if (enc)
+ if (enc) {
sme_early_encrypt(pa, size);
- else
+ } else {
sme_early_decrypt(pa, size);
+ /*
+ * ON SNP, the page state in the RMP table must happen
+ * before the page table updates.
+ */
+ early_snp_set_memory_shared((unsigned long)__va(pa), pa, 1);
+ }
+
/* Change the page encryption mask. */
new_pte = pfn_pte(pfn, new_prot);
set_pte_atomic(kpte, new_pte);
+
+ /*
+ * If page is set encrypted in the page table, then update the RMP table to
+ * add this page as private.
+ */
+ if (enc)
+ early_snp_set_memory_private((unsigned long)__va(pa), pa, 1);
}
static int __init early_set_memory_enc_dec(unsigned long vaddr,
--
2.25.1
^ permalink raw reply related [flat|nested] 183+ messages in thread* Re: [PATCH v8 12/40] x86/sev: Add helper for validating pages in early enc attribute changes
2021-12-10 15:43 ` [PATCH v8 12/40] x86/sev: Add helper for validating pages in early enc attribute changes Brijesh Singh
@ 2021-12-23 11:50 ` Borislav Petkov
2022-01-04 15:33 ` Brijesh Singh
2022-01-03 23:28 ` Venu Busireddy
1 sibling, 1 reply; 183+ messages in thread
From: Borislav Petkov @ 2021-12-23 11:50 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Michael Roth, Vlastimil Babka,
Kirill A . Shutemov, Andi Kleen, Dr . David Alan Gilbert,
tony.luck, marcorr, sathyanarayanan.kuppuswamy
On Fri, Dec 10, 2021 at 09:43:04AM -0600, Brijesh Singh wrote:
> The early_set_memory_{encrypt,decrypt}() are used for changing the
^
ed()
> page from decrypted (shared) to encrypted (private) and vice versa.
> When SEV-SNP is active, the page state transition needs to go through
> additional steps.
>
> If the page is transitioned from shared to private, then perform the
> following after the encryption attribute is set in the page table:
>
> 1. Issue the page state change VMGEXIT to add the page as a private
> in the RMP table.
> 2. Validate the page after its successfully added in the RMP table.
>
> To maintain the security guarantees, if the page is transitioned from
> private to shared, then perform the following before clearing the
> encryption attribute from the page table.
>
> 1. Invalidate the page.
> 2. Issue the page state change VMGEXIT to make the page shared in the
> RMP table.
>
> The early_set_memory_{encrypt,decrypt} can be called before the GHCB
ditto.
> is setup, use the SNP page state MSR protocol VMGEXIT defined in the GHCB
> specification to request the page state change in the RMP table.
>
> While at it, add a helper snp_prep_memory() that can be used outside
> the sev specific files to change the page state for a specified memory
"outside of the sev specific"? What is that trying to say?
/me goes and looks at the whole patchset...
Right, so that is used only in probe_roms(). So that should say:
"Add a helper ... which will be used in probe_roms(), in a later patch."
> range.
>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
> arch/x86/include/asm/sev.h | 10 ++++
> arch/x86/kernel/sev.c | 102 +++++++++++++++++++++++++++++++++++++
> arch/x86/mm/mem_encrypt.c | 51 +++++++++++++++++--
Right, for the next revision, that file is called mem_encrypt_amd.c now.
...
> diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
> index 3ba801ff6afc..5d19aad06670 100644
> --- a/arch/x86/mm/mem_encrypt.c
> +++ b/arch/x86/mm/mem_encrypt.c
> @@ -31,6 +31,7 @@
> #include <asm/processor-flags.h>
> #include <asm/msr.h>
> #include <asm/cmdline.h>
> +#include <asm/sev.h>
>
> #include "mm_internal.h"
>
> @@ -49,6 +50,34 @@ EXPORT_SYMBOL_GPL(sev_enable_key);
> /* Buffer used for early in-place encryption by BSP, no locking needed */
> static char sme_early_buffer[PAGE_SIZE] __initdata __aligned(PAGE_SIZE);
>
> +/*
> + * When SNP is active, change the page state from private to shared before
> + * copying the data from the source to destination and restore after the copy.
> + * This is required because the source address is mapped as decrypted by the
> + * caller of the routine.
> + */
> +static inline void __init snp_memcpy(void *dst, void *src, size_t sz,
> + unsigned long paddr, bool decrypt)
> +{
> + unsigned long npages = PAGE_ALIGN(sz) >> PAGE_SHIFT;
> +
> + if (!cc_platform_has(CC_ATTR_SEV_SNP) || !decrypt) {
Yeah, looking at this again, I don't really like this multiplexing.
Let's do this instead, diff ontop:
---
diff --git a/arch/x86/mm/mem_encrypt_amd.c b/arch/x86/mm/mem_encrypt_amd.c
index c14fd8254198..e3f7a84449bb 100644
--- a/arch/x86/mm/mem_encrypt_amd.c
+++ b/arch/x86/mm/mem_encrypt_amd.c
@@ -49,24 +49,18 @@ EXPORT_SYMBOL(sme_me_mask);
static char sme_early_buffer[PAGE_SIZE] __initdata __aligned(PAGE_SIZE);
/*
- * When SNP is active, change the page state from private to shared before
- * copying the data from the source to destination and restore after the copy.
- * This is required because the source address is mapped as decrypted by the
- * caller of the routine.
+ * SNP-specific routine which needs to additionally change the page state from
+ * private to shared before copying the data from the source to destination and
+ * restore after the copy.
*/
static inline void __init snp_memcpy(void *dst, void *src, size_t sz,
unsigned long paddr, bool decrypt)
{
unsigned long npages = PAGE_ALIGN(sz) >> PAGE_SHIFT;
- if (!cc_platform_has(CC_ATTR_SEV_SNP) || !decrypt) {
- memcpy(dst, src, sz);
- return;
- }
-
/*
- * With SNP, the paddr needs to be accessed decrypted, mark the page
- * shared in the RMP table before copying it.
+ * @paddr needs to be accessed decrypted, mark the page shared in the
+ * RMP table before copying it.
*/
early_snp_set_memory_shared((unsigned long)__va(paddr), paddr, npages);
@@ -124,8 +118,13 @@ static void __init __sme_early_enc_dec(resource_size_t paddr,
* Use a temporary buffer, of cache-line multiple size, to
* avoid data corruption as documented in the APM.
*/
- snp_memcpy(sme_early_buffer, src, len, paddr, enc);
- snp_memcpy(dst, sme_early_buffer, len, paddr, !enc);
+ if (cc_platform_has(CC_ATTR_SEV_SNP)) {
+ snp_memcpy(sme_early_buffer, src, len, paddr, enc);
+ snp_memcpy(dst, sme_early_buffer, len, paddr, !enc);
+ } else {
+ memcpy(sme_early_buffer, src, len);
+ memcpy(dst, sme_early_buffer, len);
+ }
early_memunmap(dst, len);
early_memunmap(src, len);
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply related [flat|nested] 183+ messages in thread* Re: [PATCH v8 12/40] x86/sev: Add helper for validating pages in early enc attribute changes
2021-12-23 11:50 ` Borislav Petkov
@ 2022-01-04 15:33 ` Brijesh Singh
0 siblings, 0 replies; 183+ messages in thread
From: Brijesh Singh @ 2022-01-04 15:33 UTC (permalink / raw)
To: Borislav Petkov
Cc: brijesh.singh, x86, linux-kernel, kvm, linux-efi,
platform-driver-x86, linux-coco, linux-mm, Thomas Gleixner,
Ingo Molnar, Joerg Roedel, Tom Lendacky, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 12/23/21 5:50 AM, Borislav Petkov wrote:
>> While at it, add a helper snp_prep_memory() that can be used outside
>> the sev specific files to change the page state for a specified memory
>
> "outside of the sev specific"? What is that trying to say?
>
> /me goes and looks at the whole patchset...
>
> Right, so that is used only in probe_roms(). So that should say:
>
> "Add a helper ... which will be used in probe_roms(), in a later patch."
>
Currently the helper is used for the probe_roms() only but it can be
used by others in future. I will go ahead and spell out saying that it
is for the probe_roms().
>
> Yeah, looking at this again, I don't really like this multiplexing.
> Let's do this instead, diff ontop:
>
thanks, I will apply your diff.
^ permalink raw reply [flat|nested] 183+ messages in thread
* Re: [PATCH v8 12/40] x86/sev: Add helper for validating pages in early enc attribute changes
2021-12-10 15:43 ` [PATCH v8 12/40] x86/sev: Add helper for validating pages in early enc attribute changes Brijesh Singh
2021-12-23 11:50 ` Borislav Petkov
@ 2022-01-03 23:28 ` Venu Busireddy
2022-01-11 21:22 ` Brijesh Singh
1 sibling, 1 reply; 183+ messages in thread
From: Venu Busireddy @ 2022-01-03 23:28 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2021-12-10 09:43:04 -0600, Brijesh Singh wrote:
> The early_set_memory_{encrypt,decrypt}() are used for changing the
s/encrypt,decrypt/encrypted,decrypted/
> page from decrypted (shared) to encrypted (private) and vice versa.
> When SEV-SNP is active, the page state transition needs to go through
> additional steps.
>
> If the page is transitioned from shared to private, then perform the
> following after the encryption attribute is set in the page table:
>
> 1. Issue the page state change VMGEXIT to add the page as a private
> in the RMP table.
> 2. Validate the page after its successfully added in the RMP table.
>
> To maintain the security guarantees, if the page is transitioned from
> private to shared, then perform the following before clearing the
> encryption attribute from the page table.
>
> 1. Invalidate the page.
> 2. Issue the page state change VMGEXIT to make the page shared in the
> RMP table.
>
> The early_set_memory_{encrypt,decrypt} can be called before the GHCB
s/encrypt,decrypt/encrypted,decrypted/
> is setup, use the SNP page state MSR protocol VMGEXIT defined in the GHCB
> specification to request the page state change in the RMP table.
>
> While at it, add a helper snp_prep_memory() that can be used outside
> the sev specific files to change the page state for a specified memory
> range.
>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
And with a few other nits below:
Reviewed-by: Venu Busireddy <venu.busireddy@oracle.com>
> diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c
> +
> + /*
> + * Ask the hypervisor to mark the memory pages as private in the RMP
> + * table.
> + */
Indentation is off. While at it, you may want to collapse it into a one
line comment.
> + early_set_page_state(paddr, npages, SNP_PAGE_STATE_PRIVATE);
> +
> + /* Validate the memory pages after they've been added in the RMP table. */
> + pvalidate_pages(vaddr, npages, 1);
> +}
> +
> +void __init early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr,
> + unsigned int npages)
> +{
> + if (!cc_platform_has(CC_ATTR_SEV_SNP))
> + return;
> +
> + /*
> + * Invalidate the memory pages before they are marked shared in the
> + * RMP table.
> + */
Collapse into one line?
> + pvalidate_pages(vaddr, npages, 0);
> +
> + /* Ask hypervisor to mark the memory pages shared in the RMP table. */
Indentation is off.
> + /*
> + * ON SNP, the page state in the RMP table must happen
> + * before the page table updates.
> + */
> + early_snp_set_memory_shared((unsigned long)__va(pa), pa, 1);
I know "1" implies "true", but to emphasize that the argument is
actually a boolean, could you please change the "1" to "true?"
> + }
> +
> /* Change the page encryption mask. */
> new_pte = pfn_pte(pfn, new_prot);
> set_pte_atomic(kpte, new_pte);
> +
> + /*
> + * If page is set encrypted in the page table, then update the RMP table to
> + * add this page as private.
> + */
> + if (enc)
> + early_snp_set_memory_private((unsigned long)__va(pa), pa, 1);
Here too, could you please change the "1" to "true?"
Venu
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 12/40] x86/sev: Add helper for validating pages in early enc attribute changes
2022-01-03 23:28 ` Venu Busireddy
@ 2022-01-11 21:22 ` Brijesh Singh
2022-01-11 21:51 ` Venu Busireddy
0 siblings, 1 reply; 183+ messages in thread
From: Brijesh Singh @ 2022-01-11 21:22 UTC (permalink / raw)
To: Venu Busireddy
Cc: brijesh.singh, x86, linux-kernel, kvm, linux-efi,
platform-driver-x86, linux-coco, linux-mm, Thomas Gleixner,
Ingo Molnar, Joerg Roedel, Tom Lendacky, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum,
Borislav Petkov, Michael Roth, Vlastimil Babka,
Kirill A . Shutemov, Andi Kleen, Dr . David Alan Gilbert,
tony.luck, marcorr, sathyanarayanan.kuppuswamy
Hi Venu,
On 1/3/22 5:28 PM, Venu Busireddy wrote:
...
>> +
>> + /*
>> + * Ask the hypervisor to mark the memory pages as private in the RMP
>> + * table.
>> + */
>
> Indentation is off. While at it, you may want to collapse it into a one
> line comment.
>
Based on previous review feedback I tried to keep the comment to 80
character limit.
>> + early_set_page_state(paddr, npages, SNP_PAGE_STATE_PRIVATE);
>> +
>> + /* Validate the memory pages after they've been added in the RMP table. */
>> + pvalidate_pages(vaddr, npages, 1);
>> +}
>> +
>> +void __init early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr,
>> + unsigned int npages)
>> +{
>> + if (!cc_platform_has(CC_ATTR_SEV_SNP))
>> + return;
>> +
>> + /*
>> + * Invalidate the memory pages before they are marked shared in the
>> + * RMP table.
>> + */
>
> Collapse into one line?
>
same as above.
...
>> + /*
>> + * ON SNP, the page state in the RMP table must happen
>> + * before the page table updates.
>> + */
>> + early_snp_set_memory_shared((unsigned long)__va(pa), pa, 1);
>
> I know "1" implies "true", but to emphasize that the argument is
> actually a boolean, could you please change the "1" to "true?"
>
I assume you mean the last argument to the
early_snp_set_memory_{private,shared}. Please note that its a number of
pages (unsigned int). The 'true' does not make sense to me.
>> + }
>> +
>> /* Change the page encryption mask. */
>> new_pte = pfn_pte(pfn, new_prot);
>> set_pte_atomic(kpte, new_pte);
>> +
>> + /*
>> + * If page is set encrypted in the page table, then update the RMP table to
>> + * add this page as private.
>> + */
>> + if (enc)
>> + early_snp_set_memory_private((unsigned long)__va(pa), pa, 1);
>
> Here too, could you please change the "1" to "true?"
>
same as above.
thanks
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 12/40] x86/sev: Add helper for validating pages in early enc attribute changes
2022-01-11 21:22 ` Brijesh Singh
@ 2022-01-11 21:51 ` Venu Busireddy
2022-01-11 21:57 ` Brijesh Singh
0 siblings, 1 reply; 183+ messages in thread
From: Venu Busireddy @ 2022-01-11 21:51 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2022-01-11 15:22:01 -0600, Brijesh Singh wrote:
> Hi Venu,
>
>
> On 1/3/22 5:28 PM, Venu Busireddy wrote:
> ...
>
> > > +
> > > + /*
> > > + * Ask the hypervisor to mark the memory pages as private in the RMP
> > > + * table.
> > > + */
> >
> > Indentation is off. While at it, you may want to collapse it into a one
> > line comment.
> >
>
> Based on previous review feedback I tried to keep the comment to 80
> character limit.
Isn't the line length limit 100 now? Also, there are quite a few lines
that are longer than 80 characters in this file, and elsewhere.
But you can ignore my comment.
> > > + early_set_page_state(paddr, npages, SNP_PAGE_STATE_PRIVATE);
> > > +
> > > + /* Validate the memory pages after they've been added in the RMP table. */
> > > + pvalidate_pages(vaddr, npages, 1);
> > > +}
> > > +
> > > +void __init early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr,
> > > + unsigned int npages)
> > > +{
> > > + if (!cc_platform_has(CC_ATTR_SEV_SNP))
> > > + return;
> > > +
> > > + /*
> > > + * Invalidate the memory pages before they are marked shared in the
> > > + * RMP table.
> > > + */
> >
> > Collapse into one line?
> >
>
> same as above.
Same as above.
>
> ...
>
> > > + /*
> > > + * ON SNP, the page state in the RMP table must happen
> > > + * before the page table updates.
> > > + */
> > > + early_snp_set_memory_shared((unsigned long)__va(pa), pa, 1);
> >
> > I know "1" implies "true", but to emphasize that the argument is
> > actually a boolean, could you please change the "1" to "true?"
> >
>
> I assume you mean the last argument to the
> early_snp_set_memory_{private,shared}. Please note that its a number of
> pages (unsigned int). The 'true' does not make sense to me.
Sorry. While reading the code, I was looking at the invocations
of pvalidate_pages(), where 0 and 1 are passed instead of "false"
and "true" for the third argument. But while replying to the thread,
I marked my comment at the wrong place. I meant to suggest to change
the third argument to pvalidate_pages().
> > > + }
> > > +
> > > /* Change the page encryption mask. */
> > > new_pte = pfn_pte(pfn, new_prot);
> > > set_pte_atomic(kpte, new_pte);
> > > +
> > > + /*
> > > + * If page is set encrypted in the page table, then update the RMP table to
> > > + * add this page as private.
> > > + */
> > > + if (enc)
> > > + early_snp_set_memory_private((unsigned long)__va(pa), pa, 1);
> >
> > Here too, could you please change the "1" to "true?"
> >
>
> same as above.
>
> thanks
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 12/40] x86/sev: Add helper for validating pages in early enc attribute changes
2022-01-11 21:51 ` Venu Busireddy
@ 2022-01-11 21:57 ` Brijesh Singh
2022-01-11 22:42 ` Venu Busireddy
0 siblings, 1 reply; 183+ messages in thread
From: Brijesh Singh @ 2022-01-11 21:57 UTC (permalink / raw)
To: Venu Busireddy
Cc: brijesh.singh, x86, linux-kernel, kvm, linux-efi,
platform-driver-x86, linux-coco, linux-mm, Thomas Gleixner,
Ingo Molnar, Joerg Roedel, Tom Lendacky, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum,
Borislav Petkov, Michael Roth, Vlastimil Babka,
Kirill A . Shutemov, Andi Kleen, Dr . David Alan Gilbert,
tony.luck, marcorr, sathyanarayanan.kuppuswamy
On 1/11/22 3:51 PM, Venu Busireddy wrote:
> On 2022-01-11 15:22:01 -0600, Brijesh Singh wrote:
>> Hi Venu,
>>
>>
>> On 1/3/22 5:28 PM, Venu Busireddy wrote:
>> ...
>>
>>>> +
>>>> + /*
>>>> + * Ask the hypervisor to mark the memory pages as private in the RMP
>>>> + * table.
>>>> + */
>>>
>>> Indentation is off. While at it, you may want to collapse it into a one
>>> line comment.
>>>
>>
>> Based on previous review feedback I tried to keep the comment to 80
>> character limit.
>
> Isn't the line length limit 100 now? Also, there are quite a few lines
> that are longer than 80 characters in this file, and elsewhere.
>
> But you can ignore my comment.
>
Yes, the actual line limit is 100, but I was asked to keep the comments
to 80 cols [1] to keep it consistent with other comments in this file.
https://lore.kernel.org/lkml/f9a69ad8-54bb-70f1-d606-6497e5753bb0@amd.com/
thanks
^ permalink raw reply [flat|nested] 183+ messages in thread
* Re: [PATCH v8 12/40] x86/sev: Add helper for validating pages in early enc attribute changes
2022-01-11 21:57 ` Brijesh Singh
@ 2022-01-11 22:42 ` Venu Busireddy
0 siblings, 0 replies; 183+ messages in thread
From: Venu Busireddy @ 2022-01-11 22:42 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2022-01-11 15:57:13 -0600, Brijesh Singh wrote:
>
>
> On 1/11/22 3:51 PM, Venu Busireddy wrote:
> > On 2022-01-11 15:22:01 -0600, Brijesh Singh wrote:
> > > Hi Venu,
> > >
> > >
> > > On 1/3/22 5:28 PM, Venu Busireddy wrote:
> > > ...
> > >
> > > > > +
> > > > > + /*
> > > > > + * Ask the hypervisor to mark the memory pages as private in the RMP
> > > > > + * table.
> > > > > + */
> > > >
> > > > Indentation is off. While at it, you may want to collapse it into a one
> > > > line comment.
> > > >
> > >
> > > Based on previous review feedback I tried to keep the comment to 80
> > > character limit.
> >
> > Isn't the line length limit 100 now? Also, there are quite a few lines
> > that are longer than 80 characters in this file, and elsewhere.
> >
> > But you can ignore my comment.
> >
>
> Yes, the actual line limit is 100, but I was asked to keep the comments to
> 80 cols [1] to keep it consistent with other comments in this file.
Well, now that you mention it, the comment that immediately precedes this
one in the file is 91 characters long, and the comment that immediately
follows this one is 82 characters long! And both those lines are also
added as part of this patch.
Venu
>
> https://lore.kernel.org/lkml/f9a69ad8-54bb-70f1-d606-6497e5753bb0@amd.com/
>
> thanks
^ permalink raw reply [flat|nested] 183+ messages in thread
* [PATCH v8 13/40] x86/kernel: Make the bss.decrypted section shared in RMP table
2021-12-10 15:42 [PATCH v8 00/40] Add AMD Secure Nested Paging (SEV-SNP) Guest Support Brijesh Singh
` (11 preceding siblings ...)
2021-12-10 15:43 ` [PATCH v8 12/40] x86/sev: Add helper for validating pages in early enc attribute changes Brijesh Singh
@ 2021-12-10 15:43 ` Brijesh Singh
2021-12-28 11:53 ` Borislav Petkov
2022-01-04 17:56 ` Venu Busireddy
2021-12-10 15:43 ` [PATCH v8 14/40] x86/kernel: Validate rom memory before accessing when SEV-SNP is active Brijesh Singh
` (27 subsequent siblings)
40 siblings, 2 replies; 183+ messages in thread
From: Brijesh Singh @ 2021-12-10 15:43 UTC (permalink / raw)
To: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm
Cc: Thomas Gleixner, Ingo Molnar, Joerg Roedel, Tom Lendacky,
H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy, Brijesh Singh
The encryption attribute for the bss.decrypted region is cleared in the
initial page table build. This is because the section contains the data
that need to be shared between the guest and the hypervisor.
When SEV-SNP is active, just clearing the encryption attribute in the
page table is not enough. The page state need to be updated in the RMP
table.
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
arch/x86/kernel/head64.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index fa02402dcb9b..72c5082a3ba4 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -143,7 +143,14 @@ static unsigned long sme_postprocess_startup(struct boot_params *bp, pmdval_t *p
if (sme_get_me_mask()) {
vaddr = (unsigned long)__start_bss_decrypted;
vaddr_end = (unsigned long)__end_bss_decrypted;
+
for (; vaddr < vaddr_end; vaddr += PMD_SIZE) {
+ /*
+ * When SEV-SNP is active then transition the page to shared in the RMP
+ * table so that it is consistent with the page table attribute change.
+ */
+ early_snp_set_memory_shared(__pa(vaddr), __pa(vaddr), PTRS_PER_PMD);
+
i = pmd_index(vaddr);
pmd[i] -= sme_get_me_mask();
}
--
2.25.1
^ permalink raw reply related [flat|nested] 183+ messages in thread* Re: [PATCH v8 13/40] x86/kernel: Make the bss.decrypted section shared in RMP table
2021-12-10 15:43 ` [PATCH v8 13/40] x86/kernel: Make the bss.decrypted section shared in RMP table Brijesh Singh
@ 2021-12-28 11:53 ` Borislav Petkov
2022-01-04 17:56 ` Venu Busireddy
1 sibling, 0 replies; 183+ messages in thread
From: Borislav Petkov @ 2021-12-28 11:53 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Michael Roth, Vlastimil Babka,
Kirill A . Shutemov, Andi Kleen, Dr . David Alan Gilbert,
tony.luck, marcorr, sathyanarayanan.kuppuswamy
On Fri, Dec 10, 2021 at 09:43:05AM -0600, Brijesh Singh wrote:
> The encryption attribute for the bss.decrypted region is cleared in the
s/region/section/
s/bss.decrypted/.bss..decrypted/g
if you're going to call it by its name, use the correct one pls.
Ditto in the Subject.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 13/40] x86/kernel: Make the bss.decrypted section shared in RMP table
2021-12-10 15:43 ` [PATCH v8 13/40] x86/kernel: Make the bss.decrypted section shared in RMP table Brijesh Singh
2021-12-28 11:53 ` Borislav Petkov
@ 2022-01-04 17:56 ` Venu Busireddy
2022-01-05 19:52 ` Brijesh Singh
1 sibling, 1 reply; 183+ messages in thread
From: Venu Busireddy @ 2022-01-04 17:56 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2021-12-10 09:43:05 -0600, Brijesh Singh wrote:
> The encryption attribute for the bss.decrypted region is cleared in the
> initial page table build. This is because the section contains the data
> that need to be shared between the guest and the hypervisor.
>
> When SEV-SNP is active, just clearing the encryption attribute in the
> page table is not enough. The page state need to be updated in the RMP
> table.
>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
> arch/x86/kernel/head64.c | 7 +++++++
> 1 file changed, 7 insertions(+)
>
> diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
> index fa02402dcb9b..72c5082a3ba4 100644
> --- a/arch/x86/kernel/head64.c
> +++ b/arch/x86/kernel/head64.c
> @@ -143,7 +143,14 @@ static unsigned long sme_postprocess_startup(struct boot_params *bp, pmdval_t *p
> if (sme_get_me_mask()) {
> vaddr = (unsigned long)__start_bss_decrypted;
> vaddr_end = (unsigned long)__end_bss_decrypted;
> +
> for (; vaddr < vaddr_end; vaddr += PMD_SIZE) {
> + /*
> + * When SEV-SNP is active then transition the page to shared in the RMP
> + * table so that it is consistent with the page table attribute change.
> + */
> + early_snp_set_memory_shared(__pa(vaddr), __pa(vaddr), PTRS_PER_PMD);
Shouldn't the first argument be vaddr as below?
early_snp_set_memory_shared(vaddr, __pa(vaddr), PTRS_PER_PMD);
Venu
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 13/40] x86/kernel: Make the bss.decrypted section shared in RMP table
2022-01-04 17:56 ` Venu Busireddy
@ 2022-01-05 19:52 ` Brijesh Singh
2022-01-05 20:27 ` Dave Hansen
0 siblings, 1 reply; 183+ messages in thread
From: Brijesh Singh @ 2022-01-05 19:52 UTC (permalink / raw)
To: Venu Busireddy
Cc: brijesh.singh, x86, linux-kernel, kvm, linux-efi,
platform-driver-x86, linux-coco, linux-mm, Thomas Gleixner,
Ingo Molnar, Joerg Roedel, Tom Lendacky, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum,
Borislav Petkov, Michael Roth, Vlastimil Babka,
Kirill A . Shutemov, Andi Kleen, Dr . David Alan Gilbert,
tony.luck, marcorr, sathyanarayanan.kuppuswamy
On 1/4/22 11:56 AM, Venu Busireddy wrote:
> On 2021-12-10 09:43:05 -0600, Brijesh Singh wrote:
>> The encryption attribute for the bss.decrypted region is cleared in the
>> initial page table build. This is because the section contains the data
>> that need to be shared between the guest and the hypervisor.
>>
>> When SEV-SNP is active, just clearing the encryption attribute in the
>> page table is not enough. The page state need to be updated in the RMP
>> table.
>>
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>> ---
>> arch/x86/kernel/head64.c | 7 +++++++
>> 1 file changed, 7 insertions(+)
>>
>> diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
>> index fa02402dcb9b..72c5082a3ba4 100644
>> --- a/arch/x86/kernel/head64.c
>> +++ b/arch/x86/kernel/head64.c
>> @@ -143,7 +143,14 @@ static unsigned long sme_postprocess_startup(struct boot_params *bp, pmdval_t *p
>> if (sme_get_me_mask()) {
>> vaddr = (unsigned long)__start_bss_decrypted;
>> vaddr_end = (unsigned long)__end_bss_decrypted;
>> +
>> for (; vaddr < vaddr_end; vaddr += PMD_SIZE) {
>> + /*
>> + * When SEV-SNP is active then transition the page to shared in the RMP
>> + * table so that it is consistent with the page table attribute change.
>> + */
>> + early_snp_set_memory_shared(__pa(vaddr), __pa(vaddr), PTRS_PER_PMD);
>
> Shouldn't the first argument be vaddr as below?
>
Nope, sme_postprocess_startup() is called while we are fixing the
initial page table and running with identity mapping (so va == pa).
thanks
> early_snp_set_memory_shared(vaddr, __pa(vaddr), PTRS_PER_PMD);
>
> Venu
>
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 13/40] x86/kernel: Make the bss.decrypted section shared in RMP table
2022-01-05 19:52 ` Brijesh Singh
@ 2022-01-05 20:27 ` Dave Hansen
2022-01-05 21:39 ` Brijesh Singh
0 siblings, 1 reply; 183+ messages in thread
From: Dave Hansen @ 2022-01-05 20:27 UTC (permalink / raw)
To: Brijesh Singh, Venu Busireddy
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 1/5/22 11:52, Brijesh Singh wrote:
>>> for (; vaddr < vaddr_end; vaddr += PMD_SIZE) {
>>> + /*
>>> + * When SEV-SNP is active then transition the page to shared in the RMP
>>> + * table so that it is consistent with the page table attribute change.
>>> + */
>>> + early_snp_set_memory_shared(__pa(vaddr), __pa(vaddr), PTRS_PER_PMD);
>>
>> Shouldn't the first argument be vaddr as below?
>
> Nope, sme_postprocess_startup() is called while we are fixing the
> initial page table and running with identity mapping (so va == pa).
I'm not sure I've ever seen a line of code that wanted a comment so badly.
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 13/40] x86/kernel: Make the bss.decrypted section shared in RMP table
2022-01-05 20:27 ` Dave Hansen
@ 2022-01-05 21:39 ` Brijesh Singh
2022-01-06 17:40 ` Venu Busireddy
0 siblings, 1 reply; 183+ messages in thread
From: Brijesh Singh @ 2022-01-05 21:39 UTC (permalink / raw)
To: Dave Hansen, Venu Busireddy
Cc: brijesh.singh, x86, linux-kernel, kvm, linux-efi,
platform-driver-x86, linux-coco, linux-mm, Thomas Gleixner,
Ingo Molnar, Joerg Roedel, Tom Lendacky, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum,
Borislav Petkov, Michael Roth, Vlastimil Babka,
Kirill A . Shutemov, Andi Kleen, Dr . David Alan Gilbert,
tony.luck, marcorr, sathyanarayanan.kuppuswamy
On 1/5/22 2:27 PM, Dave Hansen wrote:
> On 1/5/22 11:52, Brijesh Singh wrote:
>>>> for (; vaddr < vaddr_end; vaddr += PMD_SIZE) {
>>>> + /*
>>>> + * When SEV-SNP is active then transition the page to
>>>> shared in the RMP
>>>> + * table so that it is consistent with the page table
>>>> attribute change.
>>>> + */
>>>> + early_snp_set_memory_shared(__pa(vaddr), __pa(vaddr),
>>>> PTRS_PER_PMD);
>>>
>>> Shouldn't the first argument be vaddr as below?
>>
>> Nope, sme_postprocess_startup() is called while we are fixing the
>> initial page table and running with identity mapping (so va == pa).
>
> I'm not sure I've ever seen a line of code that wanted a comment so badly.
The early_snp_set_memory_shared() call the PVALIDATE instruction to
clear the validated bit from the BSS region. The PVALIDATE instruction
needs a virtual address, so we need to use the identity mapped virtual
address so that PVALIDATE can clear the validated bit. I will add more
comments to clarify it.
-Brijesh
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 13/40] x86/kernel: Make the bss.decrypted section shared in RMP table
2022-01-05 21:39 ` Brijesh Singh
@ 2022-01-06 17:40 ` Venu Busireddy
2022-01-06 19:06 ` Tom Lendacky
0 siblings, 1 reply; 183+ messages in thread
From: Venu Busireddy @ 2022-01-06 17:40 UTC (permalink / raw)
To: Brijesh Singh
Cc: Dave Hansen, x86, linux-kernel, kvm, linux-efi,
platform-driver-x86, linux-coco, linux-mm, Thomas Gleixner,
Ingo Molnar, Joerg Roedel, Tom Lendacky, H. Peter Anvin,
Ard Biesheuvel, Paolo Bonzini, Sean Christopherson,
Vitaly Kuznetsov, Jim Mattson, Andy Lutomirski, Dave Hansen,
Sergio Lopez, Peter Gonda, Peter Zijlstra, Srinivas Pandruvada,
David Rientjes, Dov Murik, Tobin Feldman-Fitzthum,
Borislav Petkov, Michael Roth, Vlastimil Babka,
Kirill A . Shutemov, Andi Kleen, Dr . David Alan Gilbert,
tony.luck, marcorr, sathyanarayanan.kuppuswamy
On 2022-01-05 15:39:22 -0600, Brijesh Singh wrote:
>
>
> On 1/5/22 2:27 PM, Dave Hansen wrote:
> > On 1/5/22 11:52, Brijesh Singh wrote:
> > > > > for (; vaddr < vaddr_end; vaddr += PMD_SIZE) {
> > > > > + /*
> > > > > + * When SEV-SNP is active then transition the
> > > > > page to shared in the RMP
> > > > > + * table so that it is consistent with the page
> > > > > table attribute change.
> > > > > + */
> > > > > + early_snp_set_memory_shared(__pa(vaddr),
> > > > > __pa(vaddr), PTRS_PER_PMD);
> > > >
> > > > Shouldn't the first argument be vaddr as below?
> > >
> > > Nope, sme_postprocess_startup() is called while we are fixing the
> > > initial page table and running with identity mapping (so va == pa).
> >
> > I'm not sure I've ever seen a line of code that wanted a comment so badly.
>
> The early_snp_set_memory_shared() call the PVALIDATE instruction to clear
> the validated bit from the BSS region. The PVALIDATE instruction needs a
> virtual address, so we need to use the identity mapped virtual address so
> that PVALIDATE can clear the validated bit. I will add more comments to
> clarify it.
Looking forward to see your final comments explaining this. I can't
still follow why, when PVALIDATE needs the virtual address, we are doing
a __pa() on the vaddr.
Venu
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 13/40] x86/kernel: Make the bss.decrypted section shared in RMP table
2022-01-06 17:40 ` Venu Busireddy
@ 2022-01-06 19:06 ` Tom Lendacky
2022-01-06 20:16 ` Venu Busireddy
0 siblings, 1 reply; 183+ messages in thread
From: Tom Lendacky @ 2022-01-06 19:06 UTC (permalink / raw)
To: Venu Busireddy, Brijesh Singh
Cc: Dave Hansen, x86, linux-kernel, kvm, linux-efi,
platform-driver-x86, linux-coco, linux-mm, Thomas Gleixner,
Ingo Molnar, Joerg Roedel, H. Peter Anvin, Ard Biesheuvel,
Paolo Bonzini, Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 1/6/22 11:40 AM, Venu Busireddy wrote:
> On 2022-01-05 15:39:22 -0600, Brijesh Singh wrote:
>>
>>
>> On 1/5/22 2:27 PM, Dave Hansen wrote:
>>> On 1/5/22 11:52, Brijesh Singh wrote:
>>>>>> for (; vaddr < vaddr_end; vaddr += PMD_SIZE) {
>>>>>> + /*
>>>>>> + * When SEV-SNP is active then transition the
>>>>>> page to shared in the RMP
>>>>>> + * table so that it is consistent with the page
>>>>>> table attribute change.
>>>>>> + */
>>>>>> + early_snp_set_memory_shared(__pa(vaddr),
>>>>>> __pa(vaddr), PTRS_PER_PMD);
>>>>>
>>>>> Shouldn't the first argument be vaddr as below?
>>>>
>>>> Nope, sme_postprocess_startup() is called while we are fixing the
>>>> initial page table and running with identity mapping (so va == pa).
>>>
>>> I'm not sure I've ever seen a line of code that wanted a comment so badly.
>>
>> The early_snp_set_memory_shared() call the PVALIDATE instruction to clear
>> the validated bit from the BSS region. The PVALIDATE instruction needs a
>> virtual address, so we need to use the identity mapped virtual address so
>> that PVALIDATE can clear the validated bit. I will add more comments to
>> clarify it.
>
> Looking forward to see your final comments explaining this. I can't
> still follow why, when PVALIDATE needs the virtual address, we are doing
> a __pa() on the vaddr.
It's because of the phase of booting that the kernel is in. At this point,
the kernel is running in identity mapped mode (VA == PA). The
__start_bss_decrypted address is a regular kernel address, e.g. for the
kernel I'm on it is 0xffffffffa7600000. Since the PVALIDATE instruction
requires a valid virtual address, the code needs to perform a __pa()
against __start_bss_decrypted to get the identity mapped virtual address
that is currently in place.
It is not until the .Ljump_to_C_code label in head_64.S that the
addressing switches from identity mapped to kernel addresses.
Thanks,
Tom
>
> Venu
>
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 13/40] x86/kernel: Make the bss.decrypted section shared in RMP table
2022-01-06 19:06 ` Tom Lendacky
@ 2022-01-06 20:16 ` Venu Busireddy
2022-01-06 20:50 ` Tom Lendacky
0 siblings, 1 reply; 183+ messages in thread
From: Venu Busireddy @ 2022-01-06 20:16 UTC (permalink / raw)
To: Tom Lendacky
Cc: Brijesh Singh, Dave Hansen, x86, linux-kernel, kvm, linux-efi,
platform-driver-x86, linux-coco, linux-mm, Thomas Gleixner,
Ingo Molnar, Joerg Roedel, H. Peter Anvin, Ard Biesheuvel,
Paolo Bonzini, Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2022-01-06 13:06:13 -0600, Tom Lendacky wrote:
> On 1/6/22 11:40 AM, Venu Busireddy wrote:
> > On 2022-01-05 15:39:22 -0600, Brijesh Singh wrote:
> > >
> > >
> > > On 1/5/22 2:27 PM, Dave Hansen wrote:
> > > > On 1/5/22 11:52, Brijesh Singh wrote:
> > > > > > > for (; vaddr < vaddr_end; vaddr += PMD_SIZE) {
> > > > > > > + /*
> > > > > > > + * When SEV-SNP is active then transition the
> > > > > > > page to shared in the RMP
> > > > > > > + * table so that it is consistent with the page
> > > > > > > table attribute change.
> > > > > > > + */
> > > > > > > + early_snp_set_memory_shared(__pa(vaddr),
> > > > > > > __pa(vaddr), PTRS_PER_PMD);
> > > > > >
> > > > > > Shouldn't the first argument be vaddr as below?
> > > > >
> > > > > Nope, sme_postprocess_startup() is called while we are fixing the
> > > > > initial page table and running with identity mapping (so va == pa).
> > > >
> > > > I'm not sure I've ever seen a line of code that wanted a comment so badly.
> > >
> > > The early_snp_set_memory_shared() call the PVALIDATE instruction to clear
> > > the validated bit from the BSS region. The PVALIDATE instruction needs a
> > > virtual address, so we need to use the identity mapped virtual address so
> > > that PVALIDATE can clear the validated bit. I will add more comments to
> > > clarify it.
> >
> > Looking forward to see your final comments explaining this. I can't
> > still follow why, when PVALIDATE needs the virtual address, we are doing
> > a __pa() on the vaddr.
>
> It's because of the phase of booting that the kernel is in. At this point,
> the kernel is running in identity mapped mode (VA == PA). The
> __start_bss_decrypted address is a regular kernel address, e.g. for the
> kernel I'm on it is 0xffffffffa7600000. Since the PVALIDATE instruction
> requires a valid virtual address, the code needs to perform a __pa() against
> __start_bss_decrypted to get the identity mapped virtual address that is
> currently in place.
Perhaps my confusion stems from the fact that __pa(x) is defined either
as "((unsigned long ) (x))" (for the cases where paddr and vaddr are
same), or as "__phys_addr((unsigned long )(x))", where a vaddr needs to
be converted to a paddr. If the paddr and vaddr are same in our case,
what exactly is the _pa(vaddr) doing to the vaddr?
Venu
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 13/40] x86/kernel: Make the bss.decrypted section shared in RMP table
2022-01-06 20:16 ` Venu Busireddy
@ 2022-01-06 20:50 ` Tom Lendacky
0 siblings, 0 replies; 183+ messages in thread
From: Tom Lendacky @ 2022-01-06 20:50 UTC (permalink / raw)
To: Venu Busireddy
Cc: Brijesh Singh, Dave Hansen, x86, linux-kernel, kvm, linux-efi,
platform-driver-x86, linux-coco, linux-mm, Thomas Gleixner,
Ingo Molnar, Joerg Roedel, H. Peter Anvin, Ard Biesheuvel,
Paolo Bonzini, Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 1/6/22 2:16 PM, Venu Busireddy wrote:
> On 2022-01-06 13:06:13 -0600, Tom Lendacky wrote:
>> On 1/6/22 11:40 AM, Venu Busireddy wrote:
>>> On 2022-01-05 15:39:22 -0600, Brijesh Singh wrote:
>>>>
>>>>
>>>> On 1/5/22 2:27 PM, Dave Hansen wrote:
>>>>> On 1/5/22 11:52, Brijesh Singh wrote:
>>>>>>>> for (; vaddr < vaddr_end; vaddr += PMD_SIZE) {
>>>>>>>> + /*
>>>>>>>> + * When SEV-SNP is active then transition the
>>>>>>>> page to shared in the RMP
>>>>>>>> + * table so that it is consistent with the page
>>>>>>>> table attribute change.
>>>>>>>> + */
>>>>>>>> + early_snp_set_memory_shared(__pa(vaddr),
>>>>>>>> __pa(vaddr), PTRS_PER_PMD);
>>>>>>>
>>>>>>> Shouldn't the first argument be vaddr as below?
>>>>>>
>>>>>> Nope, sme_postprocess_startup() is called while we are fixing the
>>>>>> initial page table and running with identity mapping (so va == pa).
>>>>>
>>>>> I'm not sure I've ever seen a line of code that wanted a comment so badly.
>>>>
>>>> The early_snp_set_memory_shared() call the PVALIDATE instruction to clear
>>>> the validated bit from the BSS region. The PVALIDATE instruction needs a
>>>> virtual address, so we need to use the identity mapped virtual address so
>>>> that PVALIDATE can clear the validated bit. I will add more comments to
>>>> clarify it.
>>>
>>> Looking forward to see your final comments explaining this. I can't
>>> still follow why, when PVALIDATE needs the virtual address, we are doing
>>> a __pa() on the vaddr.
>>
>> It's because of the phase of booting that the kernel is in. At this point,
>> the kernel is running in identity mapped mode (VA == PA). The
>> __start_bss_decrypted address is a regular kernel address, e.g. for the
>> kernel I'm on it is 0xffffffffa7600000. Since the PVALIDATE instruction
>> requires a valid virtual address, the code needs to perform a __pa() against
>> __start_bss_decrypted to get the identity mapped virtual address that is
>> currently in place.
>
> Perhaps my confusion stems from the fact that __pa(x) is defined either
> as "((unsigned long ) (x))" (for the cases where paddr and vaddr are
> same), or as "__phys_addr((unsigned long )(x))", where a vaddr needs to
> be converted to a paddr. If the paddr and vaddr are same in our case,
> what exactly is the _pa(vaddr) doing to the vaddr?
But they are not the same and the head64.c file is compiled without
defining a value for __pa(), so __pa() is __phys_addr((unsigned long)(x)).
The virtual address value of __start_bss_decrypted, for me, is
0xffffffffa7600000, and that does not equal the physical address (take a
look at your /proc/kallsyms). However, since the code is running identity
mapped and with a page table without kernel virtual addresses, it cannot
use that value. It needs to convert that value to the identity mapped
virtual address and that is done using __pa(). Only after using __pa() on
__start_bss_decrypted, do you get a virtual address that maps to and is
equal to the physical address.
You may want to step through the boot code using KVM to see what the
environment is and why things are done the way they are.
Thanks,
Tom
>
> Venu
>
^ permalink raw reply [flat|nested] 183+ messages in thread
* [PATCH v8 14/40] x86/kernel: Validate rom memory before accessing when SEV-SNP is active
2021-12-10 15:42 [PATCH v8 00/40] Add AMD Secure Nested Paging (SEV-SNP) Guest Support Brijesh Singh
` (12 preceding siblings ...)
2021-12-10 15:43 ` [PATCH v8 13/40] x86/kernel: Make the bss.decrypted section shared in RMP table Brijesh Singh
@ 2021-12-10 15:43 ` Brijesh Singh
2021-12-28 15:40 ` Borislav Petkov
2021-12-10 15:43 ` [PATCH v8 15/40] x86/mm: Add support to validate memory when changing C-bit Brijesh Singh
` (26 subsequent siblings)
40 siblings, 1 reply; 183+ messages in thread
From: Brijesh Singh @ 2021-12-10 15:43 UTC (permalink / raw)
To: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm
Cc: Thomas Gleixner, Ingo Molnar, Joerg Roedel, Tom Lendacky,
H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy, Brijesh Singh
The probe_roms() access the memory range (0xc0000 - 0x10000) to probe
various ROMs. The memory range is not part of the E820 system RAM
range. The memory range is mapped as private (i.e encrypted) in page
table.
When SEV-SNP is active, all the private memory must be validated before
the access. The ROM range was not part of E820 map, so the guest BIOS
did not validate it. An access to invalidated memory will cause a VC
exception. The guest does not support handling not-validated VC exception
yet, so validate the ROM memory regions before it is accessed.
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
arch/x86/kernel/probe_roms.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kernel/probe_roms.c b/arch/x86/kernel/probe_roms.c
index 36e84d904260..d19a80565252 100644
--- a/arch/x86/kernel/probe_roms.c
+++ b/arch/x86/kernel/probe_roms.c
@@ -21,6 +21,7 @@
#include <asm/sections.h>
#include <asm/io.h>
#include <asm/setup_arch.h>
+#include <asm/sev.h>
static struct resource system_rom_resource = {
.name = "System ROM",
@@ -197,11 +198,21 @@ static int __init romchecksum(const unsigned char *rom, unsigned long length)
void __init probe_roms(void)
{
- const unsigned char *rom;
unsigned long start, length, upper;
+ const unsigned char *rom;
unsigned char c;
int i;
+ /*
+ * The ROM memory is not part of the E820 system RAM and is not pre-validated
+ * by the BIOS. The kernel page table maps the ROM region as encrypted memory,
+ * the SEV-SNP requires the encrypted memory must be validated before the
+ * access. Validate the ROM before accessing it.
+ */
+ snp_prep_memory(video_rom_resource.start,
+ ((system_rom_resource.end + 1) - video_rom_resource.start),
+ SNP_PAGE_STATE_PRIVATE);
+
/* video rom */
upper = adapter_rom_resources[0].start;
for (start = video_rom_resource.start; start < upper; start += 2048) {
--
2.25.1
^ permalink raw reply related [flat|nested] 183+ messages in thread* Re: [PATCH v8 14/40] x86/kernel: Validate rom memory before accessing when SEV-SNP is active
2021-12-10 15:43 ` [PATCH v8 14/40] x86/kernel: Validate rom memory before accessing when SEV-SNP is active Brijesh Singh
@ 2021-12-28 15:40 ` Borislav Petkov
0 siblings, 0 replies; 183+ messages in thread
From: Borislav Petkov @ 2021-12-28 15:40 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Michael Roth, Vlastimil Babka,
Kirill A . Shutemov, Andi Kleen, Dr . David Alan Gilbert,
tony.luck, marcorr, sathyanarayanan.kuppuswamy
On Fri, Dec 10, 2021 at 09:43:06AM -0600, Brijesh Singh wrote:
> Subject: Re: [PATCH v8 14/40] x86/kernel: Validate rom memory before accessing when SEV-SNP is active
s/rom/ROM/
> The probe_roms() access the memory range (0xc0000 - 0x10000) to probe
"probe_roms() accesses... "
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 183+ messages in thread
* [PATCH v8 15/40] x86/mm: Add support to validate memory when changing C-bit
2021-12-10 15:42 [PATCH v8 00/40] Add AMD Secure Nested Paging (SEV-SNP) Guest Support Brijesh Singh
` (13 preceding siblings ...)
2021-12-10 15:43 ` [PATCH v8 14/40] x86/kernel: Validate rom memory before accessing when SEV-SNP is active Brijesh Singh
@ 2021-12-10 15:43 ` Brijesh Singh
2021-12-29 11:09 ` Borislav Petkov
2022-01-04 22:31 ` Venu Busireddy
2021-12-10 15:43 ` [PATCH v8 16/40] KVM: SVM: Define sev_features and vmpl field in the VMSA Brijesh Singh
` (25 subsequent siblings)
40 siblings, 2 replies; 183+ messages in thread
From: Brijesh Singh @ 2021-12-10 15:43 UTC (permalink / raw)
To: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm
Cc: Thomas Gleixner, Ingo Molnar, Joerg Roedel, Tom Lendacky,
H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy, Brijesh Singh
The set_memory_{encrypt,decrypt}() are used for changing the pages
from decrypted (shared) to encrypted (private) and vice versa.
When SEV-SNP is active, the page state transition needs to go through
additional steps.
If the page is transitioned from shared to private, then perform the
following after the encryption attribute is set in the page table:
1. Issue the page state change VMGEXIT to add the memory region in
the RMP table.
2. Validate the memory region after the RMP entry is added.
To maintain the security guarantees, if the page is transitioned from
private to shared, then perform the following before encryption attribute
is removed from the page table:
1. Invalidate the page.
2. Issue the page state change VMGEXIT to remove the page from RMP table.
To change the page state in the RMP table, use the Page State Change
VMGEXIT defined in the GHCB specification.
The GHCB specification provides the flexibility to use either 4K or 2MB
page size in during the page state change (PSC) request. For now use the
4K page size for all the PSC until page size tracking is supported in the
kernel.
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
arch/x86/include/asm/sev-common.h | 22 ++++
arch/x86/include/asm/sev.h | 4 +
arch/x86/include/asm/svm.h | 4 +-
arch/x86/include/uapi/asm/svm.h | 2 +
arch/x86/kernel/sev.c | 161 +++++++++++++++++++++++++++++-
arch/x86/mm/pat/set_memory.c | 15 +++
6 files changed, 204 insertions(+), 4 deletions(-)
diff --git a/arch/x86/include/asm/sev-common.h b/arch/x86/include/asm/sev-common.h
index 6dc27963690e..123a96f7dff2 100644
--- a/arch/x86/include/asm/sev-common.h
+++ b/arch/x86/include/asm/sev-common.h
@@ -105,6 +105,28 @@ enum psc_op {
#define GHCB_HV_FT_SNP BIT_ULL(0)
+/* SNP Page State Change NAE event */
+#define VMGEXIT_PSC_MAX_ENTRY 253
+
+struct psc_hdr {
+ u16 cur_entry;
+ u16 end_entry;
+ u32 reserved;
+} __packed;
+
+struct psc_entry {
+ u64 cur_page : 12,
+ gfn : 40,
+ operation : 4,
+ pagesize : 1,
+ reserved : 7;
+} __packed;
+
+struct snp_psc_desc {
+ struct psc_hdr hdr;
+ struct psc_entry entries[VMGEXIT_PSC_MAX_ENTRY];
+} __packed;
+
#define GHCB_MSR_TERM_REQ 0x100
#define GHCB_MSR_TERM_REASON_SET_POS 12
#define GHCB_MSR_TERM_REASON_SET_MASK 0xf
diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index eec2e1b9d557..f5d0569fd02b 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h
@@ -128,6 +128,8 @@ void __init early_snp_set_memory_private(unsigned long vaddr, unsigned long padd
void __init early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr,
unsigned int npages);
void __init snp_prep_memory(unsigned long paddr, unsigned int sz, enum psc_op op);
+void snp_set_memory_shared(unsigned long vaddr, unsigned int npages);
+void snp_set_memory_private(unsigned long vaddr, unsigned int npages);
#else
static inline void sev_es_ist_enter(struct pt_regs *regs) { }
static inline void sev_es_ist_exit(void) { }
@@ -142,6 +144,8 @@ early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr, unsigned
static inline void __init
early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr, unsigned int npages) { }
static inline void __init snp_prep_memory(unsigned long paddr, unsigned int sz, enum psc_op op) { }
+static inline void snp_set_memory_shared(unsigned long vaddr, unsigned int npages) { }
+static inline void snp_set_memory_private(unsigned long vaddr, unsigned int npages) { }
#endif
#endif
diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index b00dbc5fac2b..d3277486a6c0 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -309,11 +309,13 @@ struct vmcb_save_area {
u64 x87_state_gpa;
} __packed;
+#define GHCB_SHARED_BUF_SIZE 2032
+
struct ghcb {
struct vmcb_save_area save;
u8 reserved_save[2048 - sizeof(struct vmcb_save_area)];
- u8 shared_buffer[2032];
+ u8 shared_buffer[GHCB_SHARED_BUF_SIZE];
u8 reserved_1[10];
u16 protocol_version; /* negotiated SEV-ES/GHCB protocol version */
diff --git a/arch/x86/include/uapi/asm/svm.h b/arch/x86/include/uapi/asm/svm.h
index b0ad00f4c1e1..0dcdb6e0c913 100644
--- a/arch/x86/include/uapi/asm/svm.h
+++ b/arch/x86/include/uapi/asm/svm.h
@@ -108,6 +108,7 @@
#define SVM_VMGEXIT_AP_JUMP_TABLE 0x80000005
#define SVM_VMGEXIT_SET_AP_JUMP_TABLE 0
#define SVM_VMGEXIT_GET_AP_JUMP_TABLE 1
+#define SVM_VMGEXIT_PSC 0x80000010
#define SVM_VMGEXIT_HV_FEATURES 0x8000fffd
#define SVM_VMGEXIT_UNSUPPORTED_EVENT 0x8000ffff
@@ -219,6 +220,7 @@
{ SVM_VMGEXIT_NMI_COMPLETE, "vmgexit_nmi_complete" }, \
{ SVM_VMGEXIT_AP_HLT_LOOP, "vmgexit_ap_hlt_loop" }, \
{ SVM_VMGEXIT_AP_JUMP_TABLE, "vmgexit_ap_jump_table" }, \
+ { SVM_VMGEXIT_PSC, "vmgexit_page_state_change" }, \
{ SVM_VMGEXIT_HV_FEATURES, "vmgexit_hypervisor_feature" }, \
{ SVM_EXIT_ERR, "invalid_guest_state" }
diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c
index 2971aa280ce6..35c772bf9f6c 100644
--- a/arch/x86/kernel/sev.c
+++ b/arch/x86/kernel/sev.c
@@ -574,7 +574,7 @@ static void pvalidate_pages(unsigned long vaddr, unsigned int npages, bool valid
}
}
-static void __init early_set_page_state(unsigned long paddr, unsigned int npages, enum psc_op op)
+static void __init early_set_pages_state(unsigned long paddr, unsigned int npages, enum psc_op op)
{
unsigned long paddr_end;
u64 val;
@@ -622,7 +622,7 @@ void __init early_snp_set_memory_private(unsigned long vaddr, unsigned long padd
* Ask the hypervisor to mark the memory pages as private in the RMP
* table.
*/
- early_set_page_state(paddr, npages, SNP_PAGE_STATE_PRIVATE);
+ early_set_pages_state(paddr, npages, SNP_PAGE_STATE_PRIVATE);
/* Validate the memory pages after they've been added in the RMP table. */
pvalidate_pages(vaddr, npages, 1);
@@ -641,7 +641,7 @@ void __init early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr
pvalidate_pages(vaddr, npages, 0);
/* Ask hypervisor to mark the memory pages shared in the RMP table. */
- early_set_page_state(paddr, npages, SNP_PAGE_STATE_SHARED);
+ early_set_pages_state(paddr, npages, SNP_PAGE_STATE_SHARED);
}
void __init snp_prep_memory(unsigned long paddr, unsigned int sz, enum psc_op op)
@@ -659,6 +659,161 @@ void __init snp_prep_memory(unsigned long paddr, unsigned int sz, enum psc_op op
WARN(1, "invalid memory op %d\n", op);
}
+static int vmgexit_psc(struct snp_psc_desc *desc)
+{
+ int cur_entry, end_entry, ret = 0;
+ struct snp_psc_desc *data;
+ struct ghcb_state state;
+ unsigned long flags;
+ struct ghcb *ghcb;
+
+ /* __sev_get_ghcb() need to run with IRQs disabled because it using per-cpu GHCB */
+ local_irq_save(flags);
+
+ ghcb = __sev_get_ghcb(&state);
+ if (unlikely(!ghcb))
+ panic("SEV-SNP: Failed to get GHCB\n");
+
+ /* Copy the input desc into GHCB shared buffer */
+ data = (struct snp_psc_desc *)ghcb->shared_buffer;
+ memcpy(ghcb->shared_buffer, desc, min_t(int, GHCB_SHARED_BUF_SIZE, sizeof(*desc)));
+
+ /*
+ * As per the GHCB specification, the hypervisor can resume the guest
+ * before processing all the entries. Check whether all the entries
+ * are processed. If not, then keep retrying.
+ *
+ * The stragtegy here is to wait for the hypervisor to change the page
+ * state in the RMP table before guest accesses the memory pages. If the
+ * page state change was not successful, then later memory access will result
+ * in a crash.
+ */
+ cur_entry = data->hdr.cur_entry;
+ end_entry = data->hdr.end_entry;
+
+ while (data->hdr.cur_entry <= data->hdr.end_entry) {
+ ghcb_set_sw_scratch(ghcb, (u64)__pa(data));
+
+ ret = sev_es_ghcb_hv_call(ghcb, true, NULL, SVM_VMGEXIT_PSC, 0, 0);
+
+ /*
+ * Page State Change VMGEXIT can pass error code through
+ * exit_info_2.
+ */
+ if (WARN(ret || ghcb->save.sw_exit_info_2,
+ "SEV-SNP: PSC failed ret=%d exit_info_2=%llx\n",
+ ret, ghcb->save.sw_exit_info_2)) {
+ ret = 1;
+ goto out;
+ }
+
+ /* Verify that reserved bit is not set */
+ if (WARN(data->hdr.reserved, "Reserved bit is set in the PSC header\n")) {
+ ret = 1;
+ goto out;
+ }
+
+ /*
+ * Sanity check that entry processing is not going backward.
+ * This will happen only if hypervisor is tricking us.
+ */
+ if (WARN(data->hdr.end_entry > end_entry || cur_entry > data->hdr.cur_entry,
+"SEV-SNP: PSC processing going backward, end_entry %d (got %d) cur_entry %d (got %d)\n",
+ end_entry, data->hdr.end_entry, cur_entry, data->hdr.cur_entry)) {
+ ret = 1;
+ goto out;
+ }
+ }
+
+out:
+ __sev_put_ghcb(&state);
+ local_irq_restore(flags);
+
+ return ret;
+}
+
+static void __set_pages_state(struct snp_psc_desc *data, unsigned long vaddr,
+ unsigned long vaddr_end, int op)
+{
+ struct psc_hdr *hdr;
+ struct psc_entry *e;
+ unsigned long pfn;
+ int i;
+
+ hdr = &data->hdr;
+ e = data->entries;
+
+ memset(data, 0, sizeof(*data));
+ i = 0;
+
+ while (vaddr < vaddr_end) {
+ if (is_vmalloc_addr((void *)vaddr))
+ pfn = vmalloc_to_pfn((void *)vaddr);
+ else
+ pfn = __pa(vaddr) >> PAGE_SHIFT;
+
+ e->gfn = pfn;
+ e->operation = op;
+ hdr->end_entry = i;
+ e->pagesize = RMP_PG_SIZE_4K;
+
+ vaddr = vaddr + PAGE_SIZE;
+ e++;
+ i++;
+ }
+
+ if (vmgexit_psc(data))
+ sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PSC);
+}
+
+static void set_pages_state(unsigned long vaddr, unsigned int npages, int op)
+{
+ unsigned long vaddr_end, next_vaddr;
+ struct snp_psc_desc *desc;
+
+ desc = kmalloc(sizeof(*desc), GFP_KERNEL_ACCOUNT);
+ if (!desc)
+ panic("SEV-SNP: failed to allocate memory for PSC descriptor\n");
+
+ vaddr = vaddr & PAGE_MASK;
+ vaddr_end = vaddr + (npages << PAGE_SHIFT);
+
+ while (vaddr < vaddr_end) {
+ /*
+ * Calculate the last vaddr that can be fit in one
+ * struct snp_psc_desc.
+ */
+ next_vaddr = min_t(unsigned long, vaddr_end,
+ (VMGEXIT_PSC_MAX_ENTRY * PAGE_SIZE) + vaddr);
+
+ __set_pages_state(desc, vaddr, next_vaddr, op);
+
+ vaddr = next_vaddr;
+ }
+
+ kfree(desc);
+}
+
+void snp_set_memory_shared(unsigned long vaddr, unsigned int npages)
+{
+ if (!cc_platform_has(CC_ATTR_SEV_SNP))
+ return;
+
+ pvalidate_pages(vaddr, npages, 0);
+
+ set_pages_state(vaddr, npages, SNP_PAGE_STATE_SHARED);
+}
+
+void snp_set_memory_private(unsigned long vaddr, unsigned int npages)
+{
+ if (!cc_platform_has(CC_ATTR_SEV_SNP))
+ return;
+
+ set_pages_state(vaddr, npages, SNP_PAGE_STATE_PRIVATE);
+
+ pvalidate_pages(vaddr, npages, 1);
+}
+
int sev_es_setup_ap_jump_table(struct real_mode_header *rmh)
{
u16 startup_cs, startup_ip;
diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
index b4072115c8ef..5dc17d446204 100644
--- a/arch/x86/mm/pat/set_memory.c
+++ b/arch/x86/mm/pat/set_memory.c
@@ -32,6 +32,7 @@
#include <asm/set_memory.h>
#include <asm/hyperv-tlfs.h>
#include <asm/mshyperv.h>
+#include <asm/sev.h>
#include "../mm_internal.h"
@@ -2012,8 +2013,22 @@ static int __set_memory_enc_pgtable(unsigned long addr, int numpages, bool enc)
*/
cpa_flush(&cpa, !this_cpu_has(X86_FEATURE_SME_COHERENT));
+ /*
+ * To maintain the security guarantees of SEV-SNP guest invalidate the memory
+ * before clearing the encryption attribute.
+ */
+ if (!enc)
+ snp_set_memory_shared(addr, numpages);
+
ret = __change_page_attr_set_clr(&cpa, 1);
+ /*
+ * Now that memory is mapped encrypted in the page table, validate it
+ * so that is consistent with the above page state.
+ */
+ if (!ret && enc)
+ snp_set_memory_private(addr, numpages);
+
/*
* After changing the encryption attribute, we need to flush TLBs again
* in case any speculative TLB caching occurred (but no need to flush
--
2.25.1
^ permalink raw reply related [flat|nested] 183+ messages in thread* Re: [PATCH v8 15/40] x86/mm: Add support to validate memory when changing C-bit
2021-12-10 15:43 ` [PATCH v8 15/40] x86/mm: Add support to validate memory when changing C-bit Brijesh Singh
@ 2021-12-29 11:09 ` Borislav Petkov
2022-01-04 22:31 ` Venu Busireddy
1 sibling, 0 replies; 183+ messages in thread
From: Borislav Petkov @ 2021-12-29 11:09 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Michael Roth, Vlastimil Babka,
Kirill A . Shutemov, Andi Kleen, Dr . David Alan Gilbert,
tony.luck, marcorr, sathyanarayanan.kuppuswamy
On Fri, Dec 10, 2021 at 09:43:07AM -0600, Brijesh Singh wrote:
> The set_memory_{encrypt,decrypt}() are used for changing the pages
$ git grep -E "set_memory_decrypt\W"
$
Please check all your commit messages whether you're quoting the proper
functions.
> from decrypted (shared) to encrypted (private) and vice versa.
> When SEV-SNP is active, the page state transition needs to go through
> additional steps.
... "done by the guest."
I think it is important to state here who's supposed to do those
additional steps.
...
> @@ -659,6 +659,161 @@ void __init snp_prep_memory(unsigned long paddr, unsigned int sz, enum psc_op op
> WARN(1, "invalid memory op %d\n", op);
> }
>
> +static int vmgexit_psc(struct snp_psc_desc *desc)
> +{
> + int cur_entry, end_entry, ret = 0;
> + struct snp_psc_desc *data;
> + struct ghcb_state state;
> + unsigned long flags;
> + struct ghcb *ghcb;
> +
> + /* __sev_get_ghcb() need to run with IRQs disabled because it using per-cpu GHCB */
"... because it uses a per-CPU GHCB."
> + local_irq_save(flags);
> +
> + ghcb = __sev_get_ghcb(&state);
> + if (unlikely(!ghcb))
> + panic("SEV-SNP: Failed to get GHCB\n");
__sev_get_ghcb() will already panic if even the backup GHCB is active so
you don't need to panic here too - just check the retval.
> + /* Copy the input desc into GHCB shared buffer */
> + data = (struct snp_psc_desc *)ghcb->shared_buffer;
> + memcpy(ghcb->shared_buffer, desc, min_t(int, GHCB_SHARED_BUF_SIZE, sizeof(*desc)));
> +
> + /*
> + * As per the GHCB specification, the hypervisor can resume the guest
> + * before processing all the entries. Check whether all the entries
> + * are processed. If not, then keep retrying.
> + *
> + * The stragtegy here is to wait for the hypervisor to change the page
+ * The stragtegy here is to wait for the hypervisor to change the page
Unknown word [stragtegy] in comment, suggestions:
['strategy', 'strategist']
> + * state in the RMP table before guest accesses the memory pages. If the
> + * page state change was not successful, then later memory access will result
> + * in a crash.
> + */
> + cur_entry = data->hdr.cur_entry;
> + end_entry = data->hdr.end_entry;
> +
> + while (data->hdr.cur_entry <= data->hdr.end_entry) {
> + ghcb_set_sw_scratch(ghcb, (u64)__pa(data));
> +
Add a comment here:
/* This will advance the shared buffer data points to. */
I had asked about it already but nada:
"So then you *absoulutely* want to use data->hdr everywhere and then also
write why in the comment above the check that data gets updated by the
HV call."
> + ret = sev_es_ghcb_hv_call(ghcb, true, NULL, SVM_VMGEXIT_PSC, 0, 0);
> +
> + /*
> + * Page State Change VMGEXIT can pass error code through
> + * exit_info_2.
> + */
> + if (WARN(ret || ghcb->save.sw_exit_info_2,
> + "SEV-SNP: PSC failed ret=%d exit_info_2=%llx\n",
> + ret, ghcb->save.sw_exit_info_2)) {
> + ret = 1;
> + goto out;
> + }
> +
> + /* Verify that reserved bit is not set */
> + if (WARN(data->hdr.reserved, "Reserved bit is set in the PSC header\n")) {
> + ret = 1;
> + goto out;
> + }
> +
> + /*
> + * Sanity check that entry processing is not going backward.
"... backwards."
> + * This will happen only if hypervisor is tricking us.
> + */
> + if (WARN(data->hdr.end_entry > end_entry || cur_entry > data->hdr.cur_entry,
> +"SEV-SNP: PSC processing going backward, end_entry %d (got %d) cur_entry %d (got %d)\n",
> + end_entry, data->hdr.end_entry, cur_entry, data->hdr.cur_entry)) {
> + ret = 1;
> + goto out;
> + }
> + }
> +
> +out:
> + __sev_put_ghcb(&state);
> + local_irq_restore(flags);
> +
> + return ret;
> +}
> +
> +static void __set_pages_state(struct snp_psc_desc *data, unsigned long vaddr,
> + unsigned long vaddr_end, int op)
> +{
> + struct psc_hdr *hdr;
> + struct psc_entry *e;
> + unsigned long pfn;
> + int i;
> +
> + hdr = &data->hdr;
> + e = data->entries;
> +
> + memset(data, 0, sizeof(*data));
> + i = 0;
> +
> + while (vaddr < vaddr_end) {
> + if (is_vmalloc_addr((void *)vaddr))
> + pfn = vmalloc_to_pfn((void *)vaddr);
> + else
> + pfn = __pa(vaddr) >> PAGE_SHIFT;
> +
> + e->gfn = pfn;
> + e->operation = op;
> + hdr->end_entry = i;
/*
* Current SNP implementation doesn't keep track of the page size so use
* 4K for simplicity.
*/
> + e->pagesize = RMP_PG_SIZE_4K;
> +
> + vaddr = vaddr + PAGE_SIZE;
> + e++;
> + i++;
> + }
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 15/40] x86/mm: Add support to validate memory when changing C-bit
2021-12-10 15:43 ` [PATCH v8 15/40] x86/mm: Add support to validate memory when changing C-bit Brijesh Singh
2021-12-29 11:09 ` Borislav Petkov
@ 2022-01-04 22:31 ` Venu Busireddy
1 sibling, 0 replies; 183+ messages in thread
From: Venu Busireddy @ 2022-01-04 22:31 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2021-12-10 09:43:07 -0600, Brijesh Singh wrote:
> The set_memory_{encrypt,decrypt}() are used for changing the pages
s/set_memory_{encrypt,decrypt}/snp_set_memory_{shared,private}/
> from decrypted (shared) to encrypted (private) and vice versa.
> When SEV-SNP is active, the page state transition needs to go through
> additional steps.
>
> If the page is transitioned from shared to private, then perform the
> following after the encryption attribute is set in the page table:
>
> 1. Issue the page state change VMGEXIT to add the memory region in
> the RMP table.
> 2. Validate the memory region after the RMP entry is added.
>
> To maintain the security guarantees, if the page is transitioned from
> private to shared, then perform the following before encryption attribute
> is removed from the page table:
>
> 1. Invalidate the page.
> 2. Issue the page state change VMGEXIT to remove the page from RMP table.
>
> To change the page state in the RMP table, use the Page State Change
> VMGEXIT defined in the GHCB specification.
>
> The GHCB specification provides the flexibility to use either 4K or 2MB
> page size in during the page state change (PSC) request. For now use the
> 4K page size for all the PSC until page size tracking is supported in the
> kernel.
>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
[snip]
> diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c
> index 2971aa280ce6..35c772bf9f6c 100644
> --- a/arch/x86/kernel/sev.c
> +++ b/arch/x86/kernel/sev.c
> @@ -574,7 +574,7 @@ static void pvalidate_pages(unsigned long vaddr, unsigned int npages, bool valid
> }
> }
>
> -static void __init early_set_page_state(unsigned long paddr, unsigned int npages, enum psc_op op)
> +static void __init early_set_pages_state(unsigned long paddr, unsigned int npages, enum psc_op op)
Is there a need to change the name? "npages" can take a value of 1 too.
Hence, early_set_page_state() appears to be a better name!
> + /*
> + * Page State Change VMGEXIT can pass error code through
> + * exit_info_2.
> + */
Collapse into one line?
> +void snp_set_memory_shared(unsigned long vaddr, unsigned int npages)
> +{
> + if (!cc_platform_has(CC_ATTR_SEV_SNP))
> + return;
> +
> + pvalidate_pages(vaddr, npages, 0);
Replace '0' with "false"?
> +
> + set_pages_state(vaddr, npages, SNP_PAGE_STATE_SHARED);
> +}
> +
> +void snp_set_memory_private(unsigned long vaddr, unsigned int npages)
> +{
> + if (!cc_platform_has(CC_ATTR_SEV_SNP))
> + return;
> +
> + set_pages_state(vaddr, npages, SNP_PAGE_STATE_PRIVATE);
> +
> + pvalidate_pages(vaddr, npages, 1);
Replace '1' with "true"?
Venu
^ permalink raw reply [flat|nested] 183+ messages in thread
* [PATCH v8 16/40] KVM: SVM: Define sev_features and vmpl field in the VMSA
2021-12-10 15:42 [PATCH v8 00/40] Add AMD Secure Nested Paging (SEV-SNP) Guest Support Brijesh Singh
` (14 preceding siblings ...)
2021-12-10 15:43 ` [PATCH v8 15/40] x86/mm: Add support to validate memory when changing C-bit Brijesh Singh
@ 2021-12-10 15:43 ` Brijesh Singh
2022-01-04 22:59 ` Venu Busireddy
2021-12-10 15:43 ` [PATCH v8 17/40] KVM: SVM: Create a separate mapping for the SEV-ES save area Brijesh Singh
` (24 subsequent siblings)
40 siblings, 1 reply; 183+ messages in thread
From: Brijesh Singh @ 2021-12-10 15:43 UTC (permalink / raw)
To: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm
Cc: Thomas Gleixner, Ingo Molnar, Joerg Roedel, Tom Lendacky,
H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy, Brijesh Singh
The hypervisor uses the sev_features field (offset 3B0h) in the Save State
Area to control the SEV-SNP guest features such as SNPActive, vTOM,
ReflectVC etc. An SEV-SNP guest can read the SEV_FEATURES fields through
the SEV_STATUS MSR.
While at it, update the dump_vmcb() to log the VMPL level.
See APM2 Table 15-34 and B-4 for more details.
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
arch/x86/include/asm/svm.h | 6 ++++--
arch/x86/kvm/svm/svm.c | 4 ++--
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index d3277486a6c0..c3fad5172584 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -238,7 +238,8 @@ struct vmcb_save_area {
struct vmcb_seg ldtr;
struct vmcb_seg idtr;
struct vmcb_seg tr;
- u8 reserved_1[43];
+ u8 reserved_1[42];
+ u8 vmpl;
u8 cpl;
u8 reserved_2[4];
u64 efer;
@@ -303,7 +304,8 @@ struct vmcb_save_area {
u64 sw_exit_info_1;
u64 sw_exit_info_2;
u64 sw_scratch;
- u8 reserved_11[56];
+ u64 sev_features;
+ u8 reserved_11[48];
u64 xcr0;
u8 valid_bitmap[16];
u64 x87_state_gpa;
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 65707bee208d..d3a6356fa1af 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -3290,8 +3290,8 @@ static void dump_vmcb(struct kvm_vcpu *vcpu)
"tr:",
save01->tr.selector, save01->tr.attrib,
save01->tr.limit, save01->tr.base);
- pr_err("cpl: %d efer: %016llx\n",
- save->cpl, save->efer);
+ pr_err("vmpl: %d cpl: %d efer: %016llx\n",
+ save->vmpl, save->cpl, save->efer);
pr_err("%-15s %016llx %-13s %016llx\n",
"cr0:", save->cr0, "cr2:", save->cr2);
pr_err("%-15s %016llx %-13s %016llx\n",
--
2.25.1
^ permalink raw reply related [flat|nested] 183+ messages in thread* Re: [PATCH v8 16/40] KVM: SVM: Define sev_features and vmpl field in the VMSA
2021-12-10 15:43 ` [PATCH v8 16/40] KVM: SVM: Define sev_features and vmpl field in the VMSA Brijesh Singh
@ 2022-01-04 22:59 ` Venu Busireddy
0 siblings, 0 replies; 183+ messages in thread
From: Venu Busireddy @ 2022-01-04 22:59 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2021-12-10 09:43:08 -0600, Brijesh Singh wrote:
> The hypervisor uses the sev_features field (offset 3B0h) in the Save State
> Area to control the SEV-SNP guest features such as SNPActive, vTOM,
> ReflectVC etc. An SEV-SNP guest can read the SEV_FEATURES fields through
> the SEV_STATUS MSR.
>
> While at it, update the dump_vmcb() to log the VMPL level.
>
> See APM2 Table 15-34 and B-4 for more details.
>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Venu Busireddy <venu.busireddy@oracle.com>
> ---
> arch/x86/include/asm/svm.h | 6 ++++--
> arch/x86/kvm/svm/svm.c | 4 ++--
> 2 files changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
> index d3277486a6c0..c3fad5172584 100644
> --- a/arch/x86/include/asm/svm.h
> +++ b/arch/x86/include/asm/svm.h
> @@ -238,7 +238,8 @@ struct vmcb_save_area {
> struct vmcb_seg ldtr;
> struct vmcb_seg idtr;
> struct vmcb_seg tr;
> - u8 reserved_1[43];
> + u8 reserved_1[42];
> + u8 vmpl;
> u8 cpl;
> u8 reserved_2[4];
> u64 efer;
> @@ -303,7 +304,8 @@ struct vmcb_save_area {
> u64 sw_exit_info_1;
> u64 sw_exit_info_2;
> u64 sw_scratch;
> - u8 reserved_11[56];
> + u64 sev_features;
> + u8 reserved_11[48];
> u64 xcr0;
> u8 valid_bitmap[16];
> u64 x87_state_gpa;
> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> index 65707bee208d..d3a6356fa1af 100644
> --- a/arch/x86/kvm/svm/svm.c
> +++ b/arch/x86/kvm/svm/svm.c
> @@ -3290,8 +3290,8 @@ static void dump_vmcb(struct kvm_vcpu *vcpu)
> "tr:",
> save01->tr.selector, save01->tr.attrib,
> save01->tr.limit, save01->tr.base);
> - pr_err("cpl: %d efer: %016llx\n",
> - save->cpl, save->efer);
> + pr_err("vmpl: %d cpl: %d efer: %016llx\n",
^
Extra space?
> + save->vmpl, save->cpl, save->efer);
> pr_err("%-15s %016llx %-13s %016llx\n",
> "cr0:", save->cr0, "cr2:", save->cr2);
> pr_err("%-15s %016llx %-13s %016llx\n",
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 183+ messages in thread
* [PATCH v8 17/40] KVM: SVM: Create a separate mapping for the SEV-ES save area
2021-12-10 15:42 [PATCH v8 00/40] Add AMD Secure Nested Paging (SEV-SNP) Guest Support Brijesh Singh
` (15 preceding siblings ...)
2021-12-10 15:43 ` [PATCH v8 16/40] KVM: SVM: Define sev_features and vmpl field in the VMSA Brijesh Singh
@ 2021-12-10 15:43 ` Brijesh Singh
2021-12-30 12:19 ` Borislav Petkov
2022-01-05 1:38 ` Venu Busireddy
2021-12-10 15:43 ` [PATCH v8 18/40] KVM: SVM: Create a separate mapping for the GHCB " Brijesh Singh
` (23 subsequent siblings)
40 siblings, 2 replies; 183+ messages in thread
From: Brijesh Singh @ 2021-12-10 15:43 UTC (permalink / raw)
To: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm
Cc: Thomas Gleixner, Ingo Molnar, Joerg Roedel, Tom Lendacky,
H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy, Brijesh Singh
The save area for SEV-ES/SEV-SNP guests, as used by the hardware, is
different from the save area of a non SEV-ES/SEV-SNP guest.
This is the first step in defining the multiple save areas to keep them
separate and ensuring proper operation amongst the different types of
guests. Create an SEV-ES/SEV-SNP save area and adjust usage to the new
save area definition where needed.
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
arch/x86/include/asm/svm.h | 83 +++++++++++++++++++++++++++++---------
arch/x86/kvm/svm/sev.c | 24 +++++------
arch/x86/kvm/svm/svm.h | 2 +-
3 files changed, 77 insertions(+), 32 deletions(-)
diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index c3fad5172584..3ce2e575a2de 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -227,6 +227,7 @@ struct vmcb_seg {
u64 base;
} __packed;
+/* Save area definition for legacy and SEV-MEM guests */
struct vmcb_save_area {
struct vmcb_seg es;
struct vmcb_seg cs;
@@ -243,8 +244,58 @@ struct vmcb_save_area {
u8 cpl;
u8 reserved_2[4];
u64 efer;
+ u8 reserved_3[112];
+ u64 cr4;
+ u64 cr3;
+ u64 cr0;
+ u64 dr7;
+ u64 dr6;
+ u64 rflags;
+ u64 rip;
+ u8 reserved_4[88];
+ u64 rsp;
+ u64 s_cet;
+ u64 ssp;
+ u64 isst_addr;
+ u64 rax;
+ u64 star;
+ u64 lstar;
+ u64 cstar;
+ u64 sfmask;
+ u64 kernel_gs_base;
+ u64 sysenter_cs;
+ u64 sysenter_esp;
+ u64 sysenter_eip;
+ u64 cr2;
+ u8 reserved_5[32];
+ u64 g_pat;
+ u64 dbgctl;
+ u64 br_from;
+ u64 br_to;
+ u64 last_excp_from;
+ u64 last_excp_to;
+ u8 reserved_6[72];
+ u32 spec_ctrl; /* Guest version of SPEC_CTRL at 0x2E0 */
+} __packed;
+
+/* Save area definition for SEV-ES and SEV-SNP guests */
+struct sev_es_save_area {
+ struct vmcb_seg es;
+ struct vmcb_seg cs;
+ struct vmcb_seg ss;
+ struct vmcb_seg ds;
+ struct vmcb_seg fs;
+ struct vmcb_seg gs;
+ struct vmcb_seg gdtr;
+ struct vmcb_seg ldtr;
+ struct vmcb_seg idtr;
+ struct vmcb_seg tr;
+ u8 reserved_1[43];
+ u8 cpl;
+ u8 reserved_2[4];
+ u64 efer;
u8 reserved_3[104];
- u64 xss; /* Valid for SEV-ES only */
+ u64 xss;
u64 cr4;
u64 cr3;
u64 cr0;
@@ -272,22 +323,14 @@ struct vmcb_save_area {
u64 br_to;
u64 last_excp_from;
u64 last_excp_to;
-
- /*
- * The following part of the save area is valid only for
- * SEV-ES guests when referenced through the GHCB or for
- * saving to the host save area.
- */
- u8 reserved_7[72];
- u32 spec_ctrl; /* Guest version of SPEC_CTRL at 0x2E0 */
- u8 reserved_7b[4];
+ u8 reserved_7[80];
u32 pkru;
- u8 reserved_7a[20];
- u64 reserved_8; /* rax already available at 0x01f8 */
+ u8 reserved_9[20];
+ u64 reserved_10; /* rax already available at 0x01f8 */
u64 rcx;
u64 rdx;
u64 rbx;
- u64 reserved_9; /* rsp already available at 0x01d8 */
+ u64 reserved_11; /* rsp already available at 0x01d8 */
u64 rbp;
u64 rsi;
u64 rdi;
@@ -299,13 +342,13 @@ struct vmcb_save_area {
u64 r13;
u64 r14;
u64 r15;
- u8 reserved_10[16];
+ u8 reserved_12[16];
u64 sw_exit_code;
u64 sw_exit_info_1;
u64 sw_exit_info_2;
u64 sw_scratch;
u64 sev_features;
- u8 reserved_11[48];
+ u8 reserved_13[48];
u64 xcr0;
u8 valid_bitmap[16];
u64 x87_state_gpa;
@@ -314,8 +357,8 @@ struct vmcb_save_area {
#define GHCB_SHARED_BUF_SIZE 2032
struct ghcb {
- struct vmcb_save_area save;
- u8 reserved_save[2048 - sizeof(struct vmcb_save_area)];
+ struct sev_es_save_area save;
+ u8 reserved_save[2048 - sizeof(struct sev_es_save_area)];
u8 shared_buffer[GHCB_SHARED_BUF_SIZE];
@@ -325,13 +368,15 @@ struct ghcb {
} __packed;
-#define EXPECTED_VMCB_SAVE_AREA_SIZE 1032
+#define EXPECTED_VMCB_SAVE_AREA_SIZE 740
+#define EXPECTED_SEV_ES_SAVE_AREA_SIZE 1032
#define EXPECTED_VMCB_CONTROL_AREA_SIZE 1024
#define EXPECTED_GHCB_SIZE PAGE_SIZE
static inline void __unused_size_checks(void)
{
BUILD_BUG_ON(sizeof(struct vmcb_save_area) != EXPECTED_VMCB_SAVE_AREA_SIZE);
+ BUILD_BUG_ON(sizeof(struct sev_es_save_area) != EXPECTED_SEV_ES_SAVE_AREA_SIZE);
BUILD_BUG_ON(sizeof(struct vmcb_control_area) != EXPECTED_VMCB_CONTROL_AREA_SIZE);
BUILD_BUG_ON(sizeof(struct ghcb) != EXPECTED_GHCB_SIZE);
}
@@ -401,7 +446,7 @@ struct vmcb {
/* GHCB Accessor functions */
#define GHCB_BITMAP_IDX(field) \
- (offsetof(struct vmcb_save_area, field) / sizeof(u64))
+ (offsetof(struct sev_es_save_area, field) / sizeof(u64))
#define DEFINE_GHCB_ACCESSORS(field) \
static inline bool ghcb_##field##_is_valid(const struct ghcb *ghcb) \
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 7656a2c5662a..63334af988af 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -558,12 +558,20 @@ static int sev_launch_update_data(struct kvm *kvm, struct kvm_sev_cmd *argp)
static int sev_es_sync_vmsa(struct vcpu_svm *svm)
{
- struct vmcb_save_area *save = &svm->vmcb->save;
+ struct sev_es_save_area *save = svm->sev_es.vmsa;
/* Check some debug related fields before encrypting the VMSA */
- if (svm->vcpu.guest_debug || (save->dr7 & ~DR7_FIXED_1))
+ if (svm->vcpu.guest_debug || (svm->vmcb->save.dr7 & ~DR7_FIXED_1))
return -EINVAL;
+ /*
+ * SEV-ES will use a VMSA that is pointed to by the VMCB, not
+ * the traditional VMSA that is part of the VMCB. Copy the
+ * traditional VMSA as it has been built so far (in prep
+ * for LAUNCH_UPDATE_VMSA) to be the initial SEV-ES state.
+ */
+ memcpy(save, &svm->vmcb->save, sizeof(svm->vmcb->save));
+
/* Sync registgers */
save->rax = svm->vcpu.arch.regs[VCPU_REGS_RAX];
save->rbx = svm->vcpu.arch.regs[VCPU_REGS_RBX];
@@ -591,14 +599,6 @@ static int sev_es_sync_vmsa(struct vcpu_svm *svm)
save->xss = svm->vcpu.arch.ia32_xss;
save->dr6 = svm->vcpu.arch.dr6;
- /*
- * SEV-ES will use a VMSA that is pointed to by the VMCB, not
- * the traditional VMSA that is part of the VMCB. Copy the
- * traditional VMSA as it has been built so far (in prep
- * for LAUNCH_UPDATE_VMSA) to be the initial SEV-ES state.
- */
- memcpy(svm->sev_es.vmsa, save, sizeof(*save));
-
return 0;
}
@@ -2904,7 +2904,7 @@ void sev_es_vcpu_reset(struct vcpu_svm *svm)
void sev_es_prepare_guest_switch(struct vcpu_svm *svm, unsigned int cpu)
{
struct svm_cpu_data *sd = per_cpu(svm_data, cpu);
- struct vmcb_save_area *hostsa;
+ struct sev_es_save_area *hostsa;
/*
* As an SEV-ES guest, hardware will restore the host state on VMEXIT,
@@ -2914,7 +2914,7 @@ void sev_es_prepare_guest_switch(struct vcpu_svm *svm, unsigned int cpu)
vmsave(__sme_page_pa(sd->save_area));
/* XCR0 is restored on VMEXIT, save the current host value */
- hostsa = (struct vmcb_save_area *)(page_address(sd->save_area) + 0x400);
+ hostsa = (struct sev_es_save_area *)(page_address(sd->save_area) + 0x400);
hostsa->xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK);
/* PKRU is restored on VMEXIT, save the current host value */
diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
index 1c7306c370fa..cecfcdb1a1b3 100644
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -127,7 +127,7 @@ struct svm_nested_state {
struct vcpu_sev_es_state {
/* SEV-ES support */
- struct vmcb_save_area *vmsa;
+ struct sev_es_save_area *vmsa;
struct ghcb *ghcb;
struct kvm_host_map ghcb_map;
bool received_first_sipi;
--
2.25.1
^ permalink raw reply related [flat|nested] 183+ messages in thread* Re: [PATCH v8 17/40] KVM: SVM: Create a separate mapping for the SEV-ES save area
2021-12-10 15:43 ` [PATCH v8 17/40] KVM: SVM: Create a separate mapping for the SEV-ES save area Brijesh Singh
@ 2021-12-30 12:19 ` Borislav Petkov
2022-01-05 1:38 ` Venu Busireddy
1 sibling, 0 replies; 183+ messages in thread
From: Borislav Petkov @ 2021-12-30 12:19 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Michael Roth, Vlastimil Babka,
Kirill A . Shutemov, Andi Kleen, Dr . David Alan Gilbert,
tony.luck, marcorr, sathyanarayanan.kuppuswamy
On Fri, Dec 10, 2021 at 09:43:09AM -0600, Brijesh Singh wrote:
> +/* Save area definition for SEV-ES and SEV-SNP guests */
> +struct sev_es_save_area {
I'd still call it sev_save_area for simplicity. And
EXPECTED_SEV_SAVE_AREA_SIZE and so on.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
^ permalink raw reply [flat|nested] 183+ messages in thread* Re: [PATCH v8 17/40] KVM: SVM: Create a separate mapping for the SEV-ES save area
2021-12-10 15:43 ` [PATCH v8 17/40] KVM: SVM: Create a separate mapping for the SEV-ES save area Brijesh Singh
2021-12-30 12:19 ` Borislav Petkov
@ 2022-01-05 1:38 ` Venu Busireddy
1 sibling, 0 replies; 183+ messages in thread
From: Venu Busireddy @ 2022-01-05 1:38 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2021-12-10 09:43:09 -0600, Brijesh Singh wrote:
> The save area for SEV-ES/SEV-SNP guests, as used by the hardware, is
> different from the save area of a non SEV-ES/SEV-SNP guest.
>
> This is the first step in defining the multiple save areas to keep them
> separate and ensuring proper operation amongst the different types of
> guests. Create an SEV-ES/SEV-SNP save area and adjust usage to the new
> save area definition where needed.
>
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Venu Busireddy <venu.busireddy@oracle.com>
> ---
> arch/x86/include/asm/svm.h | 83 +++++++++++++++++++++++++++++---------
> arch/x86/kvm/svm/sev.c | 24 +++++------
> arch/x86/kvm/svm/svm.h | 2 +-
> 3 files changed, 77 insertions(+), 32 deletions(-)
>
^ permalink raw reply [flat|nested] 183+ messages in thread
* [PATCH v8 18/40] KVM: SVM: Create a separate mapping for the GHCB save area
2021-12-10 15:42 [PATCH v8 00/40] Add AMD Secure Nested Paging (SEV-SNP) Guest Support Brijesh Singh
` (16 preceding siblings ...)
2021-12-10 15:43 ` [PATCH v8 17/40] KVM: SVM: Create a separate mapping for the SEV-ES save area Brijesh Singh
@ 2021-12-10 15:43 ` Brijesh Singh
2022-01-05 18:41 ` Venu Busireddy
2021-12-10 15:43 ` [PATCH v8 19/40] KVM: SVM: Update the SEV-ES save area mapping Brijesh Singh
` (22 subsequent siblings)
40 siblings, 1 reply; 183+ messages in thread
From: Brijesh Singh @ 2021-12-10 15:43 UTC (permalink / raw)
To: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm
Cc: Thomas Gleixner, Ingo Molnar, Joerg Roedel, Tom Lendacky,
H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy, Brijesh Singh
From: Tom Lendacky <thomas.lendacky@amd.com>
The initial implementation of the GHCB spec was based on trying to keep
the register state offsets the same relative to the VM save area. However,
the save area for SEV-ES has changed within the hardware causing the
relation between the SEV-ES save area to change relative to the GHCB save
area.
This is the second step in defining the multiple save areas to keep them
separate and ensuring proper operation amongst the different types of
guests. Create a GHCB save area that matches the GHCB specification.
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
arch/x86/include/asm/svm.h | 48 +++++++++++++++++++++++++++++++++++---
1 file changed, 45 insertions(+), 3 deletions(-)
diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index 3ce2e575a2de..5ff1fa364a31 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -354,11 +354,51 @@ struct sev_es_save_area {
u64 x87_state_gpa;
} __packed;
+struct ghcb_save_area {
+ u8 reserved_1[203];
+ u8 cpl;
+ u8 reserved_2[116];
+ u64 xss;
+ u8 reserved_3[24];
+ u64 dr7;
+ u8 reserved_4[16];
+ u64 rip;
+ u8 reserved_5[88];
+ u64 rsp;
+ u8 reserved_6[24];
+ u64 rax;
+ u8 reserved_7[264];
+ u64 rcx;
+ u64 rdx;
+ u64 rbx;
+ u8 reserved_8[8];
+ u64 rbp;
+ u64 rsi;
+ u64 rdi;
+ u64 r8;
+ u64 r9;
+ u64 r10;
+ u64 r11;
+ u64 r12;
+ u64 r13;
+ u64 r14;
+ u64 r15;
+ u8 reserved_9[16];
+ u64 sw_exit_code;
+ u64 sw_exit_info_1;
+ u64 sw_exit_info_2;
+ u64 sw_scratch;
+ u8 reserved_10[56];
+ u64 xcr0;
+ u8 valid_bitmap[16];
+ u64 x87_state_gpa;
+} __packed;
+
#define GHCB_SHARED_BUF_SIZE 2032
struct ghcb {
- struct sev_es_save_area save;
- u8 reserved_save[2048 - sizeof(struct sev_es_save_area)];
+ struct ghcb_save_area save;
+ u8 reserved_save[2048 - sizeof(struct ghcb_save_area)];
u8 shared_buffer[GHCB_SHARED_BUF_SIZE];
@@ -369,6 +409,7 @@ struct ghcb {
#define EXPECTED_VMCB_SAVE_AREA_SIZE 740
+#define EXPECTED_GHCB_SAVE_AREA_SIZE 1032
#define EXPECTED_SEV_ES_SAVE_AREA_SIZE 1032
#define EXPECTED_VMCB_CONTROL_AREA_SIZE 1024
#define EXPECTED_GHCB_SIZE PAGE_SIZE
@@ -376,6 +417,7 @@ struct ghcb {
static inline void __unused_size_checks(void)
{
BUILD_BUG_ON(sizeof(struct vmcb_save_area) != EXPECTED_VMCB_SAVE_AREA_SIZE);
+ BUILD_BUG_ON(sizeof(struct ghcb_save_area) != EXPECTED_GHCB_SAVE_AREA_SIZE);
BUILD_BUG_ON(sizeof(struct sev_es_save_area) != EXPECTED_SEV_ES_SAVE_AREA_SIZE);
BUILD_BUG_ON(sizeof(struct vmcb_control_area) != EXPECTED_VMCB_CONTROL_AREA_SIZE);
BUILD_BUG_ON(sizeof(struct ghcb) != EXPECTED_GHCB_SIZE);
@@ -446,7 +488,7 @@ struct vmcb {
/* GHCB Accessor functions */
#define GHCB_BITMAP_IDX(field) \
- (offsetof(struct sev_es_save_area, field) / sizeof(u64))
+ (offsetof(struct ghcb_save_area, field) / sizeof(u64))
#define DEFINE_GHCB_ACCESSORS(field) \
static inline bool ghcb_##field##_is_valid(const struct ghcb *ghcb) \
--
2.25.1
^ permalink raw reply related [flat|nested] 183+ messages in thread* Re: [PATCH v8 18/40] KVM: SVM: Create a separate mapping for the GHCB save area
2021-12-10 15:43 ` [PATCH v8 18/40] KVM: SVM: Create a separate mapping for the GHCB " Brijesh Singh
@ 2022-01-05 18:41 ` Venu Busireddy
0 siblings, 0 replies; 183+ messages in thread
From: Venu Busireddy @ 2022-01-05 18:41 UTC (permalink / raw)
To: Brijesh Singh
Cc: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm, Thomas Gleixner, Ingo Molnar, Joerg Roedel,
Tom Lendacky, H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy
On 2021-12-10 09:43:10 -0600, Brijesh Singh wrote:
> From: Tom Lendacky <thomas.lendacky@amd.com>
>
> The initial implementation of the GHCB spec was based on trying to keep
> the register state offsets the same relative to the VM save area. However,
> the save area for SEV-ES has changed within the hardware causing the
> relation between the SEV-ES save area to change relative to the GHCB save
> area.
>
> This is the second step in defining the multiple save areas to keep them
> separate and ensuring proper operation amongst the different types of
> guests. Create a GHCB save area that matches the GHCB specification.
>
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Venu Busireddy <venu.busireddy@oracle.com>
> ---
> arch/x86/include/asm/svm.h | 48 +++++++++++++++++++++++++++++++++++---
> 1 file changed, 45 insertions(+), 3 deletions(-)
>
^ permalink raw reply [flat|nested] 183+ messages in thread
* [PATCH v8 19/40] KVM: SVM: Update the SEV-ES save area mapping
2021-12-10 15:42 [PATCH v8 00/40] Add AMD Secure Nested Paging (SEV-SNP) Guest Support Brijesh Singh
` (17 preceding siblings ...)
2021-12-10 15:43 ` [PATCH v8 18/40] KVM: SVM: Create a separate mapping for the GHCB " Brijesh Singh
@ 2021-12-10 15:43 ` Brijesh Singh
2022-01-05 18:54 ` Venu Busireddy
2021-12-10 15:43 ` [PATCH v8 20/40] x86/sev: Use SEV-SNP AP creation to start secondary CPUs Brijesh Singh
` (21 subsequent siblings)
40 siblings, 1 reply; 183+ messages in thread
From: Brijesh Singh @ 2021-12-10 15:43 UTC (permalink / raw)
To: x86, linux-kernel, kvm, linux-efi, platform-driver-x86,
linux-coco, linux-mm
Cc: Thomas Gleixner, Ingo Molnar, Joerg Roedel, Tom Lendacky,
H. Peter Anvin, Ard Biesheuvel, Paolo Bonzini,
Sean Christopherson, Vitaly Kuznetsov, Jim Mattson,
Andy Lutomirski, Dave Hansen, Sergio Lopez, Peter Gonda,
Peter Zijlstra, Srinivas Pandruvada, David Rientjes, Dov Murik,
Tobin Feldman-Fitzthum, Borislav Petkov, Michael Roth,
Vlastimil Babka, Kirill A . Shutemov, Andi Kleen,
Dr . David Alan Gilbert, tony.luck, marcorr,
sathyanarayanan.kuppuswamy, Brijesh Singh
From: Tom Lendacky <thomas.lendacky@amd.com>
This is the final step in defining the multiple save areas to keep them
separate and ensuring proper operation amongst the different types of
guests. Update the SEV-ES/SEV-SNP save area to match the APM. This save
area will be used for the upcoming SEV-SNP AP Creation NAE event support.
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
arch/x86/include/asm/svm.h | 66 +++++++++++++++++++++++++++++---------
1 file changed, 50 insertions(+), 16 deletions(-)
diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index 5ff1fa364a31..7d90321e7775 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -290,7 +290,13 @@ struct sev_es_save_area {
struct vmcb_seg ldtr;
struct vmcb_seg idtr;
struct vmcb_seg tr;
- u8 reserved_1[43];
+ u64 vmpl0_ssp;
+ u64 vmpl1_ssp;
+ u64 vmpl2_ssp;
+ u64 vmpl3_ssp;
+ u64 u_cet;
+ u8 reserved_1[2];
+ u8 vmpl;
u8 cpl;
u8 reserved_2[4];
u64 efer;
@@ -303,9 +309,19 @@ struct sev_es_save_area {
u64 dr6;
u64 rflags;
u64 rip;
- u8 reserved_4[88];
+ u64 dr0;
+ u64 dr1;
+ u64 dr2;
+ u64 dr3;
+ u64 dr0_addr_mask;
+ u64 dr1_addr_mask;
+ u64 dr2_addr_mask;
+ u64 dr3_addr_mask;
+ u8 reserved_4[24];
u64 rsp;
- u8 reserved_5[24];
+ u64 s_cet;
+ u64 ssp;
+ u64 isst_addr;
u64 rax;
u64 star;
u64 lstar;
@@ -316,7 +332,7 @@ struct sev_es_save_area {
u64 sysenter_esp;
u64 sysenter_eip;
u64 cr2;
- u8 reserved_6[32];
+ u8 reserved_5[32];
u64 g_pat;
u64 dbgctl;
u64 br_from;
@@ -325,12 +341,12 @@ struct sev_es_save_area {
u64 last_excp_to;
u8 reserved_7[80];
u32 pkru;
- u8 reserved_9[20];
- u64 reserved_10; /* rax already available at 0x01f8 */
+ u8 reserved_8[20];
+ u64 reserved_9; /* rax already available at 0x01f8 */
u64 rcx;
u64 rdx;
u64 rbx;
- u64 reserved_11; /* rsp already available at 0x01d8 */
+ u64 reserved_10; /* rsp already available at 0x01d8 */
u64 rbp;
u64 rsi;
u64 rdi;
@@ -342,16 +358,34 @@ struct sev_es_save_area {
u64 r13;
u64 r14;
u64 r15;
- u8 reserved_12[16];
- u64 sw_exit_code;
- u64 sw_exit_info_1;
- u64 sw_exit_info_2;
- u64 sw_scratch;
+ u8 reserved_11[16];
+ u64 guest_exit_info_1;
+ u64 guest_exit_info_2;
+ u64 guest_exit_int_info;
+ u64 guest_nrip;
u64 sev_features;
- u8 reserved_13[48];
+ u64 vintr_ctrl;
+ u64 guest_exit_code;
+ u64 virtual_tom;
+ u64 tlb_id;
+ u64 pcpu_id;
+ u64 event_inj;
u64 xcr0;
- u8 valid_bitmap[16];
- u64 x87_state_gpa;
+ u8 reserved_12[16];
+
+ /* Floating point area */
+ u64 x87_dp;
+ u32 mxcsr;
+ u16 x87_ftw;
+ u16 x87_fsw;
+ u16 x87_fcw;
+ u16 x87_fop;
+ u16 x87_ds;
+ u16 x87_cs;
+ u64 x87_rip;
+ u8 fpreg_x87[80];
+ u8 fpreg_xmm[256];
+ u8 fpreg_ymm[256];