Skip to content

Commit d6e2cc5

Browse files
mrutland-armwilldeacon
authored andcommitted
arm64: extable: add type and data fields
Subsequent patches will add specialized handlers for fixups, in addition to the simple PC fixup and BPF handlers we have today. In preparation, this patch adds a new `type` field to struct exception_table_entry, and uses this to distinguish the fixup and BPF cases. A `data` field is also added so that subsequent patches can associate data specific to each exception site (e.g. register numbers). Handlers are named ex_handler_*() for consistency, following the exmaple of x86. At the same time, get_ex_fixup() is split out into a helper so that it can be used by other ex_handler_*() functions ins subsequent patches. This patch will increase the size of the exception tables, which will be remedied by subsequent patches removing redundant fixup code. There should be no functional change as a result of this patch. Since each entry is now 12 bytes in size, we must reduce the alignment of each entry from `.align 3` (i.e. 8 bytes) to `.align 2` (i.e. 4 bytes), which is the natrual alignment of the `insn` and `fixup` fields. The current 8-byte alignment is a holdover from when the `insn` and `fixup` fields was 8 bytes, and while not harmful has not been necessary since commit: 6c94f27 ("arm64: switch to relative exception tables") Similarly, RO_EXCEPTION_TABLE_ALIGN is dropped to 4 bytes. Concurrently with this patch, x86's exception table entry format is being updated (similarly to a 12-byte format, with 32-bytes of absolute data). Once both have been merged it should be possible to unify the sorttable logic for the two. Signed-off-by: Mark Rutland <[email protected]> Reviewed-by: Ard Biesheuvel <[email protected]> Cc: Alexei Starovoitov <[email protected]> Cc: Andrii Nakryiko <[email protected]> Cc: Catalin Marinas <[email protected]> Cc: Daniel Borkmann <[email protected]> Cc: James Morse <[email protected]> Cc: Jean-Philippe Brucker <[email protected]> Cc: Robin Murphy <[email protected]> Cc: Will Deacon <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent 5d0e790 commit d6e2cc5

File tree

6 files changed

+96
-23
lines changed

6 files changed

+96
-23
lines changed

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

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,27 @@
22
#ifndef __ASM_ASM_EXTABLE_H
33
#define __ASM_ASM_EXTABLE_H
44

5+
#define EX_TYPE_NONE 0
6+
#define EX_TYPE_FIXUP 1
7+
#define EX_TYPE_BPF 2
8+
59
#ifdef __ASSEMBLY__
610

7-
#define __ASM_EXTABLE_RAW(insn, fixup) \
8-
.pushsection __ex_table, "a"; \
9-
.align 3; \
10-
.long ((insn) - .); \
11-
.long ((fixup) - .); \
11+
#define __ASM_EXTABLE_RAW(insn, fixup, type, data) \
12+
.pushsection __ex_table, "a"; \
13+
.align 2; \
14+
.long ((insn) - .); \
15+
.long ((fixup) - .); \
16+
.short (type); \
17+
.short (data); \
1218
.popsection;
1319

1420
/*
1521
* Create an exception table entry for `insn`, which will branch to `fixup`
1622
* when an unhandled fault is taken.
1723
*/
1824
.macro _asm_extable, insn, fixup
19-
__ASM_EXTABLE_RAW(\insn, \fixup)
25+
__ASM_EXTABLE_RAW(\insn, \fixup, EX_TYPE_FIXUP, 0)
2026
.endm
2127

2228
/*
@@ -33,15 +39,17 @@
3339

3440
#include <linux/stringify.h>
3541

36-
#define __ASM_EXTABLE_RAW(insn, fixup) \
37-
".pushsection __ex_table, \"a\"\n" \
38-
".align 3\n" \
39-
".long ((" insn ") - .)\n" \
40-
".long ((" fixup ") - .)\n" \
42+
#define __ASM_EXTABLE_RAW(insn, fixup, type, data) \
43+
".pushsection __ex_table, \"a\"\n" \
44+
".align 2\n" \
45+
".long ((" insn ") - .)\n" \
46+
".long ((" fixup ") - .)\n" \
47+
".short (" type ")\n" \
48+
".short (" data ")\n" \
4149
".popsection\n"
4250

4351
#define _ASM_EXTABLE(insn, fixup) \
44-
__ASM_EXTABLE_RAW(#insn, #fixup)
52+
__ASM_EXTABLE_RAW(#insn, #fixup, __stringify(EX_TYPE_FIXUP), "0")
4553

4654
#endif /* __ASSEMBLY__ */
4755

arch/arm64/include/asm/extable.h

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,21 @@
1818
struct exception_table_entry
1919
{
2020
int insn, fixup;
21+
short type, data;
2122
};
2223

2324
#define ARCH_HAS_RELATIVE_EXTABLE
2425

26+
#define swap_ex_entry_fixup(a, b, tmp, delta) \
27+
do { \
28+
(a)->fixup = (b)->fixup + (delta); \
29+
(b)->fixup = (tmp).fixup - (delta); \
30+
(a)->type = (b)->type; \
31+
(b)->type = (tmp).type; \
32+
(a)->data = (b)->data; \
33+
(b)->data = (tmp).data; \
34+
} while (0)
35+
2536
static inline bool in_bpf_jit(struct pt_regs *regs)
2637
{
2738
if (!IS_ENABLED(CONFIG_BPF_JIT))
@@ -32,12 +43,12 @@ static inline bool in_bpf_jit(struct pt_regs *regs)
3243
}
3344

