security: tlk: move ote_print_logs to common code
[linux-3.10.git] / security / tlk_driver / ote_comms.c
1 /*
2  * Copyright (c) 2012-2014 NVIDIA Corporation. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */
18
19 #include <linux/atomic.h>
20 #include <linux/uaccess.h>
21 #include <linux/module.h>
22 #include <linux/slab.h>
23 #include <linux/fs.h>
24 #include <linux/printk.h>
25 #include <linux/ioctl.h>
26 #include <linux/sched.h>
27 #include <linux/mm.h>
28 #include <linux/pagemap.h>
29
30 #include "ote_protocol.h"
31
32 bool verbose_smc;
33 core_param(verbose_smc, verbose_smc, bool, 0644);
34
35 #define SET_RESULT(req, r, ro)  { req->result = r; req->result_origin = ro; }
36
37 static struct te_shmem_desc *te_add_shmem_desc(void *buffer, size_t size,
38                 struct tlk_context *context)
39 {
40         struct te_shmem_desc *shmem_desc = NULL;
41         shmem_desc = kzalloc(sizeof(struct te_shmem_desc), GFP_KERNEL);
42         if (shmem_desc) {
43                 INIT_LIST_HEAD(&(shmem_desc->list));
44                 shmem_desc->buffer = buffer;
45                 shmem_desc->size = size;
46                 list_add_tail(&shmem_desc->list, &(context->shmem_alloc_list));
47         }
48
49         return shmem_desc;
50 }
51
52 static int te_pin_mem_buffers(void *buffer, size_t size,
53                 struct tlk_context *context)
54 {
55         struct te_shmem_desc *shmem_desc = NULL;
56         int ret = 0;
57
58         shmem_desc = te_add_shmem_desc(buffer, size, context);
59         if (!shmem_desc) {
60                 pr_err("%s: te_add_shmem_desc Failed\n", __func__);
61                 ret = OTE_ERROR_OUT_OF_MEMORY;
62                 goto error;
63         }
64
65         return OTE_SUCCESS;
66 error:
67         return ret;
68 }
69
70 static int te_setup_temp_buffers(struct te_request *request,
71                 struct tlk_context *context)
72 {
73         uint32_t i;
74         int ret = OTE_SUCCESS;
75         struct te_oper_param *params = request->params;
76
77         for (i = 0; i < request->params_size; i++) {
78                 switch (params[i].type) {
79                 case TE_PARAM_TYPE_NONE:
80                 case TE_PARAM_TYPE_INT_RO:
81                 case TE_PARAM_TYPE_INT_RW:
82                         break;
83                 case TE_PARAM_TYPE_MEM_RO:
84                 case TE_PARAM_TYPE_MEM_RW:
85                         ret = te_pin_mem_buffers(
86                                 params[i].u.Mem.base,
87                                 params[i].u.Mem.len,
88                                 context);
89                         if (ret < 0) {
90                                 pr_err("%s failed with err (%d)\n",
91                                         __func__, ret);
92                                 ret = OTE_ERROR_BAD_PARAMETERS;
93                                 break;
94                         }
95                         break;
96                 default:
97                         pr_err("%s: OTE_ERROR_BAD_PARAMETERS\n", __func__);
98                         ret = OTE_ERROR_BAD_PARAMETERS;
99                         break;
100                 }
101         }
102         return ret;
103 }
104
105 static int te_setup_temp_buffers_compat(struct te_request_compat *request,
106                 struct tlk_context *context)
107 {
108         uint32_t i;
109         int ret = OTE_SUCCESS;
110         struct te_oper_param_compat *params;
111
112         params = (struct te_oper_param_compat *)(uintptr_t)request->params;
113         for (i = 0; i < request->params_size; i++) {
114                 switch (params[i].type) {
115                 case TE_PARAM_TYPE_NONE:
116                 case TE_PARAM_TYPE_INT_RO:
117                 case TE_PARAM_TYPE_INT_RW:
118                         break;
119                 case TE_PARAM_TYPE_MEM_RO:
120                 case TE_PARAM_TYPE_MEM_RW:
121                         ret = te_pin_mem_buffers(
122                                 (void *)(uintptr_t)params[i].u.Mem.base,
123                                 params[i].u.Mem.len,
124                                 context);
125                         if (ret < 0) {
126                                 pr_err("%s failed with err (%d)\n",
127                                         __func__, ret);
128                                 ret = OTE_ERROR_BAD_PARAMETERS;
129                                 break;
130                         }
131                         break;
132                 default:
133                         pr_err("%s: OTE_ERROR_BAD_PARAMETERS\n", __func__);
134                         ret = OTE_ERROR_BAD_PARAMETERS;
135                         break;
136                 }
137         }
138         return ret;
139 }
140
141 static void te_del_shmem_desc(void *buffer, struct tlk_context *context)
142 {
143         struct te_shmem_desc *shmem_desc, *tmp_shmem_desc;
144
145         list_for_each_entry_safe(shmem_desc, tmp_shmem_desc,
146                 &(context->shmem_alloc_list), list) {
147                 if (shmem_desc->buffer == buffer) {
148                         list_del(&shmem_desc->list);
149                         kfree(shmem_desc);
150                 }
151         }
152 }
153
154 /*
155  * Deregister previously initialized shared memory
156  */
157 void te_unregister_memory(void *buffer,
158         struct tlk_context *context)
159 {
160         if (!(list_empty(&(context->shmem_alloc_list))))
161                 te_del_shmem_desc(buffer, context);
162         else
163                 pr_err("No buffers to unpin\n");
164 }
165
166 static void te_unpin_temp_buffers(struct te_request *request,
167         struct tlk_context *context)
168 {
169         uint32_t i;
170         struct te_oper_param *params = request->params;
171
172         for (i = 0; i < request->params_size; i++) {
173                 switch (params[i].type) {
174                 case TE_PARAM_TYPE_NONE:
175                 case TE_PARAM_TYPE_INT_RO:
176                 case TE_PARAM_TYPE_INT_RW:
177                         break;
178                 case TE_PARAM_TYPE_MEM_RO:
179                 case TE_PARAM_TYPE_MEM_RW:
180                         te_unregister_memory(params[i].u.Mem.base, context);
181                         break;
182                 default:
183                         pr_err("%s: OTE_ERROR_BAD_PARAMETERS\n", __func__);
184                         break;
185                 }
186         }
187 }
188
189 static void te_unpin_temp_buffers_compat(struct te_request_compat *request,
190         struct tlk_context *context)
191 {
192         uint32_t i;
193         struct te_oper_param_compat *params;
194
195         params = (struct te_oper_param_compat *)(uintptr_t)request->params;
196         for (i = 0; i < request->params_size; i++) {
197                 switch (params[i].type) {
198                 case TE_PARAM_TYPE_NONE:
199                 case TE_PARAM_TYPE_INT_RO:
200                 case TE_PARAM_TYPE_INT_RW:
201                         break;
202                 case TE_PARAM_TYPE_MEM_RO:
203                 case TE_PARAM_TYPE_MEM_RW:
204                         te_unregister_memory(
205                                 (void *)(uintptr_t)params[i].u.Mem.base,
206                                 context);
207                         break;
208                 default:
209                         pr_err("%s: OTE_ERROR_BAD_PARAMETERS\n", __func__);
210                         break;
211                 }
212         }
213 }
214
215 #ifdef CONFIG_SMP
216 cpumask_t saved_cpu_mask;
217 static void switch_cpumask_to_cpu0(void)
218 {
219         long ret;
220         cpumask_t local_cpu_mask = CPU_MASK_NONE;
221
222         cpu_set(0, local_cpu_mask);
223         cpumask_copy(&saved_cpu_mask, tsk_cpus_allowed(current));
224         ret = sched_setaffinity(0, &local_cpu_mask);
225         if (ret)
226                 pr_err("sched_setaffinity #1 -> 0x%lX", ret);
227 }
228
229 static void restore_cpumask(void)
230 {
231         long ret = sched_setaffinity(0, &saved_cpu_mask);
232         if (ret)
233                 pr_err("sched_setaffinity #2 -> 0x%lX", ret);
234 }
235 #else
236 static inline void switch_cpumask_to_cpu0(void) {};
237 static inline void restore_cpumask(void) {};
238 #endif
239
240 uint32_t tlk_generic_smc(uint32_t arg0, uintptr_t arg1, uintptr_t arg2)
241 {
242         uint32_t retval;
243
244         switch_cpumask_to_cpu0();
245
246         retval = _tlk_generic_smc(arg0, arg1, arg2);
247         while (retval == 0xFFFFFFFD)
248                 retval = _tlk_generic_smc((60 << 24), 0, 0);
249
250         restore_cpumask();
251
252         /* Print TLK logs if any */
253         ote_print_logs();
254
255         return retval;
256 }
257
258 uint32_t tlk_extended_smc(uintptr_t *regs)
259 {
260         uint32_t retval;
261
262         switch_cpumask_to_cpu0();
263
264         retval = _tlk_extended_smc(regs);
265         while (retval == 0xFFFFFFFD)
266                 retval = _tlk_generic_smc((60 << 24), 0, 0);
267
268         restore_cpumask();
269
270         /* Print TLK logs if any */
271         ote_print_logs();
272
273         return retval;
274 }
275
276 /*
277  * Do an SMC call
278  */
279 static void do_smc(struct te_request *request, struct tlk_device *dev)
280 {
281         uint32_t smc_args;
282         uint32_t smc_params = 0;
283
284         if (dev->req_param_buf) {
285                 smc_args = (char *)request - dev->req_param_buf;
286                 if (request->params)
287                         smc_params = (char *)request->params -
288                                                 dev->req_param_buf;
289         } else {
290                 smc_args = (uint32_t)virt_to_phys(request);
291                 if (request->params)
292                         smc_params = (uint32_t)virt_to_phys(request->params);
293         }
294
295         tlk_generic_smc(request->type, smc_args, smc_params);
296 }
297
298 /*
299  * Do an SMC call
300  */
301 static void do_smc_compat(struct te_request_compat *request,
302                           struct tlk_device *dev)
303 {
304         uint32_t smc_args;
305         uint32_t smc_params = 0;
306
307         smc_args = (char *)request - dev->req_param_buf;
308         if (request->params) {
309                 smc_params =
310                         (char *)(uintptr_t)request->params - dev->req_param_buf;
311         }
312
313         tlk_generic_smc(request->type, smc_args, smc_params);
314 }
315
316 /*
317  * VPR programming SMC
318  */
319 int te_set_vpr_params(void *vpr_base, size_t vpr_size)
320 {
321         uint32_t retval;
322
323         /* Share the same lock used when request is send from user side */
324         mutex_lock(&smc_lock);
325
326         retval = tlk_generic_smc(TE_SMC_PROGRAM_VPR, (uintptr_t)vpr_base,
327                         vpr_size);
328
329         mutex_unlock(&smc_lock);
330
331         if (retval != OTE_SUCCESS) {
332                 pr_err("te_set_vpr_params failed err (0x%x)\n", retval);
333                 return -EINVAL;
334         }
335         return 0;
336 }
337 EXPORT_SYMBOL(te_set_vpr_params);
338
339 /*
340  * Open session SMC (supporting client-based te_open_session() calls)
341  */
342 void te_open_session(struct te_opensession *cmd,
343                      struct te_request *request,
344                      struct tlk_context *context)
345 {
346         int ret;
347
348         ret = te_setup_temp_buffers(request, context);
349         if (ret != OTE_SUCCESS) {
350                 pr_err("te_setup_temp_buffers failed err (0x%x)\n", ret);
351                 SET_RESULT(request, ret, OTE_RESULT_ORIGIN_API);
352                 return;
353         }
354
355         memcpy(&request->dest_uuid,
356                &cmd->dest_uuid,
357                sizeof(struct te_service_id));
358
359         pr_info("OPEN_CLIENT_SESSION: 0x%x 0x%x 0x%x 0x%x\n",
360                 request->dest_uuid[0],
361                 request->dest_uuid[1],
362                 request->dest_uuid[2],
363                 request->dest_uuid[3]);
364
365         request->type = TE_SMC_OPEN_SESSION;
366
367         do_smc(request, context->dev);
368
369         te_unpin_temp_buffers(request, context);
370 }
371
372 /*
373  * Close session SMC (supporting client-based te_close_session() calls)
374  */
375 void te_close_session(struct te_closesession *cmd,
376                       struct te_request *request,
377                       struct tlk_context *context)
378 {
379         request->session_id = cmd->session_id;
380         request->type = TE_SMC_CLOSE_SESSION;
381
382         do_smc(request, context->dev);
383         if (request->result)
384                 pr_info("Error closing session: %08x\n", request->result);
385 }
386
387 /*
388  * Launch operation SMC (supporting client-based te_launch_operation() calls)
389  */
390 void te_launch_operation(struct te_launchop *cmd,
391                          struct te_request *request,
392                          struct tlk_context *context)
393 {
394         int ret;
395
396         ret = te_setup_temp_buffers(request, context);
397         if (ret != OTE_SUCCESS) {
398                 pr_err("te_setup_temp_buffers failed err (0x%x)\n", ret);
399                 SET_RESULT(request, ret, OTE_RESULT_ORIGIN_API);
400                 return;
401         }
402
403         request->session_id = cmd->session_id;
404         request->command_id = cmd->operation.command;
405         request->type = TE_SMC_LAUNCH_OPERATION;
406
407         do_smc(request, context->dev);
408
409         te_unpin_temp_buffers(request, context);
410 }
411
412 /*
413  * Open session SMC (supporting client-based te_open_session() calls)
414  */
415 void te_open_session_compat(struct te_opensession_compat *cmd,
416                             struct te_request_compat *request,
417                             struct tlk_context *context)
418 {
419         int ret;
420
421         ret = te_setup_temp_buffers_compat(request, context);
422         if (ret != OTE_SUCCESS) {
423                 pr_err("te_setup_temp_buffers failed err (0x%x)\n", ret);
424                 SET_RESULT(request, ret, OTE_RESULT_ORIGIN_API);
425                 return;
426         }
427
428         memcpy(&request->dest_uuid,
429                &cmd->dest_uuid,
430                sizeof(struct te_service_id));
431
432         pr_info("OPEN_CLIENT_SESSION_COMPAT: 0x%x 0x%x 0x%x 0x%x\n",
433                 request->dest_uuid[0],
434                 request->dest_uuid[1],
435                 request->dest_uuid[2],
436                 request->dest_uuid[3]);
437
438         request->type = TE_SMC_OPEN_SESSION;
439
440         do_smc_compat(request, context->dev);
441
442         te_unpin_temp_buffers_compat(request, context);
443 }
444
445 /*
446  * Close session SMC (supporting client-based te_close_session() calls)
447  */
448 void te_close_session_compat(struct te_closesession_compat *cmd,
449                              struct te_request_compat *request,
450                              struct tlk_context *context)
451 {
452         request->session_id = cmd->session_id;
453         request->type = TE_SMC_CLOSE_SESSION;
454
455         do_smc_compat(request, context->dev);
456         if (request->result)
457                 pr_info("Error closing session: %08x\n", request->result);
458 }
459
460 /*
461  * Launch operation SMC (supporting client-based te_launch_operation() calls)
462  */
463 void te_launch_operation_compat(struct te_launchop_compat *cmd,
464                                 struct te_request_compat *request,
465                                 struct tlk_context *context)
466 {
467         int ret;
468
469         ret = te_setup_temp_buffers_compat(request, context);
470         if (ret != OTE_SUCCESS) {
471                 pr_err("te_setup_temp_buffers failed err (0x%x)\n", ret);
472                 SET_RESULT(request, ret, OTE_RESULT_ORIGIN_API);
473                 return;
474         }
475
476         request->session_id = cmd->session_id;
477         request->command_id = cmd->operation.command;
478         request->type = TE_SMC_LAUNCH_OPERATION;
479
480         do_smc_compat(request, context->dev);
481
482         te_unpin_temp_buffers_compat(request, context);
483 }
484
485 static int __init tlk_register_irq_handler(void)
486 {
487         tlk_generic_smc(TE_SMC_REGISTER_IRQ_HANDLER,
488                 (uintptr_t)tlk_irq_handler, 0);
489         return 0;
490 }
491
492 arch_initcall(tlk_register_irq_handler);