1 // SPDX-License-Identifier: MIT
3 * Copyright 2019 Advanced Micro Devices, Inc.
6 #include <linux/device.h>
8 #include <linux/tee_drv.h>
9 #include <linux/psp-tee.h>
10 #include <linux/slab.h>
11 #include <linux/psp-sev.h>
12 #include "amdtee_if.h"
13 #include "amdtee_private.h"
15 static int tee_params_to_amd_params(struct tee_param
*tee
, u32 count
,
16 struct tee_operation
*amd
)
24 if (!tee
|| !amd
|| count
> TEE_MAX_PARAMS
)
28 for (i
= 0; i
< count
; i
++) {
29 /* AMD TEE does not support meta parameter */
30 if (tee
[i
].attr
> TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT
)
33 amd
->param_types
|= ((tee
[i
].attr
& 0xF) << i
* 4);
36 for (i
= 0; i
< count
; i
++) {
37 type
= TEE_PARAM_TYPE_GET(amd
->param_types
, i
);
38 pr_debug("%s: type[%d] = 0x%x\n", __func__
, i
, type
);
40 if (type
== TEE_OP_PARAM_TYPE_INVALID
)
43 if (type
== TEE_OP_PARAM_TYPE_NONE
)
46 /* It is assumed that all values are within 2^32-1 */
47 if (type
> TEE_OP_PARAM_TYPE_VALUE_INOUT
) {
48 u32 buf_id
= get_buffer_id(tee
[i
].u
.memref
.shm
);
50 amd
->params
[i
].mref
.buf_id
= buf_id
;
51 amd
->params
[i
].mref
.offset
= tee
[i
].u
.memref
.shm_offs
;
52 amd
->params
[i
].mref
.size
= tee
[i
].u
.memref
.size
;
53 pr_debug("%s: bufid[%d] = 0x%x, offset[%d] = 0x%x, size[%d] = 0x%x\n",
55 i
, amd
->params
[i
].mref
.buf_id
,
56 i
, amd
->params
[i
].mref
.offset
,
57 i
, amd
->params
[i
].mref
.size
);
60 pr_warn("%s: Discarding value c", __func__
);
62 amd
->params
[i
].val
.a
= tee
[i
].u
.value
.a
;
63 amd
->params
[i
].val
.b
= tee
[i
].u
.value
.b
;
64 pr_debug("%s: a[%d] = 0x%x, b[%d] = 0x%x\n", __func__
,
65 i
, amd
->params
[i
].val
.a
,
66 i
, amd
->params
[i
].val
.b
);
72 static int amd_params_to_tee_params(struct tee_param
*tee
, u32 count
,
73 struct tee_operation
*amd
)
81 if (!tee
|| !amd
|| count
> TEE_MAX_PARAMS
)
84 /* Assumes amd->param_types is valid */
85 for (i
= 0; i
< count
; i
++) {
86 type
= TEE_PARAM_TYPE_GET(amd
->param_types
, i
);
87 pr_debug("%s: type[%d] = 0x%x\n", __func__
, i
, type
);
89 if (type
== TEE_OP_PARAM_TYPE_INVALID
||
90 type
> TEE_OP_PARAM_TYPE_MEMREF_INOUT
)
93 if (type
== TEE_OP_PARAM_TYPE_NONE
||
94 type
== TEE_OP_PARAM_TYPE_VALUE_INPUT
||
95 type
== TEE_OP_PARAM_TYPE_MEMREF_INPUT
)
99 * It is assumed that buf_id remains unchanged for
100 * both open_session and invoke_cmd call
102 if (type
> TEE_OP_PARAM_TYPE_MEMREF_INPUT
) {
103 tee
[i
].u
.memref
.shm_offs
= amd
->params
[i
].mref
.offset
;
104 tee
[i
].u
.memref
.size
= amd
->params
[i
].mref
.size
;
105 pr_debug("%s: bufid[%d] = 0x%x, offset[%d] = 0x%x, size[%d] = 0x%x\n",
107 i
, amd
->params
[i
].mref
.buf_id
,
108 i
, amd
->params
[i
].mref
.offset
,
109 i
, amd
->params
[i
].mref
.size
);
111 /* field 'c' not supported by AMD TEE */
112 tee
[i
].u
.value
.a
= amd
->params
[i
].val
.a
;
113 tee
[i
].u
.value
.b
= amd
->params
[i
].val
.b
;
114 tee
[i
].u
.value
.c
= 0;
115 pr_debug("%s: a[%d] = 0x%x, b[%d] = 0x%x\n",
117 i
, amd
->params
[i
].val
.a
,
118 i
, amd
->params
[i
].val
.b
);
124 int handle_unload_ta(u32 ta_handle
)
126 struct tee_cmd_unload_ta cmd
= {0};
133 cmd
.ta_handle
= ta_handle
;
135 ret
= psp_tee_process_cmd(TEE_CMD_ID_UNLOAD_TA
, (void *)&cmd
,
136 sizeof(cmd
), &status
);
137 if (!ret
&& status
!= 0) {
138 pr_err("unload ta: status = 0x%x\n", status
);
145 int handle_close_session(u32 ta_handle
, u32 info
)
147 struct tee_cmd_close_session cmd
= {0};
154 cmd
.ta_handle
= ta_handle
;
155 cmd
.session_info
= info
;
157 ret
= psp_tee_process_cmd(TEE_CMD_ID_CLOSE_SESSION
, (void *)&cmd
,
158 sizeof(cmd
), &status
);
159 if (!ret
&& status
!= 0) {
160 pr_err("close session: status = 0x%x\n", status
);
167 void handle_unmap_shmem(u32 buf_id
)
169 struct tee_cmd_unmap_shared_mem cmd
= {0};
175 ret
= psp_tee_process_cmd(TEE_CMD_ID_UNMAP_SHARED_MEM
, (void *)&cmd
,
176 sizeof(cmd
), &status
);
178 pr_debug("unmap shared memory: buf_id %u status = 0x%x\n",
182 int handle_invoke_cmd(struct tee_ioctl_invoke_arg
*arg
, u32 sinfo
,
185 struct tee_cmd_invoke_cmd cmd
= {0};
188 if (!arg
|| (!p
&& arg
->num_params
))
191 arg
->ret_origin
= TEEC_ORIGIN_COMMS
;
193 if (arg
->session
== 0) {
194 arg
->ret
= TEEC_ERROR_BAD_PARAMETERS
;
198 ret
= tee_params_to_amd_params(p
, arg
->num_params
, &cmd
.op
);
200 pr_err("invalid Params. Abort invoke command\n");
201 arg
->ret
= TEEC_ERROR_BAD_PARAMETERS
;
205 cmd
.ta_handle
= get_ta_handle(arg
->session
);
206 cmd
.cmd_id
= arg
->func
;
207 cmd
.session_info
= sinfo
;
209 ret
= psp_tee_process_cmd(TEE_CMD_ID_INVOKE_CMD
, (void *)&cmd
,
210 sizeof(cmd
), &arg
->ret
);
212 arg
->ret
= TEEC_ERROR_COMMUNICATION
;
214 ret
= amd_params_to_tee_params(p
, arg
->num_params
, &cmd
.op
);
216 pr_err("invoke command: failed to copy output\n");
217 arg
->ret
= TEEC_ERROR_GENERIC
;
220 arg
->ret_origin
= cmd
.return_origin
;
221 pr_debug("invoke command: RO = 0x%x ret = 0x%x\n",
222 arg
->ret_origin
, arg
->ret
);
228 int handle_map_shmem(u32 count
, struct shmem_desc
*start
, u32
*buf_id
)
230 struct tee_cmd_map_shared_mem
*cmd
;
235 if (!count
|| !start
|| !buf_id
)
238 cmd
= kzalloc(sizeof(*cmd
), GFP_KERNEL
);
242 /* Size must be page aligned */
243 for (i
= 0; i
< count
; i
++) {
244 if (!start
[i
].kaddr
|| (start
[i
].size
& (PAGE_SIZE
- 1))) {
249 if ((u64
)start
[i
].kaddr
& (PAGE_SIZE
- 1)) {
250 pr_err("map shared memory: page unaligned. addr 0x%llx",
251 (u64
)start
[i
].kaddr
);
257 cmd
->sg_list
.count
= count
;
259 /* Create buffer list */
260 for (i
= 0; i
< count
; i
++) {
261 paddr
= __psp_pa(start
[i
].kaddr
);
262 cmd
->sg_list
.buf
[i
].hi_addr
= upper_32_bits(paddr
);
263 cmd
->sg_list
.buf
[i
].low_addr
= lower_32_bits(paddr
);
264 cmd
->sg_list
.buf
[i
].size
= start
[i
].size
;
265 cmd
->sg_list
.size
+= cmd
->sg_list
.buf
[i
].size
;
267 pr_debug("buf[%d]:hi addr = 0x%x\n", i
,
268 cmd
->sg_list
.buf
[i
].hi_addr
);
269 pr_debug("buf[%d]:low addr = 0x%x\n", i
,
270 cmd
->sg_list
.buf
[i
].low_addr
);
271 pr_debug("buf[%d]:size = 0x%x\n", i
, cmd
->sg_list
.buf
[i
].size
);
272 pr_debug("list size = 0x%x\n", cmd
->sg_list
.size
);
277 ret
= psp_tee_process_cmd(TEE_CMD_ID_MAP_SHARED_MEM
, (void *)cmd
,
278 sizeof(*cmd
), &status
);
279 if (!ret
&& !status
) {
280 *buf_id
= cmd
->buf_id
;
281 pr_debug("mapped buffer ID = 0x%x\n", *buf_id
);
283 pr_err("map shared memory: status = 0x%x\n", status
);
293 int handle_open_session(struct tee_ioctl_open_session_arg
*arg
, u32
*info
,
296 struct tee_cmd_open_session cmd
= {0};
299 if (!arg
|| !info
|| (!p
&& arg
->num_params
))
302 arg
->ret_origin
= TEEC_ORIGIN_COMMS
;
304 if (arg
->session
== 0) {
305 arg
->ret
= TEEC_ERROR_GENERIC
;
309 ret
= tee_params_to_amd_params(p
, arg
->num_params
, &cmd
.op
);
311 pr_err("invalid Params. Abort open session\n");
312 arg
->ret
= TEEC_ERROR_BAD_PARAMETERS
;
316 cmd
.ta_handle
= get_ta_handle(arg
->session
);
319 ret
= psp_tee_process_cmd(TEE_CMD_ID_OPEN_SESSION
, (void *)&cmd
,
320 sizeof(cmd
), &arg
->ret
);
322 arg
->ret
= TEEC_ERROR_COMMUNICATION
;
324 ret
= amd_params_to_tee_params(p
, arg
->num_params
, &cmd
.op
);
326 pr_err("open session: failed to copy output\n");
327 arg
->ret
= TEEC_ERROR_GENERIC
;
330 arg
->ret_origin
= cmd
.return_origin
;
331 *info
= cmd
.session_info
;
332 pr_debug("open session: session info = 0x%x\n", *info
);
335 pr_debug("open session: ret = 0x%x RO = 0x%x\n", arg
->ret
,
341 int handle_load_ta(void *data
, u32 size
, struct tee_ioctl_open_session_arg
*arg
)
343 struct tee_cmd_load_ta cmd
= {0};
347 if (size
== 0 || !data
|| !arg
)
350 blob
= __psp_pa(data
);
351 if (blob
& (PAGE_SIZE
- 1)) {
352 pr_err("load TA: page unaligned. blob 0x%llx", blob
);
356 cmd
.hi_addr
= upper_32_bits(blob
);
357 cmd
.low_addr
= lower_32_bits(blob
);
360 ret
= psp_tee_process_cmd(TEE_CMD_ID_LOAD_TA
, (void *)&cmd
,
361 sizeof(cmd
), &arg
->ret
);
363 arg
->ret_origin
= TEEC_ORIGIN_COMMS
;
364 arg
->ret
= TEEC_ERROR_COMMUNICATION
;
366 set_session_id(cmd
.ta_handle
, 0, &arg
->session
);
369 pr_debug("load TA: TA handle = 0x%x, RO = 0x%x, ret = 0x%x\n",
370 cmd
.ta_handle
, arg
->ret_origin
, arg
->ret
);