xref: /openbmc/linux/drivers/crypto/ccp/tee-dev.c (revision 33960acccfbd7f24d443cb3d0312ac28abe62bae)
1*33960accSRijo Thomas // SPDX-License-Identifier: MIT
2*33960accSRijo Thomas /*
3*33960accSRijo Thomas  * AMD Trusted Execution Environment (TEE) interface
4*33960accSRijo Thomas  *
5*33960accSRijo Thomas  * Author: Rijo Thomas <Rijo-john.Thomas@amd.com>
6*33960accSRijo Thomas  * Author: Devaraj Rangasamy <Devaraj.Rangasamy@amd.com>
7*33960accSRijo Thomas  *
8*33960accSRijo Thomas  * Copyright 2019 Advanced Micro Devices, Inc.
9*33960accSRijo Thomas  */
10*33960accSRijo Thomas 
11*33960accSRijo Thomas #include <linux/types.h>
12*33960accSRijo Thomas #include <linux/mutex.h>
13*33960accSRijo Thomas #include <linux/delay.h>
14*33960accSRijo Thomas #include <linux/slab.h>
15*33960accSRijo Thomas #include <linux/gfp.h>
16*33960accSRijo Thomas #include <linux/psp-sev.h>
17*33960accSRijo Thomas 
18*33960accSRijo Thomas #include "psp-dev.h"
19*33960accSRijo Thomas #include "tee-dev.h"
20*33960accSRijo Thomas 
21*33960accSRijo Thomas static bool psp_dead;
22*33960accSRijo Thomas 
23*33960accSRijo Thomas static int tee_alloc_ring(struct psp_tee_device *tee, int ring_size)
24*33960accSRijo Thomas {
25*33960accSRijo Thomas 	struct ring_buf_manager *rb_mgr = &tee->rb_mgr;
26*33960accSRijo Thomas 	void *start_addr;
27*33960accSRijo Thomas 
28*33960accSRijo Thomas 	if (!ring_size)
29*33960accSRijo Thomas 		return -EINVAL;
30*33960accSRijo Thomas 
31*33960accSRijo Thomas 	/* We need actual physical address instead of DMA address, since
32*33960accSRijo Thomas 	 * Trusted OS running on AMD Secure Processor will map this region
33*33960accSRijo Thomas 	 */
34*33960accSRijo Thomas 	start_addr = (void *)__get_free_pages(GFP_KERNEL, get_order(ring_size));
35*33960accSRijo Thomas 	if (!start_addr)
36*33960accSRijo Thomas 		return -ENOMEM;
37*33960accSRijo Thomas 
38*33960accSRijo Thomas 	rb_mgr->ring_start = start_addr;
39*33960accSRijo Thomas 	rb_mgr->ring_size = ring_size;
40*33960accSRijo Thomas 	rb_mgr->ring_pa = __psp_pa(start_addr);
41*33960accSRijo Thomas 
42*33960accSRijo Thomas 	return 0;
43*33960accSRijo Thomas }
44*33960accSRijo Thomas 
45*33960accSRijo Thomas static void tee_free_ring(struct psp_tee_device *tee)
46*33960accSRijo Thomas {
47*33960accSRijo Thomas 	struct ring_buf_manager *rb_mgr = &tee->rb_mgr;
48*33960accSRijo Thomas 
49*33960accSRijo Thomas 	if (!rb_mgr->ring_start)
50*33960accSRijo Thomas 		return;
51*33960accSRijo Thomas 
52*33960accSRijo Thomas 	free_pages((unsigned long)rb_mgr->ring_start,
53*33960accSRijo Thomas 		   get_order(rb_mgr->ring_size));
54*33960accSRijo Thomas 
55*33960accSRijo Thomas 	rb_mgr->ring_start = NULL;
56*33960accSRijo Thomas 	rb_mgr->ring_size = 0;
57*33960accSRijo Thomas 	rb_mgr->ring_pa = 0;
58*33960accSRijo Thomas }
59*33960accSRijo Thomas 
60*33960accSRijo Thomas static int tee_wait_cmd_poll(struct psp_tee_device *tee, unsigned int timeout,
61*33960accSRijo Thomas 			     unsigned int *reg)
62*33960accSRijo Thomas {
63*33960accSRijo Thomas 	/* ~10ms sleep per loop => nloop = timeout * 100 */
64*33960accSRijo Thomas 	int nloop = timeout * 100;
65*33960accSRijo Thomas 
66*33960accSRijo Thomas 	while (--nloop) {
67*33960accSRijo Thomas 		*reg = ioread32(tee->io_regs + tee->vdata->cmdresp_reg);
68*33960accSRijo Thomas 		if (*reg & PSP_CMDRESP_RESP)
69*33960accSRijo Thomas 			return 0;
70*33960accSRijo Thomas 
71*33960accSRijo Thomas 		usleep_range(10000, 10100);
72*33960accSRijo Thomas 	}
73*33960accSRijo Thomas 
74*33960accSRijo Thomas 	dev_err(tee->dev, "tee: command timed out, disabling PSP\n");
75*33960accSRijo Thomas 	psp_dead = true;
76*33960accSRijo Thomas 
77*33960accSRijo Thomas 	return -ETIMEDOUT;
78*33960accSRijo Thomas }
79*33960accSRijo Thomas 
80*33960accSRijo Thomas static
81*33960accSRijo Thomas struct tee_init_ring_cmd *tee_alloc_cmd_buffer(struct psp_tee_device *tee)
82*33960accSRijo Thomas {
83*33960accSRijo Thomas 	struct tee_init_ring_cmd *cmd;
84*33960accSRijo Thomas 
85*33960accSRijo Thomas 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
86*33960accSRijo Thomas 	if (!cmd)
87*33960accSRijo Thomas 		return NULL;
88*33960accSRijo Thomas 
89*33960accSRijo Thomas 	cmd->hi_addr = upper_32_bits(tee->rb_mgr.ring_pa);
90*33960accSRijo Thomas 	cmd->low_addr = lower_32_bits(tee->rb_mgr.ring_pa);
91*33960accSRijo Thomas 	cmd->size = tee->rb_mgr.ring_size;
92*33960accSRijo Thomas 
93*33960accSRijo Thomas 	dev_dbg(tee->dev, "tee: ring address: high = 0x%x low = 0x%x size = %u\n",
94*33960accSRijo Thomas 		cmd->hi_addr, cmd->low_addr, cmd->size);
95*33960accSRijo Thomas 
96*33960accSRijo Thomas 	return cmd;
97*33960accSRijo Thomas }
98*33960accSRijo Thomas 
99*33960accSRijo Thomas static inline void tee_free_cmd_buffer(struct tee_init_ring_cmd *cmd)
100*33960accSRijo Thomas {
101*33960accSRijo Thomas 	kfree(cmd);
102*33960accSRijo Thomas }
103*33960accSRijo Thomas 
104*33960accSRijo Thomas static int tee_init_ring(struct psp_tee_device *tee)
105*33960accSRijo Thomas {
106*33960accSRijo Thomas 	int ring_size = MAX_RING_BUFFER_ENTRIES * sizeof(struct tee_ring_cmd);
107*33960accSRijo Thomas 	struct tee_init_ring_cmd *cmd;
108*33960accSRijo Thomas 	phys_addr_t cmd_buffer;
109*33960accSRijo Thomas 	unsigned int reg;
110*33960accSRijo Thomas 	int ret;
111*33960accSRijo Thomas 
112*33960accSRijo Thomas 	BUILD_BUG_ON(sizeof(struct tee_ring_cmd) != 1024);
113*33960accSRijo Thomas 
114*33960accSRijo Thomas 	ret = tee_alloc_ring(tee, ring_size);
115*33960accSRijo Thomas 	if (ret) {
116*33960accSRijo Thomas 		dev_err(tee->dev, "tee: ring allocation failed %d\n", ret);
117*33960accSRijo Thomas 		return ret;
118*33960accSRijo Thomas 	}
119*33960accSRijo Thomas 
120*33960accSRijo Thomas 	tee->rb_mgr.wptr = 0;
121*33960accSRijo Thomas 
122*33960accSRijo Thomas 	cmd = tee_alloc_cmd_buffer(tee);
123*33960accSRijo Thomas 	if (!cmd) {
124*33960accSRijo Thomas 		tee_free_ring(tee);
125*33960accSRijo Thomas 		return -ENOMEM;
126*33960accSRijo Thomas 	}
127*33960accSRijo Thomas 
128*33960accSRijo Thomas 	cmd_buffer = __psp_pa((void *)cmd);
129*33960accSRijo Thomas 
130*33960accSRijo Thomas 	/* Send command buffer details to Trusted OS by writing to
131*33960accSRijo Thomas 	 * CPU-PSP message registers
132*33960accSRijo Thomas 	 */
133*33960accSRijo Thomas 
134*33960accSRijo Thomas 	iowrite32(lower_32_bits(cmd_buffer),
135*33960accSRijo Thomas 		  tee->io_regs + tee->vdata->cmdbuff_addr_lo_reg);
136*33960accSRijo Thomas 	iowrite32(upper_32_bits(cmd_buffer),
137*33960accSRijo Thomas 		  tee->io_regs + tee->vdata->cmdbuff_addr_hi_reg);
138*33960accSRijo Thomas 	iowrite32(TEE_RING_INIT_CMD,
139*33960accSRijo Thomas 		  tee->io_regs + tee->vdata->cmdresp_reg);
140*33960accSRijo Thomas 
141*33960accSRijo Thomas 	ret = tee_wait_cmd_poll(tee, TEE_DEFAULT_TIMEOUT, &reg);
142*33960accSRijo Thomas 	if (ret) {
143*33960accSRijo Thomas 		dev_err(tee->dev, "tee: ring init command timed out\n");
144*33960accSRijo Thomas 		tee_free_ring(tee);
145*33960accSRijo Thomas 		goto free_buf;
146*33960accSRijo Thomas 	}
147*33960accSRijo Thomas 
148*33960accSRijo Thomas 	if (reg & PSP_CMDRESP_ERR_MASK) {
149*33960accSRijo Thomas 		dev_err(tee->dev, "tee: ring init command failed (%#010x)\n",
150*33960accSRijo Thomas 			reg & PSP_CMDRESP_ERR_MASK);
151*33960accSRijo Thomas 		tee_free_ring(tee);
152*33960accSRijo Thomas 		ret = -EIO;
153*33960accSRijo Thomas 	}
154*33960accSRijo Thomas 
155*33960accSRijo Thomas free_buf:
156*33960accSRijo Thomas 	tee_free_cmd_buffer(cmd);
157*33960accSRijo Thomas 
158*33960accSRijo Thomas 	return ret;
159*33960accSRijo Thomas }
160*33960accSRijo Thomas 
161*33960accSRijo Thomas static void tee_destroy_ring(struct psp_tee_device *tee)
162*33960accSRijo Thomas {
163*33960accSRijo Thomas 	unsigned int reg;
164*33960accSRijo Thomas 	int ret;
165*33960accSRijo Thomas 
166*33960accSRijo Thomas 	if (!tee->rb_mgr.ring_start)
167*33960accSRijo Thomas 		return;
168*33960accSRijo Thomas 
169*33960accSRijo Thomas 	if (psp_dead)
170*33960accSRijo Thomas 		goto free_ring;
171*33960accSRijo Thomas 
172*33960accSRijo Thomas 	iowrite32(TEE_RING_DESTROY_CMD,
173*33960accSRijo Thomas 		  tee->io_regs + tee->vdata->cmdresp_reg);
174*33960accSRijo Thomas 
175*33960accSRijo Thomas 	ret = tee_wait_cmd_poll(tee, TEE_DEFAULT_TIMEOUT, &reg);
176*33960accSRijo Thomas 	if (ret) {
177*33960accSRijo Thomas 		dev_err(tee->dev, "tee: ring destroy command timed out\n");
178*33960accSRijo Thomas 	} else if (reg & PSP_CMDRESP_ERR_MASK) {
179*33960accSRijo Thomas 		dev_err(tee->dev, "tee: ring destroy command failed (%#010x)\n",
180*33960accSRijo Thomas 			reg & PSP_CMDRESP_ERR_MASK);
181*33960accSRijo Thomas 	}
182*33960accSRijo Thomas 
183*33960accSRijo Thomas free_ring:
184*33960accSRijo Thomas 	tee_free_ring(tee);
185*33960accSRijo Thomas }
186*33960accSRijo Thomas 
187*33960accSRijo Thomas int tee_dev_init(struct psp_device *psp)
188*33960accSRijo Thomas {
189*33960accSRijo Thomas 	struct device *dev = psp->dev;
190*33960accSRijo Thomas 	struct psp_tee_device *tee;
191*33960accSRijo Thomas 	int ret;
192*33960accSRijo Thomas 
193*33960accSRijo Thomas 	ret = -ENOMEM;
194*33960accSRijo Thomas 	tee = devm_kzalloc(dev, sizeof(*tee), GFP_KERNEL);
195*33960accSRijo Thomas 	if (!tee)
196*33960accSRijo Thomas 		goto e_err;
197*33960accSRijo Thomas 
198*33960accSRijo Thomas 	psp->tee_data = tee;
199*33960accSRijo Thomas 
200*33960accSRijo Thomas 	tee->dev = dev;
201*33960accSRijo Thomas 	tee->psp = psp;
202*33960accSRijo Thomas 
203*33960accSRijo Thomas 	tee->io_regs = psp->io_regs;
204*33960accSRijo Thomas 
205*33960accSRijo Thomas 	tee->vdata = (struct tee_vdata *)psp->vdata->tee;
206*33960accSRijo Thomas 	if (!tee->vdata) {
207*33960accSRijo Thomas 		ret = -ENODEV;
208*33960accSRijo Thomas 		dev_err(dev, "tee: missing driver data\n");
209*33960accSRijo Thomas 		goto e_err;
210*33960accSRijo Thomas 	}
211*33960accSRijo Thomas 
212*33960accSRijo Thomas 	ret = tee_init_ring(tee);
213*33960accSRijo Thomas 	if (ret) {
214*33960accSRijo Thomas 		dev_err(dev, "tee: failed to init ring buffer\n");
215*33960accSRijo Thomas 		goto e_err;
216*33960accSRijo Thomas 	}
217*33960accSRijo Thomas 
218*33960accSRijo Thomas 	dev_notice(dev, "tee enabled\n");
219*33960accSRijo Thomas 
220*33960accSRijo Thomas 	return 0;
221*33960accSRijo Thomas 
222*33960accSRijo Thomas e_err:
223*33960accSRijo Thomas 	psp->tee_data = NULL;
224*33960accSRijo Thomas 
225*33960accSRijo Thomas 	dev_notice(dev, "tee initialization failed\n");
226*33960accSRijo Thomas 
227*33960accSRijo Thomas 	return ret;
228*33960accSRijo Thomas }
229*33960accSRijo Thomas 
230*33960accSRijo Thomas void tee_dev_destroy(struct psp_device *psp)
231*33960accSRijo Thomas {
232*33960accSRijo Thomas 	struct psp_tee_device *tee = psp->tee_data;
233*33960accSRijo Thomas 
234*33960accSRijo Thomas 	if (!tee)
235*33960accSRijo Thomas 		return;
236*33960accSRijo Thomas 
237*33960accSRijo Thomas 	tee_destroy_ring(tee);
238*33960accSRijo Thomas }
239