diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-12-19 08:23:27 -0600 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-12-19 08:23:27 -0600 |
commit | 2f26e424552efd50722f4cf61f7f080373adbb1e (patch) | |
tree | 2ee52ba17fe19a6456d7110447e7127fd56c6b18 /arch/loongarch/mm | |
parent | 96bab5b926e4c2d970f70495f4554f905babd09d (diff) | |
parent | 5535f4f70cfc15ef55b6ea7c7e17337b17337cb6 (diff) |
Merge tag 'loongarch-6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
Pull LoongArch updates from Huacai Chen:
- Switch to relative exception tables
- Add unaligned access support
- Add alternative runtime patching mechanism
- Add FDT booting support from efi system table
- Add suspend/hibernation (ACPI S3/S4) support
- Add basic STACKPROTECTOR support
- Add ftrace (function tracer) support
- Update the default config file
* tag 'loongarch-6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson: (24 commits)
LoongArch: Update Loongson-3 default config file
LoongArch: modules/ftrace: Initialize PLT at load time
LoongArch/ftrace: Add HAVE_FUNCTION_GRAPH_RET_ADDR_PTR support
LoongArch/ftrace: Add HAVE_DYNAMIC_FTRACE_WITH_ARGS support
LoongArch/ftrace: Add HAVE_DYNAMIC_FTRACE_WITH_REGS support
LoongArch/ftrace: Add dynamic function graph tracer support
LoongArch/ftrace: Add dynamic function tracer support
LoongArch/ftrace: Add recordmcount support
LoongArch/ftrace: Add basic support
LoongArch: module: Use got/plt section indices for relocations
LoongArch: Add basic STACKPROTECTOR support
LoongArch: Add hibernation (ACPI S4) support
LoongArch: Add suspend (ACPI S3) support
LoongArch: Add processing ISA Node in DeviceTree
LoongArch: Add FDT booting support from efi system table
LoongArch: Use alternative to optimize libraries
LoongArch: Add alternative runtime patching mechanism
LoongArch: Add unaligned access support
LoongArch: BPF: Add BPF exception tables
LoongArch: Remove the .fixup section usage
...
Diffstat (limited to 'arch/loongarch/mm')
-rw-r--r-- | arch/loongarch/mm/extable.c | 59 |
1 files changed, 50 insertions, 9 deletions
diff --git a/arch/loongarch/mm/extable.c b/arch/loongarch/mm/extable.c index bc20988f2b87..9ab69872dcff 100644 --- a/arch/loongarch/mm/extable.c +++ b/arch/loongarch/mm/extable.c @@ -2,21 +2,62 @@ /* * Copyright (C) 2020-2022 Loongson Technology Corporation Limited */ +#include <linux/bitfield.h> #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); +} + +static inline void regs_set_gpr(struct pt_regs *regs, + unsigned int offset, unsigned long val) +{ + if (offset && offset <= MAX_REG_OFFSET) + *(unsigned long *)((unsigned long)regs + offset) = val; +} + +static bool ex_handler_fixup(const struct exception_table_entry *ex, + struct pt_regs *regs) +{ + regs->csr_era = get_ex_fixup(ex); + + return true; +} + +static bool ex_handler_uaccess_err_zero(const struct exception_table_entry *ex, + struct pt_regs *regs) +{ + int reg_err = FIELD_GET(EX_DATA_REG_ERR, ex->data); + int reg_zero = FIELD_GET(EX_DATA_REG_ZERO, ex->data); + + regs_set_gpr(regs, reg_err * sizeof(unsigned long), -EFAULT); + regs_set_gpr(regs, reg_zero * sizeof(unsigned long), 0); + regs->csr_era = get_ex_fixup(ex); + + return true; +} -int fixup_exception(struct pt_regs *regs) +bool fixup_exception(struct pt_regs *regs) { - const struct exception_table_entry *fixup; + const struct exception_table_entry *ex; - fixup = search_exception_tables(exception_era(regs)); - if (fixup) { - regs->csr_era = fixup->fixup; + ex = search_exception_tables(exception_era(regs)); + if (!ex) + return false; - return 1; + switch (ex->type) { + case EX_TYPE_FIXUP: + return ex_handler_fixup(ex, regs); + case EX_TYPE_UACCESS_ERR_ZERO: + return ex_handler_uaccess_err_zero(ex, regs); + case EX_TYPE_BPF: + return ex_handler_bpf(ex, regs); } - return 0; + BUG(); } |