@@ -69,7 +69,7 @@ static const char *ftrace_shared_hotpatch_trampoline(const char **end)
69
69
70
70
bool ftrace_need_init_nop (void )
71
71
{
72
- return true ;
72
+ return ! MACHINE_HAS_SEQ_INSN ;
73
73
}
74
74
75
75
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
139
139
return trampoline ;
140
140
}
141
141
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 )
144
171
{
145
172
struct ftrace_hotpatch_trampoline * trampoline ;
146
173
u64 old ;
@@ -156,6 +183,15 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
156
183
return 0 ;
157
184
}
158
185
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
+
159
195
static int ftrace_patch_branch_mask (void * addr , u16 expected , bool enable )
160
196
{
161
197
u16 old ;
@@ -174,11 +210,14 @@ static int ftrace_patch_branch_mask(void *addr, u16 expected, bool enable)
174
210
int ftrace_make_nop (struct module * mod , struct dyn_ftrace * rec ,
175
211
unsigned long addr )
176
212
{
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);
179
218
}
180
219
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 )
182
221
{
183
222
struct ftrace_hotpatch_trampoline * trampoline ;
184
223
@@ -190,6 +229,14 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
190
229
return ftrace_patch_branch_mask ((void * )rec -> ip , 0xc004 , true);
191
230
}
192
231
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
+
193
240
int ftrace_update_ftrace_func (ftrace_func_t func )
194
241
{
195
242
ftrace_func = func ;
0 commit comments