#define EX_TYPE_NONE 0
#define EX_TYPE_FIXUP 1
#define EX_TYPE_BPF 2
+#define EX_TYPE_UACCESS 3
#define __EX_TABLE(_section, _fault, _target, _type) \
stringify_in_c(.section _section,"a";) \
stringify_in_c(.short 0;) \
stringify_in_c(.previous)
+#define __EX_TABLE_UA(_section, _fault, _target, _type, _reg) \
+ stringify_in_c(.section _section,"a";) \
+ stringify_in_c(.align 4;) \
+ stringify_in_c(.long (_fault) - .;) \
+ stringify_in_c(.long (_target) - .;) \
+ stringify_in_c(.short (_type);) \
+ stringify_in_c(.macro extable_reg reg;) \
+ stringify_in_c(.set found, 0;) \
+ stringify_in_c(.set regnr, 0;) \
+ stringify_in_c(.irp rs,r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15;) \
+ stringify_in_c(.ifc "\reg", "%%\rs";) \
+ stringify_in_c(.set found, 1;) \
+ stringify_in_c(.short regnr;) \
+ stringify_in_c(.endif;) \
+ stringify_in_c(.set regnr, regnr+1;) \
+ stringify_in_c(.endr;) \
+ stringify_in_c(.ifne (found != 1);) \
+ stringify_in_c(.error "extable_reg: bad register argument";) \
+ stringify_in_c(.endif;) \
+ stringify_in_c(.endm;) \
+ stringify_in_c(extable_reg _reg;) \
+ stringify_in_c(.purgem extable_reg;) \
+ stringify_in_c(.previous)
+
#define EX_TABLE(_fault, _target) \
__EX_TABLE(__ex_table, _fault, _target, EX_TYPE_FIXUP)
#define EX_TABLE_AMODE31(_fault, _target) \
__EX_TABLE(.amode31.ex_table, _fault, _target, EX_TYPE_FIXUP)
+#define EX_TABLE_UA(_fault, _target, _reg) \
+ __EX_TABLE_UA(__ex_table, _fault, _target, EX_TYPE_UACCESS, _reg)
#endif /* __ASM_EXTABLE_H */
"0: mvcos %[_to],%[_from],%[_size]\n" \
"1: xr %[rc],%[rc]\n" \
"2:\n" \
- ".pushsection .fixup, \"ax\"\n" \
- "3: lhi %[rc],%[retval]\n" \
- " jg 2b\n" \
- ".popsection\n" \
- EX_TABLE(0b,3b) EX_TABLE(1b,3b) \
+ EX_TABLE_UA(0b,2b,%[rc]) EX_TABLE_UA(1b,2b,%[rc]) \
: [rc] "=&d" (__rc), [_to] "+Q" (*(to)) \
: [_size] "d" (size), [_from] "Q" (*(from)), \
- [retval] "K" (-EFAULT), [spec] "d" (oac_spec.val) \
+ [spec] "d" (oac_spec.val) \
: "cc", "0"); \
__rc; \
})
"0: " insn " %2,%1\n" \
"1: xr %0,%0\n" \
"2:\n" \
- ".pushsection .fixup, \"ax\"\n" \
- "3: lhi %0,%3\n" \
- " jg 2b\n" \
- ".popsection\n" \
- EX_TABLE(0b,3b) EX_TABLE(1b,3b) \
+ EX_TABLE_UA(0b,2b,%0) EX_TABLE_UA(1b,2b,%0) \
: "=d" (__rc), "+Q" (*(to)) \
- : "d" (val), "K" (-EFAULT) \
+ : "d" (val) \
: "cc"); \
__rc; \
})
"0: " insn " %1,%2\n" \
"1: xr %0,%0\n" \
"2:\n" \
- ".pushsection .fixup, \"ax\"\n" \
- "3: lhi %0,%3\n" \
- " jg 2b\n" \
- ".popsection\n" \
- EX_TABLE(0b,3b) EX_TABLE(1b,3b) \
+ EX_TABLE_UA(0b,2b,%0) EX_TABLE_UA(1b,2b,%0) \
: "=d" (__rc), "+d" (val) \
- : "Q" (*(from)), "K" (-EFAULT) \
+ : "Q" (*(from)) \
: "cc"); \
__rc; \
})
// SPDX-License-Identifier: GPL-2.0
#include <linux/extable.h>
+#include <linux/errno.h>
#include <linux/panic.h>
#include <asm/asm-extable.h>
#include <asm/extable.h>
return true;
}
+static bool ex_handler_uaccess(const struct exception_table_entry *ex, struct pt_regs *regs)
+{
+ regs->gprs[ex->data] = -EFAULT;
+ regs->psw.addr = extable_fixup(ex);
+ return true;
+}
+
bool fixup_exception(struct pt_regs *regs)
{
const struct exception_table_entry *ex;
return ex_handler_fixup(ex, regs);
case EX_TYPE_BPF:
return ex_handler_bpf(ex, regs);
+ case EX_TYPE_UACCESS:
+ return ex_handler_uaccess(ex, regs);
}
panic("invalid exception table entry");
}