summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJisheng Zhang <jszhang@kernel.org>2021-11-18 14:26:05 +0300
committerPalmer Dabbelt <palmer@rivosinc.com>2022-01-06 04:52:54 +0300
commit2bf847db0c7437c28b10fba2981b9a7db4b4e0e2 (patch)
treef0248762ab49f86e123c5ac25f457e3565677d2b
parent6dd10d9166a0c06260e0ac6b1fac454117c8024a (diff)
downloadlinux-2bf847db0c7437c28b10fba2981b9a7db4b4e0e2.tar.xz
riscv: extable: add `type` and `data` fields
This is a riscv port of commit d6e2cc564775 ("arm64: extable: add `type` and `data` fields"). Signed-off-by: Jisheng Zhang <jszhang@kernel.org> Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
-rw-r--r--arch/riscv/include/asm/asm-extable.h25
-rw-r--r--arch/riscv/include/asm/extable.h17
-rw-r--r--arch/riscv/kernel/vmlinux.lds.S2
-rw-r--r--arch/riscv/mm/extable.c25
-rw-r--r--arch/riscv/net/bpf_jit_comp64.c5
-rw-r--r--scripts/sorttable.c2
6 files changed, 57 insertions, 19 deletions
diff --git a/arch/riscv/include/asm/asm-extable.h b/arch/riscv/include/asm/asm-extable.h
index b790c02dbdda..1b1f4ffd8d37 100644
--- a/arch/riscv/include/asm/asm-extable.h
+++ b/arch/riscv/include/asm/asm-extable.h
@@ -2,31 +2,40 @@
#ifndef __ASM_ASM_EXTABLE_H
#define __ASM_ASM_EXTABLE_H
+#define EX_TYPE_NONE 0
+#define EX_TYPE_FIXUP 1
+#define EX_TYPE_BPF 2
+
#ifdef __ASSEMBLY__
-#define __ASM_EXTABLE_RAW(insn, fixup) \
- .pushsection __ex_table, "a"; \
- .balign 4; \
- .long ((insn) - .); \
- .long ((fixup) - .); \
+#define __ASM_EXTABLE_RAW(insn, fixup, type, data) \
+ .pushsection __ex_table, "a"; \
+ .balign 4; \
+ .long ((insn) - .); \
+ .long ((fixup) - .); \
+ .short (type); \
+ .short (data); \
.popsection;
.macro _asm_extable, insn, fixup
- __ASM_EXTABLE_RAW(\insn, \fixup)
+ __ASM_EXTABLE_RAW(\insn, \fixup, EX_TYPE_FIXUP, 0)
.endm
#else /* __ASSEMBLY__ */
#include <linux/stringify.h>
-#define __ASM_EXTABLE_RAW(insn, fixup) \
+#define __ASM_EXTABLE_RAW(insn, fixup, type, data) \
".pushsection __ex_table, \"a\"\n" \
".balign 4\n" \
".long ((" insn ") - .)\n" \
".long ((" fixup ") - .)\n" \
+ ".short (" type ")\n" \
+ ".short (" data ")\n" \
".popsection\n"
-#define _ASM_EXTABLE(insn, fixup) __ASM_EXTABLE_RAW(#insn, #fixup)
+#define _ASM_EXTABLE(insn, fixup) \
+ __ASM_EXTABLE_RAW(#insn, #fixup, __stringify(EX_TYPE_FIXUP), "0")
#endif /* __ASSEMBLY__ */
diff --git a/arch/riscv/include/asm/extable.h b/arch/riscv/include/asm/extable.h
index e4374dde02b4..512012d193dc 100644
--- a/arch/riscv/include/asm/extable.h
+++ b/arch/riscv/include/asm/extable.h
@@ -17,18 +17,29 @@
struct exception_table_entry {
int insn, fixup;
+ short type, data;
};
#define ARCH_HAS_RELATIVE_EXTABLE
+#define swap_ex_entry_fixup(a, b, tmp, delta) \
+do { \
+ (a)->fixup = (b)->fixup + (delta); \
+ (b)->fixup = (tmp).fixup - (delta); \
+ (a)->type = (b)->type; \
+ (b)->type = (tmp).type; \
+ (a)->data = (b)->data; \
+ (b)->data = (tmp).data; \
+} while (0)
+
bool fixup_exception(struct pt_regs *regs);
#if defined(CONFIG_BPF_JIT) && defined(CONFIG_ARCH_RV64I)
-bool rv_bpf_fixup_exception(const struct exception_table_entry *ex, struct pt_regs *regs);
+bool ex_handler_bpf(const struct exception_table_entry *ex, struct pt_regs *regs);
#else
static inline bool
-rv_bpf_fixup_exception(const struct exception_table_entry *ex,
- struct pt_regs *regs)
+ex_handler_bpf(const struct exception_table_entry *ex,
+ struct pt_regs *regs)
{
return false;
}
diff --git a/arch/riscv/kernel/vmlinux.lds.S b/arch/riscv/kernel/vmlinux.lds.S
index 5104f3a871e3..0e5ae851929e 100644
--- a/arch/riscv/kernel/vmlinux.lds.S
+++ b/arch/riscv/kernel/vmlinux.lds.S
@@ -4,7 +4,7 @@
* Copyright (C) 2017 SiFive
*/
-#define RO_EXCEPTION_TABLE_ALIGN 16
+#define RO_EXCEPTION_TABLE_ALIGN 4
#ifdef CONFIG_XIP_KERNEL
#include "vmlinux-xip.lds.S"
diff --git a/arch/riscv/mm/extable.c b/arch/riscv/mm/extable.c
index 3c561f1d0115..91e52c4bb33a 100644
--- a/arch/riscv/mm/extable.c
+++ b/arch/riscv/mm/extable.c
@@ -10,6 +10,20 @@
#include <linux/extable.h>
#include <linux/module.h>
#include <linux/uaccess.h>
+#include <asm/asm-extable.h>
+
+static inline unsigned long
+get_ex_fixup(const struct exception_table_entry *ex)
+{
+ return ((unsigned long)&ex->fixup + ex->fixup);
+}
+
+static bool ex_handler_fixup(const struct exception_table_entry *ex,
+ struct pt_regs *regs)
+{
+ regs->epc = get_ex_fixup(ex);
+ return true;
+}
bool fixup_exception(struct pt_regs *regs)
{
@@ -19,9 +33,12 @@ bool fixup_exception(struct pt_regs *regs)
if (!ex)
return false;
- if (regs->epc >= BPF_JIT_REGION_START && regs->epc < BPF_JIT_REGION_END)
- return rv_bpf_fixup_exception(ex, regs);
+ switch (ex->type) {
+ case EX_TYPE_FIXUP:
+ return ex_handler_fixup(ex, regs);
+ case EX_TYPE_BPF:
+ return ex_handler_bpf(ex, regs);
+ }
- regs->epc = (unsigned long)&ex->fixup + ex->fixup;
- return true;
+ BUG();
}
diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index 7714081cbb64..69bab7e28f91 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -459,8 +459,8 @@ static int emit_call(bool fixed, u64 addr, struct rv_jit_context *ctx)
#define BPF_FIXUP_OFFSET_MASK GENMASK(26, 0)
#define BPF_FIXUP_REG_MASK GENMASK(31, 27)
-bool rv_bpf_fixup_exception(const struct exception_table_entry *ex,
- struct pt_regs *regs)
+bool ex_handler_bpf(const struct exception_table_entry *ex,
+ struct pt_regs *regs)
{
off_t offset = FIELD_GET(BPF_FIXUP_OFFSET_MASK, ex->fixup);
int regs_offset = FIELD_GET(BPF_FIXUP_REG_MASK, ex->fixup);
@@ -514,6 +514,7 @@ static int add_exception_handler(const struct bpf_insn *insn,
ex->fixup = FIELD_PREP(BPF_FIXUP_OFFSET_MASK, offset) |
FIELD_PREP(BPF_FIXUP_REG_MASK, dst_reg);
+ ex->type = EX_TYPE_BPF;
ctx->nexentries++;
return 0;
diff --git a/scripts/sorttable.c b/scripts/sorttable.c
index f4a8255036b5..82b162b3941b 100644
--- a/scripts/sorttable.c
+++ b/scripts/sorttable.c
@@ -337,6 +337,7 @@ static int do_file(char const *const fname, void *addr)
switch (r2(&ehdr->e_machine)) {
case EM_386:
case EM_AARCH64:
+ case EM_RISCV:
case EM_X86_64:
custom_sort = sort_relative_table_with_data;
break;
@@ -346,7 +347,6 @@ static int do_file(char const *const fname, void *addr)
case EM_PARISC:
case EM_PPC:
case EM_PPC64:
- case EM_RISCV:
custom_sort = sort_relative_table;
break;
case EM_ARCOMPACT: