Skip to content

Commit efd9cd0

Browse files
author
Vasily Gorbik
committed
s390/ftrace: Avoid trampolines if possible
When a sequential instruction fetching facility is present, it is safe to patch ftrace NOPs in function prologues. All of them are 8-byte aligned. Reviewed-by: Heiko Carstens <[email protected]> Signed-off-by: Vasily Gorbik <[email protected]>
1 parent 3079915 commit efd9cd0

File tree

1 file changed

+53
-6
lines changed

1 file changed

+53
-6
lines changed

arch/s390/kernel/ftrace.c

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ static const char *ftrace_shared_hotpatch_trampoline(const char **end)
6969

7070
bool ftrace_need_init_nop(void)
7171
{
72-
return true;
72+
return !MACHINE_HAS_SEQ_INSN;
7373
}
7474

7575
int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec)
@@ -139,8 +139,35 @@ static struct ftrace_hotpatch_trampoline *ftrace_get_trampoline(struct dyn_ftrac
139139
return trampoline;
140140
}
141141

142-
int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
143-
unsigned long addr)
142+
static inline struct ftrace_insn
143+
ftrace_generate_branch_insn(unsigned long ip, unsigned long target)
144+
{
145+
/* brasl r0,target or brcl 0,0 */
146+
return (struct ftrace_insn){ .opc = target ? 0xc005 : 0xc004,
147+
.disp = target ? (target - ip) / 2 : 0 };
148+
}
149+
150+
static int ftrace_patch_branch_insn(unsigned long ip, unsigned long old_target,
151+
unsigned long target)
152+
{
153+
struct ftrace_insn orig = ftrace_generate_branch_insn(ip, old_target);
154+
struct ftrace_insn new = ftrace_generate_branch_insn(ip, target);
155+
struct ftrace_insn old;
156+
157+
if (!IS_ALIGNED(ip, 8))
158+
return -EINVAL;
159+
if (copy_from_kernel_nofault(&old, (void *)ip, sizeof(old)))
160+
return -EFAULT;
161+
/* Verify that the to be replaced code matches what we expect. */
162+
if (memcmp(&orig, &old, sizeof(old)))
163+
return -EINVAL;
164+
s390_kernel_write((void *)ip, &new, sizeof(new));
165+
return 0;
166+
}
167+
168+
static int ftrace_modify_trampoline_call(struct dyn_ftrace *rec,
169+
unsigned long old_addr,
170+
unsigned long addr)
144171
{
145172
struct ftrace_hotpatch_trampoline *trampoline;
146173
u64 old;
@@ -156,6 +183,15 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
156183
return 0;
157184
}
158185

186+
int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
187+
unsigned long addr)
188+
{
189+
if (MACHINE_HAS_SEQ_INSN)
190+
return ftrace_patch_branch_insn(rec->ip, old_addr, addr);
191+
else
192+
return ftrace_modify_trampoline_call(rec, old_addr, addr);
193+
}
194+
159195
static int ftrace_patch_branch_mask(void *addr, u16 expected, bool enable)
160196
{
161197
u16 old;
@@ -174,11 +210,14 @@ static int ftrace_patch_branch_mask(void *addr, u16 expected, bool enable)
174210
int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
175211
unsigned long addr)
176212
{
177-
/* Expect brcl 0xf,... */
178-
return ftrace_patch_branch_mask((void *)rec->ip, 0xc0f4, false);
213+
/* Expect brcl 0xf,... for the !MACHINE_HAS_SEQ_INSN case */
214+
if (MACHINE_HAS_SEQ_INSN)
215+
return ftrace_patch_branch_insn(rec->ip, addr, 0);
216+
else
217+
return ftrace_patch_branch_mask((void *)rec->ip, 0xc0f4, false);
179218
}
180219

181-
int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
220+
static int ftrace_make_trampoline_call(struct dyn_ftrace *rec, unsigned long addr)
182221
{
183222
struct ftrace_hotpatch_trampoline *trampoline;
184223

@@ -190,6 +229,14 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
190229
return ftrace_patch_branch_mask((void *)rec->ip, 0xc004, true);
191230
}
192231

232+
int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
233+
{
234+
if (MACHINE_HAS_SEQ_INSN)
235+
return ftrace_patch_branch_insn(rec->ip, 0, addr);
236+
else
237+
return ftrace_make_trampoline_call(rec, addr);
238+
}
239+
193240
int ftrace_update_ftrace_func(ftrace_func_t func)
194241
{
195242
ftrace_func = func;

0 commit comments

Comments
 (0)