Skip to content

Commit 3702a05

Browse files
codomaniaherbertx
authored andcommitted
crypto: ccp - add timeout support in the SEV command
Currently, the CCP driver assumes that the SEV command issued to the PSP will always return (i.e. it will never hang). But recently, firmware bugs have shown that a command can hang. Since of the SEV commands are used in probe routines, this can cause boot hangs and/or loss of virtualization capabilities. To protect against firmware bugs, add a timeout in the SEV command execution flow. If a command does not complete within the specified timeout then return -ETIMEOUT and stop the driver from executing any further commands since the state of the SEV firmware is unknown. Cc: Tom Lendacky <thomas.lendacky@amd.com> Cc: Gary Hook <Gary.Hook@amd.com> Cc: Herbert Xu <herbert@gondor.apana.org.au> Cc: linux-kernel@vger.kernel.org Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
1 parent 5736184 commit 3702a05

File tree

1 file changed

+41
-5
lines changed

1 file changed

+41
-5
lines changed

drivers/crypto/ccp/psp-dev.c

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,17 @@ static DEFINE_MUTEX(sev_cmd_mutex);
3838
static struct sev_misc_dev *misc_dev;
3939
static struct psp_device *psp_master;
4040

41+
static int psp_cmd_timeout = 100;
42+
module_param(psp_cmd_timeout, int, 0644);
43+
MODULE_PARM_DESC(psp_cmd_timeout, " default timeout value, in seconds, for PSP commands");
44+
45+
static int psp_probe_timeout = 5;
46+
module_param(psp_probe_timeout, int, 0644);
47+
MODULE_PARM_DESC(psp_probe_timeout, " default timeout value, in seconds, during PSP device probe");
48+
49+
static bool psp_dead;
50+
static int psp_timeout;
51+
4152
static struct psp_device *psp_alloc_struct(struct sp_device *sp)
4253
{
4354
struct device *dev = sp->dev;
@@ -82,10 +93,19 @@ static irqreturn_t psp_irq_handler(int irq, void *data)
8293
return IRQ_HANDLED;
8394
}
8495

85-
static void sev_wait_cmd_ioc(struct psp_device *psp, unsigned int *reg)
96+
static int sev_wait_cmd_ioc(struct psp_device *psp,
97+
unsigned int *reg, unsigned int timeout)
8698
{
87-
wait_event(psp->sev_int_queue, psp->sev_int_rcvd);
99+
int ret;
100+
101+
ret = wait_event_timeout(psp->sev_int_queue,
102+
psp->sev_int_rcvd, timeout * HZ);
103+
if (!ret)
104+
return -ETIMEDOUT;
105+
88106
*reg = ioread32(psp->io_regs + psp->vdata->cmdresp_reg);
107+
108+
return 0;
89109
}
90110

91111
static int sev_cmd_buffer_len(int cmd)
@@ -133,12 +153,15 @@ static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret)
133153
if (!psp)
134154
return -ENODEV;
135155

156+
if (psp_dead)
157+
return -EBUSY;
158+
136159
/* Get the physical address of the command buffer */
137160
phys_lsb = data ? lower_32_bits(__psp_pa(data)) : 0;
138161
phys_msb = data ? upper_32_bits(__psp_pa(data)) : 0;
139162

140-
dev_dbg(psp->dev, "sev command id %#x buffer 0x%08x%08x\n",
141-
cmd, phys_msb, phys_lsb);
163+
dev_dbg(psp->dev, "sev command id %#x buffer 0x%08x%08x timeout %us\n",
164+
cmd, phys_msb, phys_lsb, psp_timeout);
142165

143166
print_hex_dump_debug("(in): ", DUMP_PREFIX_OFFSET, 16, 2, data,
144167
sev_cmd_buffer_len(cmd), false);
@@ -154,7 +177,18 @@ static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret)
154177
iowrite32(reg, psp->io_regs + psp->vdata->cmdresp_reg);
155178

156179
/* wait for command completion */
157-
sev_wait_cmd_ioc(psp, &reg);
180+
ret = sev_wait_cmd_ioc(psp, &reg, psp_timeout);
181+
if (ret) {
182+
if (psp_ret)
183+
*psp_ret = 0;
184+
185+
dev_err(psp->dev, "sev command %#x timed out, disabling PSP \n", cmd);
186+
psp_dead = true;
187+
188+
return ret;
189+
}
190+
191+
psp_timeout = psp_cmd_timeout;
158192

159193
if (psp_ret)
160194
*psp_ret = reg & PSP_CMDRESP_ERR_MASK;
@@ -888,6 +922,8 @@ void psp_pci_init(void)
888922

889923
psp_master = sp->psp_data;
890924

925+
psp_timeout = psp_probe_timeout;
926+
891927
if (sev_get_api_version())
892928
goto err;
893929

0 commit comments

Comments
 (0)