Re: [PATCH v5 02/13] x86/sev: Check for the presence of an SVSM in the SNP Secrets page

From: Borislav Petkov
Date: Wed Jun 05 2024 - 15:39:08 EST


On Wed, Jun 05, 2024 at 10:18:45AM -0500, Tom Lendacky wrote:
> During early boot phases, check for the presence of an SVSM when running
> as an SEV-SNP guest.
>
> An SVSM is present if not running at VMPL0 and the 64-bit value at offset
> 0x148 into the secrets page is non-zero. If an SVSM is present, save the
> SVSM Calling Area address (CAA), located at offset 0x150 into the secrets
> page, and set the VMPL level of the guest, which should be non-zero, to
> indicate the presence of an SVSM.
>
> Signed-off-by: Tom Lendacky <thomas.lendacky@xxxxxxx>
> ---
> .../arch/x86/amd-memory-encryption.rst | 23 ++++++
> arch/x86/boot/compressed/sev.c | 21 +++---
> arch/x86/include/asm/sev-common.h | 4 ++
> arch/x86/include/asm/sev.h | 34 ++++++++-
> arch/x86/kernel/sev-shared.c | 71 +++++++++++++++++++
> arch/x86/kernel/sev.c | 7 ++
> 6 files changed, 151 insertions(+), 9 deletions(-)

I did some touch-ups ontop:

diff --git a/Documentation/arch/x86/amd-memory-encryption.rst b/Documentation/arch/x86/amd-memory-encryption.rst
index 79eebaa85b7d..6df3264f23b9 100644
--- a/Documentation/arch/x86/amd-memory-encryption.rst
+++ b/Documentation/arch/x86/amd-memory-encryption.rst
@@ -135,7 +135,7 @@ Secure VM Service Module (SVSM)
SNP provides a feature called Virtual Machine Privilege Levels (VMPL) which
defines four privilege levels at which guest software can run. The most
privileged level is 0 and numerically higher numbers have lesser privileges.
-More details in the AMD64 APM[1] Vol 2, section "15.35.7 Virtual Machine
+More details in the AMD64 APM Vol 2, section "15.35.7 Virtual Machine
Privilege Levels", docID: 24593.

When using that feature, different services can run at different protection
@@ -150,7 +150,11 @@ services. An example fur such a privileged operation is PVALIDATE which is
In this scenario, the software running at VMPL0 is usually called a Secure VM
Service Module (SVSM). Discovery of an SVSM and the API used to communicate
with it is documented in "Secure VM Service Module for SEV-SNP Guests", docID:
-58019[2].
+58019.

-[1] https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/programmer-references/24593.pdf
-[2] https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/specifications/58019.pdf
+(Latest versions of the above-mentioned documents can be found by using
+a search engine like duckduckgo.com and typing in:
+
+ site:amd.com "Secure VM Service Module for SEV-SNP Guests", docID: 58019
+
+for example.)
diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
index 927b71495122..c65820b192b4 100644
--- a/arch/x86/boot/compressed/sev.c
+++ b/arch/x86/boot/compressed/sev.c
@@ -465,7 +465,7 @@ static bool early_snp_init(struct boot_params *bp)
/*
* Record the SVSM Calling Area (CA) address if the guest is not
* running at VMPL0. The CA will be used to communicate with the
- * SVSM to perform the SVSM services.
+ * SVSM and request its services.
*/
svsm_setup_ca(cc_info);

diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index 16d09c1a8ceb..2a44376f9f91 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h
@@ -204,19 +204,18 @@ static __always_inline void sev_es_nmi_complete(void)
extern int __init sev_es_efi_map_ghcbs(pgd_t *pgd);
extern void sev_enable(struct boot_params *bp);

+/*
+ * RMPADJUST modifies the RMP permissions of a page of a lesser-
+ * privileged (numerically higher) VMPL.
+ *
+ * If the guest is running at a higher-privilege than the privilege
+ * level the instruction is targeting, the instruction will succeed,
+ * otherwise, it will fail.
+ */
static inline int rmpadjust(unsigned long vaddr, bool rmp_psize, unsigned long attrs)
{
int rc;

- /*
- * RMPADJUST modifies the RMP permissions of a page of a lesser-privileged
- * (numerically higher) VMPL.
- *
- * If the guest is running at a higher-privilege than the privilege level
- * the instruction is targeting, the instruction will succeed, otherwise,
- * it will fail.
- */
-
/* "rmpadjust" mnemonic support in binutils 2.36 and newer */
asm volatile(".byte 0xF3,0x0F,0x01,0xFE\n\t"
: "=a"(rc)
diff --git a/arch/x86/kernel/sev-shared.c b/arch/x86/kernel/sev-shared.c
index 739362066e00..06a5078150b5 100644
--- a/arch/x86/kernel/sev-shared.c
+++ b/arch/x86/kernel/sev-shared.c
@@ -1330,6 +1330,11 @@ static void __head svsm_setup_ca(const struct cc_blob_sev_info *cc_info)
RIP_REL_REF(snp_vmpl) = secrets_page->svsm_guest_vmpl;

caa = secrets_page->svsm_caa;
+
+ /*
+ * An open-coded PAGE_ALIGNED() in order to avoid including
+ * kernel-proper headers into the decompressor.
+ */
if (caa & (PAGE_SIZE - 1))
sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_SVSM_CAA);

--
Regards/Gruss,
Boris.

https://people.kernel.org/tglx/notes-about-netiquette