mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-05 00:25:24 -04:00
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 commit894979689d("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:894979689d("s390/ftrace: provide separate ftrace_caller/ftrace_regs_caller implementations") Reviewed-by: Sven Schnelle <svens@linux.ibm.com> Acked-by: Ilya Leoshkevich <iii@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
This commit is contained in:
committed by
Vasily Gorbik
parent
6b4b54c7ca
commit
9fa881f7e3
@@ -159,9 +159,38 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec)
|
||||
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,
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -188,6 +217,12 @@ static void brcl_enable(void *brcl)
|
||||
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user