Merge remote-tracking branch 'asoc/fix/dapm' into asoc-linus
[sfrench/cifs-2.6.git] / arch / arm64 / kernel / armv8_deprecated.c
1 /*
2  *  Copyright (C) 2014 ARM Limited
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 version 2 as
6  * published by the Free Software Foundation.
7  */
8
9 #include <linux/cpu.h>
10 #include <linux/init.h>
11 #include <linux/list.h>
12 #include <linux/perf_event.h>
13 #include <linux/sched.h>
14 #include <linux/slab.h>
15 #include <linux/sysctl.h>
16
17 #include <asm/insn.h>
18 #include <asm/opcodes.h>
19 #include <asm/system_misc.h>
20 #include <asm/traps.h>
21 #include <asm/uaccess.h>
22
23 #define CREATE_TRACE_POINTS
24 #include "trace-events-emulation.h"
25
26 /*
27  * The runtime support for deprecated instruction support can be in one of
28  * following three states -
29  *
30  * 0 = undef
31  * 1 = emulate (software emulation)
32  * 2 = hw (supported in hardware)
33  */
34 enum insn_emulation_mode {
35         INSN_UNDEF,
36         INSN_EMULATE,
37         INSN_HW,
38 };
39
40 enum legacy_insn_status {
41         INSN_DEPRECATED,
42         INSN_OBSOLETE,
43 };
44
45 struct insn_emulation_ops {
46         const char              *name;
47         enum legacy_insn_status status;
48         struct undef_hook       *hooks;
49         int                     (*set_hw_mode)(bool enable);
50 };
51
52 struct insn_emulation {
53         struct list_head node;
54         struct insn_emulation_ops *ops;
55         int current_mode;
56         int min;
57         int max;
58 };
59
60 static LIST_HEAD(insn_emulation);
61 static int nr_insn_emulated;
62 static DEFINE_RAW_SPINLOCK(insn_emulation_lock);
63
64 static void register_emulation_hooks(struct insn_emulation_ops *ops)
65 {
66         struct undef_hook *hook;
67
68         BUG_ON(!ops->hooks);
69
70         for (hook = ops->hooks; hook->instr_mask; hook++)
71                 register_undef_hook(hook);
72
73         pr_notice("Registered %s emulation handler\n", ops->name);
74 }
75
76 static void remove_emulation_hooks(struct insn_emulation_ops *ops)
77 {
78         struct undef_hook *hook;
79
80         BUG_ON(!ops->hooks);
81
82         for (hook = ops->hooks; hook->instr_mask; hook++)
83                 unregister_undef_hook(hook);
84
85         pr_notice("Removed %s emulation handler\n", ops->name);
86 }
87
88 static int update_insn_emulation_mode(struct insn_emulation *insn,
89                                        enum insn_emulation_mode prev)
90 {
91         int ret = 0;
92
93         switch (prev) {
94         case INSN_UNDEF: /* Nothing to be done */
95                 break;
96         case INSN_EMULATE:
97                 remove_emulation_hooks(insn->ops);
98                 break;
99         case INSN_HW:
100                 if (insn->ops->set_hw_mode) {
101                         insn->ops->set_hw_mode(false);
102                         pr_notice("Disabled %s support\n", insn->ops->name);
103                 }
104                 break;
105         }
106
107         switch (insn->current_mode) {
108         case INSN_UNDEF:
109                 break;
110         case INSN_EMULATE:
111                 register_emulation_hooks(insn->ops);
112                 break;
113         case INSN_HW:
114                 if (insn->ops->set_hw_mode && insn->ops->set_hw_mode(true))
115                         pr_notice("Enabled %s support\n", insn->ops->name);
116                 else
117                         ret = -EINVAL;
118                 break;
119         }
120
121         return ret;
122 }
123
124 static void register_insn_emulation(struct insn_emulation_ops *ops)
125 {
126         unsigned long flags;
127         struct insn_emulation *insn;
128
129         insn = kzalloc(sizeof(*insn), GFP_KERNEL);
130         insn->ops = ops;
131         insn->min = INSN_UNDEF;
132
133         switch (ops->status) {
134         case INSN_DEPRECATED:
135                 insn->current_mode = INSN_EMULATE;
136                 insn->max = INSN_HW;
137                 break;
138         case INSN_OBSOLETE:
139                 insn->current_mode = INSN_UNDEF;
140                 insn->max = INSN_EMULATE;
141                 break;
142         }
143
144         raw_spin_lock_irqsave(&insn_emulation_lock, flags);
145         list_add(&insn->node, &insn_emulation);
146         nr_insn_emulated++;
147         raw_spin_unlock_irqrestore(&insn_emulation_lock, flags);
148
149         /* Register any handlers if required */
150         update_insn_emulation_mode(insn, INSN_UNDEF);
151 }
152
153 static int emulation_proc_handler(struct ctl_table *table, int write,
154                                   void __user *buffer, size_t *lenp,
155                                   loff_t *ppos)
156 {
157         int ret = 0;
158         struct insn_emulation *insn = (struct insn_emulation *) table->data;
159         enum insn_emulation_mode prev_mode = insn->current_mode;
160
161         table->data = &insn->current_mode;
162         ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
163
164         if (ret || !write || prev_mode == insn->current_mode)
165                 goto ret;
166
167         ret = update_insn_emulation_mode(insn, prev_mode);
168         if (ret) {
169                 /* Mode change failed, revert to previous mode. */
170                 insn->current_mode = prev_mode;
171                 update_insn_emulation_mode(insn, INSN_UNDEF);
172         }
173 ret:
174         table->data = insn;
175         return ret;
176 }
177
178 static struct ctl_table ctl_abi[] = {
179         {
180                 .procname = "abi",
181                 .mode = 0555,
182         },
183         { }
184 };
185
186 static void register_insn_emulation_sysctl(struct ctl_table *table)
187 {
188         unsigned long flags;
189         int i = 0;
190         struct insn_emulation *insn;
191         struct ctl_table *insns_sysctl, *sysctl;
192
193         insns_sysctl = kzalloc(sizeof(*sysctl) * (nr_insn_emulated + 1),
194                               GFP_KERNEL);
195
196         raw_spin_lock_irqsave(&insn_emulation_lock, flags);
197         list_for_each_entry(insn, &insn_emulation, node) {
198                 sysctl = &insns_sysctl[i];
199
200                 sysctl->mode = 0644;
201                 sysctl->maxlen = sizeof(int);
202
203                 sysctl->procname = insn->ops->name;
204                 sysctl->data = insn;
205                 sysctl->extra1 = &insn->min;
206                 sysctl->extra2 = &insn->max;
207                 sysctl->proc_handler = emulation_proc_handler;
208                 i++;
209         }
210         raw_spin_unlock_irqrestore(&insn_emulation_lock, flags);
211
212         table->child = insns_sysctl;
213         register_sysctl_table(table);
214 }
215
216 /*
217  *  Implement emulation of the SWP/SWPB instructions using load-exclusive and
218  *  store-exclusive.
219  *
220  *  Syntax of SWP{B} instruction: SWP{B}<c> <Rt>, <Rt2>, [<Rn>]
221  *  Where: Rt  = destination
222  *         Rt2 = source
223  *         Rn  = address
224  */
225
226 /*
227  * Error-checking SWP macros implemented using ldxr{b}/stxr{b}
228  */
229 #define __user_swpX_asm(data, addr, res, temp, B)               \
230         __asm__ __volatile__(                                   \
231         "       mov             %w2, %w1\n"                     \
232         "0:     ldxr"B"         %w1, [%3]\n"                    \
233         "1:     stxr"B"         %w0, %w2, [%3]\n"               \
234         "       cbz             %w0, 2f\n"                      \
235         "       mov             %w0, %w4\n"                     \
236         "2:\n"                                                  \
237         "       .pushsection     .fixup,\"ax\"\n"               \
238         "       .align          2\n"                            \
239         "3:     mov             %w0, %w5\n"                     \
240         "       b               2b\n"                           \
241         "       .popsection"                                    \
242         "       .pushsection     __ex_table,\"a\"\n"            \
243         "       .align          3\n"                            \
244         "       .quad           0b, 3b\n"                       \
245         "       .quad           1b, 3b\n"                       \
246         "       .popsection"                                    \
247         : "=&r" (res), "+r" (data), "=&r" (temp)                \
248         : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT)              \
249         : "memory")
250
251 #define __user_swp_asm(data, addr, res, temp) \
252         __user_swpX_asm(data, addr, res, temp, "")
253 #define __user_swpb_asm(data, addr, res, temp) \
254         __user_swpX_asm(data, addr, res, temp, "b")
255
256 /*
257  * Bit 22 of the instruction encoding distinguishes between
258  * the SWP and SWPB variants (bit set means SWPB).
259  */
260 #define TYPE_SWPB (1 << 22)
261
262 /*
263  * Set up process info to signal segmentation fault - called on access error.
264  */
265 static void set_segfault(struct pt_regs *regs, unsigned long addr)
266 {
267         siginfo_t info;
268
269         down_read(&current->mm->mmap_sem);
270         if (find_vma(current->mm, addr) == NULL)
271                 info.si_code = SEGV_MAPERR;
272         else
273                 info.si_code = SEGV_ACCERR;
274         up_read(&current->mm->mmap_sem);
275
276         info.si_signo = SIGSEGV;
277         info.si_errno = 0;
278         info.si_addr  = (void *) instruction_pointer(regs);
279
280         pr_debug("SWP{B} emulation: access caused memory abort!\n");
281         arm64_notify_die("Illegal memory access", regs, &info, 0);
282 }
283
284 static int emulate_swpX(unsigned int address, unsigned int *data,
285                         unsigned int type)
286 {
287         unsigned int res = 0;
288
289         if ((type != TYPE_SWPB) && (address & 0x3)) {
290                 /* SWP to unaligned address not permitted */
291                 pr_debug("SWP instruction on unaligned pointer!\n");
292                 return -EFAULT;
293         }
294
295         while (1) {
296                 unsigned long temp;
297
298                 if (type == TYPE_SWPB)
299                         __user_swpb_asm(*data, address, res, temp);
300                 else
301                         __user_swp_asm(*data, address, res, temp);
302
303                 if (likely(res != -EAGAIN) || signal_pending(current))
304                         break;
305
306                 cond_resched();
307         }
308
309         return res;
310 }
311
312 /*
313  * swp_handler logs the id of calling process, dissects the instruction, sanity
314  * checks the memory location, calls emulate_swpX for the actual operation and
315  * deals with fixup/error handling before returning
316  */
317 static int swp_handler(struct pt_regs *regs, u32 instr)
318 {
319         u32 destreg, data, type, address = 0;
320         int rn, rt2, res = 0;
321
322         perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->pc);
323
324         type = instr & TYPE_SWPB;
325
326         switch (arm_check_condition(instr, regs->pstate)) {
327         case ARM_OPCODE_CONDTEST_PASS:
328                 break;
329         case ARM_OPCODE_CONDTEST_FAIL:
330                 /* Condition failed - return to next instruction */
331                 goto ret;
332         case ARM_OPCODE_CONDTEST_UNCOND:
333                 /* If unconditional encoding - not a SWP, undef */
334                 return -EFAULT;
335         default:
336                 return -EINVAL;
337         }
338
339         rn = aarch32_insn_extract_reg_num(instr, A32_RN_OFFSET);
340         rt2 = aarch32_insn_extract_reg_num(instr, A32_RT2_OFFSET);
341
342         address = (u32)regs->user_regs.regs[rn];
343         data    = (u32)regs->user_regs.regs[rt2];
344         destreg = aarch32_insn_extract_reg_num(instr, A32_RT_OFFSET);
345
346         pr_debug("addr in r%d->0x%08x, dest is r%d, source in r%d->0x%08x)\n",
347                 rn, address, destreg,
348                 aarch32_insn_extract_reg_num(instr, A32_RT2_OFFSET), data);
349
350         /* Check access in reasonable access range for both SWP and SWPB */
351         if (!access_ok(VERIFY_WRITE, (address & ~3), 4)) {
352                 pr_debug("SWP{B} emulation: access to 0x%08x not allowed!\n",
353                         address);
354                 goto fault;
355         }
356
357         res = emulate_swpX(address, &data, type);
358         if (res == -EFAULT)
359                 goto fault;
360         else if (res == 0)
361                 regs->user_regs.regs[destreg] = data;
362
363 ret:
364         if (type == TYPE_SWPB)
365                 trace_instruction_emulation("swpb", regs->pc);
366         else
367                 trace_instruction_emulation("swp", regs->pc);
368
369         pr_warn_ratelimited("\"%s\" (%ld) uses obsolete SWP{B} instruction at 0x%llx\n",
370                         current->comm, (unsigned long)current->pid, regs->pc);
371
372         regs->pc += 4;
373         return 0;
374
375 fault:
376         set_segfault(regs, address);
377
378         return 0;
379 }
380
381 /*
382  * Only emulate SWP/SWPB executed in ARM state/User mode.
383  * The kernel must be SWP free and SWP{B} does not exist in Thumb.
384  */
385 static struct undef_hook swp_hooks[] = {
386         {
387                 .instr_mask     = 0x0fb00ff0,
388                 .instr_val      = 0x01000090,
389                 .pstate_mask    = COMPAT_PSR_MODE_MASK,
390                 .pstate_val     = COMPAT_PSR_MODE_USR,
391                 .fn             = swp_handler
392         },
393         { }
394 };
395
396 static struct insn_emulation_ops swp_ops = {
397         .name = "swp",
398         .status = INSN_OBSOLETE,
399         .hooks = swp_hooks,
400         .set_hw_mode = NULL,
401 };
402
403 static int cp15barrier_handler(struct pt_regs *regs, u32 instr)
404 {
405         perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->pc);
406
407         switch (arm_check_condition(instr, regs->pstate)) {
408         case ARM_OPCODE_CONDTEST_PASS:
409                 break;
410         case ARM_OPCODE_CONDTEST_FAIL:
411                 /* Condition failed - return to next instruction */
412                 goto ret;
413         case ARM_OPCODE_CONDTEST_UNCOND:
414                 /* If unconditional encoding - not a barrier instruction */
415                 return -EFAULT;
416         default:
417                 return -EINVAL;
418         }
419
420         switch (aarch32_insn_mcr_extract_crm(instr)) {
421         case 10:
422                 /*
423                  * dmb - mcr p15, 0, Rt, c7, c10, 5
424                  * dsb - mcr p15, 0, Rt, c7, c10, 4
425                  */
426                 if (aarch32_insn_mcr_extract_opc2(instr) == 5) {
427                         dmb(sy);
428                         trace_instruction_emulation(
429                                 "mcr p15, 0, Rt, c7, c10, 5 ; dmb", regs->pc);
430                 } else {
431                         dsb(sy);
432                         trace_instruction_emulation(
433                                 "mcr p15, 0, Rt, c7, c10, 4 ; dsb", regs->pc);
434                 }
435                 break;
436         case 5:
437                 /*
438                  * isb - mcr p15, 0, Rt, c7, c5, 4
439                  *
440                  * Taking an exception or returning from one acts as an
441                  * instruction barrier. So no explicit barrier needed here.
442                  */
443                 trace_instruction_emulation(
444                         "mcr p15, 0, Rt, c7, c5, 4 ; isb", regs->pc);
445                 break;
446         }
447
448 ret:
449         pr_warn_ratelimited("\"%s\" (%ld) uses deprecated CP15 Barrier instruction at 0x%llx\n",
450                         current->comm, (unsigned long)current->pid, regs->pc);
451
452         regs->pc += 4;
453         return 0;
454 }
455
456 #define SCTLR_EL1_CP15BEN (1 << 5)
457
458 static inline void config_sctlr_el1(u32 clear, u32 set)
459 {
460         u32 val;
461
462         asm volatile("mrs %0, sctlr_el1" : "=r" (val));
463         val &= ~clear;
464         val |= set;
465         asm volatile("msr sctlr_el1, %0" : : "r" (val));
466 }
467
468 static void enable_cp15_ben(void *info)
469 {
470         config_sctlr_el1(0, SCTLR_EL1_CP15BEN);
471 }
472
473 static void disable_cp15_ben(void *info)
474 {
475         config_sctlr_el1(SCTLR_EL1_CP15BEN, 0);
476 }
477
478 static int cpu_hotplug_notify(struct notifier_block *b,
479                               unsigned long action, void *hcpu)
480 {
481         switch (action) {
482         case CPU_STARTING:
483         case CPU_STARTING_FROZEN:
484                 enable_cp15_ben(NULL);
485                 return NOTIFY_DONE;
486         case CPU_DYING:
487         case CPU_DYING_FROZEN:
488                 disable_cp15_ben(NULL);
489                 return NOTIFY_DONE;
490         }
491
492         return NOTIFY_OK;
493 }
494
495 static struct notifier_block cpu_hotplug_notifier = {
496         .notifier_call = cpu_hotplug_notify,
497 };
498
499 static int cp15_barrier_set_hw_mode(bool enable)
500 {
501         if (enable) {
502                 register_cpu_notifier(&cpu_hotplug_notifier);
503                 on_each_cpu(enable_cp15_ben, NULL, true);
504         } else {
505                 unregister_cpu_notifier(&cpu_hotplug_notifier);
506                 on_each_cpu(disable_cp15_ben, NULL, true);
507         }
508
509         return true;
510 }
511
512 static struct undef_hook cp15_barrier_hooks[] = {
513         {
514                 .instr_mask     = 0x0fff0fdf,
515                 .instr_val      = 0x0e070f9a,
516                 .pstate_mask    = COMPAT_PSR_MODE_MASK,
517                 .pstate_val     = COMPAT_PSR_MODE_USR,
518                 .fn             = cp15barrier_handler,
519         },
520         {
521                 .instr_mask     = 0x0fff0fff,
522                 .instr_val      = 0x0e070f95,
523                 .pstate_mask    = COMPAT_PSR_MODE_MASK,
524                 .pstate_val     = COMPAT_PSR_MODE_USR,
525                 .fn             = cp15barrier_handler,
526         },
527         { }
528 };
529
530 static struct insn_emulation_ops cp15_barrier_ops = {
531         .name = "cp15_barrier",
532         .status = INSN_DEPRECATED,
533         .hooks = cp15_barrier_hooks,
534         .set_hw_mode = cp15_barrier_set_hw_mode,
535 };
536
537 /*
538  * Invoked as late_initcall, since not needed before init spawned.
539  */
540 static int __init armv8_deprecated_init(void)
541 {
542         if (IS_ENABLED(CONFIG_SWP_EMULATION))
543                 register_insn_emulation(&swp_ops);
544
545         if (IS_ENABLED(CONFIG_CP15_BARRIER_EMULATION))
546                 register_insn_emulation(&cp15_barrier_ops);
547
548         register_insn_emulation_sysctl(ctl_abi);
549
550         return 0;
551 }
552
553 late_initcall(armv8_deprecated_init);