Commit 9fa881f7 authored by Heiko Carstens's avatar Heiko Carstens Committed by Vasily Gorbik

s390/ftrace: fix ftrace_caller/ftrace_regs_caller generation

ftrace_caller was used for both ftrace_caller and ftrace_regs_caller,
which means that the target address of the hotpatch trampoline was
never updated.

With commit 89497968 ("s390/ftrace: provide separate
ftrace_caller/ftrace_regs_caller implementations") a separate
ftrace_regs_caller entry point was implemeted, however it was
forgotten to implement the necessary changes for ftrace_modify_call
and ftrace_make_call, where the branch target has to be modified
accordingly.

Therefore add the missing code now.

Fixes: 89497968 ("s390/ftrace: provide separate ftrace_caller/ftrace_regs_caller implementations")
Reviewed-by: default avatarSven Schnelle <svens@linux.ibm.com>
Acked-by: default avatarIlya Leoshkevich <iii@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent 6b4b54c7
...@@ -159,9 +159,38 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec) ...@@ -159,9 +159,38 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec)
return 0; return 0;
} }
static struct ftrace_hotpatch_trampoline *ftrace_get_trampoline(struct dyn_ftrace *rec)
{
struct ftrace_hotpatch_trampoline *trampoline;
struct ftrace_insn insn;
s64 disp;
u16 opc;
if (copy_from_kernel_nofault(&insn, (void *)rec->ip, sizeof(insn)))
return ERR_PTR(-EFAULT);
disp = (s64)insn.disp * 2;
trampoline = (void *)(rec->ip + disp);
if (get_kernel_nofault(opc, &trampoline->brasl_opc))
return ERR_PTR(-EFAULT);
if (opc != 0xc015)
return ERR_PTR(-EINVAL);
return trampoline;
}
int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
unsigned long addr) unsigned long addr)
{ {
struct ftrace_hotpatch_trampoline *trampoline;
u64 old;
trampoline = ftrace_get_trampoline(rec);
if (IS_ERR(trampoline))
return PTR_ERR(trampoline);
if (get_kernel_nofault(old, &trampoline->interceptor))
return -EFAULT;
if (old != old_addr)
return -EINVAL;
s390_kernel_write(&trampoline->interceptor, &addr, sizeof(addr));
return 0; return 0;
} }
...@@ -188,6 +217,12 @@ static void brcl_enable(void *brcl) ...@@ -188,6 +217,12 @@ static void brcl_enable(void *brcl)
int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
{ {
struct ftrace_hotpatch_trampoline *trampoline;
trampoline = ftrace_get_trampoline(rec);
if (IS_ERR(trampoline))
return PTR_ERR(trampoline);
s390_kernel_write(&trampoline->interceptor, &addr, sizeof(addr));
brcl_enable((void *)rec->ip); brcl_enable((void *)rec->ip);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment