dt-bindings: clock: drop useless consumer example
[linux-2.6-microblaze.git] / arch / arm64 / mm / extable.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Based on arch/arm/mm/extable.c
4  */
5
6 #include <linux/bitfield.h>
7 #include <linux/extable.h>
8 #include <linux/uaccess.h>
9
10 #include <asm/asm-extable.h>
11 #include <asm/ptrace.h>
12
13 static inline unsigned long
14 get_ex_fixup(const struct exception_table_entry *ex)
15 {
16         return ((unsigned long)&ex->fixup + ex->fixup);
17 }
18
19 static bool ex_handler_fixup(const struct exception_table_entry *ex,
20                              struct pt_regs *regs)
21 {
22         regs->pc = get_ex_fixup(ex);
23         return true;
24 }
25
26 static bool ex_handler_uaccess_err_zero(const struct exception_table_entry *ex,
27                                         struct pt_regs *regs)
28 {
29         int reg_err = FIELD_GET(EX_DATA_REG_ERR, ex->data);
30         int reg_zero = FIELD_GET(EX_DATA_REG_ZERO, ex->data);
31
32         pt_regs_write_reg(regs, reg_err, -EFAULT);
33         pt_regs_write_reg(regs, reg_zero, 0);
34
35         regs->pc = get_ex_fixup(ex);
36         return true;
37 }
38
39 static bool
40 ex_handler_load_unaligned_zeropad(const struct exception_table_entry *ex,
41                                   struct pt_regs *regs)
42 {
43         int reg_data = FIELD_GET(EX_DATA_REG_DATA, ex->type);
44         int reg_addr = FIELD_GET(EX_DATA_REG_ADDR, ex->type);
45         unsigned long data, addr, offset;
46
47         addr = pt_regs_read_reg(regs, reg_addr);
48
49         offset = addr & 0x7UL;
50         addr &= ~0x7UL;
51
52         data = *(unsigned long*)addr;
53
54 #ifndef __AARCH64EB__
55         data >>= 8 * offset;
56 #else
57         data <<= 8 * offset;
58 #endif
59
60         pt_regs_write_reg(regs, reg_data, data);
61
62         regs->pc = get_ex_fixup(ex);
63         return true;
64 }
65
66 bool fixup_exception(struct pt_regs *regs)
67 {
68         const struct exception_table_entry *ex;
69
70         ex = search_exception_tables(instruction_pointer(regs));
71         if (!ex)
72                 return false;
73
74         switch (ex->type) {
75         case EX_TYPE_FIXUP:
76                 return ex_handler_fixup(ex, regs);
77         case EX_TYPE_BPF:
78                 return ex_handler_bpf(ex, regs);
79         case EX_TYPE_UACCESS_ERR_ZERO:
80                 return ex_handler_uaccess_err_zero(ex, regs);
81         case EX_TYPE_LOAD_UNALIGNED_ZEROPAD:
82                 return ex_handler_load_unaligned_zeropad(ex, regs);
83         }
84
85         BUG();
86 }