Skip to content

Commit 20802d8

Browse files
xhackerustcpalmer-dabbelt
authored andcommitted
riscv: extable: add a dedicated uaccess handler
Inspired by commit 2e77a62 ("arm64: extable: add a dedicated uaccess handler"), do similar to riscv to add a dedicated uaccess exception handler to update registers in exception context and subsequently return back into the function which faulted, so we remove the need for fixups specialized to each faulting instruction. Signed-off-by: Jisheng Zhang <[email protected]> Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent ff4b8ca commit 20802d8

File tree

4 files changed

+78
-70
lines changed

4 files changed

+78
-70
lines changed

arch/riscv/include/asm/asm-extable.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#define EX_TYPE_NONE 0
66
#define EX_TYPE_FIXUP 1
77
#define EX_TYPE_BPF 2
8+
#define EX_TYPE_UACCESS_ERR_ZERO 3
89

910
#ifdef __ASSEMBLY__
1011

@@ -23,7 +24,9 @@
2324

2425
#else /* __ASSEMBLY__ */
2526

27+
#include <linux/bits.h>
2628
#include <linux/stringify.h>
29+
#include <asm/gpr-num.h>
2730

2831
#define __ASM_EXTABLE_RAW(insn, fixup, type, data) \
2932
".pushsection __ex_table, \"a\"\n" \
@@ -37,6 +40,26 @@
3740
#define _ASM_EXTABLE(insn, fixup) \
3841
__ASM_EXTABLE_RAW(#insn, #fixup, __stringify(EX_TYPE_FIXUP), "0")
3942

43+
#define EX_DATA_REG_ERR_SHIFT 0
44+
#define EX_DATA_REG_ERR GENMASK(4, 0)
45+
#define EX_DATA_REG_ZERO_SHIFT 5
46+
#define EX_DATA_REG_ZERO GENMASK(9, 5)
47+
48+
#define EX_DATA_REG(reg, gpr) \
49+
"((.L__gpr_num_" #gpr ") << " __stringify(EX_DATA_REG_##reg##_SHIFT) ")"
50+
51+
#define _ASM_EXTABLE_UACCESS_ERR_ZERO(insn, fixup, err, zero) \
52+
__DEFINE_ASM_GPR_NUMS \
53+
__ASM_EXTABLE_RAW(#insn, #fixup, \
54+
__stringify(EX_TYPE_UACCESS_ERR_ZERO), \
55+
"(" \
56+
EX_DATA_REG(ERR, err) " | " \
57+
EX_DATA_REG(ZERO, zero) \
58+
")")
59+
60+
#define _ASM_EXTABLE_UACCESS_ERR(insn, fixup, err) \
61+
_ASM_EXTABLE_UACCESS_ERR_ZERO(insn, fixup, err, zero)
62+
4063
#endif /* __ASSEMBLY__ */
4164

4265
#endif /* __ASM_ASM_EXTABLE_H */

arch/riscv/include/asm/futex.h

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,14 @@
2121

2222
#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
2323
{ \
24-
uintptr_t tmp; \
2524
__enable_user_access(); \
2625
__asm__ __volatile__ ( \
2726
"1: " insn " \n" \
2827
"2: \n" \
29-
" .section .fixup,\"ax\" \n" \
30-
" .balign 4 \n" \
31-
"3: li %[r],%[e] \n" \
32-
" jump 2b,%[t] \n" \
33-
" .previous \n" \
34-
_ASM_EXTABLE(1b, 3b) \
28+
_ASM_EXTABLE_UACCESS_ERR(1b, 2b, %[r]) \
3529
: [r] "+r" (ret), [ov] "=&r" (oldval), \
36-
[u] "+m" (*uaddr), [t] "=&r" (tmp) \
37-
: [op] "Jr" (oparg), [e] "i" (-EFAULT) \
30+
[u] "+m" (*uaddr) \
31+
: [op] "Jr" (oparg) \
3832
: "memory"); \
3933
__disable_user_access(); \
4034
}
@@ -96,15 +90,10 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
9690
"2: sc.w.aqrl %[t],%z[nv],%[u] \n"
9791
" bnez %[t],1b \n"
9892
"3: \n"
99-
" .section .fixup,\"ax\" \n"
100-
" .balign 4 \n"
101-
"4: li %[r],%[e] \n"
102-
" jump 3b,%[t] \n"
103-
" .previous \n"
104-
_ASM_EXTABLE(1b, 4b) \
105-
_ASM_EXTABLE(2b, 4b) \
93+
_ASM_EXTABLE_UACCESS_ERR(1b, 3b, %[r]) \
94+
_ASM_EXTABLE_UACCESS_ERR(2b, 3b, %[r]) \
10695
: [r] "+r" (ret), [v] "=&r" (val), [u] "+m" (*uaddr), [t] "=&r" (tmp)
107-
: [ov] "Jr" (oldval), [nv] "Jr" (newval), [e] "i" (-EFAULT)
96+
: [ov] "Jr" (oldval), [nv] "Jr" (newval)
10897
: "memory");
10998
__disable_user_access();
11099

