@@ -129,162 +129,6 @@ static unsigned long find_ftrace_tramp(unsigned long ip)
129129 return 0 ;
130130}
131131
132- #ifdef CONFIG_MODULES
133- /*
134- * Examine the existing instructions for __ftrace_make_call.
135- * They should effectively be a NOP, and follow formal constraints,
136- * depending on the ABI. Return false if they don't.
137- */
138- static bool expected_nop_sequence (void * ip , ppc_inst_t op0 , ppc_inst_t op1 )
139- {
140- if (IS_ENABLED (CONFIG_DYNAMIC_FTRACE_WITH_REGS ))
141- return ppc_inst_equal (op0 , ppc_inst (PPC_RAW_NOP ()));
142- else
143- return ppc_inst_equal (op0 , ppc_inst (PPC_RAW_BRANCH (8 ))) &&
144- ppc_inst_equal (op1 , ppc_inst (PPC_INST_LD_TOC ));
145- }
146-
147- static int
148- __ftrace_make_call (struct dyn_ftrace * rec , unsigned long addr )
149- {
150- ppc_inst_t op [2 ];
151- void * ip = (void * )rec -> ip ;
152- unsigned long entry , ptr , tramp ;
153- struct module * mod = rec -> arch .mod ;
154-
155- /* read where this goes */
156- if (copy_inst_from_kernel_nofault (op , ip ))
157- return - EFAULT ;
158-
159- if (!IS_ENABLED (CONFIG_DYNAMIC_FTRACE_WITH_REGS ) &&
160- copy_inst_from_kernel_nofault (op + 1 , ip + 4 ))
161- return - EFAULT ;
162-
163- if (!expected_nop_sequence (ip , op [0 ], op [1 ])) {
164- pr_err ("Unexpected call sequence at %p: %08lx %08lx\n" , ip ,
165- ppc_inst_as_ulong (op [0 ]), ppc_inst_as_ulong (op [1 ]));
166- return - EINVAL ;
167- }
168-
169- /* If we never set up ftrace trampoline(s), then bail */
170- if (!mod -> arch .tramp ||
171- (IS_ENABLED (CONFIG_DYNAMIC_FTRACE_WITH_REGS ) && !mod -> arch .tramp_regs )) {
172- pr_err ("No ftrace trampoline\n" );
173- return - EINVAL ;
174- }
175-
176- if (IS_ENABLED (CONFIG_DYNAMIC_FTRACE_WITH_REGS ) && rec -> flags & FTRACE_FL_REGS )
177- tramp = mod -> arch .tramp_regs ;
178- else
179- tramp = mod -> arch .tramp ;
180-
181- if (module_trampoline_target (mod , tramp , & ptr )) {
182- pr_err ("Failed to get trampoline target\n" );
183- return - EFAULT ;
184- }
185-
186- pr_devel ("trampoline target %lx" , ptr );
187-
188- entry = ppc_global_function_entry ((void * )addr );
189- /* This should match what was called */
190- if (ptr != entry ) {
191- pr_err ("addr %lx does not match expected %lx\n" , ptr , entry );
192- return - EINVAL ;
193- }
194-
195- if (patch_branch (ip , tramp , BRANCH_SET_LINK )) {
196- pr_err ("REL24 out of range!\n" );
197- return - EINVAL ;
198- }
199-
200- return 0 ;
201- }
202- #else
203- static int __ftrace_make_call (struct dyn_ftrace * rec , unsigned long addr )
204- {
205- return 0 ;
206- }
207- #endif /* CONFIG_MODULES */
208-
209- static int __ftrace_make_call_kernel (struct dyn_ftrace * rec , unsigned long addr )
210- {
211- ppc_inst_t op ;
212- void * ip = (void * )rec -> ip ;
213- unsigned long tramp , entry , ptr ;
214-
215- /* Make sure we're being asked to patch branch to a known ftrace addr */
216- entry = ppc_global_function_entry ((void * )ftrace_caller );
217- ptr = ppc_global_function_entry ((void * )addr );
218-
219- if (ptr != entry && IS_ENABLED (CONFIG_DYNAMIC_FTRACE_WITH_REGS ))
220- entry = ppc_global_function_entry ((void * )ftrace_regs_caller );
221-
222- if (ptr != entry ) {
223- pr_err ("Unknown ftrace addr to patch: %ps\n" , (void * )ptr );
224- return - EINVAL ;
225- }
226-
227- /* Make sure we have a nop */
228- if (copy_inst_from_kernel_nofault (& op , ip )) {
229- pr_err ("Unable to read ftrace location %p\n" , ip );
230- return - EFAULT ;
231- }
232-
233- if (!ppc_inst_equal (op , ppc_inst (PPC_RAW_NOP ()))) {
234- pr_err ("Unexpected call sequence at %p: %08lx\n" ,
235- ip , ppc_inst_as_ulong (op ));
236- return - EINVAL ;
237- }
238-
239- tramp = find_ftrace_tramp ((unsigned long )ip );
240- if (!tramp ) {
241- pr_err ("No ftrace trampolines reachable from %ps\n" , ip );
242- return - EINVAL ;
243- }
244-
245- if (patch_branch (ip , tramp , BRANCH_SET_LINK )) {
246- pr_err ("Error patching branch to ftrace tramp!\n" );
247- return - EINVAL ;
248- }
249-
250- return 0 ;
251- }
252-
253- int ftrace_make_call (struct dyn_ftrace * rec , unsigned long addr )
254- {
255- unsigned long ip = rec -> ip ;
256- ppc_inst_t old , new ;
257-
258- /*
259- * If the calling address is more that 24 bits away,
260- * then we had to use a trampoline to make the call.
261- * Otherwise just update the call site.
262- */
263- if (test_24bit_addr (ip , addr )) {
264- /* within range */
265- old = ppc_inst (PPC_RAW_NOP ());
266- new = ftrace_call_replace (ip , addr , 1 );
267- return ftrace_modify_code (ip , old , new );
268- } else if (core_kernel_text (ip )) {
269- return __ftrace_make_call_kernel (rec , addr );
270- } else if (!IS_ENABLED (CONFIG_MODULES )) {
271- /* We should not get here without modules */
272- return - EINVAL ;
273- }
274-
275- /*
276- * Out of range jumps are called from modules.
277- * Being that we are converting from nop, it had better
278- * already have a module defined.
279- */
280- if (!rec -> arch .mod ) {
281- pr_err ("No module loaded\n" );
282- return - EINVAL ;
283- }
284-
285- return __ftrace_make_call (rec , addr );
286- }
287-
288132#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
289133#ifdef CONFIG_MODULES
290134static int
@@ -419,6 +263,37 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
419263}
420264#endif
421265
266+ int ftrace_make_call (struct dyn_ftrace * rec , unsigned long addr )
267+ {
268+ unsigned long tramp , ip = rec -> ip ;
269+ ppc_inst_t old , new ;
270+ struct module * mod ;
271+
272+ old = ppc_inst (PPC_RAW_NOP ());
273+ if (is_offset_in_branch_range (addr - ip )) {
274+ /* Within range */
275+ new = ftrace_create_branch_inst (ip , addr , 1 );
276+ return ftrace_modify_code (ip , old , new );
277+ } else if (core_kernel_text (ip )) {
278+ /* We would be branching to one of our ftrace tramps */
279+ tramp = find_ftrace_tramp (ip );
280+ if (!tramp ) {
281+ pr_err ("0x%lx: No ftrace trampolines reachable\n" , ip );
282+ return - EINVAL ;
283+ }
284+ new = ftrace_create_branch_inst (ip , tramp , 1 );
285+ return ftrace_modify_code (ip , old , new );
286+ } else if (IS_ENABLED (CONFIG_MODULES )) {
287+ /* Module code would be going to one of the module stubs */
288+ mod = rec -> arch .mod ;
289+ tramp = (addr == (unsigned long )ftrace_caller ? mod -> arch .tramp : mod -> arch .tramp_regs );
290+ new = ftrace_create_branch_inst (ip , tramp , 1 );
291+ return ftrace_modify_code (ip , old , new );
292+ }
293+
294+ return - EINVAL ;
295+ }
296+
422297int ftrace_make_nop (struct module * mod , struct dyn_ftrace * rec , unsigned long addr )
423298{
424299 unsigned long tramp , ip = rec -> ip ;
0 commit comments