2 * Copyright (c) 2015, Linaro Limited
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
14 #include <linux/device.h>
15 #include <linux/slab.h>
16 #include <linux/uaccess.h>
17 #include "optee_private.h"
19 void optee_supp_init(struct optee_supp
*supp
)
21 memset(supp
, 0, sizeof(*supp
));
22 mutex_init(&supp
->ctx_mutex
);
23 mutex_init(&supp
->thrd_mutex
);
24 mutex_init(&supp
->supp_mutex
);
25 init_completion(&supp
->data_to_supp
);
26 init_completion(&supp
->data_from_supp
);
29 void optee_supp_uninit(struct optee_supp
*supp
)
31 mutex_destroy(&supp
->ctx_mutex
);
32 mutex_destroy(&supp
->thrd_mutex
);
33 mutex_destroy(&supp
->supp_mutex
);
37 * optee_supp_thrd_req() - request service from supplicant
38 * @ctx: context doing the request
39 * @func: function requested
40 * @num_params: number of elements in @param array
41 * @param: parameters for function
43 * Returns result of operation to be passed to secure world
45 u32
optee_supp_thrd_req(struct tee_context
*ctx
, u32 func
, size_t num_params
,
46 struct tee_param
*param
)
49 struct optee
*optee
= tee_get_drvdata(ctx
->teedev
);
50 struct optee_supp
*supp
= &optee
->supp
;
54 * Other threads blocks here until we've copied our answer from
57 while (mutex_lock_interruptible(&supp
->thrd_mutex
)) {
58 /* See comment below on when the RPC can be interrupted. */
59 mutex_lock(&supp
->ctx_mutex
);
60 interruptable
= !supp
->ctx
;
61 mutex_unlock(&supp
->ctx_mutex
);
63 return TEEC_ERROR_COMMUNICATION
;
67 * We have exclusive access now since the supplicant at this
68 * point is either doing a
69 * wait_for_completion_interruptible(&supp->data_to_supp) or is in
70 * userspace still about to do the ioctl() to enter
71 * optee_supp_recv() below.
75 supp
->num_params
= num_params
;
77 supp
->req_posted
= true;
79 /* Let supplicant get the data */
80 complete(&supp
->data_to_supp
);
83 * Wait for supplicant to process and return result, once we've
84 * returned from wait_for_completion(data_from_supp) we have
85 * exclusive access again.
87 while (wait_for_completion_interruptible(&supp
->data_from_supp
)) {
88 mutex_lock(&supp
->ctx_mutex
);
89 interruptable
= !supp
->ctx
;
92 * There's no supplicant available and since the
93 * supp->ctx_mutex currently is held none can
94 * become available until the mutex released
97 * Interrupting an RPC to supplicant is only
98 * allowed as a way of slightly improving the user
99 * experience in case the supplicant hasn't been
100 * started yet. During normal operation the supplicant
101 * will serve all requests in a timely manner and
102 * interrupting then wouldn't make sense.
104 supp
->ret
= TEEC_ERROR_COMMUNICATION
;
105 init_completion(&supp
->data_to_supp
);
107 mutex_unlock(&supp
->ctx_mutex
);
114 supp
->req_posted
= false;
116 /* We're done, let someone else talk to the supplicant now. */
117 mutex_unlock(&supp
->thrd_mutex
);
123 * optee_supp_recv() - receive request for supplicant
124 * @ctx: context receiving the request
125 * @func: requested function in supplicant
126 * @num_params: number of elements allocated in @param, updated with number
128 * @param: space for parameters for @func
130 * Returns 0 on success or <0 on failure
132 int optee_supp_recv(struct tee_context
*ctx
, u32
*func
, u32
*num_params
,
133 struct tee_param
*param
)
135 struct tee_device
*teedev
= ctx
->teedev
;
136 struct optee
*optee
= tee_get_drvdata(teedev
);
137 struct optee_supp
*supp
= &optee
->supp
;
141 * In case two threads in one supplicant is calling this function
142 * simultaneously we need to protect the data with a mutex which
143 * we'll release before returning.
145 mutex_lock(&supp
->supp_mutex
);
147 if (supp
->supp_next_send
) {
149 * optee_supp_recv() has been called again without
150 * a optee_supp_send() in between. Supplicant has
151 * probably been restarted before it was able to
152 * write back last result. Abort last request and
155 if (supp
->req_posted
) {
156 supp
->ret
= TEEC_ERROR_COMMUNICATION
;
157 supp
->supp_next_send
= false;
158 complete(&supp
->data_from_supp
);
163 * This is where supplicant will be hanging most of the
164 * time, let's make this interruptable so we can easily
165 * restart supplicant if needed.
167 if (wait_for_completion_interruptible(&supp
->data_to_supp
)) {
172 /* We have exlusive access to the data */
174 if (*num_params
< supp
->num_params
) {
176 * Not enough room for parameters, tell supplicant
177 * it failed and abort last request.
179 supp
->ret
= TEEC_ERROR_COMMUNICATION
;
181 complete(&supp
->data_from_supp
);
186 *num_params
= supp
->num_params
;
187 memcpy(param
, supp
->param
,
188 sizeof(struct tee_param
) * supp
->num_params
);
190 /* Allow optee_supp_send() below to do its work */
191 supp
->supp_next_send
= true;
195 mutex_unlock(&supp
->supp_mutex
);
200 * optee_supp_send() - send result of request from supplicant
201 * @ctx: context sending result
202 * @ret: return value of request
203 * @num_params: number of parameters returned
204 * @param: returned parameters
206 * Returns 0 on success or <0 on failure.
208 int optee_supp_send(struct tee_context
*ctx
, u32 ret
, u32 num_params
,
209 struct tee_param
*param
)
211 struct tee_device
*teedev
= ctx
->teedev
;
212 struct optee
*optee
= tee_get_drvdata(teedev
);
213 struct optee_supp
*supp
= &optee
->supp
;
218 * We still have exclusive access to the data since that's how we
219 * left it when returning from optee_supp_read().
222 /* See comment on mutex in optee_supp_read() above */
223 mutex_lock(&supp
->supp_mutex
);
225 if (!supp
->supp_next_send
) {
227 * Something strange is going on, supplicant shouldn't
228 * enter optee_supp_send() in this state
234 if (num_params
!= supp
->num_params
) {
236 * Something is wrong, let supplicant restart. Next call to
237 * optee_supp_recv() will give an error to the requesting
238 * thread and release it.
244 /* Update out and in/out parameters */
245 for (n
= 0; n
< num_params
; n
++) {
246 struct tee_param
*p
= supp
->param
+ n
;
249 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT
:
250 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT
:
251 p
->u
.value
.a
= param
[n
].u
.value
.a
;
252 p
->u
.value
.b
= param
[n
].u
.value
.b
;
253 p
->u
.value
.c
= param
[n
].u
.value
.c
;
255 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT
:
256 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT
:
257 p
->u
.memref
.size
= param
[n
].u
.memref
.size
;
265 /* Allow optee_supp_recv() above to do its work */
266 supp
->supp_next_send
= false;
268 /* Let the requesting thread continue */
269 complete(&supp
->data_from_supp
);
271 mutex_unlock(&supp
->supp_mutex
);