Skip to content

Commit 484a8ed

Browse files
hcahcaVasily Gorbik
authored andcommitted
s390/extable: add dedicated uaccess handler
This is more or less a combination of commit 2e77a62 ("arm64: extable: add a dedicated uaccess handler") and commit 4b5305d ("x86/extable: Extend extable functionality"). To describe the problem that needs to solved let's cite the full arm64 commit message: ------ For inline assembly, we place exception fixups out-of-line in the `.fixup` section such that these are out of the way of the fast path. This has a few drawbacks: * Since the fixup code is anonymous, backtraces will symbolize fixups as offsets from the nearest prior symbol, currently `__entry_tramp_text_end`. This is confusing, and painful to debug without access to the relevant vmlinux. * Since the exception handler adjusts the PC to execute the fixup, and the fixup uses a direct branch back into the function it fixes, backtraces of fixups miss the original function. This is confusing, and violates requirements for RELIABLE_STACKTRACE (and therefore LIVEPATCH). * Inline assembly and associated fixups are generated from templates, and we have many copies of logically identical fixups which only differ in which specific registers are written to and which address is branched to at the end of the fixup. This is potentially wasteful of I-cache resources, and makes it hard to add additional logic to fixups without significant bloat. This patch address all three concerns for inline uaccess fixups by adding a dedicated exception handler which updates registers in exception context and subsequent returns back into the function which faulted, removing the need for fixups specialized to each faulting instruction. Other than backtracing, there should be no functional change as a result of this patch. ------ Acked-by: Alexander Gordeev <agordeev@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
1 parent 3d66718 commit 484a8ed

3 files changed

Lines changed: 43 additions & 18 deletions

File tree

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define EX_TYPE_NONE 0
99
#define EX_TYPE_FIXUP 1
1010
#define EX_TYPE_BPF 2
11+
#define EX_TYPE_UACCESS 3
1112

1213
#define __EX_TABLE(_section, _fault, _target, _type) \
1314
stringify_in_c(.section _section,"a";) \
@@ -18,9 +19,35 @@
1819
stringify_in_c(.short 0;) \
1920
stringify_in_c(.previous)
2021

22+
#define __EX_TABLE_UA(_section, _fault, _target, _type, _reg) \
23+
stringify_in_c(.section _section,"a";) \
24+
stringify_in_c(.align 4;) \
25+
stringify_in_c(.long (_fault) - .;) \
26+
stringify_in_c(.long (_target) - .;) \
27+
stringify_in_c(.short (_type);) \
28+
stringify_in_c(.macro extable_reg reg;) \
29+
stringify_in_c(.set found, 0;) \
30+
stringify_in_c(.set regnr, 0;) \
31+
stringify_in_c(.irp rs,r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15;) \
32+
stringify_in_c(.ifc "\reg", "%%\rs";) \
33+
stringify_in_c(.set found, 1;) \
34+
stringify_in_c(.short regnr;) \
35+
stringify_in_c(.endif;) \
36+
stringify_in_c(.set regnr, regnr+1;) \
37+
stringify_in_c(.endr;) \
38+
stringify_in_c(.ifne (found != 1);) \
39+
stringify_in_c(.error "extable_reg: bad register argument";) \
40+
stringify_in_c(.endif;) \
41+
stringify_in_c(.endm;) \
42+
stringify_in_c(extable_reg _reg;) \
43+
stringify_in_c(.purgem extable_reg;) \
44+
stringify_in_c(.previous)
45+
2146
#define EX_TABLE(_fault, _target) \
2247
__EX_TABLE(__ex_table, _fault, _target, EX_TYPE_FIXUP)
2348
#define EX_TABLE_AMODE31(_fault, _target) \
2449
__EX_TABLE(.amode31.ex_table, _fault, _target, EX_TYPE_FIXUP)
50+
#define EX_TABLE_UA(_fault, _target, _reg) \
51+
__EX_TABLE_UA(__ex_table, _fault, _target, EX_TYPE_UACCESS, _reg)
2552

2653
#endif /* __ASM_EXTABLE_H */

arch/s390/include/asm/uaccess.h

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,10 @@ union oac {
8181
"0: mvcos %[_to],%[_from],%[_size]\n" \
8282
"1: xr %[rc],%[rc]\n" \
8383
"2:\n" \
84-
".pushsection .fixup, \"ax\"\n" \
85-
"3: lhi %[rc],%[retval]\n" \
86-
" jg 2b\n" \
87-
".popsection\n" \
88-
EX_TABLE(0b,3b) EX_TABLE(1b,3b) \
84+
EX_TABLE_UA(0b,2b,%[rc]) EX_TABLE_UA(1b,2b,%[rc]) \
8985
: [rc] "=&d" (__rc), [_to] "+Q" (*(to)) \
9086
: [_size] "d" (size), [_from] "Q" (*(from)), \
91-
[retval] "K" (-EFAULT), [spec] "d" (oac_spec.val) \
87+
[spec] "d" (oac_spec.val) \
9288
: "cc", "0"); \
9389
__rc; \
9490
})
@@ -295,13 +291,9 @@ int __noreturn __put_kernel_bad(void);
295291
"0: " insn " %2,%1\n" \
296292
"1: xr %0,%0\n" \
297293
"2:\n" \
298-
".pushsection .fixup, \"ax\"\n" \
299-
"3: lhi %0,%3\n" \
300-
" jg 2b\n" \
301-
".popsection\n" \
302-
EX_TABLE(0b,3b) EX_TABLE(1b,3b) \
294+
EX_TABLE_UA(0b,2b,%0) EX_TABLE_UA(1b,2b,%0) \
303295
: "=d" (__rc), "+Q" (*(to)) \
304-
: "d" (val), "K" (-EFAULT) \
296+
: "d" (val) \
305297
: "cc"); \
306298
__rc; \
307299
})
@@ -342,13 +334,9 @@ int __noreturn __get_kernel_bad(void);
342334
"0: " insn " %1,%2\n" \
343335
"1: xr %0,%0\n" \
344336
"2:\n" \
345-
".pushsection .fixup, \"ax\"\n" \
346-
"3: lhi %0,%3\n" \
347-
" jg 2b\n" \
348-
".popsection\n" \
349-
EX_TABLE(0b,3b) EX_TABLE(1b,3b) \
337+
EX_TABLE_UA(0b,2b,%0) EX_TABLE_UA(1b,2b,%0) \
350338
: "=d" (__rc), "+d" (val) \
351-
: "Q" (*(from)), "K" (-EFAULT) \
339+
: "Q" (*(from)) \
352340
: "cc"); \
353341
__rc; \
354342
})

arch/s390/mm/extable.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// SPDX-License-Identifier: GPL-2.0
22

33
#include <linux/extable.h>
4+
#include <linux/errno.h>
45
#include <linux/panic.h>
56
#include <asm/asm-extable.h>
67
#include <asm/extable.h>
@@ -23,6 +24,13 @@ static bool ex_handler_fixup(const struct exception_table_entry *ex, struct pt_r
2324
return true;
2425
}
2526

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+
2634
bool fixup_exception(struct pt_regs *regs)
2735
{
2836
const struct exception_table_entry *ex;
@@ -35,6 +43,8 @@ bool fixup_exception(struct pt_regs *regs)
3543
return ex_handler_fixup(ex, regs);
3644
case EX_TYPE_BPF:
3745
return ex_handler_bpf(ex, regs);
46+
case EX_TYPE_UACCESS:
47+
return ex_handler_uaccess(ex, regs);
3848
}
3949
panic("invalid exception table entry");
4050
}

0 commit comments

Comments
 (0)