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