Skip to content

Commit 9fa881f

Browse files
hcahcaVasily Gorbik
authored andcommitted
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 8949796 ("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: 8949796 ("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>
1 parent 6b4b54c commit 9fa881f

File tree

1 file changed

+35
-0
lines changed

1 file changed

+35
-0
lines changed

arch/s390/kernel/ftrace.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,38 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec)
159159
return 0;
160160
}
161161

162+
static struct ftrace_hotpatch_trampoline *ftrace_get_trampoline(struct dyn_ftrace *rec)
163+
{
164+
struct ftrace_hotpatch_trampoline *trampoline;
165+
struct ftrace_insn insn;
166+
s64 disp;
167+
u16 opc;
168+
169+
if (copy_from_kernel_nofault(&insn, (void *)rec->ip, sizeof(insn)))
170+
return ERR_PTR(-EFAULT);
171+
disp = (s64)insn.disp * 2;
172+
trampoline = (void *)(rec->ip + disp);
173+
if (get_kernel_nofault(opc, &trampoline->brasl_opc))
174+
return ERR_PTR(-EFAULT);
175+
if (opc != 0xc015)
176+
return ERR_PTR(-EINVAL);
177+
return trampoline;
178+
}
179+
162180
int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
163181
unsigned long addr)
164182
{
183+
struct ftrace_hotpatch_trampoline *trampoline;
184+
u64 old;
185+
186+
trampoline = ftrace_get_trampoline(rec);
187+
if (IS_ERR(trampoline))
188+
return PTR_ERR(trampoline);
189+
if (get_kernel_nofault(old, &trampoline->interceptor))
190+
return -EFAULT;
191+
if (old != old_addr)
192+
return -EINVAL;
193+
s390_kernel_write(&trampoline->interceptor, &addr, sizeof(addr));
165194
return 0;
166195
}
167196

@@ -188,6 +217,12 @@ static void brcl_enable(void *brcl)
188217

189218
int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
190219
{
220+
struct ftrace_hotpatch_trampoline *trampoline;
221+
222+
trampoline = ftrace_get_trampoline(rec);
223+
if (IS_ERR(trampoline))
224+
return PTR_ERR(trampoline);
225+
s390_kernel_write(&trampoline->interceptor, &addr, sizeof(addr));
191226
brcl_enable((void *)rec->ip);
192227
return 0;
193228
}

0 commit comments

Comments
 (0)