* [PATCH v2 0/4] Fixes for PMF and CCP drivers after S4
@ 2025-12-11 21:28 Mario Limonciello (AMD)
2025-12-11 21:28 ` [PATCH v2 1/4] platform/x86/amd/pmf: Prevent TEE errors after hibernate Mario Limonciello (AMD)
` (4 more replies)
0 siblings, 5 replies; 9+ messages in thread
From: Mario Limonciello (AMD) @ 2025-12-11 21:28 UTC (permalink / raw)
To: Tom Lendacky, Herbert Xu, Shyam Sundar S K, Ilpo Järvinen
Cc: John Allen, David S . Miller, Hans de Goede,
open list:AMD CRYPTOGRAPHIC COPROCESSOR (CCP) DRIVER,
open list:AMD PMF DRIVER, Lars Francke, Mario Limonciello
Lars Francke reported that the PMF driver fails to work afer S4 with:
ccp 0000:c3:00.2: tee: command 0x5 timed out, disabling PSP
This is because there is a TA loaded to the TEE environment that
is lost during S4. The TEE rings need to be reinitialized and the
TA needs to be reloaded.
This series adds those flows to the PMF and CCP drivers.
---
v2:
* Fixes for potential race conditions in hibernate resume
* Fix for error handling if tee ring is never destroyed
* Fixes for dead PSP (which can lead to hangs)
* Fixes for LKP robot reported issues
Mario Limonciello (AMD) (3):
crypto: ccp - Declare PSP dead if PSP_CMD_TEE_RING_INIT fails
crypto: ccp - Send PSP_CMD_TEE_RING_DESTROY when PSP_CMD_TEE_RING_INIT
fails
crypto: ccp - Add an S4 restore flow
Shyam Sundar S K (1):
platform/x86/amd/pmf: Prevent TEE errors after hibernate
drivers/crypto/ccp/sp-dev.c | 13 ++++++
drivers/crypto/ccp/sp-dev.h | 1 +
drivers/crypto/ccp/sp-pci.c | 16 ++++++-
drivers/crypto/ccp/tee-dev.c | 17 ++++++++
drivers/crypto/ccp/tee-dev.h | 6 +++
drivers/platform/x86/amd/pmf/core.c | 62 ++++++++++++++++++++++++++-
drivers/platform/x86/amd/pmf/pmf.h | 10 +++++
drivers/platform/x86/amd/pmf/tee-if.c | 12 ++----
8 files changed, 126 insertions(+), 11 deletions(-)
--
2.51.2
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 1/4] platform/x86/amd/pmf: Prevent TEE errors after hibernate
2025-12-11 21:28 [PATCH v2 0/4] Fixes for PMF and CCP drivers after S4 Mario Limonciello (AMD)
@ 2025-12-11 21:28 ` Mario Limonciello (AMD)
2025-12-11 21:28 ` [PATCH v2 2/4] crypto: ccp - Declare PSP dead if PSP_CMD_TEE_RING_INIT fails Mario Limonciello (AMD)
` (3 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Mario Limonciello (AMD) @ 2025-12-11 21:28 UTC (permalink / raw)
To: Tom Lendacky, Herbert Xu, Shyam Sundar S K, Ilpo Järvinen
Cc: John Allen, David S . Miller, Hans de Goede,
open list:AMD CRYPTOGRAPHIC COPROCESSOR (CCP) DRIVER,
open list:AMD PMF DRIVER, Lars Francke, Patil Rajesh Reddy,
Mario Limonciello
From: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
After resuming from hibernate, TEE commands can time out and cause PSP
disables. Fix this by reinitializing the Trusted Application (TA) and
cancelling the pb workqueue in the hibernate callbacks to avoid these
errors.
ccp 0000:c4:00.2: tee: command 0x5 timed out, disabling PSP
amd-pmf AMDI0107:00: TEE enact cmd failed. err: ffff000e, ret:0
amd-pmf AMDI0107:00: TEE enact cmd failed. err: ffff000e, ret:0
amd-pmf AMDI0107:00: TEE enact cmd failed. err: ffff000e, ret:0
Fixes: ae82cef7d9c5 ("platform/x86/amd/pmf: Add support for PMF-TA interaction")
Reported-by: Lars Francke <lars.francke@gmail.com>
Closes: https://lore.kernel.org/platform-driver-x86/CAD-Ua_gfJnQSo8ucS_7ZwzuhoBRJ14zXP7s8b-zX3ZcxcyWePw@mail.gmail.com/
Co-developed-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
[ML: Add more tags]
Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
---
drivers/platform/x86/amd/pmf/core.c | 62 ++++++++++++++++++++++++++-
drivers/platform/x86/amd/pmf/pmf.h | 10 +++++
drivers/platform/x86/amd/pmf/tee-if.c | 12 ++----
3 files changed, 74 insertions(+), 10 deletions(-)
diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
index bc544a4a5266..e787480f4df2 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -314,6 +314,61 @@ int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev)
return 0;
}
+static int amd_pmf_reinit_ta(struct amd_pmf_dev *pdev)
+{
+ bool status;
+ int ret, i;
+
+ for (i = 0; i < ARRAY_SIZE(amd_pmf_ta_uuid); i++) {
+ ret = amd_pmf_tee_init(pdev, &amd_pmf_ta_uuid[i]);
+ if (ret) {
+ dev_err(pdev->dev, "TEE init failed for UUID[%d] ret: %d\n", i, ret);
+ return ret;
+ }
+
+ ret = amd_pmf_start_policy_engine(pdev);
+ dev_dbg(pdev->dev, "start policy engine ret: %d (UUID idx: %d)\n", ret, i);
+ status = ret == TA_PMF_TYPE_SUCCESS;
+ if (status)
+ break;
+ amd_pmf_tee_deinit(pdev);
+ }
+
+ return 0;
+}
+
+static int amd_pmf_restore_handler(struct device *dev)
+{
+ struct amd_pmf_dev *pdev = dev_get_drvdata(dev);
+ int ret;
+
+ if (pdev->buf) {
+ ret = amd_pmf_set_dram_addr(pdev, false);
+ if (ret)
+ return ret;
+ }
+
+ if (pdev->smart_pc_enabled)
+ amd_pmf_reinit_ta(pdev);
+
+ return 0;
+}
+
+static int amd_pmf_freeze_handler(struct device *dev)
+{
+ struct amd_pmf_dev *pdev = dev_get_drvdata(dev);
+
+ if (!pdev->smart_pc_enabled)
+ return 0;
+
+ cancel_delayed_work_sync(&pdev->pb_work);
+ /* Clear all TEE resources */
+ amd_pmf_tee_deinit(pdev);
+ pdev->session_id = 0;
+
+ return 0;
+}
+
static int amd_pmf_suspend_handler(struct device *dev)
{
struct amd_pmf_dev *pdev = dev_get_drvdata(dev);
@@ -347,7 +402,12 @@ static int amd_pmf_resume_handler(struct device *dev)
return 0;
}
-static DEFINE_SIMPLE_DEV_PM_OPS(amd_pmf_pm, amd_pmf_suspend_handler, amd_pmf_resume_handler);
+static const struct dev_pm_ops amd_pmf_pm = {
+ .suspend = amd_pmf_suspend_handler,
+ .resume = amd_pmf_resume_handler,
+ .freeze = amd_pmf_freeze_handler,
+ .restore = amd_pmf_restore_handler,
+};
static void amd_pmf_init_features(struct amd_pmf_dev *dev)
{
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index bd19f2a6bc78..2da1885d8791 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -122,6 +122,12 @@ struct cookie_header {
typedef void (*apmf_event_handler_t)(acpi_handle handle, u32 event, void *data);
+static const uuid_t amd_pmf_ta_uuid[] __used = { UUID_INIT(0xd9b39bf2, 0x66bd, 0x4154, 0xaf, 0xb8,
+ 0x8a, 0xcc, 0x2b, 0x2b, 0x60, 0xd6),
+ UUID_INIT(0x6fd93b77, 0x3fb8, 0x524d, 0xb1, 0x2d,
+ 0xc5, 0x29, 0xb1, 0x3d, 0x85, 0x43),
+ };
+
/* APTS PMF BIOS Interface */
struct amd_pmf_apts_output {
u16 table_version;
@@ -888,4 +894,8 @@ void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_tab
void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in);
int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev);
+int amd_pmf_tee_init(struct amd_pmf_dev *dev, const uuid_t *uuid);
+void amd_pmf_tee_deinit(struct amd_pmf_dev *dev);
+int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev);
+
#endif /* PMF_H */
diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
index 6e8116bef4f6..903045935237 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -27,12 +27,6 @@ module_param(pb_side_load, bool, 0444);
MODULE_PARM_DESC(pb_side_load, "Sideload policy binaries debug policy failures");
#endif
-static const uuid_t amd_pmf_ta_uuid[] = { UUID_INIT(0xd9b39bf2, 0x66bd, 0x4154, 0xaf, 0xb8, 0x8a,
- 0xcc, 0x2b, 0x2b, 0x60, 0xd6),
- UUID_INIT(0x6fd93b77, 0x3fb8, 0x524d, 0xb1, 0x2d, 0xc5,
- 0x29, 0xb1, 0x3d, 0x85, 0x43),
- };
-
static const char *amd_pmf_uevent_as_str(unsigned int state)
{
switch (state) {
@@ -312,7 +306,7 @@ static void amd_pmf_invoke_cmd(struct work_struct *work)
schedule_delayed_work(&dev->pb_work, msecs_to_jiffies(pb_actions_ms));
}
-static int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev)
+int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev)
{
struct cookie_header *header;
int res;
@@ -468,7 +462,7 @@ static int amd_pmf_register_input_device(struct amd_pmf_dev *dev)
return 0;
}
-static int amd_pmf_tee_init(struct amd_pmf_dev *dev, const uuid_t *uuid)
+int amd_pmf_tee_init(struct amd_pmf_dev *dev, const uuid_t *uuid)
{
u32 size;
int ret;
@@ -516,7 +510,7 @@ static int amd_pmf_tee_init(struct amd_pmf_dev *dev, const uuid_t *uuid)
return ret;
}
-static void amd_pmf_tee_deinit(struct amd_pmf_dev *dev)
+void amd_pmf_tee_deinit(struct amd_pmf_dev *dev)
{
if (!dev->tee_ctx)
return;
--
2.51.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 2/4] crypto: ccp - Declare PSP dead if PSP_CMD_TEE_RING_INIT fails
2025-12-11 21:28 [PATCH v2 0/4] Fixes for PMF and CCP drivers after S4 Mario Limonciello (AMD)
2025-12-11 21:28 ` [PATCH v2 1/4] platform/x86/amd/pmf: Prevent TEE errors after hibernate Mario Limonciello (AMD)
@ 2025-12-11 21:28 ` Mario Limonciello (AMD)
2025-12-11 21:28 ` [PATCH v2 3/4] crypto: ccp - Add an S4 restore flow Mario Limonciello (AMD)
` (2 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Mario Limonciello (AMD) @ 2025-12-11 21:28 UTC (permalink / raw)
To: Tom Lendacky, Herbert Xu, Shyam Sundar S K, Ilpo Järvinen
Cc: John Allen, David S . Miller, Hans de Goede,
open list:AMD CRYPTOGRAPHIC COPROCESSOR (CCP) DRIVER,
open list:AMD PMF DRIVER, Lars Francke, Mario Limonciello
tee_init_ring() only declares PSP dead if the command times out.
If there is any other failure it is still considered fatal though.
Set psp_dead for other failures as well.
Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
---
drivers/crypto/ccp/tee-dev.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/crypto/ccp/tee-dev.c b/drivers/crypto/ccp/tee-dev.c
index 5e1d80724678..af881daa5855 100644
--- a/drivers/crypto/ccp/tee-dev.c
+++ b/drivers/crypto/ccp/tee-dev.c
@@ -125,6 +125,7 @@ static int tee_init_ring(struct psp_tee_device *tee)
dev_err(tee->dev, "tee: ring init command failed (%#010lx)\n",
FIELD_GET(PSP_CMDRESP_STS, reg));
tee_free_ring(tee);
+ psp_dead = true;
ret = -EIO;
}
--
2.51.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 3/4] crypto: ccp - Add an S4 restore flow
2025-12-11 21:28 [PATCH v2 0/4] Fixes for PMF and CCP drivers after S4 Mario Limonciello (AMD)
2025-12-11 21:28 ` [PATCH v2 1/4] platform/x86/amd/pmf: Prevent TEE errors after hibernate Mario Limonciello (AMD)
2025-12-11 21:28 ` [PATCH v2 2/4] crypto: ccp - Declare PSP dead if PSP_CMD_TEE_RING_INIT fails Mario Limonciello (AMD)
@ 2025-12-11 21:28 ` Mario Limonciello (AMD)
2025-12-11 22:03 ` Tom Lendacky
2025-12-11 21:28 ` [PATCH v2 4/4] crypto: ccp - Send PSP_CMD_TEE_RING_DESTROY when PSP_CMD_TEE_RING_INIT fails Mario Limonciello (AMD)
2025-12-11 22:23 ` [PATCH v2 0/4] Fixes for PMF and CCP drivers after S4 Tom Lendacky
4 siblings, 1 reply; 9+ messages in thread
From: Mario Limonciello (AMD) @ 2025-12-11 21:28 UTC (permalink / raw)
To: Tom Lendacky, Herbert Xu, Shyam Sundar S K, Ilpo Järvinen
Cc: John Allen, David S . Miller, Hans de Goede,
open list:AMD CRYPTOGRAPHIC COPROCESSOR (CCP) DRIVER,
open list:AMD PMF DRIVER, Lars Francke, Mario Limonciello (AMD)
The system will have lost power during S4. The ring used for TEE
communications needs to be initialized before use.
Fixes: f892a21f51162 ("crypto: ccp - use generic power management")
Reported-by: Lars Francke <lars.francke@gmail.com>
Closes: https://lore.kernel.org/platform-driver-x86/CAD-Ua_gfJnQSo8ucS_7ZwzuhoBRJ14zXP7s8b-zX3ZcxcyWePw@mail.gmail.com/
Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
---
v2:
* Fix LKP errors
* Remove free phase
---
drivers/crypto/ccp/sp-dev.c | 13 +++++++++++++
drivers/crypto/ccp/sp-dev.h | 1 +
drivers/crypto/ccp/sp-pci.c | 16 +++++++++++++++-
drivers/crypto/ccp/tee-dev.c | 5 +++++
drivers/crypto/ccp/tee-dev.h | 6 ++++++
5 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/drivers/crypto/ccp/sp-dev.c b/drivers/crypto/ccp/sp-dev.c
index 3467f6db4f50..e3fa94d14026 100644
--- a/drivers/crypto/ccp/sp-dev.c
+++ b/drivers/crypto/ccp/sp-dev.c
@@ -21,6 +21,7 @@
#include "sev-dev.h"
#include "ccp-dev.h"
+#include "tee-dev.h"
#include "sp-dev.h"
MODULE_AUTHOR("Tom Lendacky <thomas.lendacky@amd.com>");
@@ -230,6 +231,18 @@ int sp_resume(struct sp_device *sp)
return 0;
}
+int sp_restore(struct sp_device *sp)
+{
+ if (sp->dev_vdata->psp_vdata->tee) {
+ int r = tee_restore(sp->psp_data);
+
+ if (r)
+ return r;
+ }
+
+ return sp_resume(sp);
+}
+
struct sp_device *sp_get_psp_master_device(void)
{
struct sp_device *i, *ret = NULL;
diff --git a/drivers/crypto/ccp/sp-dev.h b/drivers/crypto/ccp/sp-dev.h
index 6f9d7063257d..37b38afaab14 100644
--- a/drivers/crypto/ccp/sp-dev.h
+++ b/drivers/crypto/ccp/sp-dev.h
@@ -141,6 +141,7 @@ void sp_destroy(struct sp_device *sp);
int sp_suspend(struct sp_device *sp);
int sp_resume(struct sp_device *sp);
+int sp_restore(struct sp_device *sp);
int sp_request_ccp_irq(struct sp_device *sp, irq_handler_t handler,
const char *name, void *data);
void sp_free_ccp_irq(struct sp_device *sp, void *data);
diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c
index e7bb803912a6..ce55563b224d 100644
--- a/drivers/crypto/ccp/sp-pci.c
+++ b/drivers/crypto/ccp/sp-pci.c
@@ -353,6 +353,13 @@ static int __maybe_unused sp_pci_resume(struct device *dev)
return sp_resume(sp);
}
+static int __maybe_unused sp_pci_restore(struct device *dev)
+{
+ struct sp_device *sp = dev_get_drvdata(dev);
+
+ return sp_restore(sp);
+}
+
#ifdef CONFIG_CRYPTO_DEV_SP_PSP
static const struct sev_vdata sevv1 = {
.cmdresp_reg = 0x10580, /* C2PMSG_32 */
@@ -544,7 +551,14 @@ static const struct pci_device_id sp_pci_table[] = {
};
MODULE_DEVICE_TABLE(pci, sp_pci_table);
-static SIMPLE_DEV_PM_OPS(sp_pci_pm_ops, sp_pci_suspend, sp_pci_resume);
+static const struct dev_pm_ops sp_pci_pm_ops = {
+ .suspend = pm_sleep_ptr(sp_pci_suspend),
+ .resume = pm_sleep_ptr(sp_pci_resume),
+ .freeze = pm_sleep_ptr(sp_pci_suspend),
+ .thaw = pm_sleep_ptr(sp_pci_resume),
+ .poweroff = pm_sleep_ptr(sp_pci_suspend),
+ .restore_early = pm_sleep_ptr(sp_pci_restore),
+};
static struct pci_driver sp_pci_driver = {
.name = "ccp",
diff --git a/drivers/crypto/ccp/tee-dev.c b/drivers/crypto/ccp/tee-dev.c
index af881daa5855..11c4b05e2f3a 100644
--- a/drivers/crypto/ccp/tee-dev.c
+++ b/drivers/crypto/ccp/tee-dev.c
@@ -366,3 +366,8 @@ int psp_check_tee_status(void)
return 0;
}
EXPORT_SYMBOL(psp_check_tee_status);
+
+int tee_restore(struct psp_device *psp)
+{
+ return tee_init_ring(psp->tee_data);
+}
diff --git a/drivers/crypto/ccp/tee-dev.h b/drivers/crypto/ccp/tee-dev.h
index ea9a2b7c05f5..3409253ac557 100644
--- a/drivers/crypto/ccp/tee-dev.h
+++ b/drivers/crypto/ccp/tee-dev.h
@@ -112,4 +112,10 @@ struct tee_ring_cmd {
int tee_dev_init(struct psp_device *psp);
void tee_dev_destroy(struct psp_device *psp);
+#ifdef CONFIG_CRYPTO_DEV_SP_PSP
+int tee_restore(struct psp_device *psp);
+#else
+static inline int tee_restore(struct psp_device *psp) { return 0; }
+#endif /* CONFIG_CRYPTO_DEV_SP_PSP */
+
#endif /* __TEE_DEV_H__ */
--
2.51.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 4/4] crypto: ccp - Send PSP_CMD_TEE_RING_DESTROY when PSP_CMD_TEE_RING_INIT fails
2025-12-11 21:28 [PATCH v2 0/4] Fixes for PMF and CCP drivers after S4 Mario Limonciello (AMD)
` (2 preceding siblings ...)
2025-12-11 21:28 ` [PATCH v2 3/4] crypto: ccp - Add an S4 restore flow Mario Limonciello (AMD)
@ 2025-12-11 21:28 ` Mario Limonciello (AMD)
2025-12-11 22:21 ` Tom Lendacky
2025-12-13 19:05 ` Shyam Sundar S K
2025-12-11 22:23 ` [PATCH v2 0/4] Fixes for PMF and CCP drivers after S4 Tom Lendacky
4 siblings, 2 replies; 9+ messages in thread
From: Mario Limonciello (AMD) @ 2025-12-11 21:28 UTC (permalink / raw)
To: Tom Lendacky, Herbert Xu, Shyam Sundar S K, Ilpo Järvinen
Cc: John Allen, David S . Miller, Hans de Goede,
open list:AMD CRYPTOGRAPHIC COPROCESSOR (CCP) DRIVER,
open list:AMD PMF DRIVER, Lars Francke, Mario Limonciello
The hibernate resume sequence involves loading a resume kernel that is
just used for loading the hibernate image before shifting back to the
existing kernel.
During that hibernate resume sequence the resume kernel may have loaded
the ccp driver. If this happens the resume kernel will also have called
PSP_CMD_TEE_RING_INIT but it will never have called
PSP_CMD_TEE_RING_DESTROY.
This is problematic because the existing kernel needs to re-initialize the
ring. One could argue that the existing kernel should call destroy
as part of restore() but there is no guarantee that the resume kernel did
or didn't load the ccp driver. There is also no callback opportunity for
the resume kernel to destroy before handing back control to the existing
kernel.
Similar problems could potentially exist with the use of kdump and
crash handling. I actually reproduced this issue like this:
1) rmmod ccp
2) hibernate the system
3) resume the system
4) modprobe ccp
The resume kernel will have loaded ccp but never destroyed and then when
I try to modprobe it fails.
Because of these possible cases add a flow that checks the error code from
the PSP_CMD_TEE_RING_INIT call and tries to call PSP_CMD_TEE_RING_DESTROY
if it failed. If this succeeds then call PSP_CMD_TEE_RING_INIT again.
Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
---
drivers/crypto/ccp/tee-dev.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/crypto/ccp/tee-dev.c b/drivers/crypto/ccp/tee-dev.c
index 11c4b05e2f3a..34096cb6ebdc 100644
--- a/drivers/crypto/ccp/tee-dev.c
+++ b/drivers/crypto/ccp/tee-dev.c
@@ -90,6 +90,7 @@ static int tee_init_ring(struct psp_tee_device *tee)
{
int ring_size = MAX_RING_BUFFER_ENTRIES * sizeof(struct tee_ring_cmd);
struct tee_init_ring_cmd *cmd;
+ bool retry = false;
unsigned int reg;
int ret;
@@ -112,6 +113,7 @@ static int tee_init_ring(struct psp_tee_device *tee)
/* Send command buffer details to Trusted OS by writing to
* CPU-PSP message registers
*/
+init:
ret = psp_mailbox_command(tee->psp, PSP_CMD_TEE_RING_INIT, cmd,
TEE_DEFAULT_CMD_TIMEOUT, ®);
if (ret) {
@@ -122,6 +124,15 @@ static int tee_init_ring(struct psp_tee_device *tee)
}
if (FIELD_GET(PSP_CMDRESP_STS, reg)) {
+ if (!retry && FIELD_GET(PSP_CMDRESP_STS, reg) == 0x0000000d) {
+ dev_dbg(tee->dev, "tee: ring init command failed with busy status, retrying\n");
+ ret = psp_mailbox_command(tee->psp, PSP_CMD_TEE_RING_DESTROY, NULL,
+ TEE_DEFAULT_CMD_TIMEOUT, ®);
+ if (!ret) {
+ retry = true;
+ goto init;
+ }
+ }
dev_err(tee->dev, "tee: ring init command failed (%#010lx)\n",
FIELD_GET(PSP_CMDRESP_STS, reg));
tee_free_ring(tee);
--
2.51.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 3/4] crypto: ccp - Add an S4 restore flow
2025-12-11 21:28 ` [PATCH v2 3/4] crypto: ccp - Add an S4 restore flow Mario Limonciello (AMD)
@ 2025-12-11 22:03 ` Tom Lendacky
0 siblings, 0 replies; 9+ messages in thread
From: Tom Lendacky @ 2025-12-11 22:03 UTC (permalink / raw)
To: Mario Limonciello (AMD), Herbert Xu, Shyam Sundar S K,
Ilpo Järvinen
Cc: John Allen, David S . Miller, Hans de Goede,
open list:AMD CRYPTOGRAPHIC COPROCESSOR (CCP) DRIVER,
open list:AMD PMF DRIVER, Lars Francke
On 12/11/25 15:28, Mario Limonciello (AMD) wrote:
> The system will have lost power during S4. The ring used for TEE
> communications needs to be initialized before use.
>
> Fixes: f892a21f51162 ("crypto: ccp - use generic power management")
> Reported-by: Lars Francke <lars.francke@gmail.com>
> Closes: https://lore.kernel.org/platform-driver-x86/CAD-Ua_gfJnQSo8ucS_7ZwzuhoBRJ14zXP7s8b-zX3ZcxcyWePw@mail.gmail.com/
> Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
> ---
> v2:
> * Fix LKP errors
> * Remove free phase
> ---
> drivers/crypto/ccp/sp-dev.c | 13 +++++++++++++
> drivers/crypto/ccp/sp-dev.h | 1 +
> drivers/crypto/ccp/sp-pci.c | 16 +++++++++++++++-
> drivers/crypto/ccp/tee-dev.c | 5 +++++
> drivers/crypto/ccp/tee-dev.h | 6 ++++++
> 5 files changed, 40 insertions(+), 1 deletion(-)
This should follow the same type of flow that initialization follows by
checking for psp_vdata and calling a restore function in psp-dev.c. The
restore function in psp-dev.c in turn calls tee.
Thanks,
Tom
>
> diff --git a/drivers/crypto/ccp/sp-dev.c b/drivers/crypto/ccp/sp-dev.c
> index 3467f6db4f50..e3fa94d14026 100644
> --- a/drivers/crypto/ccp/sp-dev.c
> +++ b/drivers/crypto/ccp/sp-dev.c
> @@ -21,6 +21,7 @@
>
> #include "sev-dev.h"
> #include "ccp-dev.h"
> +#include "tee-dev.h"
> #include "sp-dev.h"
>
> MODULE_AUTHOR("Tom Lendacky <thomas.lendacky@amd.com>");
> @@ -230,6 +231,18 @@ int sp_resume(struct sp_device *sp)
> return 0;
> }
>
> +int sp_restore(struct sp_device *sp)
> +{
> + if (sp->dev_vdata->psp_vdata->tee) {
> + int r = tee_restore(sp->psp_data);
> +
> + if (r)
> + return r;
> + }
> +
> + return sp_resume(sp);
> +}
> +
> struct sp_device *sp_get_psp_master_device(void)
> {
> struct sp_device *i, *ret = NULL;
> diff --git a/drivers/crypto/ccp/sp-dev.h b/drivers/crypto/ccp/sp-dev.h
> index 6f9d7063257d..37b38afaab14 100644
> --- a/drivers/crypto/ccp/sp-dev.h
> +++ b/drivers/crypto/ccp/sp-dev.h
> @@ -141,6 +141,7 @@ void sp_destroy(struct sp_device *sp);
>
> int sp_suspend(struct sp_device *sp);
> int sp_resume(struct sp_device *sp);
> +int sp_restore(struct sp_device *sp);
> int sp_request_ccp_irq(struct sp_device *sp, irq_handler_t handler,
> const char *name, void *data);
> void sp_free_ccp_irq(struct sp_device *sp, void *data);
> diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c
> index e7bb803912a6..ce55563b224d 100644
> --- a/drivers/crypto/ccp/sp-pci.c
> +++ b/drivers/crypto/ccp/sp-pci.c
> @@ -353,6 +353,13 @@ static int __maybe_unused sp_pci_resume(struct device *dev)
> return sp_resume(sp);
> }
>
> +static int __maybe_unused sp_pci_restore(struct device *dev)
> +{
> + struct sp_device *sp = dev_get_drvdata(dev);
> +
> + return sp_restore(sp);
> +}
> +
> #ifdef CONFIG_CRYPTO_DEV_SP_PSP
> static const struct sev_vdata sevv1 = {
> .cmdresp_reg = 0x10580, /* C2PMSG_32 */
> @@ -544,7 +551,14 @@ static const struct pci_device_id sp_pci_table[] = {
> };
> MODULE_DEVICE_TABLE(pci, sp_pci_table);
>
> -static SIMPLE_DEV_PM_OPS(sp_pci_pm_ops, sp_pci_suspend, sp_pci_resume);
> +static const struct dev_pm_ops sp_pci_pm_ops = {
> + .suspend = pm_sleep_ptr(sp_pci_suspend),
> + .resume = pm_sleep_ptr(sp_pci_resume),
> + .freeze = pm_sleep_ptr(sp_pci_suspend),
> + .thaw = pm_sleep_ptr(sp_pci_resume),
> + .poweroff = pm_sleep_ptr(sp_pci_suspend),
> + .restore_early = pm_sleep_ptr(sp_pci_restore),
> +};
>
> static struct pci_driver sp_pci_driver = {
> .name = "ccp",
> diff --git a/drivers/crypto/ccp/tee-dev.c b/drivers/crypto/ccp/tee-dev.c
> index af881daa5855..11c4b05e2f3a 100644
> --- a/drivers/crypto/ccp/tee-dev.c
> +++ b/drivers/crypto/ccp/tee-dev.c
> @@ -366,3 +366,8 @@ int psp_check_tee_status(void)
> return 0;
> }
> EXPORT_SYMBOL(psp_check_tee_status);
> +
> +int tee_restore(struct psp_device *psp)
> +{
> + return tee_init_ring(psp->tee_data);
> +}
> diff --git a/drivers/crypto/ccp/tee-dev.h b/drivers/crypto/ccp/tee-dev.h
> index ea9a2b7c05f5..3409253ac557 100644
> --- a/drivers/crypto/ccp/tee-dev.h
> +++ b/drivers/crypto/ccp/tee-dev.h
> @@ -112,4 +112,10 @@ struct tee_ring_cmd {
> int tee_dev_init(struct psp_device *psp);
> void tee_dev_destroy(struct psp_device *psp);
>
> +#ifdef CONFIG_CRYPTO_DEV_SP_PSP
> +int tee_restore(struct psp_device *psp);
> +#else
> +static inline int tee_restore(struct psp_device *psp) { return 0; }
> +#endif /* CONFIG_CRYPTO_DEV_SP_PSP */
> +
> #endif /* __TEE_DEV_H__ */
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 4/4] crypto: ccp - Send PSP_CMD_TEE_RING_DESTROY when PSP_CMD_TEE_RING_INIT fails
2025-12-11 21:28 ` [PATCH v2 4/4] crypto: ccp - Send PSP_CMD_TEE_RING_DESTROY when PSP_CMD_TEE_RING_INIT fails Mario Limonciello (AMD)
@ 2025-12-11 22:21 ` Tom Lendacky
2025-12-13 19:05 ` Shyam Sundar S K
1 sibling, 0 replies; 9+ messages in thread
From: Tom Lendacky @ 2025-12-11 22:21 UTC (permalink / raw)
To: Mario Limonciello (AMD), Herbert Xu, Shyam Sundar S K,
Ilpo Järvinen
Cc: John Allen, David S . Miller, Hans de Goede,
open list:AMD CRYPTOGRAPHIC COPROCESSOR (CCP) DRIVER,
open list:AMD PMF DRIVER, Lars Francke
On 12/11/25 15:28, Mario Limonciello (AMD) wrote:
> The hibernate resume sequence involves loading a resume kernel that is
> just used for loading the hibernate image before shifting back to the
> existing kernel.
>
> During that hibernate resume sequence the resume kernel may have loaded
> the ccp driver. If this happens the resume kernel will also have called
> PSP_CMD_TEE_RING_INIT but it will never have called
> PSP_CMD_TEE_RING_DESTROY.
>
> This is problematic because the existing kernel needs to re-initialize the
> ring. One could argue that the existing kernel should call destroy
> as part of restore() but there is no guarantee that the resume kernel did
> or didn't load the ccp driver. There is also no callback opportunity for
> the resume kernel to destroy before handing back control to the existing
> kernel.
>
> Similar problems could potentially exist with the use of kdump and
> crash handling. I actually reproduced this issue like this:
>
> 1) rmmod ccp
> 2) hibernate the system
> 3) resume the system
> 4) modprobe ccp
>
> The resume kernel will have loaded ccp but never destroyed and then when
> I try to modprobe it fails.
>
> Because of these possible cases add a flow that checks the error code from
> the PSP_CMD_TEE_RING_INIT call and tries to call PSP_CMD_TEE_RING_DESTROY
> if it failed. If this succeeds then call PSP_CMD_TEE_RING_INIT again.
>
> Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
> ---
> drivers/crypto/ccp/tee-dev.c | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/drivers/crypto/ccp/tee-dev.c b/drivers/crypto/ccp/tee-dev.c
> index 11c4b05e2f3a..34096cb6ebdc 100644
> --- a/drivers/crypto/ccp/tee-dev.c
> +++ b/drivers/crypto/ccp/tee-dev.c
> @@ -90,6 +90,7 @@ static int tee_init_ring(struct psp_tee_device *tee)
> {
> int ring_size = MAX_RING_BUFFER_ENTRIES * sizeof(struct tee_ring_cmd);
> struct tee_init_ring_cmd *cmd;
> + bool retry = false;
> unsigned int reg;
> int ret;
>
> @@ -112,6 +113,7 @@ static int tee_init_ring(struct psp_tee_device *tee)
> /* Send command buffer details to Trusted OS by writing to
> * CPU-PSP message registers
> */
> +init:
> ret = psp_mailbox_command(tee->psp, PSP_CMD_TEE_RING_INIT, cmd,
> TEE_DEFAULT_CMD_TIMEOUT, ®);
> if (ret) {
> @@ -122,6 +124,15 @@ static int tee_init_ring(struct psp_tee_device *tee)
> }
>
> if (FIELD_GET(PSP_CMDRESP_STS, reg)) {
> + if (!retry && FIELD_GET(PSP_CMDRESP_STS, reg) == 0x0000000d) {
> + dev_dbg(tee->dev, "tee: ring init command failed with busy status, retrying\n");
Add a comment here about hibernate/resume and what could be occurring
and why you are issuing PSP_CMD_TEE_RING_DESTROY would be good to have.
> + ret = psp_mailbox_command(tee->psp, PSP_CMD_TEE_RING_DESTROY, NULL,
> + TEE_DEFAULT_CMD_TIMEOUT, ®);
Alignment.
Thanks,
Tom
> + if (!ret) {
> + retry = true;
> + goto init;
> + }
> + }
> dev_err(tee->dev, "tee: ring init command failed (%#010lx)\n",
> FIELD_GET(PSP_CMDRESP_STS, reg));
> tee_free_ring(tee);
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 0/4] Fixes for PMF and CCP drivers after S4
2025-12-11 21:28 [PATCH v2 0/4] Fixes for PMF and CCP drivers after S4 Mario Limonciello (AMD)
` (3 preceding siblings ...)
2025-12-11 21:28 ` [PATCH v2 4/4] crypto: ccp - Send PSP_CMD_TEE_RING_DESTROY when PSP_CMD_TEE_RING_INIT fails Mario Limonciello (AMD)
@ 2025-12-11 22:23 ` Tom Lendacky
4 siblings, 0 replies; 9+ messages in thread
From: Tom Lendacky @ 2025-12-11 22:23 UTC (permalink / raw)
To: Mario Limonciello (AMD), Herbert Xu, Shyam Sundar S K,
Ilpo Järvinen
Cc: John Allen, David S . Miller, Hans de Goede,
open list:AMD CRYPTOGRAPHIC COPROCESSOR (CCP) DRIVER,
open list:AMD PMF DRIVER, Lars Francke
On 12/11/25 15:28, Mario Limonciello (AMD) wrote:
> Lars Francke reported that the PMF driver fails to work afer S4 with:
> ccp 0000:c3:00.2: tee: command 0x5 timed out, disabling PSP
>
> This is because there is a TA loaded to the TEE environment that
> is lost during S4. The TEE rings need to be reinitialized and the
> TA needs to be reloaded.
>
> This series adds those flows to the PMF and CCP drivers.
You should also include Rijo Thomas <Rijo-john.Thomas@amd.com> on this
series.
Thanks,
Tom
>
> ---
> v2:
> * Fixes for potential race conditions in hibernate resume
> * Fix for error handling if tee ring is never destroyed
> * Fixes for dead PSP (which can lead to hangs)
> * Fixes for LKP robot reported issues
>
> Mario Limonciello (AMD) (3):
> crypto: ccp - Declare PSP dead if PSP_CMD_TEE_RING_INIT fails
> crypto: ccp - Send PSP_CMD_TEE_RING_DESTROY when PSP_CMD_TEE_RING_INIT
> fails
> crypto: ccp - Add an S4 restore flow
>
> Shyam Sundar S K (1):
> platform/x86/amd/pmf: Prevent TEE errors after hibernate
>
> drivers/crypto/ccp/sp-dev.c | 13 ++++++
> drivers/crypto/ccp/sp-dev.h | 1 +
> drivers/crypto/ccp/sp-pci.c | 16 ++++++-
> drivers/crypto/ccp/tee-dev.c | 17 ++++++++
> drivers/crypto/ccp/tee-dev.h | 6 +++
> drivers/platform/x86/amd/pmf/core.c | 62 ++++++++++++++++++++++++++-
> drivers/platform/x86/amd/pmf/pmf.h | 10 +++++
> drivers/platform/x86/amd/pmf/tee-if.c | 12 ++----
> 8 files changed, 126 insertions(+), 11 deletions(-)
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 4/4] crypto: ccp - Send PSP_CMD_TEE_RING_DESTROY when PSP_CMD_TEE_RING_INIT fails
2025-12-11 21:28 ` [PATCH v2 4/4] crypto: ccp - Send PSP_CMD_TEE_RING_DESTROY when PSP_CMD_TEE_RING_INIT fails Mario Limonciello (AMD)
2025-12-11 22:21 ` Tom Lendacky
@ 2025-12-13 19:05 ` Shyam Sundar S K
1 sibling, 0 replies; 9+ messages in thread
From: Shyam Sundar S K @ 2025-12-13 19:05 UTC (permalink / raw)
To: Mario Limonciello (AMD), Tom Lendacky, Herbert Xu,
Ilpo Järvinen
Cc: John Allen, David S . Miller, Hans de Goede,
open list:AMD CRYPTOGRAPHIC COPROCESSOR (CCP) DRIVER,
open list:AMD PMF DRIVER, Lars Francke
Hi Mario,
On 12/12/2025 02:58, Mario Limonciello (AMD) wrote:
> The hibernate resume sequence involves loading a resume kernel that is
> just used for loading the hibernate image before shifting back to the
> existing kernel.
>
> During that hibernate resume sequence the resume kernel may have loaded
> the ccp driver. If this happens the resume kernel will also have called
> PSP_CMD_TEE_RING_INIT but it will never have called
> PSP_CMD_TEE_RING_DESTROY.
>
> This is problematic because the existing kernel needs to re-initialize the
> ring. One could argue that the existing kernel should call destroy
> as part of restore() but there is no guarantee that the resume kernel did
> or didn't load the ccp driver. There is also no callback opportunity for
> the resume kernel to destroy before handing back control to the existing
> kernel.
>
> Similar problems could potentially exist with the use of kdump and
> crash handling. I actually reproduced this issue like this:
>
> 1) rmmod ccp
> 2) hibernate the system
> 3) resume the system
> 4) modprobe ccp
>
> The resume kernel will have loaded ccp but never destroyed and then when
> I try to modprobe it fails.
>
> Because of these possible cases add a flow that checks the error code from
> the PSP_CMD_TEE_RING_INIT call and tries to call PSP_CMD_TEE_RING_DESTROY
> if it failed. If this succeeds then call PSP_CMD_TEE_RING_INIT again.
>
> Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
> ---
> drivers/crypto/ccp/tee-dev.c | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/drivers/crypto/ccp/tee-dev.c b/drivers/crypto/ccp/tee-dev.c
> index 11c4b05e2f3a..34096cb6ebdc 100644
> --- a/drivers/crypto/ccp/tee-dev.c
> +++ b/drivers/crypto/ccp/tee-dev.c
> @@ -90,6 +90,7 @@ static int tee_init_ring(struct psp_tee_device *tee)
> {
> int ring_size = MAX_RING_BUFFER_ENTRIES * sizeof(struct tee_ring_cmd);
> struct tee_init_ring_cmd *cmd;
> + bool retry = false;
> unsigned int reg;
> int ret;
>
> @@ -112,6 +113,7 @@ static int tee_init_ring(struct psp_tee_device *tee)
> /* Send command buffer details to Trusted OS by writing to
> * CPU-PSP message registers
> */
> +init:
label can be "retry_init".
> ret = psp_mailbox_command(tee->psp, PSP_CMD_TEE_RING_INIT, cmd,
> TEE_DEFAULT_CMD_TIMEOUT, ®);
> if (ret) {
> @@ -122,6 +124,15 @@ static int tee_init_ring(struct psp_tee_device *tee)
> }
>
> if (FIELD_GET(PSP_CMDRESP_STS, reg)) {
> + if (!retry && FIELD_GET(PSP_CMDRESP_STS, reg) == 0x0000000d) {
and while you enter this condition, a comment would be helpful.
Something like:
/* Handle stale ring from hibernate resume */
Also, you may want a macro.
#define PSP_TEE_STATUS_RING_BUSY 0x0000000d /* Ring already
initialized */
> + dev_dbg(tee->dev, "tee: ring init command failed with busy status, retrying\n");
This is an unusual condition indicating hibernate residual state?
So it can be dev_info() or dev_warn()
> + ret = psp_mailbox_command(tee->psp, PSP_CMD_TEE_RING_DESTROY, NULL,
> + TEE_DEFAULT_CMD_TIMEOUT, ®);
> + if (!ret) {
Should probably also verify FIELD_GET(PSP_CMDRESP_STS, reg) is zero to
ensure destroy actually succeeded.
i.e.
if (!ret && !FIELD_GET(PSP_CMDRESP_STS, reg)) {
..
}
Thanks,
Shyam
> + retry = true;
> + goto init;
> + }
> + }
> dev_err(tee->dev, "tee: ring init command failed (%#010lx)\n",
> FIELD_GET(PSP_CMDRESP_STS, reg));
> tee_free_ring(tee);
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2025-12-13 19:05 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-11 21:28 [PATCH v2 0/4] Fixes for PMF and CCP drivers after S4 Mario Limonciello (AMD)
2025-12-11 21:28 ` [PATCH v2 1/4] platform/x86/amd/pmf: Prevent TEE errors after hibernate Mario Limonciello (AMD)
2025-12-11 21:28 ` [PATCH v2 2/4] crypto: ccp - Declare PSP dead if PSP_CMD_TEE_RING_INIT fails Mario Limonciello (AMD)
2025-12-11 21:28 ` [PATCH v2 3/4] crypto: ccp - Add an S4 restore flow Mario Limonciello (AMD)
2025-12-11 22:03 ` Tom Lendacky
2025-12-11 21:28 ` [PATCH v2 4/4] crypto: ccp - Send PSP_CMD_TEE_RING_DESTROY when PSP_CMD_TEE_RING_INIT fails Mario Limonciello (AMD)
2025-12-11 22:21 ` Tom Lendacky
2025-12-13 19:05 ` Shyam Sundar S K
2025-12-11 22:23 ` [PATCH v2 0/4] Fixes for PMF and CCP drivers after S4 Tom Lendacky
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).