diff options
author | Andre Przywara <andre.przywara@arm.com> | 2014-11-28 13:40:45 +0000 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2014-12-04 10:28:24 +0000 |
commit | 932ded4b0b9bf111fbf9d176ec12152a0d29b0fd (patch) | |
tree | 72ae4cdbea21713d55576bf12fa8c095d3b48679 /arch/arm64/kernel/module.c | |
parent | cbbf2e6ed7c2adabfa5cc64901c7b89e029d1e20 (diff) | |
download | op-kernel-dev-932ded4b0b9bf111fbf9d176ec12152a0d29b0fd.zip op-kernel-dev-932ded4b0b9bf111fbf9d176ec12152a0d29b0fd.tar.gz |
arm64: add module support for alternatives fixups
Currently the kernel patches all necessary instructions once at boot
time, so modules are not covered by this.
Change the apply_alternatives() function to take a beginning and an
end pointer and introduce a new variant (apply_alternatives_all()) to
cover the existing use case for the static kernel image section.
Add a module_finalize() function to arm64 to check for an
alternatives section in a module and patch only the instructions from
that specific area.
Since that module code is not touched before the module
initialization has ended, we don't need to halt the machine before
doing the patching in the module's code.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'arch/arm64/kernel/module.c')
-rw-r--r-- | arch/arm64/kernel/module.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c index 1eb1cc9..fd027b1 100644 --- a/arch/arm64/kernel/module.c +++ b/arch/arm64/kernel/module.c @@ -26,6 +26,7 @@ #include <linux/moduleloader.h> #include <linux/vmalloc.h> #include <asm/insn.h> +#include <asm/sections.h> #define AARCH64_INSN_IMM_MOVNZ AARCH64_INSN_IMM_MAX #define AARCH64_INSN_IMM_MOVK AARCH64_INSN_IMM_16 @@ -394,3 +395,20 @@ overflow: me->name, (int)ELF64_R_TYPE(rel[i].r_info), val); return -ENOEXEC; } + +int module_finalize(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, + struct module *me) +{ + 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) == 0) { + apply_alternatives((void *)s->sh_addr, s->sh_size); + return 0; + } + } + + return 0; +} |