1 // SPDX-License-Identifier: GPL-2.0-or-later 1 2 /* 3 * Copyright (C) 2009 Sunplus Core Technology 4 * Lennox Wu <lennox.wu@sunplusct.com> 5 * Chen Liqin <liqin.chen@sunplusct.com> 6 * Copyright (C) 2013 Regents of the Universit 7 */ 8 9 10 #include <linux/bitfield.h> 11 #include <linux/extable.h> 12 #include <linux/module.h> 13 #include <linux/uaccess.h> 14 #include <asm/asm-extable.h> 15 #include <asm/ptrace.h> 16 17 static inline unsigned long 18 get_ex_fixup(const struct exception_table_entr 19 { 20 return ((unsigned long)&ex->fixup + ex 21 } 22 23 static bool ex_handler_fixup(const struct exce 24 struct pt_regs *r 25 { 26 regs->epc = get_ex_fixup(ex); 27 return true; 28 } 29 30 static inline unsigned long regs_get_gpr(struc 31 { 32 if (unlikely(!offset || offset > MAX_R 33 return 0; 34 35 return *(unsigned long *)((unsigned lo 36 } 37 38 static inline void regs_set_gpr(struct pt_regs 39 unsigned long 40 { 41 if (unlikely(offset > MAX_REG_OFFSET)) 42 return; 43 44 if (offset) 45 *(unsigned long *)((unsigned l 46 } 47 48 static bool ex_handler_uaccess_err_zero(const 49 struct 50 { 51 int reg_err = FIELD_GET(EX_DATA_REG_ER 52 int reg_zero = FIELD_GET(EX_DATA_REG_Z 53 54 regs_set_gpr(regs, reg_err * sizeof(un 55 regs_set_gpr(regs, reg_zero * sizeof(u 56 57 regs->epc = get_ex_fixup(ex); 58 return true; 59 } 60 61 static bool 62 ex_handler_load_unaligned_zeropad(const struct 63 struct pt_re 64 { 65 int reg_data = FIELD_GET(EX_DATA_REG_D 66 int reg_addr = FIELD_GET(EX_DATA_REG_A 67 unsigned long data, addr, offset; 68 69 addr = regs_get_gpr(regs, reg_addr * s 70 71 offset = addr & 0x7UL; 72 addr &= ~0x7UL; 73 74 data = *(unsigned long *)addr >> (offs 75 76 regs_set_gpr(regs, reg_data * sizeof(u 77 78 regs->epc = get_ex_fixup(ex); 79 return true; 80 } 81 82 bool fixup_exception(struct pt_regs *regs) 83 { 84 const struct exception_table_entry *ex 85 86 ex = search_exception_tables(regs->epc 87 if (!ex) 88 return false; 89 90 switch (ex->type) { 91 case EX_TYPE_FIXUP: 92 return ex_handler_fixup(ex, re 93 case EX_TYPE_BPF: 94 return ex_handler_bpf(ex, regs 95 case EX_TYPE_UACCESS_ERR_ZERO: 96 return ex_handler_uaccess_err_ 97 case EX_TYPE_LOAD_UNALIGNED_ZEROPAD: 98 return ex_handler_load_unalign 99 } 100 101 BUG(); 102 } 103
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.