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