Skip to content
/ linux Public

Commit 1733d16

Browse files
superm1Sasha Levin
authored andcommitted
crypto: ccp - Send PSP_CMD_TEE_RING_DESTROY when PSP_CMD_TEE_RING_INIT fails
[ Upstream commit 7b85137 ] 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. Fixes: f892a21 ("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/ Tested-by: Yijun Shen <Yijun.Shen@Dell.com> Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org> Reviewed-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> Acked-by: Tom Lendacky <thomas.lendacky@amd.com> Link: https://patch.msgid.link/20260116041132.153674-6-superm1@kernel.org Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 2abf05a commit 1733d16

File tree

2 files changed

+15
-0
lines changed

2 files changed

+15
-0
lines changed

drivers/crypto/ccp/tee-dev.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ static int tee_init_ring(struct psp_tee_device *tee)
113113
{
114114
int ring_size = MAX_RING_BUFFER_ENTRIES * sizeof(struct tee_ring_cmd);
115115
struct tee_init_ring_cmd *cmd;
116+
bool retry = false;
116117
unsigned int reg;
117118
int ret;
118119

@@ -135,6 +136,7 @@ static int tee_init_ring(struct psp_tee_device *tee)
135136
/* Send command buffer details to Trusted OS by writing to
136137
* CPU-PSP message registers
137138
*/
139+
retry_init:
138140
ret = psp_mailbox_command(tee->psp, PSP_CMD_TEE_RING_INIT, cmd,
139141
TEE_DEFAULT_CMD_TIMEOUT, &reg);
140142
if (ret) {
@@ -145,6 +147,18 @@ static int tee_init_ring(struct psp_tee_device *tee)
145147
}
146148

147149
if (FIELD_GET(PSP_CMDRESP_STS, reg)) {
150+
/*
151+
* During the hibernate resume sequence driver may have gotten loaded
152+
* but the ring not properly destroyed. If the ring doesn't work, try
153+
* to destroy and re-init once.
154+
*/
155+
if (!retry && FIELD_GET(PSP_CMDRESP_STS, reg) == PSP_TEE_STS_RING_BUSY) {
156+
dev_info(tee->dev, "tee: ring init command failed with busy status, retrying\n");
157+
if (tee_send_destroy_cmd(tee)) {
158+
retry = true;
159+
goto retry_init;
160+
}
161+
}
148162
dev_err(tee->dev, "tee: ring init command failed (%#010lx)\n",
149163
FIELD_GET(PSP_CMDRESP_STS, reg));
150164
tee_free_ring(tee);

include/linux/psp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
* and should include an appropriate local definition in their source file.
1919
*/
2020
#define PSP_CMDRESP_STS GENMASK(15, 0)
21+
#define PSP_TEE_STS_RING_BUSY 0x0000000d /* Ring already initialized */
2122
#define PSP_CMDRESP_CMD GENMASK(23, 16)
2223
#define PSP_CMDRESP_RESERVED GENMASK(29, 24)
2324
#define PSP_CMDRESP_RECOVERY BIT(30)

0 commit comments

Comments
 (0)