8560de1ef12ca0f6b07621837e3fa46547d98d41
[tegra/ote_partner/tlk_driver.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 #include <asm/smp_plat.h>
30
31 #include "ote_protocol.h"
32
33 bool verbose_smc;
34 core_param(verbose_smc, verbose_smc, bool, 0644);
35
36 #define SET_RESULT(req, r, ro)  { req->result = r; req->result_origin = ro; }
37
38 static int te_pin_user_pages(void *buffer, size_t size,
39                 unsigned long *pages_ptr)
40 {
41         int ret = 0;
42         unsigned int nr_pages;
43         struct page **pages = NULL;
44
45         nr_pages = (((unsigned int)buffer & (PAGE_SIZE - 1)) +
46                         (size + PAGE_SIZE - 1)) >> PAGE_SHIFT;
47
48         pages = kzalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
49         if (!pages)
50                 return -ENOMEM;
51
52         down_read(&current->mm->mmap_sem);
53         ret = get_user_pages(current, current->mm, (unsigned long)buffer,
54                                 nr_pages, WRITE, 0, pages, NULL);
55         if (ret < 0)
56                 ret = get_user_pages(current, current->mm, (unsigned long)buffer,
57                                 nr_pages, WRITE, 1/*force*/, pages, NULL);
58         up_read(&current->mm->mmap_sem);
59
60         *pages_ptr = (unsigned long) pages;
61
62         return ret;
63 }
64
65 static struct te_shmem_desc *te_add_shmem_desc(void *buffer, size_t size,
66                 unsigned int nr_pages, struct page **pages,
67                 struct tlk_context *context)
68 {
69         struct te_shmem_desc *shmem_desc = NULL;
70         shmem_desc = kzalloc(sizeof(struct te_shmem_desc), GFP_KERNEL);
71         if (shmem_desc) {
72                 INIT_LIST_HEAD(&(shmem_desc->list));
73                 shmem_desc->buffer = buffer;
74                 shmem_desc->size = size;
75                 shmem_desc->nr_pages = nr_pages;
76                 shmem_desc->pages = pages;
77                 list_add_tail(&shmem_desc->list, &(context->shmem_alloc_list));
78         }
79
80         return shmem_desc;
81 }
82
83 static int te_pin_mem_buffers(void *buffer, size_t size,
84                 struct tlk_context *context)
85 {
86         struct te_shmem_desc *shmem_desc = NULL;
87         int ret = 0;
88
89         nr_pages = te_pin_user_pages(buffer, size, &pages);
90         if (nr_pages <= 0) {
91                 pr_err("%s: te_pin_user_pages Failed (%d)\n", __func__,
92                         nr_pages);
93                 ret = OTE_ERROR_OUT_OF_MEMORY;
94                 goto error;
95         }
96
97         shmem_desc = te_add_shmem_desc(buffer, size,
98                                 nr_pages, (struct page **)pages, context);
99         if (!shmem_desc) {
100                 pr_err("%s: te_add_shmem_desc Failed\n", __func__);
101                 ret = OTE_ERROR_OUT_OF_MEMORY;
102                 goto error;
103         }
104
105         return OTE_SUCCESS;
106 error:
107         return ret;
108 }
109
110 static int te_setup_temp_buffers(struct te_request *request,
111                 struct tlk_context *context)
112 {
113         uint32_t i;
114         int ret = OTE_SUCCESS;
115         struct te_oper_param *params = request->params;
116
117         for (i = 0; i < request->params_size; i++) {
118                 switch (params[i].type) {
119                 case TE_PARAM_TYPE_NONE:
120                 case TE_PARAM_TYPE_INT_RO:
121                 case TE_PARAM_TYPE_INT_RW:
122                         break;
123                 case TE_PARAM_TYPE_MEM_RO:
124                 case TE_PARAM_TYPE_MEM_RW:
125                         ret = te_pin_mem_buffers(
126                                 params[i].u.Mem.base,
127                                 params[i].u.Mem.len,
128                                 context);
129                         if (ret < 0) {
130                                 pr_err("%s failed with err (%d)\n",
131                                         __func__, ret);
132                                 ret = OTE_ERROR_BAD_PARAMETERS;
133                                 break;
134                         }
135                         break;
136                 default:
137                         pr_err("%s: OTE_ERROR_BAD_PARAMETERS\n", __func__);
138                         ret = OTE_ERROR_BAD_PARAMETERS;
139                         break;
140                 }
141         }
142         return ret;
143 }
144
145 static int te_setup_temp_buffers_compat(struct te_request_compat *request,
146                 struct tlk_context *context)
147 {
148         uint32_t i;
149         int ret = OTE_SUCCESS;
150         struct te_oper_param_compat *params;
151
152         params = (struct te_oper_param_compat *)(uintptr_t)request->params;
153         for (i = 0; i < request->params_size; i++) {
154                 switch (params[i].type) {
155                 case TE_PARAM_TYPE_NONE:
156                 case TE_PARAM_TYPE_INT_RO:
157                 case TE_PARAM_TYPE_INT_RW:
158                         break;
159                 case TE_PARAM_TYPE_MEM_RO:
160                 case TE_PARAM_TYPE_MEM_RW:
161                         ret = te_pin_mem_buffers(
162                                 (void *)(uintptr_t)params[i].u.Mem.base,
163                                 params[i].u.Mem.len,
164                                 context);
165                         if (ret < 0) {
166                                 pr_err("%s failed with err (%d)\n",
167                                         __func__, ret);
168                                 ret = OTE_ERROR_BAD_PARAMETERS;
169                                 break;
170                         }
171                         break;
172                 default:
173                         pr_err("%s: OTE_ERROR_BAD_PARAMETERS\n", __func__);
174                         ret = OTE_ERROR_BAD_PARAMETERS;
175                         break;
176                 }
177         }
178         return ret;
179 }
180
181 static void te_del_shmem_desc(void *buffer, struct tlk_context *context)
182 {
183         struct te_shmem_desc *shmem_desc, *tmp_shmem_desc;
184
185         list_for_each_entry_safe(shmem_desc, tmp_shmem_desc,
186                 &(context->shmem_alloc_list), list) {
187                 if (shmem_desc->buffer == buffer) {
188                         list_del(&shmem_desc->list);
189                         for (i = 0; i < shmem_desc->nr_pages; i++)
190                                 page_cache_release(shmem_desc->pages[i]);
191                         kfree(shmem_desc->pages);
192                         kfree(shmem_desc);
193                 }
194         }
195 }
196
197 /*
198  * Deregister previously initialized shared memory
199  */
200 void te_unregister_memory(void *buffer,
201         struct tlk_context *context)
202 {
203         if (!(list_empty(&(context->shmem_alloc_list))))
204                 te_del_shmem_desc(buffer, context);
205         else
206                 pr_err("No buffers to unpin\n");
207 }
208
209 static void te_unpin_temp_buffers(struct te_request *request,
210         struct tlk_context *context)
211 {
212         uint32_t i;
213         struct te_oper_param *params = request->params;
214
215         for (i = 0; i < request->params_size; i++) {
216                 switch (params[i].type) {
217                 case TE_PARAM_TYPE_NONE:
218                 case TE_PARAM_TYPE_INT_RO:
219                 case TE_PARAM_TYPE_INT_RW:
220                         break;
221                 case TE_PARAM_TYPE_MEM_RO:
222                 case TE_PARAM_TYPE_MEM_RW:
223                         te_unregister_memory(params[i].u.Mem.base, context);
224                         break;
225                 default:
226                         pr_err("%s: OTE_ERROR_BAD_PARAMETERS\n", __func__);
227                         break;
228                 }
229         }
230 }
231
232 static void te_unpin_temp_buffers_compat(struct te_request_compat *request,
233         struct tlk_context *context)
234 {
235         uint32_t i;
236         struct te_oper_param_compat *params;
237
238         params = (struct te_oper_param_compat *)(uintptr_t)request->params;
239         for (i = 0; i < request->params_size; i++) {
240                 switch (params[i].type) {
241                 case TE_PARAM_TYPE_NONE:
242                 case TE_PARAM_TYPE_INT_RO:
243                 case TE_PARAM_TYPE_INT_RW:
244                         break;
245                 case TE_PARAM_TYPE_MEM_RO:
246                 case TE_PARAM_TYPE_MEM_RW:
247                         te_unregister_memory(
248                                 (void *)(uintptr_t)params[i].u.Mem.base,
249                                 context);
250                         break;
251                 default:
252                         pr_err("%s: OTE_ERROR_BAD_PARAMETERS\n", __func__);
253                         break;
254                 }
255         }
256 }
257
258 #ifdef CONFIG_SMP
259 cpumask_t saved_cpu_mask;
260 static void switch_cpumask_to_cpu0(void)
261 {
262         long ret;
263         cpumask_t local_cpu_mask = CPU_MASK_NONE;
264
265         cpu_set(0, local_cpu_mask);
266         cpumask_copy(&saved_cpu_mask, tsk_cpus_allowed(current));
267         ret = sched_setaffinity(0, &local_cpu_mask);
268         if (ret)
269                 pr_err("sched_setaffinity #1 -> 0x%lX", ret);
270 }
271
272 static void restore_cpumask(void)
273 {
274         long ret = sched_setaffinity(0, &saved_cpu_mask);
275         if (ret)
276                 pr_err("sched_setaffinity #2 -> 0x%lX", ret);
277 }
278 #else
279 static inline void switch_cpumask_to_cpu0(void) {};
280 static inline void restore_cpumask(void) {};
281 #endif
282
283 uint32_t tlk_generic_smc(uint32_t arg0, uintptr_t arg1, uintptr_t arg2)
284 {
285         uint32_t retval;
286
287         switch_cpumask_to_cpu0();
288
289         retval = _tlk_generic_smc(arg0, arg1, arg2);
290         while (retval == TE_ERROR_PREEMPT_BY_IRQ ||
291                retval == TE_ERROR_PREEMPT_BY_FS) {
292                 if (retval == TE_ERROR_PREEMPT_BY_IRQ) {
293                         retval = _tlk_generic_smc((60 << 24), 0, 0);
294                 } else {
295                         tlk_ss_op();
296                         retval = _tlk_generic_smc(TE_SMC_SS_REQ_COMPLETE, 0, 0);
297                 }
298         }
299
300         restore_cpumask();
301
302         /* Print TLK logs if any */
303         ote_print_logs();
304
305         return retval;
306 }
307
308 uint32_t tlk_extended_smc(uintptr_t *regs)
309 {
310         uint32_t retval;
311
312         switch_cpumask_to_cpu0();
313
314         retval = _tlk_extended_smc(regs);
315         while (retval == 0xFFFFFFFD)
316                 retval = _tlk_generic_smc((60 << 24), 0, 0);
317
318         restore_cpumask();
319
320         /* Print TLK logs if any */
321         ote_print_logs();
322
323         return retval;
324 }
325
326 /*
327  * Do an SMC call
328  */
329 static void do_smc(struct te_request *request, struct tlk_device *dev)
330 {
331         uint32_t smc_args;
332         uint32_t smc_params = 0;
333
334         if (dev->req_param_buf) {
335                 smc_args = (char *)request - dev->req_param_buf;
336                 if (request->params)
337                         smc_params = (char *)request->params -
338                                                 dev->req_param_buf;
339         } else {
340                 smc_args = (uint32_t)virt_to_phys(request);
341                 if (request->params)
342                         smc_params = (uint32_t)virt_to_phys(request->params);
343         }
344
345         tlk_generic_smc(request->type, smc_args, smc_params);
346 }
347
348 /*
349  * Do an SMC call
350  */
351 static void do_smc_compat(struct te_request_compat *request,
352                           struct tlk_device *dev)
353 {
354         uint32_t smc_args;
355         uint32_t smc_params = 0;
356
357         smc_args = (char *)request - dev->req_param_buf;
358         if (request->params) {
359                 smc_params =
360                         (char *)(uintptr_t)request->params - dev->req_param_buf;
361         }
362
363         tlk_generic_smc(request->type, smc_args, smc_params);
364 }
365
366 struct tlk_smc_work_args {
367         uint32_t arg0;
368         uint32_t arg1;
369         uint32_t arg2;
370 };
371
372 static long tlk_generic_smc_on_cpu0(void *args)
373 {
374         struct tlk_smc_work_args *work;
375         int cpu = cpu_logical_map(smp_processor_id());
376         uint32_t retval;
377
378         BUG_ON(cpu != 0);
379
380         work = (struct tlk_smc_work_args *)args;
381         retval = _tlk_generic_smc(work->arg0, work->arg1, work->arg2);
382         while (retval == 0xFFFFFFFD)
383                 retval = _tlk_generic_smc((60 << 24), 0, 0);
384         return retval;
385 }
386
387 /*
388  * VPR programming SMC
389  *
390  * This routine is called both from normal threads and worker threads.
391  * The worker threads are per-cpu and have PF_NO_SETAFFINITY set, so
392  * any calls to sched_setaffinity will fail.
393  *
394  * If it's a worker thread on CPU0, just invoke the SMC directly. If
395  * it's running on a non-CPU0, use work_on_cpu() to schedule the SMC
396  * on CPU0.
397  */
398 int te_set_vpr_params(void *vpr_base, size_t vpr_size)
399 {
400         uint32_t retval;
401
402         /* Share the same lock used when request is send from user side */
403         mutex_lock(&smc_lock);
404
405         if (current->flags &
406             (PF_WQ_WORKER | PF_NO_SETAFFINITY | PF_KTHREAD)) {
407                 struct tlk_smc_work_args work_args;
408                 int cpu = cpu_logical_map(smp_processor_id());
409
410                 work_args.arg0 = TE_SMC_PROGRAM_VPR;
411                 work_args.arg1 = (uint32_t)vpr_base;
412                 work_args.arg2 = vpr_size;
413
414                 /* workers don't change CPU. depending on the CPU, execute
415                  * directly or sched work */
416                 if (cpu == 0 && (current->flags & PF_WQ_WORKER))
417                         retval = tlk_generic_smc_on_cpu0(&work_args);
418                 else
419                         retval = work_on_cpu(0,
420                                         tlk_generic_smc_on_cpu0, &work_args);
421         } else {
422                 retval = tlk_generic_smc(TE_SMC_PROGRAM_VPR,
423                                         (uintptr_t)vpr_base, vpr_size);
424         }
425
426         mutex_unlock(&smc_lock);
427
428         if (retval != OTE_SUCCESS) {
429                 pr_err("te_set_vpr_params failed err (0x%x)\n", retval);
430                 return -EINVAL;
431         }
432         return 0;
433 }
434 EXPORT_SYMBOL(te_set_vpr_params);
435
436 /*
437  * Open session SMC (supporting client-based te_open_session() calls)
438  */
439 void te_open_session(struct te_opensession *cmd,
440                      struct te_request *request,
441                      struct tlk_context *context)
442 {
443         int ret;
444
445         ret = te_setup_temp_buffers(request, context);
446         if (ret != OTE_SUCCESS) {
447                 pr_err("te_setup_temp_buffers failed err (0x%x)\n", ret);
448                 SET_RESULT(request, ret, OTE_RESULT_ORIGIN_API);
449                 return;
450         }
451
452         memcpy(&request->dest_uuid,
453                &cmd->dest_uuid,
454                sizeof(struct te_service_id));
455
456         pr_info("OPEN_CLIENT_SESSION: 0x%x 0x%x 0x%x 0x%x\n",
457                 request->dest_uuid[0],
458                 request->dest_uuid[1],
459                 request->dest_uuid[2],
460                 request->dest_uuid[3]);
461
462         request->type = TE_SMC_OPEN_SESSION;
463
464         do_smc(request, context->dev);
465
466         te_unpin_temp_buffers(request, context);
467 }
468
469 /*
470  * Close session SMC (supporting client-based te_close_session() calls)
471  */
472 void te_close_session(struct te_closesession *cmd,
473                       struct te_request *request,
474                       struct tlk_context *context)
475 {
476         request->session_id = cmd->session_id;
477         request->type = TE_SMC_CLOSE_SESSION;
478
479         do_smc(request, context->dev);
480         if (request->result)
481                 pr_info("Error closing session: %08x\n", request->result);
482 }
483
484 /*
485  * Launch operation SMC (supporting client-based te_launch_operation() calls)
486  */
487 void te_launch_operation(struct te_launchop *cmd,
488                          struct te_request *request,
489                          struct tlk_context *context)
490 {
491         int ret;
492
493         ret = te_setup_temp_buffers(request, context);
494         if (ret != OTE_SUCCESS) {
495                 pr_err("te_setup_temp_buffers failed err (0x%x)\n", ret);
496                 SET_RESULT(request, ret, OTE_RESULT_ORIGIN_API);
497                 return;
498         }
499
500         request->session_id = cmd->session_id;
501         request->command_id = cmd->operation.command;
502         request->type = TE_SMC_LAUNCH_OPERATION;
503
504         do_smc(request, context->dev);
505
506         te_unpin_temp_buffers(request, context);
507 }
508
509 /*
510  * Open session SMC (supporting client-based te_open_session() calls)
511  */
512 void te_open_session_compat(struct te_opensession_compat *cmd,
513                             struct te_request_compat *request,
514                             struct tlk_context *context)
515 {
516         int ret;
517
518         ret = te_setup_temp_buffers_compat(request, context);
519         if (ret != OTE_SUCCESS) {
520                 pr_err("te_setup_temp_buffers failed err (0x%x)\n", ret);
521                 SET_RESULT(request, ret, OTE_RESULT_ORIGIN_API);
522                 return;
523         }
524
525         memcpy(&request->dest_uuid,
526                &cmd->dest_uuid,
527                sizeof(struct te_service_id));
528
529         pr_info("OPEN_CLIENT_SESSION_COMPAT: 0x%x 0x%x 0x%x 0x%x\n",
530                 request->dest_uuid[0],
531                 request->dest_uuid[1],
532                 request->dest_uuid[2],
533                 request->dest_uuid[3]);
534
535         request->type = TE_SMC_OPEN_SESSION;
536
537         do_smc_compat(request, context->dev);
538
539         te_unpin_temp_buffers_compat(request, context);
540 }
541
542 /*
543  * Close session SMC (supporting client-based te_close_session() calls)
544  */
545 void te_close_session_compat(struct te_closesession_compat *cmd,
546                              struct te_request_compat *request,
547                              struct tlk_context *context)
548 {
549         request->session_id = cmd->session_id;
550         request->type = TE_SMC_CLOSE_SESSION;
551
552         do_smc_compat(request, context->dev);
553         if (request->result)
554                 pr_info("Error closing session: %08x\n", request->result);
555 }
556
557 /*
558  * Launch operation SMC (supporting client-based te_launch_operation() calls)
559  */
560 void te_launch_operation_compat(struct te_launchop_compat *cmd,
561                                 struct te_request_compat *request,
562                                 struct tlk_context *context)
563 {
564         int ret;
565
566         ret = te_setup_temp_buffers_compat(request, context);
567         if (ret != OTE_SUCCESS) {
568                 pr_err("te_setup_temp_buffers failed err (0x%x)\n", ret);
569                 SET_RESULT(request, ret, OTE_RESULT_ORIGIN_API);
570                 return;
571         }
572
573         request->session_id = cmd->session_id;
574         request->command_id = cmd->operation.command;
575         request->type = TE_SMC_LAUNCH_OPERATION;
576
577         do_smc_compat(request, context->dev);
578
579         te_unpin_temp_buffers_compat(request, context);
580 }
581
582 static int __init tlk_register_irq_handler(void)
583 {
584         tlk_generic_smc(TE_SMC_REGISTER_IRQ_HANDLER,
585                 (uintptr_t)tlk_irq_handler, 0);
586         return 0;
587 }
588
589 arch_initcall(tlk_register_irq_handler);