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