1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <linux/extable.h> 4 #include <linux/errno.h> 5 #include <linux/panic.h> 6 #include <asm/asm-extable.h> 7 #include <asm/extable.h> 8 9 const struct exception_table_entry *s390_search_extables(unsigned long addr) 10 { 11 const struct exception_table_entry *fixup; 12 size_t num; 13 14 fixup = search_exception_tables(addr); 15 if (fixup) 16 return fixup; 17 num = __stop_amode31_ex_table - __start_amode31_ex_table; 18 return search_extable(__start_amode31_ex_table, num, addr); 19 } 20 21 static bool ex_handler_fixup(const struct exception_table_entry *ex, struct pt_regs *regs) 22 { 23 regs->psw.addr = extable_fixup(ex); 24 return true; 25 } 26 27 static bool ex_handler_uaccess(const struct exception_table_entry *ex, struct pt_regs *regs) 28 { 29 regs->gprs[ex->data] = -EFAULT; 30 regs->psw.addr = extable_fixup(ex); 31 return true; 32 } 33 34 bool fixup_exception(struct pt_regs *regs) 35 { 36 const struct exception_table_entry *ex; 37 38 ex = s390_search_extables(instruction_pointer(regs)); 39 if (!ex) 40 return false; 41 switch (ex->type) { 42 case EX_TYPE_FIXUP: 43 return ex_handler_fixup(ex, regs); 44 case EX_TYPE_BPF: 45 return ex_handler_bpf(ex, regs); 46 case EX_TYPE_UACCESS: 47 return ex_handler_uaccess(ex, regs); 48 } 49 panic("invalid exception table entry"); 50 } 51