1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
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>
11 static inline unsigned long
12 get_ex_fixup(const struct exception_table_entry
*ex
)
14 return ((unsigned long)&ex
->fixup
+ ex
->fixup
);
17 static inline void regs_set_gpr(struct pt_regs
*regs
,
18 unsigned int offset
, unsigned long val
)
20 if (offset
&& offset
<= MAX_REG_OFFSET
)
21 *(unsigned long *)((unsigned long)regs
+ offset
) = val
;
24 static bool ex_handler_fixup(const struct exception_table_entry
*ex
,
27 regs
->csr_era
= get_ex_fixup(ex
);
32 static bool ex_handler_uaccess_err_zero(const struct exception_table_entry
*ex
,
35 int reg_err
= FIELD_GET(EX_DATA_REG_ERR
, ex
->data
);
36 int reg_zero
= FIELD_GET(EX_DATA_REG_ZERO
, ex
->data
);
38 regs_set_gpr(regs
, reg_err
* sizeof(unsigned long), -EFAULT
);
39 regs_set_gpr(regs
, reg_zero
* sizeof(unsigned long), 0);
40 regs
->csr_era
= get_ex_fixup(ex
);
45 bool fixup_exception(struct pt_regs
*regs
)
47 const struct exception_table_entry
*ex
;
49 ex
= search_exception_tables(exception_era(regs
));
55 return ex_handler_fixup(ex
, regs
);
56 case EX_TYPE_UACCESS_ERR_ZERO
:
57 return ex_handler_uaccess_err_zero(ex
, regs
);
59 return ex_handler_bpf(ex
, regs
);