Skip to content

Commit 5441a07

Browse files
codomaniaherbertx
authored andcommitted
crypto: ccp - shutdown SEV firmware on kexec
The commit 97f9ac3 ("crypto: ccp - Add support for SEV-ES to the PSP driver") added support to allocate Trusted Memory Region (TMR) used during the SEV-ES firmware initialization. The TMR gets locked during the firmware initialization and unlocked during the shutdown. While the TMR is locked, access to it is disallowed. Currently, the CCP driver does not shutdown the firmware during the kexec reboot, leaving the TMR memory locked. Register a callback to shutdown the SEV firmware on the kexec boot. Fixes: 97f9ac3 ("crypto: ccp - Add support for SEV-ES to the PSP driver") Reported-by: Lucas Nussbaum <[email protected]> Tested-by: Lucas Nussbaum <[email protected]> Cc: <[email protected]> Cc: Tom Lendacky <[email protected]> Cc: Joerg Roedel <[email protected]> Cc: Herbert Xu <[email protected]> Cc: David Rientjes <[email protected]> Signed-off-by: Brijesh Singh <[email protected]> Acked-by: Tom Lendacky <[email protected]> Signed-off-by: Herbert Xu <[email protected]>
1 parent 1dd0d7f commit 5441a07

File tree

2 files changed

+35
-26
lines changed

2 files changed

+35
-26
lines changed

drivers/crypto/ccp/sev-dev.c

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,9 @@ static int __sev_platform_shutdown_locked(int *error)
300300
struct sev_device *sev = psp_master->sev_data;
301301
int ret;
302302

303+
if (sev->state == SEV_STATE_UNINIT)
304+
return 0;
305+
303306
ret = __sev_do_cmd_locked(SEV_CMD_SHUTDOWN, NULL, error);
304307
if (ret)
305308
return ret;
@@ -1019,13 +1022,29 @@ int sev_dev_init(struct psp_device *psp)
10191022
return ret;
10201023
}
10211024

1025+
static void sev_firmware_shutdown(struct sev_device *sev)
1026+
{
1027+
sev_platform_shutdown(NULL);
1028+
1029+
if (sev_es_tmr) {
1030+
/* The TMR area was encrypted, flush it from the cache */
1031+
wbinvd_on_all_cpus();
1032+
1033+
free_pages((unsigned long)sev_es_tmr,
1034+
get_order(SEV_ES_TMR_SIZE));
1035+
sev_es_tmr = NULL;
1036+
}
1037+
}
1038+
10221039
void sev_dev_destroy(struct psp_device *psp)
10231040
{
10241041
struct sev_device *sev = psp->sev_data;
10251042

10261043
if (!sev)
10271044
return;
10281045

1046+
sev_firmware_shutdown(sev);
1047+
10291048
if (sev->misc)
10301049
kref_put(&misc_dev->refcount, sev_exit);
10311050

@@ -1056,21 +1075,6 @@ void sev_pci_init(void)
10561075
if (sev_get_api_version())
10571076
goto err;
10581077

1059-
/*
1060-
* If platform is not in UNINIT state then firmware upgrade and/or
1061-
* platform INIT command will fail. These command require UNINIT state.
1062-
*
1063-
* In a normal boot we should never run into case where the firmware
1064-
* is not in UNINIT state on boot. But in case of kexec boot, a reboot
1065-
* may not go through a typical shutdown sequence and may leave the
1066-
* firmware in INIT or WORKING state.
1067-
*/
1068-
1069-
if (sev->state != SEV_STATE_UNINIT) {
1070-
sev_platform_shutdown(NULL);
1071-
sev->state = SEV_STATE_UNINIT;
1072-
}
1073-
10741078
if (sev_version_greater_or_equal(0, 15) &&
10751079
sev_update_firmware(sev->dev) == 0)
10761080
sev_get_api_version();
@@ -1115,17 +1119,10 @@ void sev_pci_init(void)
11151119

11161120
void sev_pci_exit(void)
11171121
{
1118-
if (!psp_master->sev_data)
1119-
return;
1120-
1121-
sev_platform_shutdown(NULL);
1122+
struct sev_device *sev = psp_master->sev_data;
11221123

1123-
if (sev_es_tmr) {
1124-
/* The TMR area was encrypted, flush it from the cache */
1125-
wbinvd_on_all_cpus();
1124+
if (!sev)
1125+
return;
11261126

1127-
free_pages((unsigned long)sev_es_tmr,
1128-
get_order(SEV_ES_TMR_SIZE));
1129-
sev_es_tmr = NULL;
1130-
}
1127+
sev_firmware_shutdown(sev);
11311128
}

drivers/crypto/ccp/sp-pci.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,17 @@ static int sp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
241241
return ret;
242242
}
243243

244+
static void sp_pci_shutdown(struct pci_dev *pdev)
245+
{
246+
struct device *dev = &pdev->dev;
247+
struct sp_device *sp = dev_get_drvdata(dev);
248+
249+
if (!sp)
250+
return;
251+
252+
sp_destroy(sp);
253+
}
254+
244255
static void sp_pci_remove(struct pci_dev *pdev)
245256
{
246257
struct device *dev = &pdev->dev;
@@ -371,6 +382,7 @@ static struct pci_driver sp_pci_driver = {
371382
.id_table = sp_pci_table,
372383
.probe = sp_pci_probe,
373384
.remove = sp_pci_remove,
385+
.shutdown = sp_pci_shutdown,
374386
.driver.pm = &sp_pci_pm_ops,
375387
};
376388

0 commit comments

Comments
 (0)