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
13#include "sp-dev.h"
14#include "psp-dev.h"
15#include "sev-dev.h"
16#include "tee-dev.h"
17#include "platform-access.h"
18#include "dbc.h"
19
20struct psp_device *psp_master;
21
22static struct psp_device *psp_alloc_struct(struct sp_device *sp)
23{
24	struct device *dev = sp->dev;
25	struct psp_device *psp;
26
27	psp = devm_kzalloc(dev, sizeof(*psp), GFP_KERNEL);
28	if (!psp)
29		return NULL;
30
31	psp->dev = dev;
32	psp->sp = sp;
33
34	snprintf(psp->name, sizeof(psp->name), "psp-%u", sp->ord);
35
36	return psp;
37}
38
39static irqreturn_t psp_irq_handler(int irq, void *data)
40{
41	struct psp_device *psp = data;
42	unsigned int status;
43
44	/* Read the interrupt status: */
45	status = ioread32(psp->io_regs + psp->vdata->intsts_reg);
46
47	/* Clear the interrupt status by writing the same value we read. */
48	iowrite32(status, psp->io_regs + psp->vdata->intsts_reg);
49
50	/* invoke subdevice interrupt handlers */
51	if (status) {
52		if (psp->sev_irq_handler)
53			psp->sev_irq_handler(irq, psp->sev_irq_data, status);
54	}
55
56	return IRQ_HANDLED;
57}
58
59static unsigned int psp_get_capability(struct psp_device *psp)
60{
61	unsigned int val = ioread32(psp->io_regs + psp->vdata->feature_reg);
62
63	/*
64	 * Check for a access to the registers.  If this read returns
65	 * 0xffffffff, it's likely that the system is running a broken
66	 * BIOS which disallows access to the device. Stop here and
67	 * fail the PSP initialization (but not the load, as the CCP
68	 * could get properly initialized).
69	 */
70	if (val == 0xffffffff) {
71		dev_notice(psp->dev, "psp: unable to access the device: you might be running a broken BIOS.\n");
72		return -ENODEV;
73	}
74	psp->capability = val;
75
76	/* Detect if TSME and SME are both enabled */
77	if (psp->capability & PSP_CAPABILITY_PSP_SECURITY_REPORTING &&
78	    psp->capability & (PSP_SECURITY_TSME_STATUS << PSP_CAPABILITY_PSP_SECURITY_OFFSET) &&
79	    cc_platform_has(CC_ATTR_HOST_MEM_ENCRYPT))
80		dev_notice(psp->dev, "psp: Both TSME and SME are active, SME is unnecessary when TSME is active.\n");
81
82	return 0;
83}
84
85static int psp_check_sev_support(struct psp_device *psp)
86{
87	/* Check if device supports SEV feature */
88	if (!(psp->capability & PSP_CAPABILITY_SEV)) {
89		dev_dbg(psp->dev, "psp does not support SEV\n");
90		return -ENODEV;
91	}
92
93	return 0;
94}
95
96static int psp_check_tee_support(struct psp_device *psp)
97{
98	/* Check if device supports TEE feature */
99	if (!(psp->capability & PSP_CAPABILITY_TEE)) {
100		dev_dbg(psp->dev, "psp does not support TEE\n");
101		return -ENODEV;
102	}
103
104	return 0;
105}
106
107static void psp_init_platform_access(struct psp_device *psp)
108{
109	int ret;
110
111	ret = platform_access_dev_init(psp);
112	if (ret) {
113		dev_warn(psp->dev, "platform access init failed: %d\n", ret);
114		return;
115	}
116
117	/* dbc must come after platform access as it tests the feature */
118	ret = dbc_dev_init(psp);
119	if (ret)
120		dev_warn(psp->dev, "failed to init dynamic boost control: %d\n",
121			 ret);
122}
123
124static int psp_init(struct psp_device *psp)
125{
126	int ret;
127
128	if (!psp_check_sev_support(psp)) {
129		ret = sev_dev_init(psp);
130		if (ret)
131			return ret;
132	}
133
134	if (!psp_check_tee_support(psp)) {
135		ret = tee_dev_init(psp);
136		if (ret)
137			return ret;
138	}
139
140	if (psp->vdata->platform_access)
141		psp_init_platform_access(psp);
142
143	return 0;
144}
145
146int psp_dev_init(struct sp_device *sp)
147{
148	struct device *dev = sp->dev;
149	struct psp_device *psp;
150	int ret;
151
152	ret = -ENOMEM;
153	psp = psp_alloc_struct(sp);
154	if (!psp)
155		goto e_err;
156
157	sp->psp_data = psp;
158
159	psp->vdata = (struct psp_vdata *)sp->dev_vdata->psp_vdata;
160	if (!psp->vdata) {
161		ret = -ENODEV;
162		dev_err(dev, "missing driver data\n");
163		goto e_err;
164	}
165
166	psp->io_regs = sp->io_map;
167
168	ret = psp_get_capability(psp);
169	if (ret)
170		goto e_disable;
171
172	/* Disable and clear interrupts until ready */
173	iowrite32(0, psp->io_regs + psp->vdata->inten_reg);
174	iowrite32(-1, psp->io_regs + psp->vdata->intsts_reg);
175
176	/* Request an irq */
177	ret = sp_request_psp_irq(psp->sp, psp_irq_handler, psp->name, psp);
178	if (ret) {
179		dev_err(dev, "psp: unable to allocate an IRQ\n");
180		goto e_err;
181	}
182
183	/* master device must be set for platform access */
184	if (psp->sp->set_psp_master_device)
185		psp->sp->set_psp_master_device(psp->sp);
186
187	ret = psp_init(psp);
188	if (ret)
189		goto e_irq;
190
191	/* Enable interrupt */
192	iowrite32(-1, psp->io_regs + psp->vdata->inten_reg);
193
194	dev_notice(dev, "psp enabled\n");
195
196	return 0;
197
198e_irq:
199	if (sp->clear_psp_master_device)
200		sp->clear_psp_master_device(sp);
201
202	sp_free_psp_irq(psp->sp, psp);
203e_err:
204	sp->psp_data = NULL;
205
206	dev_notice(dev, "psp initialization failed\n");
207
208	return ret;
209
210e_disable:
211	sp->psp_data = NULL;
212
213	return ret;
214}
215
216void psp_dev_destroy(struct sp_device *sp)
217{
218	struct psp_device *psp = sp->psp_data;
219
220	if (!psp)
221		return;
222
223	sev_dev_destroy(psp);
224
225	tee_dev_destroy(psp);
226
227	dbc_dev_destroy(psp);
228
229	platform_access_dev_destroy(psp);
230
231	sp_free_psp_irq(sp, psp);
232
233	if (sp->clear_psp_master_device)
234		sp->clear_psp_master_device(sp);
235}
236
237void psp_set_sev_irq_handler(struct psp_device *psp, psp_irq_handler_t handler,
238			     void *data)
239{
240	psp->sev_irq_data = data;
241	psp->sev_irq_handler = handler;
242}
243
244void psp_clear_sev_irq_handler(struct psp_device *psp)
245{
246	psp_set_sev_irq_handler(psp, NULL, NULL);
247}
248
249struct psp_device *psp_get_master_device(void)
250{
251	struct sp_device *sp = sp_get_psp_master_device();
252
253	return sp ? sp->psp_data : NULL;
254}
255
256void psp_pci_init(void)
257{
258	psp_master = psp_get_master_device();
259
260	if (!psp_master)
261		return;
262
263	sev_pci_init();
264}
265
266void psp_pci_exit(void)
267{
268	if (!psp_master)
269		return;
270
271	sev_pci_exit();
272}
273