arch/riscv/include/asm/uaccess.h

Lines changed: 22 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -81,22 +81,14 @@ static inline int __access_ok(unsigned long addr, unsigned long size)
8181

8282
#define __get_user_asm(insn, x, ptr, err) \
8383
do { \
84-
uintptr_t __tmp; \
8584
__typeof__(x) __x; \
8685
__asm__ __volatile__ ( \
8786
"1:\n" \
88-
" " insn " %1, %3\n" \
87+
" " insn " %1, %2\n" \
8988
"2:\n" \
90-
" .section .fixup,\"ax\"\n" \
91-
" .balign 4\n" \
92-
"3:\n" \
93-
" li %0, %4\n" \
94-
" li %1, 0\n" \
95-
" jump 2b, %2\n" \
96-
" .previous\n" \
97-
_ASM_EXTABLE(1b, 3b) \
98-
: "+r" (err), "=&r" (__x), "=r" (__tmp) \
99-
: "m" (*(ptr)), "i" (-EFAULT)); \
89+
_ASM_EXTABLE_UACCESS_ERR_ZERO(1b, 2b, %0, %1) \
90+
: "+r" (err), "=&r" (__x) \
91+
: "m" (*(ptr))); \
10092
(x) = __x; \
10193
} while (0)
10294

@@ -108,27 +100,18 @@ do { \
108100
do { \
109101
u32 __user *__ptr = (u32 __user *)(ptr); \
110102
u32 __lo, __hi; \
111-
uintptr_t __tmp; \
112103
__asm__ __volatile__ ( \
113104
"1:\n" \
114-
" lw %1, %4\n" \
105+
" lw %1, %3\n" \
115106
"2:\n" \
116-
" lw %2, %5\n" \
107+
" lw %2, %4\n" \
117108
"3:\n" \
118-
" .section .fixup,\"ax\"\n" \
119-
" .balign 4\n" \
120-
"4:\n" \
121-
" li %0, %6\n" \
122-
" li %1, 0\n" \
123-
" li %2, 0\n" \
124-
" jump 3b, %3\n" \
125-
" .previous\n" \
126-
_ASM_EXTABLE(1b, 4b) \
127-
_ASM_EXTABLE(2b, 4b) \
128-
: "+r" (err), "=&r" (__lo), "=r" (__hi), \
129-
"=r" (__tmp) \
130-
: "m" (__ptr[__LSW]), "m" (__ptr[__MSW]), \
131-
"i" (-EFAULT)); \
109+
_ASM_EXTABLE_UACCESS_ERR_ZERO(1b, 3b, %0, %1) \
110+
_ASM_EXTABLE_UACCESS_ERR_ZERO(2b, 3b, %0, %1) \
111+
: "+r" (err), "=&r" (__lo), "=r" (__hi) \
112+
: "m" (__ptr[__LSW]), "m" (__ptr[__MSW])); \
113+
if (err) \
114+
__hi = 0; \
132115
(x) = (__typeof__(x))((__typeof__((x)-(x)))( \
133116
(((u64)__hi << 32) | __lo))); \
134117
} while (0)
@@ -216,21 +199,14 @@ do { \
216199

217200
#define __put_user_asm(insn, x, ptr, err) \
218201
do { \
219-
uintptr_t __tmp; \
220202
__typeof__(*(ptr)) __x = x; \
221203
__asm__ __volatile__ ( \
222204
"1:\n" \
223-
" " insn " %z3, %2\n" \
205+
" " insn " %z2, %1\n" \
224206
"2:\n" \
225-
" .section .fixup,\"ax\"\n" \
226-
" .balign 4\n" \
227-
"3:\n" \
228-
" li %0, %4\n" \
229-
" jump 2b, %1\n" \
230-
" .previous\n" \
231-
_ASM_EXTABLE(1b, 3b) \
232-
: "+r" (err), "=r" (__tmp), "=m" (*(ptr)) \
233-
: "rJ" (__x), "i" (-EFAULT)); \
207+
_ASM_EXTABLE_UACCESS_ERR(1b, 2b, %0) \
208+
: "+r" (err), "=m" (*(ptr)) \
209+
: "rJ" (__x)); \
234210
} while (0)
235211

