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
This commit is contained in:
parent
88670fdb26
commit
c93d4f6ecf
@ -273,6 +273,31 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
#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)
|
int module_finalize_ftrace(struct module *module, const Elf_Shdr *sechdrs)
|
||||||
{
|
{
|
||||||
module->arch.tramp = do_plt_call(module->core_layout.base,
|
module->arch.tramp = do_plt_call(module->core_layout.base,
|
||||||
|
@ -222,9 +222,8 @@ __ftrace_make_nop(struct module *mod,
|
|||||||
struct dyn_ftrace *rec, unsigned long addr)
|
struct dyn_ftrace *rec, unsigned long addr)
|
||||||
{
|
{
|
||||||
struct ppc_inst op;
|
struct ppc_inst op;
|
||||||
unsigned int jmp[4];
|
|
||||||
unsigned long ip = rec->ip;
|
unsigned long ip = rec->ip;
|
||||||
unsigned long tramp;
|
unsigned long tramp, ptr;
|
||||||
|
|
||||||
if (copy_from_kernel_nofault(&op, (void *)ip, MCOUNT_INSN_SIZE))
|
if (copy_from_kernel_nofault(&op, (void *)ip, MCOUNT_INSN_SIZE))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
@ -238,41 +237,13 @@ __ftrace_make_nop(struct module *mod,
|
|||||||
/* lets find where the pointer goes */
|
/* lets find where the pointer goes */
|
||||||
tramp = find_bl_target(ip, op);
|
tramp = find_bl_target(ip, op);
|
||||||
|
|
||||||
/*
|
|
||||||
* On PPC32 the trampoline looks like:
|
|
||||||
* 0x3d, 0x80, 0x00, 0x00 lis r12,sym@ha
|
|
||||||
* 0x39, 0x8c, 0x00, 0x00 addi r12,r12,sym@l
|
|
||||||
* 0x7d, 0x89, 0x03, 0xa6 mtctr r12
|
|
||||||
* 0x4e, 0x80, 0x04, 0x20 bctr
|
|
||||||
*/
|
|
||||||
|
|
||||||
pr_devel("ip:%lx jumps to %lx", ip, tramp);
|
|
||||||
|
|
||||||
/* Find where the trampoline jumps to */
|
/* Find where the trampoline jumps to */
|
||||||
if (copy_from_kernel_nofault(jmp, (void *)tramp, sizeof(jmp))) {
|
if (module_trampoline_target(mod, tramp, &ptr)) {
|
||||||
pr_err("Failed to read %lx\n", tramp);
|
pr_err("Failed to get trampoline target\n");
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_devel(" %08x %08x ", jmp[0], jmp[1]);
|
if (ptr != addr) {
|
||||||
|
|
||||||
/* verify that this is what we expect it to be */
|
|
||||||
if (((jmp[0] & 0xffff0000) != 0x3d800000) ||
|
|
||||||
((jmp[1] & 0xffff0000) != 0x398c0000) ||
|
|
||||||
(jmp[2] != 0x7d8903a6) ||
|
|
||||||
(jmp[3] != 0x4e800420)) {
|
|
||||||
pr_err("Not a trampoline\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
tramp = (jmp[1] & 0xffff) |
|
|
||||||
((jmp[0] & 0xffff) << 16);
|
|
||||||
if (tramp & 0x8000)
|
|
||||||
tramp -= 0x10000;
|
|
||||||
|
|
||||||
pr_devel(" %lx ", tramp);
|
|
||||||
|
|
||||||
if (tramp != addr) {
|
|
||||||
pr_err("Trampoline location %08lx does not match addr\n",
|
pr_err("Trampoline location %08lx does not match addr\n",
|
||||||
tramp);
|
tramp);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user