3445
#ifdef CONFIG_BPF_JIT
35-
bool arm64_bpf_fixup_exception(const struct exception_table_entry *ex,
36-
struct pt_regs *regs);
46+
bool ex_handler_bpf(const struct exception_table_entry *ex,
47+
struct pt_regs *regs);
3748
#else /* !CONFIG_BPF_JIT */
3849
static inline
39-
bool arm64_bpf_fixup_exception(const struct exception_table_entry *ex,
40-
struct pt_regs *regs)
50+
bool ex_handler_bpf(const struct exception_table_entry *ex,
51+
struct pt_regs *regs)
4152
{
4253
return false;
4354
}

arch/arm64/kernel/vmlinux.lds.S

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
#define SBSS_ALIGN 0
5858
#endif
5959

60-
#define RO_EXCEPTION_TABLE_ALIGN 8
60+
#define RO_EXCEPTION_TABLE_ALIGN 4
6161
#define RUNTIME_DISCARD_EXIT
6262

6363
#include <asm-generic/vmlinux.lds.h>

arch/arm64/mm/extable.c

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,24 @@
66
#include <linux/extable.h>
77
#include <linux/uaccess.h>
88

9+
#include <asm/asm-extable.h>
10+
11+
typedef bool (*ex_handler_t)(const struct exception_table_entry *,
12+
struct pt_regs *);
13+
14+
static inline unsigned long
15+
get_ex_fixup(const struct exception_table_entry *ex)
16+
{
17+
return ((unsigned long)&ex->fixup + ex->fixup);
18+
}
19+
20+
static bool ex_handler_fixup(const struct exception_table_entry *ex,
21+
struct pt_regs *regs)
22+
{
23+
regs->pc = get_ex_fixup(ex);
24+
return true;
25+
}
26+
927
bool fixup_exception(struct pt_regs *regs)
1028
{
1129
const struct exception_table_entry *ex;
@@ -14,9 +32,12 @@ bool fixup_exception(struct pt_regs *regs)
1432
if (!ex)
1533
return false;
1634

17-
if (in_bpf_jit(regs))
18-
return arm64_bpf_fixup_exception(ex, regs);
35+
switch (ex->type) {
36+
case EX_TYPE_FIXUP:
37+
return ex_handler_fixup(ex, regs);
38+
case EX_TYPE_BPF:
39+
return ex_handler_bpf(ex, regs);
40+
}
1941

20-
regs->pc = (unsigned long)&ex->fixup + ex->fixup;
21-
return true;
42+
BUG();
2243
}

arch/arm64/net/bpf_jit_comp.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/printk.h>
1414
#include <linux/slab.h>
1515

16+
#include <asm/asm-extable.h>
1617
#include <asm/byteorder.h>
1718
#include <asm/cacheflush.h>
1819
#include <asm/debug-monitors.h>
@@ -358,8 +359,8 @@ static void build_epilogue(struct jit_ctx *ctx)
358359
#define BPF_FIXUP_OFFSET_MASK GENMASK(26, 0)
359360
#define BPF_FIXUP_REG_MASK GENMASK(31, 27)
360361

361-
bool arm64_bpf_fixup_exception(const struct exception_table_entry *ex,
362-
struct pt_regs *regs)
362+
bool ex_handler_bpf(const struct exception_table_entry *ex,
363+
struct pt_regs *regs)
363364
{
364365
off_t offset = FIELD_GET(BPF_FIXUP_OFFSET_MASK, ex->fixup);
365366
int dst_reg = FIELD_GET(BPF_FIXUP_REG_MASK, ex->fixup);
@@ -412,6 +413,8 @@ static int add_exception_handler(const struct bpf_insn *insn,
412413
ex->fixup = FIELD_PREP(BPF_FIXUP_OFFSET_MASK, offset) |
413414
FIELD_PREP(BPF_FIXUP_REG_MASK, dst_reg);
414415

416+
ex->type = EX_TYPE_BPF;
417+
415418
ctx->exentry_idx++;
416419
return 0;
417420
}

scripts/sorttable.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,34 @@ static void sort_relative_table(char *extab_image, int image_size)
231231
}
232232
}
233233

234+
static void arm64_sort_relative_table(char *extab_image, int image_size)
235+
{
236+
int i = 0;
237+
238+
while (i < image_size) {
239+
uint32_t *loc = (uint32_t *)(extab_image + i);
240+
241+
w(r(loc) + i, loc);
242+
w(r(loc + 1) + i + 4, loc + 1);
243+
/* Don't touch the fixup type or data */
244+
245+
i += sizeof(uint32_t) * 3;
246+
}
247+
248+
qsort(extab_image, image_size / 12, 12, compare_relative_table);
249+
250+
i = 0;
251+
while (i < image_size) {
252+
uint32_t *loc = (uint32_t *)(extab_image + i);
253+
254+
w(r(loc) - i, loc);
255+
w(r(loc + 1) - (i + 4), loc + 1);
256+
/* Don't touch the fixup type or data */
257+
258+
i += sizeof(uint32_t) * 3;
259+
}
260+
}
261+
234262
static void x86_sort_relative_table(char *extab_image, int image_size)
235263
{
236264
int i = 0;
@@ -343,6 +371,8 @@ static int do_file(char const *const fname, void *addr)
343371
custom_sort = s390_sort_relative_table;
344372
break;
345373
case EM_AARCH64:
374+
custom_sort = arm64_sort_relative_table;
375+
break;
346376
case EM_PARISC:
347377
case EM_PPC:
348378
case EM_PPC64:

0 commit comments

Comments
 (0)