Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/crypto/ccp/psp-dev.c
26282 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* AMD Platform Security Processor (PSP) interface
4
*
5
* Copyright (C) 2016,2019 Advanced Micro Devices, Inc.
6
*
7
* Author: Brijesh Singh <[email protected]>
8
*/
9
10
#include <linux/kernel.h>
11
#include <linux/irqreturn.h>
12
#include <linux/mutex.h>
13
#include <linux/bitfield.h>
14
#include <linux/delay.h>
15
16
#include "sp-dev.h"
17
#include "psp-dev.h"
18
#include "sev-dev.h"
19
#include "tee-dev.h"
20
#include "platform-access.h"
21
#include "dbc.h"
22
#include "hsti.h"
23
24
struct psp_device *psp_master;
25
26
#define PSP_C2PMSG_17_CMDRESP_CMD GENMASK(19, 16)
27
28
static int psp_mailbox_poll(const void __iomem *cmdresp_reg, unsigned int *cmdresp,
29
unsigned int timeout_msecs)
30
{
31
while (true) {
32
*cmdresp = ioread32(cmdresp_reg);
33
if (FIELD_GET(PSP_CMDRESP_RESP, *cmdresp))
34
return 0;
35
36
if (!timeout_msecs--)
37
break;
38
39
usleep_range(1000, 1100);
40
}
41
42
return -ETIMEDOUT;
43
}
44
45
int psp_mailbox_command(struct psp_device *psp, enum psp_cmd cmd, void *cmdbuff,
46
unsigned int timeout_msecs, unsigned int *cmdresp)
47
{
48
void __iomem *cmdresp_reg, *cmdbuff_lo_reg, *cmdbuff_hi_reg;
49
int ret;
50
51
if (!psp || !psp->vdata || !psp->vdata->cmdresp_reg ||
52
!psp->vdata->cmdbuff_addr_lo_reg || !psp->vdata->cmdbuff_addr_hi_reg)
53
return -ENODEV;
54
55
cmdresp_reg = psp->io_regs + psp->vdata->cmdresp_reg;
56
cmdbuff_lo_reg = psp->io_regs + psp->vdata->cmdbuff_addr_lo_reg;
57
cmdbuff_hi_reg = psp->io_regs + psp->vdata->cmdbuff_addr_hi_reg;
58
59
mutex_lock(&psp->mailbox_mutex);
60
61
/* Ensure mailbox is ready for a command */
62
ret = -EBUSY;
63
if (psp_mailbox_poll(cmdresp_reg, cmdresp, 0))
64
goto unlock;
65
66
if (cmdbuff) {
67
iowrite32(lower_32_bits(__psp_pa(cmdbuff)), cmdbuff_lo_reg);
68
iowrite32(upper_32_bits(__psp_pa(cmdbuff)), cmdbuff_hi_reg);
69
}
70
71
*cmdresp = FIELD_PREP(PSP_C2PMSG_17_CMDRESP_CMD, cmd);
72
iowrite32(*cmdresp, cmdresp_reg);
73
74
ret = psp_mailbox_poll(cmdresp_reg, cmdresp, timeout_msecs);
75
76
unlock:
77
mutex_unlock(&psp->mailbox_mutex);
78
79
return ret;
80
}
81
82
int psp_extended_mailbox_cmd(struct psp_device *psp, unsigned int timeout_msecs,
83
struct psp_ext_request *req)
84
{
85
unsigned int reg;
86
int ret;
87
88
print_hex_dump_debug("->psp ", DUMP_PREFIX_OFFSET, 16, 2, req,
89
req->header.payload_size, false);
90
91
ret = psp_mailbox_command(psp, PSP_CMD_TEE_EXTENDED_CMD, (void *)req,
92
timeout_msecs, &reg);
93
if (ret) {
94
return ret;
95
} else if (FIELD_GET(PSP_CMDRESP_STS, reg)) {
96
req->header.status = FIELD_GET(PSP_CMDRESP_STS, reg);
97
return -EIO;
98
}
99
100
print_hex_dump_debug("<-psp ", DUMP_PREFIX_OFFSET, 16, 2, req,
101
req->header.payload_size, false);
102
103
return 0;
104
}
105
106
static struct psp_device *psp_alloc_struct(struct sp_device *sp)
107
{
108
struct device *dev = sp->dev;
109
struct psp_device *psp;
110
111
psp = devm_kzalloc(dev, sizeof(*psp), GFP_KERNEL);
112
if (!psp)
113
return NULL;
114
115
psp->dev = dev;
116
psp->sp = sp;
117
118
snprintf(psp->name, sizeof(psp->name), "psp-%u", sp->ord);
119
120
return psp;
121
}
122
123
static irqreturn_t psp_irq_handler(int irq, void *data)
124
{
125
struct psp_device *psp = data;
126
unsigned int status;
127
128
/* Read the interrupt status: */
129
status = ioread32(psp->io_regs + psp->vdata->intsts_reg);
130
131
/* Clear the interrupt status by writing the same value we read. */
132
iowrite32(status, psp->io_regs + psp->vdata->intsts_reg);
133
134
/* invoke subdevice interrupt handlers */
135
if (status) {
136
if (psp->sev_irq_handler)
137
psp->sev_irq_handler(irq, psp->sev_irq_data, status);
138
}
139
140
return IRQ_HANDLED;
141
}
142
143
static unsigned int psp_get_capability(struct psp_device *psp)
144
{
145
unsigned int val = ioread32(psp->io_regs + psp->vdata->feature_reg);
146
147
/*
148
* Check for a access to the registers. If this read returns
149
* 0xffffffff, it's likely that the system is running a broken
150
* BIOS which disallows access to the device. Stop here and
151
* fail the PSP initialization (but not the load, as the CCP
152
* could get properly initialized).
153
*/
154
if (val == 0xffffffff) {
155
dev_notice(psp->dev, "psp: unable to access the device: you might be running a broken BIOS.\n");
156
return -ENODEV;
157
}
158
psp->capability.raw = val;
159
160
return 0;
161
}
162
163
static int psp_check_sev_support(struct psp_device *psp)
164
{
165
/* Check if device supports SEV feature */
166
if (!psp->capability.sev) {
167
dev_dbg(psp->dev, "psp does not support SEV\n");
168
return -ENODEV;
169
}
170
171
return 0;
172
}
173
174
static int psp_check_tee_support(struct psp_device *psp)
175
{
176
/* Check if device supports TEE feature */
177
if (!psp->capability.tee) {
178
dev_dbg(psp->dev, "psp does not support TEE\n");
179
return -ENODEV;
180
}
181
182
return 0;
183
}
184
185
static int psp_init(struct psp_device *psp)
186
{
187
int ret;
188
189
if (!psp_check_sev_support(psp)) {
190
ret = sev_dev_init(psp);
191
if (ret)
192
return ret;
193
}
194
195
if (!psp_check_tee_support(psp)) {
196
ret = tee_dev_init(psp);
197
if (ret)
198
return ret;
199
}
200
201
if (psp->vdata->platform_access) {
202
ret = platform_access_dev_init(psp);
203
if (ret)
204
return ret;
205
}
206
207
/* dbc must come after platform access as it tests the feature */
208
if (PSP_FEATURE(psp, DBC) ||
209
psp->capability.dbc_thru_ext) {
210
ret = dbc_dev_init(psp);
211
if (ret)
212
return ret;
213
}
214
215
/* HSTI uses platform access on some systems. */
216
ret = psp_init_hsti(psp);
217
if (ret)
218
return ret;
219
220
return 0;
221
}
222
223
int psp_dev_init(struct sp_device *sp)
224
{
225
struct device *dev = sp->dev;
226
struct psp_device *psp;
227
int ret;
228
229
ret = -ENOMEM;
230
psp = psp_alloc_struct(sp);
231
if (!psp)
232
goto e_err;
233
234
sp->psp_data = psp;
235
236
psp->vdata = (struct psp_vdata *)sp->dev_vdata->psp_vdata;
237
if (!psp->vdata) {
238
ret = -ENODEV;
239
dev_err(dev, "missing driver data\n");
240
goto e_err;
241
}
242
243
psp->io_regs = sp->io_map;
244
mutex_init(&psp->mailbox_mutex);
245
246
ret = psp_get_capability(psp);
247
if (ret)
248
goto e_disable;
249
250
/* Disable and clear interrupts until ready */
251
iowrite32(0, psp->io_regs + psp->vdata->inten_reg);
252
iowrite32(-1, psp->io_regs + psp->vdata->intsts_reg);
253
254
/* Request an irq */
255
ret = sp_request_psp_irq(psp->sp, psp_irq_handler, psp->name, psp);
256
if (ret) {
257
dev_err(dev, "psp: unable to allocate an IRQ\n");
258
goto e_err;
259
}
260
261
/* master device must be set for platform access */
262
if (psp->sp->set_psp_master_device)
263
psp->sp->set_psp_master_device(psp->sp);
264
265
ret = psp_init(psp);
266
if (ret)
267
goto e_irq;
268
269
/* Enable interrupt */
270
iowrite32(-1, psp->io_regs + psp->vdata->inten_reg);
271
272
dev_notice(dev, "psp enabled\n");
273
274
return 0;
275
276
e_irq:
277
if (sp->clear_psp_master_device)
278
sp->clear_psp_master_device(sp);
279
280
sp_free_psp_irq(psp->sp, psp);
281
e_err:
282
sp->psp_data = NULL;
283
284
dev_notice(dev, "psp initialization failed\n");
285
286
return ret;
287
288
e_disable:
289
sp->psp_data = NULL;
290
291
return ret;
292
}
293
294
void psp_dev_destroy(struct sp_device *sp)
295
{
296
struct psp_device *psp = sp->psp_data;
297
298
if (!psp)
299
return;
300
301
sev_dev_destroy(psp);
302
303
tee_dev_destroy(psp);
304
305
dbc_dev_destroy(psp);
306
307
platform_access_dev_destroy(psp);
308
309
sp_free_psp_irq(sp, psp);
310
311
if (sp->clear_psp_master_device)
312
sp->clear_psp_master_device(sp);
313
}
314
315
void psp_set_sev_irq_handler(struct psp_device *psp, psp_irq_handler_t handler,
316
void *data)
317
{
318
psp->sev_irq_data = data;
319
psp->sev_irq_handler = handler;
320
}
321
322
void psp_clear_sev_irq_handler(struct psp_device *psp)
323
{
324
psp_set_sev_irq_handler(psp, NULL, NULL);
325
}
326
327
struct psp_device *psp_get_master_device(void)
328
{
329
struct sp_device *sp = sp_get_psp_master_device();
330
331
return sp ? sp->psp_data : NULL;
332
}
333
334
void psp_pci_init(void)
335
{
336
psp_master = psp_get_master_device();
337
338
if (!psp_master)
339
return;
340
341
sev_pci_init();
342
}
343
344
void psp_pci_exit(void)
345
{
346
if (!psp_master)
347
return;
348
349
sev_pci_exit();
350
}
351
352