File Index
Files and directories
Sign in
FILE

psp-dev.c

File preview with syntax highlighting.

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