236212
#ifdef CONFIG_64BIT
@@ -241,25 +217,18 @@ do { \
241217
do { \
242218
u32 __user *__ptr = (u32 __user *)(ptr); \
243219
u64 __x = (__typeof__((x)-(x)))(x); \
244-
uintptr_t __tmp; \
245220
__asm__ __volatile__ ( \
246221
"1:\n" \
247-
" sw %z4, %2\n" \
222+
" sw %z3, %1\n" \
248223
"2:\n" \
249-
" sw %z5, %3\n" \
224+
" sw %z4, %2\n" \
250225
"3:\n" \
251-
" .section .fixup,\"ax\"\n" \
252-
" .balign 4\n" \
253-
"4:\n" \
254-
" li %0, %6\n" \
255-
" jump 3b, %1\n" \
256-
" .previous\n" \
257-
_ASM_EXTABLE(1b, 4b) \
258-
_ASM_EXTABLE(2b, 4b) \
259-
: "+r" (err), "=r" (__tmp), \
226+
_ASM_EXTABLE_UACCESS_ERR(1b, 3b, %0) \
227+
_ASM_EXTABLE_UACCESS_ERR(2b, 3b, %0) \
228+
: "+r" (err), \
260229
"=m" (__ptr[__LSW]), \
261230
"=m" (__ptr[__MSW]) \
262-
: "rJ" (__x), "rJ" (__x >> 32), "i" (-EFAULT)); \
231+
: "rJ" (__x), "rJ" (__x >> 32)); \
263232
} while (0)
264233
#endif /* CONFIG_64BIT */
265234

arch/riscv/mm/extable.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77
*/
88

99

10+
#include <linux/bitfield.h>
1011
#include <linux/extable.h>
1112
#include <linux/module.h>
1213
#include <linux/uaccess.h>
1314
#include <asm/asm-extable.h>
15+
#include <asm/ptrace.h>
1416

1517
static inline unsigned long
1618
get_ex_fixup(const struct exception_table_entry *ex)
@@ -25,6 +27,29 @@ static bool ex_handler_fixup(const struct exception_table_entry *ex,
2527
return true;
2628
}
2729

30+
static inline void regs_set_gpr(struct pt_regs *regs, unsigned int offset,
31+
unsigned long val)
32+
{
33+
if (unlikely(offset > MAX_REG_OFFSET))
34+
return;
35+
36+
if (!offset)
37+
*(unsigned long *)((unsigned long)regs + offset) = val;
38+
}
39+
40+
static bool ex_handler_uaccess_err_zero(const struct exception_table_entry *ex,
41+
struct pt_regs *regs)
42+
{
43+
int reg_err = FIELD_GET(EX_DATA_REG_ERR, ex->data);
44+
int reg_zero = FIELD_GET(EX_DATA_REG_ZERO, ex->data);
45+
46+
regs_set_gpr(regs, reg_err, -EFAULT);
47+
regs_set_gpr(regs, reg_zero, 0);
48+
49+
regs->epc = get_ex_fixup(ex);
50+
return true;
51+
}
52+
2853
bool fixup_exception(struct pt_regs *regs)
2954
{
3055
const struct exception_table_entry *ex;
@@ -38,6 +63,8 @@ bool fixup_exception(struct pt_regs *regs)
3863
return ex_handler_fixup(ex, regs);
3964
case EX_TYPE_BPF:
4065
return ex_handler_bpf(ex, regs);
66+
case EX_TYPE_UACCESS_ERR_ZERO:
67+
return ex_handler_uaccess_err_zero(ex, regs);
4168
}
4269

4370
BUG();

0 commit comments

Comments
 (0)