summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/loongarch/include/asm/asm-extable.h12
-rw-r--r--arch/loongarch/include/asm/extable.h26
-rw-r--r--arch/loongarch/include/asm/uaccess.h2
-rw-r--r--arch/loongarch/mm/extable.c32
-rw-r--r--scripts/mod/modpost.c13
-rw-r--r--scripts/sorttable.c2
6 files changed, 69 insertions, 18 deletions
diff --git a/arch/loongarch/include/asm/asm-extable.h b/arch/loongarch/include/asm/asm-extable.h
index 4f615bf56727..74f8bc75472a 100644
--- a/arch/loongarch/include/asm/asm-extable.h
+++ b/arch/loongarch/include/asm/asm-extable.h
@@ -6,9 +6,9 @@
#define __ASM_EXTABLE_RAW(insn, fixup) \
.pushsection __ex_table, "a"; \
- .balign 8; \
- .quad (insn); \
- .quad (fixup); \
+ .balign 4; \
+ .long ((insn) - .); \
+ .long ((fixup) - .); \
.popsection;
.macro _asm_extable, insn, fixup
@@ -22,9 +22,9 @@
#define __ASM_EXTABLE_RAW(insn, fixup) \
".pushsection __ex_table, \"a\"\n" \
- ".balign 8\n" \
- ".quad ((" insn "))\n" \
- ".quad ((" fixup "))\n" \
+ ".balign 4\n" \
+ ".long ((" insn ") - .)\n" \
+ ".long ((" fixup ") - .)\n" \
".popsection\n"
#define _ASM_EXTABLE(insn, fixup) \
diff --git a/arch/loongarch/include/asm/extable.h b/arch/loongarch/include/asm/extable.h
new file mode 100644
index 000000000000..b571c89705d1
--- /dev/null
+++ b/arch/loongarch/include/asm/extable.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_LOONGARCH_EXTABLE_H
+#define _ASM_LOONGARCH_EXTABLE_H
+
+/*
+ * The exception table consists of pairs of relative offsets: the first
+ * is the relative offset to an instruction that is allowed to fault,
+ * and the second is the relative offset at which the program should
+ * continue. No registers are modified, so it is entirely up to the
+ * continuation code to figure out what to do.
+ *
+ * All the routines below use bits of fixup code that are out of line
+ * with the main instruction path. This means when everything is well,
+ * we don't even have to jump over them. Further, they do not intrude
+ * on our cache or tlb entries.
+ */
+
+struct exception_table_entry {
+ int insn, fixup;
+};
+
+#define ARCH_HAS_RELATIVE_EXTABLE
+
+bool fixup_exception(struct pt_regs *regs);
+
+#endif
diff --git a/arch/loongarch/include/asm/uaccess.h b/arch/loongarch/include/asm/uaccess.h
index bf9a4e218ac0..e33282e0bdef 100644
--- a/arch/loongarch/include/asm/uaccess.h
+++ b/arch/loongarch/include/asm/uaccess.h
@@ -15,8 +15,8 @@
#include <linux/string.h>
#include <linux/extable.h>
#include <asm/pgtable.h>
+#include <asm/extable.h>
#include <asm/asm-extable.h>
-#include <asm-generic/extable.h>
#include <asm-generic/access_ok.h>
extern u64 __ua_limit;
diff --git a/arch/loongarch/mm/extable.c b/arch/loongarch/mm/extable.c
index bc20988f2b87..08a9a7d6357a 100644
--- a/arch/loongarch/mm/extable.c
+++ b/arch/loongarch/mm/extable.c
@@ -3,20 +3,32 @@
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
*/
#include <linux/extable.h>
-#include <linux/spinlock.h>
-#include <asm/branch.h>
#include <linux/uaccess.h>
+#include <asm/asm-extable.h>
+#include <asm/branch.h>
+
+static inline unsigned long
+get_ex_fixup(const struct exception_table_entry *ex)
+{
+ return ((unsigned long)&ex->fixup + ex->fixup);
+}
-int fixup_exception(struct pt_regs *regs)
+static bool ex_handler_fixup(const struct exception_table_entry *ex,
+ struct pt_regs *regs)
{
- const struct exception_table_entry *fixup;
+ regs->csr_era = get_ex_fixup(ex);
- fixup = search_exception_tables(exception_era(regs));
- if (fixup) {
- regs->csr_era = fixup->fixup;
+ return true;
+}
+
+
+bool fixup_exception(struct pt_regs *regs)
+{
+ const struct exception_table_entry *ex;
- return 1;
- }
+ ex = search_exception_tables(exception_era(regs));
+ if (!ex)
+ return false;
- return 0;
+ return ex_handler_fixup(ex, regs);
}
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 2c80da0220c3..9321c0a05ffd 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -1523,6 +1523,14 @@ static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
#define R_RISCV_SUB32 39
#endif
+#ifndef EM_LOONGARCH
+#define EM_LOONGARCH 258
+#endif
+
+#ifndef R_LARCH_SUB32
+#define R_LARCH_SUB32 55
+#endif
+
static void section_rela(const char *modname, struct elf_info *elf,
Elf_Shdr *sechdr)
{
@@ -1564,6 +1572,11 @@ static void section_rela(const char *modname, struct elf_info *elf,
ELF_R_TYPE(r.r_info) == R_RISCV_SUB32)
continue;
break;
+ case EM_LOONGARCH:
+ if (!strcmp("__ex_table", fromsec) &&
+ ELF_R_TYPE(r.r_info) == R_LARCH_SUB32)
+ continue;
+ break;
}
sym = elf->symtab_start + r_sym;
/* Skip special sections */
diff --git a/scripts/sorttable.c b/scripts/sorttable.c
index fba40e99f354..0f2beda80478 100644
--- a/scripts/sorttable.c
+++ b/scripts/sorttable.c
@@ -312,12 +312,12 @@ 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:
case EM_ARCV2:
case EM_ARM:
- case EM_LOONGARCH:
case EM_MICROBLAZE:
case EM_MIPS:
case EM_XTENSA: