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