@@ -116,112 +116,6 @@ static unsigned long find_bl_target(unsigned long ip, ppc_inst_t op)
116116 return ip + (long )offset ;
117117}
118118
119- #ifdef CONFIG_MODULES
120- static int
121- __ftrace_make_nop (struct module * mod ,
122- struct dyn_ftrace * rec , unsigned long addr )
123- {
124- unsigned long entry , ptr , tramp ;
125- unsigned long ip = rec -> ip ;
126- ppc_inst_t op , pop ;
127-
128- /* read where this goes */
129- if (copy_inst_from_kernel_nofault (& op , (void * )ip )) {
130- pr_err ("Fetching opcode failed.\n" );
131- return - EFAULT ;
132- }
133-
134- /* Make sure that this is still a 24bit jump */
135- if (!is_bl_op (op )) {
136- pr_err ("Not expected bl: opcode is %08lx\n" , ppc_inst_as_ulong (op ));
137- return - EINVAL ;
138- }
139-
140- /* lets find where the pointer goes */
141- tramp = find_bl_target (ip , op );
142-
143- pr_devel ("ip:%lx jumps to %lx" , ip , tramp );
144-
145- if (module_trampoline_target (mod , tramp , & ptr )) {
146- pr_err ("Failed to get trampoline target\n" );
147- return - EFAULT ;
148- }
149-
150- pr_devel ("trampoline target %lx" , ptr );
151-
152- entry = ppc_global_function_entry ((void * )addr );
153- /* This should match what was called */
154- if (ptr != entry ) {
155- pr_err ("addr %lx does not match expected %lx\n" , ptr , entry );
156- return - EINVAL ;
157- }
158-
159- if (IS_ENABLED (CONFIG_MPROFILE_KERNEL )) {
160- if (copy_inst_from_kernel_nofault (& op , (void * )(ip - 4 ))) {
161- pr_err ("Fetching instruction at %lx failed.\n" , ip - 4 );
162- return - EFAULT ;
163- }
164-
165- /* We expect either a mflr r0, or a std r0, LRSAVE(r1) */
166- if (!ppc_inst_equal (op , ppc_inst (PPC_RAW_MFLR (_R0 ))) &&
167- !ppc_inst_equal (op , ppc_inst (PPC_INST_STD_LR ))) {
168- pr_err ("Unexpected instruction %08lx around bl _mcount\n" ,
169- ppc_inst_as_ulong (op ));
170- return - EINVAL ;
171- }
172- } else if (IS_ENABLED (CONFIG_PPC64 )) {
173- /*
174- * Check what is in the next instruction. We can see ld r2,40(r1), but
175- * on first pass after boot we will see mflr r0.
176- */
177- if (copy_inst_from_kernel_nofault (& op , (void * )(ip + 4 ))) {
178- pr_err ("Fetching op failed.\n" );
179- return - EFAULT ;
180- }
181-
182- if (!ppc_inst_equal (op , ppc_inst (PPC_INST_LD_TOC ))) {
183- pr_err ("Expected %08lx found %08lx\n" , PPC_INST_LD_TOC ,
184- ppc_inst_as_ulong (op ));
185- return - EINVAL ;
186- }
187- }
188-
189- /*
190- * When using -mprofile-kernel or PPC32 there is no load to jump over.
191- *
192- * Otherwise our original call site looks like:
193- *
194- * bl <tramp>
195- * ld r2,XX(r1)
196- *
197- * Milton Miller pointed out that we can not simply nop the branch.
198- * If a task was preempted when calling a trace function, the nops
199- * will remove the way to restore the TOC in r2 and the r2 TOC will
200- * get corrupted.
201- *
202- * Use a b +8 to jump over the load.
203- * XXX: could make PCREL depend on MPROFILE_KERNEL
204- * XXX: check PCREL && MPROFILE_KERNEL calling sequence
205- */
206- if (IS_ENABLED (CONFIG_MPROFILE_KERNEL ) || IS_ENABLED (CONFIG_PPC32 ))
207- pop = ppc_inst (PPC_RAW_NOP ());
208- else
209- pop = ppc_inst (PPC_RAW_BRANCH (8 )); /* b +8 */
210-
211- if (patch_instruction ((u32 * )ip , pop )) {
212- pr_err ("Patching NOP failed.\n" );
213- return - EPERM ;
214- }
215-
216- return 0 ;
217- }
218- #else
219- static int __ftrace_make_nop (struct module * mod , struct dyn_ftrace * rec , unsigned long addr )
220- {
221- return 0 ;
222- }
223- #endif /* CONFIG_MODULES */
224-
225119static unsigned long find_ftrace_tramp (unsigned long ip )
226120{
227121 int i ;
@@ -235,88 +129,6 @@ static unsigned long find_ftrace_tramp(unsigned long ip)
235129 return 0 ;
236130}
237131
238- static int __ftrace_make_nop_kernel (struct dyn_ftrace * rec , unsigned long addr )
239- {
240- unsigned long tramp , ip = rec -> ip ;
241- ppc_inst_t op ;
242-
243- /* Read where this goes */
244- if (copy_inst_from_kernel_nofault (& op , (void * )ip )) {
245- pr_err ("Fetching opcode failed.\n" );
246- return - EFAULT ;
247- }
248-
249- /* Make sure that this is still a 24bit jump */
250- if (!is_bl_op (op )) {
251- pr_err ("Not expected bl: opcode is %08lx\n" , ppc_inst_as_ulong (op ));
252- return - EINVAL ;
253- }
254-
255- /* Let's find where the pointer goes */
256- tramp = find_bl_target (ip , op );
257-
258- pr_devel ("ip:%lx jumps to %lx" , ip , tramp );
259-
260- /* Are ftrace trampolines reachable? */
261- if (!find_ftrace_tramp (ip )) {
262- pr_err ("No ftrace trampolines reachable from %ps\n" , (void * )ip );
263- return - EINVAL ;
264- }
265-
266- if (patch_instruction ((u32 * )ip , ppc_inst (PPC_RAW_NOP ()))) {
267- pr_err ("Patching NOP failed.\n" );
268- return - EPERM ;
269- }
270-
271- return 0 ;
272- }
273-
274- int ftrace_make_nop (struct module * mod ,
275- struct dyn_ftrace * rec , unsigned long addr )
276- {
277- unsigned long ip = rec -> ip ;
278- ppc_inst_t old , new ;
279-
280- /*
281- * If the calling address is more that 24 bits away,
282- * then we had to use a trampoline to make the call.
283- * Otherwise just update the call site.
284- */
285- if (test_24bit_addr (ip , addr )) {
286- /* within range */
287- old = ftrace_call_replace (ip , addr , 1 );
288- new = ppc_inst (PPC_RAW_NOP ());
289- return ftrace_modify_code (ip , old , new );
290- } else if (core_kernel_text (ip )) {
291- return __ftrace_make_nop_kernel (rec , addr );
292- } else if (!IS_ENABLED (CONFIG_MODULES )) {
293- return - EINVAL ;
294- }
295-
296- /*
297- * Out of range jumps are called from modules.
298- * We should either already have a pointer to the module
299- * or it has been passed in.
300- */
301- if (!rec -> arch .mod ) {
302- if (!mod ) {
303- pr_err ("No module loaded addr=%lx\n" , addr );
304- return - EFAULT ;
305- }
306- rec -> arch .mod = mod ;
307- } else if (mod ) {
308- if (mod != rec -> arch .mod ) {
309- pr_err ("Record mod %p not equal to passed in mod %p\n" ,
310- rec -> arch .mod , mod );
311- return - EINVAL ;
312- }
313- /* nothing to do if mod == rec->arch.mod */
314- } else
315- mod = rec -> arch .mod ;
316-
317- return __ftrace_make_nop (mod , rec , addr );
318- }
319-
320132#ifdef CONFIG_MODULES
321133/*
322134 * Examine the existing instructions for __ftrace_make_call.
@@ -607,6 +419,38 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
607419}
608420#endif
609421
422+ int ftrace_make_nop (struct module * mod , struct dyn_ftrace * rec , unsigned long addr )
423+ {
424+ unsigned long tramp , ip = rec -> ip ;
425+ ppc_inst_t old , new ;
426+
427+ /* Nop-out the ftrace location */
428+ new = ppc_inst (PPC_RAW_NOP ());
429+ if (is_offset_in_branch_range (addr - ip )) {
430+ /* Within range */
431+ old = ftrace_create_branch_inst (ip , addr , 1 );
432+ return ftrace_modify_code (ip , old , new );
433+ } else if (core_kernel_text (ip )) {
434+ /* We would be branching to one of our ftrace tramps */
435+ tramp = find_ftrace_tramp (ip );
436+ if (!tramp ) {
437+ pr_err ("0x%lx: No ftrace trampolines reachable\n" , ip );
438+ return - EINVAL ;
439+ }
440+ old = ftrace_create_branch_inst (ip , tramp , 1 );
441+ return ftrace_modify_code (ip , old , new );
442+ } else if (IS_ENABLED (CONFIG_MODULES )) {
443+ /* Module code would be going to one of the module stubs */
444+ if (!mod )
445+ mod = rec -> arch .mod ;
446+ tramp = (addr == (unsigned long )ftrace_caller ? mod -> arch .tramp : mod -> arch .tramp_regs );
447+ old = ftrace_create_branch_inst (ip , tramp , 1 );
448+ return ftrace_modify_code (ip , old , new );
449+ }
450+
451+ return - EINVAL ;
452+ }
453+
610454int ftrace_init_nop (struct module * mod , struct dyn_ftrace * rec )
611455{
612456 unsigned long addr , ip = rec -> ip ;
0 commit comments