From 4051e3c3d3bce5a273f3c6cb3e37dc1ad58389b0 Mon Sep 17 00:00:00 2001 From: Mimoja Date: Sat, 29 Jul 2023 00:16:13 +0000 Subject: [PATCH] crash: Disable SNP on crashkernel kexec The crashkernel is tasked with two problems as it stands right now: During start it will read the SNP enabled IOMMU tables during early init which can cause the lapic configuration to be configured into invalid or unintuitive modes. This will then cause the crashkernel to panic due to the lapic timer calibration failing or general RCU stalling. As the crashkernel can not pick up the host kernels PSP/SEV/SNP configuration we are therefore disabeling SNP not only on the normal kexec path but also on crash-kexec. This needs to be called very early on in the machine teardown as it requires to set per-cpu state. Signed-off-by: Mimoja Signed-off-by: Johanna 'Mimoja' Amelie Schander Reviewed-by: Alexander Graf (AWS) Reviewed-by: Costin Lupu Reviewed-by: Roman Kagan --- arch/x86/kernel/crash.c | 11 +++++++++++ drivers/crypto/ccp/sev-dev.c | 29 ++++++++++++++++++++++++++--- include/linux/psp-sev.h | 8 ++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c index cdd92ab43cda4b..dd2736589130f5 100644 --- a/arch/x86/kernel/crash.c +++ b/arch/x86/kernel/crash.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -131,6 +132,16 @@ void native_machine_crash_shutdown(struct pt_regs *regs) /* The kernel is broken so disable interrupts */ local_irq_disable(); + /* + * Disable SEV/SNP to allow access to the reserved memory areas + * including a normal IOMMU configuration + * This needs to happen very early in the machine exit due to its + * cross-cpu dependencies. + */ +#ifdef CONFIG_AMD_SEV_SNP + sev_emergency_exit(); +#endif + crash_smp_send_stop(); /* diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index 3c8cd2d20016dd..5b2703d1002498 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -2264,9 +2265,12 @@ int sev_dev_init(struct psp_device *psp) static void sev_firmware_shutdown(struct sev_device *sev) { - int error; + int error, rc; - sev_platform_shutdown(NULL); + rc = sev_platform_shutdown(&error); + if (rc) + dev_err(sev->dev, "SEV: failed to shutdown platform error 0x%#x, rc %d\n", + error, rc); if (sev_es_tmr) { /* The TMR area was encrypted, flush it from the cache */ @@ -2295,7 +2299,11 @@ static void sev_firmware_shutdown(struct sev_device *sev) */ free_snp_host_map(sev); - sev_snp_shutdown(&error); + rc = sev_snp_shutdown(&error); + if (rc) + dev_err(sev->dev, "SEV: failed to shutdown SEV/SNP error 0x%#x, rc %d\n", + error, rc); + } void sev_dev_destroy(struct psp_device *psp) @@ -2379,3 +2387,18 @@ void sev_pci_exit(void) sev_firmware_shutdown(sev); } + +void sev_emergency_exit(void) +{ + struct sev_device *sev; + + if (!psp_master) + return; + + sev = psp_master->sev_data; + + if (!sev) + return; + + sev_firmware_shutdown(sev); +} diff --git a/include/linux/psp-sev.h b/include/linux/psp-sev.h index 55f6dfc2580dec..f75428947a288b 100644 --- a/include/linux/psp-sev.h +++ b/include/linux/psp-sev.h @@ -804,6 +804,14 @@ struct sev_data_snp_shutdown_ex { */ int sev_platform_init(int *error); +/** + * sev_emergency_exit - perform SEV and SNP deinitialization + * + * Intended for emergency situations like kernel crashes + * enableing kdump on the incoming kernel without running SEV/SNP + */ +void sev_emergency_exit(void); + /** * sev_platform_status - perform SEV PLATFORM_STATUS command *