1 // SPDX-License-Identifier: GPL-2.0 << 2 /* 1 /* 3 * Copyright (C) 2020-2022 Loongson Technology !! 2 * arch/ppc/mm/extable.c >> 3 * >> 4 * from arch/i386/mm/extable.c 4 */ 5 */ 5 #include <linux/bitfield.h> << 6 #include <linux/extable.h> << 7 #include <linux/uaccess.h> << 8 #include <asm/asm-extable.h> << 9 #include <asm/branch.h> << 10 6 11 static inline unsigned long !! 7 #include <linux/config.h> 12 get_ex_fixup(const struct exception_table_entr !! 8 #include <linux/module.h> 13 { !! 9 #include <linux/init.h> 14 return ((unsigned long)&ex->fixup + ex !! 10 #include <asm/uaccess.h> 15 } << 16 11 17 static inline void regs_set_gpr(struct pt_regs !! 12 extern struct exception_table_entry __start___ex_table[]; 18 unsigned int o !! 13 extern struct exception_table_entry __stop___ex_table[]; 19 { << 20 if (offset && offset <= MAX_REG_OFFSET << 21 *(unsigned long *)((unsigned l << 22 } << 23 14 24 static bool ex_handler_fixup(const struct exce !! 15 /* 25 struct pt_regs *r !! 16 * The exception table needs to be sorted because we use the macros >> 17 * which put things into the exception table in a variety of segments >> 18 * such as the prep, pmac, chrp, etc. segments as well as the init >> 19 * segment and the main kernel text segment. >> 20 */ >> 21 static inline void >> 22 sort_ex_table(struct exception_table_entry *start, >> 23 struct exception_table_entry *finish) 26 { 24 { 27 regs->csr_era = get_ex_fixup(ex); !! 25 struct exception_table_entry el, *p, *q; 28 26 29 return true; !! 27 /* insertion sort */ >> 28 for (p = start + 1; p < finish; ++p) { >> 29 /* start .. p-1 is sorted */ >> 30 if (p[0].insn < p[-1].insn) { >> 31 /* move element p down to its right place */ >> 32 el = *p; >> 33 q = p; >> 34 do { >> 35 /* el comes before q[-1], move q[-1] up one */ >> 36 q[0] = q[-1]; >> 37 --q; >> 38 } while (q > start && el.insn < q[-1].insn); >> 39 *q = el; >> 40 } >> 41 } 30 } 42 } 31 43 32 static bool ex_handler_uaccess_err_zero(const !! 44 void __init 33 struct !! 45 sort_exception_table(void) 34 { 46 { 35 int reg_err = FIELD_GET(EX_DATA_REG_ER !! 47 sort_ex_table(__start___ex_table, __stop___ex_table); 36 int reg_zero = FIELD_GET(EX_DATA_REG_Z << 37 << 38 regs_set_gpr(regs, reg_err * sizeof(un << 39 regs_set_gpr(regs, reg_zero * sizeof(u << 40 regs->csr_era = get_ex_fixup(ex); << 41 << 42 return true; << 43 } 48 } 44 49 45 bool fixup_exception(struct pt_regs *regs) !! 50 /* Simple binary search */ >> 51 const struct exception_table_entry * >> 52 search_extable(const struct exception_table_entry *first, >> 53 const struct exception_table_entry *last, >> 54 unsigned long value) 46 { 55 { 47 const struct exception_table_entry *ex !! 56 while (first <= last) { 48 !! 57 const struct exception_table_entry *mid; 49 ex = search_exception_tables(exception !! 58 long diff; 50 if (!ex) !! 59 51 return false; !! 60 mid = (last - first) / 2 + first; 52 !! 61 diff = mid->insn - value; 53 switch (ex->type) { !! 62 if (diff == 0) 54 case EX_TYPE_FIXUP: !! 63 return mid; 55 return ex_handler_fixup(ex, re !! 64 else if (diff < 0) 56 case EX_TYPE_UACCESS_ERR_ZERO: !! 65 first = mid+1; 57 return ex_handler_uaccess_err_ !! 66 else 58 case EX_TYPE_BPF: !! 67 last = mid-1; 59 return ex_handler_bpf(ex, regs !! 68 } 60 } !! 69 return NULL; 61 << 62 BUG(); << 63 } 70 } 64 71
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.