Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[linux/fpc-iii.git] / drivers / tee / optee / supp.c
blobb4ea0678a43627706ce00bc468eaf6c2b83a4403
1 /*
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);
36 /**
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)
48 bool interruptable;
49 struct optee *optee = tee_get_drvdata(ctx->teedev);
50 struct optee_supp *supp = &optee->supp;
51 u32 ret;
54 * Other threads blocks here until we've copied our answer from
55 * supplicant.
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);
62 if (interruptable)
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.
74 supp->func = func;
75 supp->num_params = num_params;
76 supp->param = param;
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;
90 if (interruptable) {
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
95 * again.
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);
108 if (interruptable)
109 break;
112 ret = supp->ret;
113 supp->param = NULL;
114 supp->req_posted = false;
116 /* We're done, let someone else talk to the supplicant now. */
117 mutex_unlock(&supp->thrd_mutex);
119 return ret;
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
127 * used elements
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;
138 int rc;
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
153 * wait for a new.
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)) {
168 rc = -ERESTARTSYS;
169 goto out;
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;
180 rc = -EINVAL;
181 complete(&supp->data_from_supp);
182 goto out;
185 *func = supp->func;
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;
193 rc = 0;
194 out:
195 mutex_unlock(&supp->supp_mutex);
196 return rc;
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;
214 size_t n;
215 int rc = 0;
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
230 rc = -ENOENT;
231 goto out;
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.
240 rc = -EINVAL;
241 goto out;
244 /* Update out and in/out parameters */
245 for (n = 0; n < num_params; n++) {
246 struct tee_param *p = supp->param + n;
248 switch (p->attr) {
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;
254 break;
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;
258 break;
259 default:
260 break;
263 supp->ret = ret;
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);
270 out:
271 mutex_unlock(&supp->supp_mutex);
272 return rc;