From: Ard Biesheuvel <ardb@kernel.org>
To: linux-efi@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, Ard Biesheuvel <ardb@kernel.org>,
Evgeniy Baskov <baskov@ispras.ru>, Borislav Petkov <bp@alien8.de>,
Andy Lutomirski <luto@kernel.org>,
Dave Hansen <dave.hansen@linux.intel.com>,
Ingo Molnar <mingo@redhat.com>,
Peter Zijlstra <peterz@infradead.org>,
Thomas Gleixner <tglx@linutronix.de>,
Alexey Khoroshilov <khoroshilov@ispras.ru>,
Peter Jones <pjones@redhat.com>,
Gerd Hoffmann <kraxel@redhat.com>, Dave Young <dyoung@redhat.com>,
Mario Limonciello <mario.limonciello@amd.com>,
Kees Cook <keescook@chromium.org>,
Tom Lendacky <thomas.lendacky@amd.com>,
"Kirill A . Shutemov" <kirill.shutemov@linux.intel.com>,
Linus Torvalds <torvalds@linux-foundation.org>,
Joerg Roedel <jroedel@suse.de>
Subject: [PATCH v7 21/22] x86/efistub: Perform SNP feature test while running in the firmware
Date: Fri, 28 Jul 2023 11:09:15 +0200 [thread overview]
Message-ID: <20230728090916.1538550-22-ardb@kernel.org> (raw)
In-Reply-To: <20230728090916.1538550-1-ardb@kernel.org>
Before refactoring the EFI stub boot flow to avoid the legacy bare metal
decompressor, duplicate the SNP feature check in the EFI stub before
handing over to the kernel proper.
The SNP feature check can be performed while running under the EFI boot
services, which means we can fail gracefully and return an error to the
bootloader if the loaded kernel does not implement support for all the
features that the hypervisor enabled.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
arch/x86/boot/compressed/sev.c | 91 ++++++++++++++------
arch/x86/include/asm/sev.h | 4 +
drivers/firmware/efi/libstub/x86-stub.c | 17 ++++
3 files changed, 86 insertions(+), 26 deletions(-)
diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
index 09dc8c187b3cc752..da25959f618ed398 100644
--- a/arch/x86/boot/compressed/sev.c
+++ b/arch/x86/boot/compressed/sev.c
@@ -367,20 +367,25 @@ static void enforce_vmpl0(void)
*/
#define SNP_FEATURES_PRESENT (0)
+u64 snp_get_unsupported_features(u64 status)
+{
+ if (!(status & MSR_AMD64_SEV_SNP_ENABLED))
+ return 0;
+
+ return status & SNP_FEATURES_IMPL_REQ & ~SNP_FEATURES_PRESENT;
+}
+
void snp_check_features(void)
{
u64 unsupported;
- if (!(sev_status & MSR_AMD64_SEV_SNP_ENABLED))
- return;
-
/*
* Terminate the boot if hypervisor has enabled any feature lacking
* guest side implementation. Pass on the unsupported features mask through
* EXIT_INFO_2 of the GHCB protocol so that those features can be reported
* as part of the guest boot failure.
*/
- unsupported = sev_status & SNP_FEATURES_IMPL_REQ & ~SNP_FEATURES_PRESENT;
+ unsupported = snp_get_unsupported_features(sev_status);
if (unsupported) {
if (ghcb_version < 2 || (!boot_ghcb && !early_setup_ghcb()))
sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
@@ -390,10 +395,45 @@ void snp_check_features(void)
}
}
-void sev_enable(struct boot_params *bp)
+/*
+ * sev_check_support - Check for SEV support in the CPU capabilities
+ *
+ * Returns < 0 if SEV is not supported, otherwise the position of the
+ * encryption bit in the page table descriptors.
+ */
+static int sev_check_support(void)
{
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 -ENODEV;
+
+ /*
+ * 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 -ENODEV;
+
+ return ebx & 0x3f;
+}
+
+void sev_enable(struct boot_params *bp)
+{
struct msr m;
+ int bitpos;
bool snp;
/*
@@ -410,26 +450,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))) {
+ bitpos = sev_check_support();
+ if (bitpos < 0) {
if (snp)
error("SEV-SNP support indicated by CC blob, but not CPUID.");
return;
@@ -461,7 +483,24 @@ 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(bitpos);
+}
+
+/*
+ * sev_get_status - Retrieve the SEV status mask
+ *
+ * Returns 0 if the CPU is not SEV capable, otherwise the value of the
+ * AMD64_SEV MSR.
+ */
+u64 sev_get_status(void)
+{
+ struct msr m;
+
+ if (sev_check_support() < 0)
+ return 0;
+
+ boot_rdmsr(MSR_AMD64_SEV, &m);
+ return m.q;
}
/* Search for Confidential Computing blob in the EFI config table. */
diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index 66c806784c5256bd..b97d239e18ea25fc 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h
@@ -210,6 +210,8 @@ bool snp_init(struct boot_params *bp);
void __init __noreturn snp_abort(void);
int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio);
void snp_accept_memory(phys_addr_t start, phys_addr_t end);
+u64 snp_get_unsupported_features(u64 status);
+u64 sev_get_status(void);
#else
static inline void sev_es_ist_enter(struct pt_regs *regs) { }
static inline void sev_es_ist_exit(void) { }
@@ -235,6 +237,8 @@ static inline int snp_issue_guest_request(u64 exit_code, struct snp_req_data *in
}
static inline void snp_accept_memory(phys_addr_t start, phys_addr_t end) { }
+static inline u64 snp_get_unsupported_features(u64 status) { return 0; }
+static inline u64 sev_get_status(void) { return 0; }
#endif
#endif
diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
index efb4f5eda6784026..3681700702126615 100644
--- a/drivers/firmware/efi/libstub/x86-stub.c
+++ b/drivers/firmware/efi/libstub/x86-stub.c
@@ -15,6 +15,7 @@
#include <asm/setup.h>
#include <asm/desc.h>
#include <asm/boot.h>
+#include <asm/sev.h>
#include "efistub.h"
#include "x86-stub.h"
@@ -790,6 +791,19 @@ static efi_status_t exit_boot(struct boot_params *boot_params, void *handle)
return EFI_SUCCESS;
}
+static bool have_unsupported_snp_features(void)
+{
+ u64 unsupported;
+
+ unsupported = snp_get_unsupported_features(sev_get_status());
+ if (unsupported) {
+ efi_err("Unsupported SEV-SNP features detected: 0x%llx\n",
+ unsupported);
+ return true;
+ }
+ return false;
+}
+
static void __noreturn enter_kernel(unsigned long kernel_addr,
struct boot_params *boot_params)
{
@@ -820,6 +834,9 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
if (efi_system_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
efi_exit(handle, EFI_INVALID_PARAMETER);
+ if (have_unsupported_snp_features())
+ efi_exit(handle, EFI_UNSUPPORTED);
+
if (IS_ENABLED(CONFIG_EFI_DXE_MEM_ATTRIBUTES)) {
efi_dxe_table = get_efi_config_table(EFI_DXE_SERVICES_TABLE_GUID);
if (efi_dxe_table &&
--
2.39.2
next prev parent reply other threads:[~2023-07-28 9:16 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-28 9:08 [PATCH v7 00/22] efi/x86: Avoid bare metal decompressor during EFI boot Ard Biesheuvel
2023-07-28 9:08 ` [PATCH v7 01/22] x86/decompressor: Don't rely on upper 32 bits of GPRs being preserved Ard Biesheuvel
2023-07-31 10:07 ` Borislav Petkov
2023-07-31 10:09 ` Ard Biesheuvel
2023-07-31 11:01 ` Borislav Petkov
2023-07-28 9:08 ` [PATCH v7 02/22] x86/head_64: Store boot_params pointer in callee save register Ard Biesheuvel
2023-08-01 11:28 ` Borislav Petkov
2023-07-28 9:08 ` [PATCH v7 03/22] x86/efistub: Branch straight to kernel entry point from C code Ard Biesheuvel
2023-07-28 9:08 ` [PATCH v7 04/22] x86/efistub: Simplify and clean up handover entry code Ard Biesheuvel
2023-07-28 9:08 ` [PATCH v7 05/22] x86/decompressor: Avoid magic offsets for EFI handover entrypoint Ard Biesheuvel
2023-07-28 9:09 ` [PATCH v7 06/22] x86/efistub: Clear BSS in EFI handover protocol entrypoint Ard Biesheuvel
2023-07-28 9:09 ` [PATCH v7 07/22] x86/decompressor: Use proper sequence to take the address of the GOT Ard Biesheuvel
2023-07-28 9:09 ` [PATCH v7 08/22] x86/decompressor: Store boot_params pointer in callee save register Ard Biesheuvel
2023-07-28 9:09 ` [PATCH v7 09/22] x86/decompressor: Call trampoline as a normal function Ard Biesheuvel
2023-07-28 9:09 ` [PATCH v7 10/22] x86/decompressor: Use standard calling convention for trampoline Ard Biesheuvel
2023-07-31 11:28 ` Borislav Petkov
2023-07-31 11:35 ` Ard Biesheuvel
2023-07-28 9:09 ` [PATCH v7 11/22] x86/decompressor: Avoid the need for a stack in the 32-bit trampoline Ard Biesheuvel
2023-08-01 10:30 ` Borislav Petkov
2023-07-28 9:09 ` [PATCH v7 12/22] x86/decompressor: Call trampoline directly from C code Ard Biesheuvel
2023-08-01 11:45 ` Borislav Petkov
2023-08-01 11:48 ` Ard Biesheuvel
2023-08-01 11:51 ` Borislav Petkov
2023-07-28 9:09 ` [PATCH v7 13/22] x86/decompressor: Only call the trampoline when changing paging levels Ard Biesheuvel
2023-07-28 9:09 ` [PATCH v7 14/22] x86/decompressor: Merge trampoline cleanup with switching code Ard Biesheuvel
2023-08-01 12:08 ` Borislav Petkov
2023-08-01 12:11 ` Ard Biesheuvel
2023-08-01 12:40 ` Borislav Petkov
2023-08-01 12:46 ` Ard Biesheuvel
2023-08-01 13:04 ` Borislav Petkov
2023-07-28 9:09 ` [PATCH v7 15/22] x86/efistub: Perform 4/5 level paging switch from the stub Ard Biesheuvel
2023-07-28 9:09 ` [PATCH v7 16/22] x86/efistub: Prefer EFI memory attributes protocol over DXE services Ard Biesheuvel
2023-07-28 9:09 ` [PATCH v7 17/22] decompress: Use 8 byte alignment Ard Biesheuvel
2023-07-28 9:09 ` [PATCH v7 18/22] x86/decompressor: Move global symbol references to C code Ard Biesheuvel
2023-07-28 9:09 ` [PATCH v7 19/22] x86/decompressor: Factor out kernel decompression and relocation Ard Biesheuvel
2023-07-28 9:09 ` [PATCH v7 20/22] efi/libstub: Add limit argument to efi_random_alloc() Ard Biesheuvel
2023-07-28 9:09 ` Ard Biesheuvel [this message]
2023-07-28 9:09 ` [PATCH v7 22/22] x86/efistub: Avoid legacy decompressor when doing EFI boot Ard Biesheuvel
2023-08-02 10:26 ` Borislav Petkov
2023-08-02 10:47 ` Ard Biesheuvel
2023-08-02 15:55 ` Borislav Petkov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230728090916.1538550-22-ardb@kernel.org \
--to=ardb@kernel.org \
--cc=baskov@ispras.ru \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=dyoung@redhat.com \
--cc=jroedel@suse.de \
--cc=keescook@chromium.org \
--cc=khoroshilov@ispras.ru \
--cc=kirill.shutemov@linux.intel.com \
--cc=kraxel@redhat.com \
--cc=linux-efi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@kernel.org \
--cc=mario.limonciello@amd.com \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
--cc=pjones@redhat.com \
--cc=tglx@linutronix.de \
--cc=thomas.lendacky@amd.com \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox