diff options
author | Christophe Leroy <christophe.leroy@csgroup.eu> | 2021-10-28 14:24:03 +0200 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2021-11-29 22:49:29 +1100 |
commit | c93d4f6ecf4b0699d0f2088f7bd9cd09af45d65a (patch) | |
tree | f68a4ab7358760ea588b5686c5f8b701bf14c048 /arch/powerpc/kernel/module_32.c | |
parent | 88670fdb26800228606c078ba4a018e9522a75a8 (diff) | |
download | linux-c93d4f6ecf4b0699d0f2088f7bd9cd09af45d65a.tar.gz linux-c93d4f6ecf4b0699d0f2088f7bd9cd09af45d65a.tar.bz2 linux-c93d4f6ecf4b0699d0f2088f7bd9cd09af45d65a.zip |
powerpc/ftrace: Add module_trampoline_target() for PPC32
module_trampoline_target() is used by __ftrace_modify_call().
Implement it for PPC32 so that CONFIG_DYNAMIC_FTRACE_WITH_REGS
can be activated on PPC32 as well.
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/42345f464fb465f0fc76f3090e250be8fc1729f0.1635423081.git.christophe.leroy@csgroup.eu
Diffstat (limited to 'arch/powerpc/kernel/module_32.c')
-rw-r--r-- | arch/powerpc/kernel/module_32.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c index f417afc08d33..5dedd76346b2 100644 --- a/arch/powerpc/kernel/module_32.c +++ b/arch/powerpc/kernel/module_32.c @@ -273,6 +273,31 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, } #ifdef CONFIG_DYNAMIC_FTRACE +int module_trampoline_target(struct module *mod, unsigned long addr, + unsigned long *target) +{ + unsigned int jmp[4]; + + /* Find where the trampoline jumps to */ + if (copy_from_kernel_nofault(jmp, (void *)addr, sizeof(jmp))) + return -EFAULT; + + /* verify that this is what we expect it to be */ + if ((jmp[0] & 0xffff0000) != PPC_RAW_LIS(_R12, 0) || + (jmp[1] & 0xffff0000) != PPC_RAW_ADDI(_R12, _R12, 0) || + jmp[2] != PPC_RAW_MTCTR(_R12) || + jmp[3] != PPC_RAW_BCTR()) + return -EINVAL; + + addr = (jmp[1] & 0xffff) | ((jmp[0] & 0xffff) << 16); + if (addr & 0x8000) + addr -= 0x10000; + + *target = addr; + + return 0; +} + int module_finalize_ftrace(struct module *module, const Elf_Shdr *sechdrs) { module->arch.tramp = do_plt_call(module->core_layout.base, |