1 // SPDX-License-Identifier: GPL-2.0 << 2 /* 1 /* 3 * linux/arch/arm/mm/extable.c !! 2 * linux/arch/ppc/mm/extable.c >> 3 * >> 4 * from linux/arch/i386/mm/extable.c 4 */ 5 */ 5 #include <linux/extable.h> << 6 #include <linux/uaccess.h> << 7 6 8 int fixup_exception(struct pt_regs *regs) !! 7 #include <linux/config.h> >> 8 #include <linux/module.h> >> 9 #include <asm/uaccess.h> >> 10 >> 11 extern struct exception_table_entry __start___ex_table[]; >> 12 extern struct exception_table_entry __stop___ex_table[]; >> 13 >> 14 /* >> 15 * The exception table needs to be sorted because we use the macros >> 16 * which put things into the exception table in a variety of segments >> 17 * such as the prep, pmac, chrp, etc. segments as well as the init >> 18 * segment and the main kernel text segment. >> 19 */ >> 20 static inline void >> 21 sort_ex_table(struct exception_table_entry *start, >> 22 struct exception_table_entry *finish) 9 { 23 { 10 const struct exception_table_entry *fi !! 24 struct exception_table_entry el, *p, *q; 11 25 12 fixup = search_exception_tables(instru !! 26 /* insertion sort */ 13 if (fixup) { !! 27 for (p = start + 1; p < finish; ++p) { 14 regs->ARM_pc = fixup->fixup; !! 28 /* start .. p-1 is sorted */ 15 #ifdef CONFIG_THUMB2_KERNEL !! 29 if (p[0].insn < p[-1].insn) { 16 /* Clear the IT state to avoid !! 30 /* move element p down to its right place */ 17 regs->ARM_cpsr &= ~PSR_IT_MASK !! 31 el = *p; 18 #endif !! 32 q = p; >> 33 do { >> 34 /* el comes before q[-1], move q[-1] up one */ >> 35 q[0] = q[-1]; >> 36 --q; >> 37 } while (q > start && el.insn < q[-1].insn); >> 38 *q = el; >> 39 } 19 } 40 } >> 41 } >> 42 >> 43 void >> 44 sort_exception_table(void) >> 45 { >> 46 sort_ex_table(__start___ex_table, __stop___ex_table); >> 47 } >> 48 >> 49 static inline unsigned long >> 50 search_one_table(const struct exception_table_entry *first, >> 51 const struct exception_table_entry *last, >> 52 unsigned long value) >> 53 { >> 54 while (first <= last) { >> 55 const struct exception_table_entry *mid; >> 56 long diff; >> 57 >> 58 mid = (last - first) / 2 + first; >> 59 diff = mid->insn - value; >> 60 if (diff == 0) >> 61 return mid->fixup; >> 62 else if (diff < 0) >> 63 first = mid+1; >> 64 else >> 65 last = mid-1; >> 66 } >> 67 return 0; >> 68 } >> 69 >> 70 unsigned long >> 71 search_exception_table(unsigned long addr) >> 72 { >> 73 unsigned long ret; >> 74 >> 75 #ifndef CONFIG_MODULES >> 76 /* There is only the kernel to search. */ >> 77 ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr); >> 78 if (ret) return ret; >> 79 #else >> 80 /* The kernel is the last "module" -- no need to treat it special. */ >> 81 struct module *mp; >> 82 for (mp = module_list; mp != NULL; mp = mp->next) { >> 83 if (mp->ex_table_start == NULL) >> 84 continue; >> 85 ret = search_one_table(mp->ex_table_start, >> 86 mp->ex_table_end - 1, addr); >> 87 if (ret) >> 88 return ret; >> 89 } >> 90 #endif 20 91 21 return fixup != NULL; !! 92 return 0; 22 } 93 } 23 94
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.