1 // SPDX-License-Identifier: GPL-2.0
3 * Based on arch/arm/mm/extable.c
6 #include <linux/bitfield.h>
7 #include <linux/extable.h>
8 #include <linux/uaccess.h>
10 #include <asm/asm-extable.h>
11 #include <asm/ptrace.h>
13 static inline unsigned long
14 get_ex_fixup(const struct exception_table_entry
*ex
)
16 return ((unsigned long)&ex
->fixup
+ ex
->fixup
);
19 static bool ex_handler_uaccess_err_zero(const struct exception_table_entry
*ex
,
22 int reg_err
= FIELD_GET(EX_DATA_REG_ERR
, ex
->data
);
23 int reg_zero
= FIELD_GET(EX_DATA_REG_ZERO
, ex
->data
);
25 pt_regs_write_reg(regs
, reg_err
, -EFAULT
);
26 pt_regs_write_reg(regs
, reg_zero
, 0);
28 regs
->pc
= get_ex_fixup(ex
);
33 ex_handler_load_unaligned_zeropad(const struct exception_table_entry
*ex
,
36 int reg_data
= FIELD_GET(EX_DATA_REG_DATA
, ex
->data
);
37 int reg_addr
= FIELD_GET(EX_DATA_REG_ADDR
, ex
->data
);
38 unsigned long data
, addr
, offset
;
40 addr
= pt_regs_read_reg(regs
, reg_addr
);
42 offset
= addr
& 0x7UL
;
45 data
= *(unsigned long*)addr
;
53 pt_regs_write_reg(regs
, reg_data
, data
);
55 regs
->pc
= get_ex_fixup(ex
);
59 bool fixup_exception(struct pt_regs
*regs
)
61 const struct exception_table_entry
*ex
;
63 ex
= search_exception_tables(instruction_pointer(regs
));
69 return ex_handler_bpf(ex
, regs
);
70 case EX_TYPE_UACCESS_ERR_ZERO
:
71 case EX_TYPE_KACCESS_ERR_ZERO
:
72 return ex_handler_uaccess_err_zero(ex
, regs
);
73 case EX_TYPE_LOAD_UNALIGNED_ZEROPAD
:
74 return ex_handler_load_unaligned_zeropad(ex
, regs
);