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 *