diff options
author | Huacai Chen <chenhuacai@loongson.cn> | 2022-12-10 15:39:59 +0100 |
---|---|---|
committer | Huacai Chen <chenhuacai@loongson.cn> | 2022-12-14 01:36:11 +0100 |
commit | 19e5eb15b00c5841b4b9bd9777af2865a40d2f39 (patch) | |
tree | f471107baccd8668f7cd72a2e8f5b5f690e30506 /arch/loongarch/kernel/module.c | |
parent | LoongArch: Add unaligned access support (diff) | |
download | linux-19e5eb15b00c5841b4b9bd9777af2865a40d2f39.tar.xz linux-19e5eb15b00c5841b4b9bd9777af2865a40d2f39.zip |
LoongArch: Add alternative runtime patching mechanism
Introduce the "alternative" mechanism from ARM64 and x86 for LoongArch
to apply runtime patching. The main purpose of this patch is to provide
a framework. In future we can use this mechanism (i.e., the ALTERNATIVE
and ALTERNATIVE_2 macros) to optimize hotspot functions according to cpu
features.
Signed-off-by: Jun Yi <yijun@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
Diffstat (limited to 'arch/loongarch/kernel/module.c')
-rw-r--r-- | arch/loongarch/kernel/module.c | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/arch/loongarch/kernel/module.c b/arch/loongarch/kernel/module.c index 097595b2fc14..825fcf77f9e7 100644 --- a/arch/loongarch/kernel/module.c +++ b/arch/loongarch/kernel/module.c @@ -17,6 +17,7 @@ #include <linux/fs.h> #include <linux/string.h> #include <linux/kernel.h> +#include <asm/alternative.h> static int rela_stack_push(s64 stack_value, s64 *rela_stack, size_t *rela_stack_top) { @@ -456,3 +457,17 @@ void *module_alloc(unsigned long size) return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, GFP_KERNEL, PAGE_KERNEL, 0, NUMA_NO_NODE, __builtin_return_address(0)); } + +int module_finalize(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, struct module *mod) +{ + const Elf_Shdr *s, *se; + const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; + + for (s = sechdrs, se = sechdrs + hdr->e_shnum; s < se; s++) { + if (!strcmp(".altinstructions", secstrs + s->sh_name)) + apply_alternatives((void *)s->sh_addr, (void *)s->sh_addr + s->sh_size); + } + + return 0; +} |