[PATCH 3/7] LoongArch: extable: Add `type` and `data` fields

From: Youling Tang
Date: Mon Oct 10 2022 - 05:32:57 EST


This is a LoongArch port of commit d6e2cc564775 ("arm64: extable: add
`type` and `data` fields").

Subsequent patches will add specialized handlers for fixups, in addition
to the simple PC fixup 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 other 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 example
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.

Signed-off-by: Youling Tang <tangyouling@xxxxxxxxxxx>
---
arch/loongarch/include/asm/asm-extable.h | 15 +++++++++++----
arch/loongarch/include/asm/extable.h | 11 +++++++++++
arch/loongarch/kernel/vmlinux.lds.S | 3 +--
arch/loongarch/mm/extable.c | 7 ++++++-
scripts/sorttable.c | 2 +-
5 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/arch/loongarch/include/asm/asm-extable.h b/arch/loongarch/include/asm/asm-extable.h
index 74f8bc75472a..634bd770e3c4 100644
--- a/arch/loongarch/include/asm/asm-extable.h
+++ b/arch/loongarch/include/asm/asm-extable.h
@@ -2,17 +2,22 @@
#ifndef __ASM_ASM_EXTABLE_H
#define __ASM_ASM_EXTABLE_H

+#define EX_TYPE_NONE 0
+#define EX_TYPE_FIXUP 1
+
#ifdef __ASSEMBLY__

-#define __ASM_EXTABLE_RAW(insn, 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__ */
@@ -20,15 +25,17 @@
#include <linux/bits.h>
#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)
+ __ASM_EXTABLE_RAW(#insn, #fixup, __stringify(EX_TYPE_FIXUP), "0")

#endif /* __ASSEMBLY__ */

diff --git a/arch/loongarch/include/asm/extable.h b/arch/loongarch/include/asm/extable.h
index b571c89705d1..92612b4364a1 100644
--- a/arch/loongarch/include/asm/extable.h
+++ b/arch/loongarch/include/asm/extable.h
@@ -17,10 +17,21 @@

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);

#endif
diff --git a/arch/loongarch/kernel/vmlinux.lds.S b/arch/loongarch/kernel/vmlinux.lds.S
index b3309a5e695b..efecda0c2361 100644
--- a/arch/loongarch/kernel/vmlinux.lds.S
+++ b/arch/loongarch/kernel/vmlinux.lds.S
@@ -4,6 +4,7 @@
#include <asm/thread_info.h>

#define PAGE_SIZE _PAGE_SIZE
+#define RO_EXCEPTION_TABLE_ALIGN 4

/*
* Put .bss..swapper_pg_dir as the first thing in .bss. This will
@@ -53,8 +54,6 @@ SECTIONS
. = ALIGN(PECOFF_SEGMENT_ALIGN);
_etext = .;

- EXCEPTION_TABLE(16)
-
.got : ALIGN(16) { *(.got) }
.plt : ALIGN(16) { *(.plt) }
.got.plt : ALIGN(16) { *(.got.plt) }
diff --git a/arch/loongarch/mm/extable.c b/arch/loongarch/mm/extable.c
index fb2b5a0268f0..56b7250fc65e 100644
--- a/arch/loongarch/mm/extable.c
+++ b/arch/loongarch/mm/extable.c
@@ -30,5 +30,10 @@ bool fixup_exception(struct pt_regs *regs)
if (!ex)
return false;

- return ex_handler_fixup(ex, regs);
+ switch (ex->type) {
+ case EX_TYPE_FIXUP:
+ return ex_handler_fixup(ex, regs);
+ }
+
+ BUG();
}
diff --git a/scripts/sorttable.c b/scripts/sorttable.c
index 0f2beda80478..83cdb843d92f 100644
--- a/scripts/sorttable.c
+++ b/scripts/sorttable.c
@@ -304,6 +304,7 @@ static int do_file(char const *const fname, void *addr)
switch (r2(&ehdr->e_machine)) {
case EM_386:
case EM_AARCH64:
+ case EM_LOONGARCH:
case EM_RISCV:
case EM_S390:
case EM_X86_64:
@@ -312,7 +313,6 @@ static int do_file(char const *const fname, void *addr)
case EM_PARISC:
case EM_PPC:
case EM_PPC64:
- case EM_LOONGARCH:
custom_sort = sort_relative_table;
break;
case EM_ARCOMPACT:
--
2.36.1