@@ -89,33 +89,11 @@ static inline int ftrace_modify_code(unsigned long ip, ppc_inst_t old, ppc_inst_
8989 return ret ;
9090}
9191
92- /*
93- * Helper functions that are the same for both PPC64 and PPC32.
94- */
95- static int test_24bit_addr (unsigned long ip , unsigned long addr )
96- {
97- addr = ppc_function_entry ((void * )addr );
98-
99- return is_offset_in_branch_range (addr - ip );
100- }
101-
10292static int is_bl_op (ppc_inst_t op )
10393{
10494 return (ppc_inst_val (op ) & ~PPC_LI_MASK ) == PPC_RAW_BL (0 );
10595}
10696
107- static unsigned long find_bl_target (unsigned long ip , ppc_inst_t op )
108- {
109- int offset ;
110-
111- offset = PPC_LI (ppc_inst_val (op ));
112- /* make it signed */
113- if (offset & 0x02000000 )
114- offset |= 0xfe000000 ;
115-
116- return ip + (long )offset ;
117- }
118-
11997static unsigned long find_ftrace_tramp (unsigned long ip )
12098{
12199 int i ;
@@ -130,136 +108,39 @@ static unsigned long find_ftrace_tramp(unsigned long ip)
130108}
131109
132110#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
133- #ifdef CONFIG_MODULES
134- static int
135- __ftrace_modify_call (struct dyn_ftrace * rec , unsigned long old_addr ,
136- unsigned long addr )
111+ int ftrace_modify_call (struct dyn_ftrace * rec , unsigned long old_addr , unsigned long addr )
137112{
138- ppc_inst_t op ;
139- unsigned long ip = rec -> ip ;
140- unsigned long entry , ptr , tramp ;
141- struct module * mod = rec -> arch .mod ;
142-
143- /* If we never set up ftrace trampolines, then bail */
144- if (!mod -> arch .tramp || !mod -> arch .tramp_regs ) {
145- pr_err ("No ftrace trampoline\n" );
146- return - EINVAL ;
147- }
148-
149- /* read where this goes */
150- if (copy_inst_from_kernel_nofault (& op , (void * )ip )) {
151- pr_err ("Fetching opcode failed.\n" );
152- return - EFAULT ;
153- }
154-
155- /* Make sure that this is still a 24bit jump */
156- if (!is_bl_op (op )) {
157- pr_err ("Not expected bl: opcode is %08lx\n" , ppc_inst_as_ulong (op ));
158- return - EINVAL ;
159- }
160-
161- /* lets find where the pointer goes */
162- tramp = find_bl_target (ip , op );
163- entry = ppc_global_function_entry ((void * )old_addr );
164-
165- pr_devel ("ip:%lx jumps to %lx" , ip , tramp );
166-
167- if (tramp != entry ) {
168- /* old_addr is not within range, so we must have used a trampoline */
169- if (module_trampoline_target (mod , tramp , & ptr )) {
170- pr_err ("Failed to get trampoline target\n" );
171- return - EFAULT ;
172- }
173-
174- pr_devel ("trampoline target %lx" , ptr );
175-
176- /* This should match what was called */
177- if (ptr != entry ) {
178- pr_err ("addr %lx does not match expected %lx\n" , ptr , entry );
179- return - EINVAL ;
180- }
181- }
182-
183- /* The new target may be within range */
184- if (test_24bit_addr (ip , addr )) {
185- /* within range */
186- if (patch_branch ((u32 * )ip , addr , BRANCH_SET_LINK )) {
187- pr_err ("REL24 out of range!\n" );
188- return - EINVAL ;
189- }
190-
191- return 0 ;
192- }
193-
194- if (rec -> flags & FTRACE_FL_REGS )
195- tramp = mod -> arch .tramp_regs ;
196- else
197- tramp = mod -> arch .tramp ;
198-
199- if (module_trampoline_target (mod , tramp , & ptr )) {
200- pr_err ("Failed to get trampoline target\n" );
201- return - EFAULT ;
202- }
203-
204- pr_devel ("trampoline target %lx" , ptr );
205-
206- entry = ppc_global_function_entry ((void * )addr );
207- /* This should match what was called */
208- if (ptr != entry ) {
209- pr_err ("addr %lx does not match expected %lx\n" , ptr , entry );
210- return - EINVAL ;
211- }
212-
213- if (patch_branch ((u32 * )ip , tramp , BRANCH_SET_LINK )) {
214- pr_err ("REL24 out of range!\n" );
215- return - EINVAL ;
216- }
217-
218- return 0 ;
219- }
220- #else
221- static int __ftrace_modify_call (struct dyn_ftrace * rec , unsigned long old_addr , unsigned long addr )
222- {
223- return 0 ;
224- }
225- #endif
226-
227- int ftrace_modify_call (struct dyn_ftrace * rec , unsigned long old_addr ,
228- unsigned long addr )
229- {
230- unsigned long ip = rec -> ip ;
113+ unsigned long tramp , tramp_old , ip = rec -> ip ;
231114 ppc_inst_t old , new ;
115+ struct module * mod ;
232116
233- /*
234- * If the calling address is more that 24 bits away,
235- * then we had to use a trampoline to make the call.
236- * Otherwise just update the call site.
237- */
238- if (test_24bit_addr (ip , addr ) && test_24bit_addr (ip , old_addr )) {
239- /* within range */
240- old = ftrace_call_replace (ip , old_addr , 1 );
241- new = ftrace_call_replace (ip , addr , 1 );
117+ if (is_offset_in_branch_range (old_addr - ip ) && is_offset_in_branch_range (addr - ip )) {
118+ /* Within range */
119+ old = ftrace_create_branch_inst (ip , old_addr , 1 );
120+ new = ftrace_create_branch_inst (ip , addr , 1 );
242121 return ftrace_modify_code (ip , old , new );
243122 } else if (core_kernel_text (ip )) {
244123 /*
245124 * We always patch out of range locations to go to the regs
246125 * variant, so there is nothing to do here
247126 */
248127 return 0 ;
249- } else if (!IS_ENABLED (CONFIG_MODULES )) {
250- /* We should not get here without modules */
251- return - EINVAL ;
252- }
253-
254- /*
255- * Out of range jumps are called from modules.
256- */
257- if (!rec -> arch .mod ) {
258- pr_err ("No module loaded\n" );
259- return - EINVAL ;
128+ } else if (IS_ENABLED (CONFIG_MODULES )) {
129+ /* Module code would be going to one of the module stubs */
130+ mod = rec -> arch .mod ;
131+ if (addr == (unsigned long )ftrace_caller ) {
132+ tramp_old = mod -> arch .tramp_regs ;
133+ tramp = mod -> arch .tramp ;
134+ } else {
135+ tramp_old = mod -> arch .tramp ;
136+ tramp = mod -> arch .tramp_regs ;
137+ }
138+ old = ftrace_create_branch_inst (ip , tramp_old , 1 );
139+ new = ftrace_create_branch_inst (ip , tramp , 1 );
140+ return ftrace_modify_code (ip , old , new );
260141 }
261142
262- return __ftrace_modify_call ( rec , old_addr , addr ) ;
143+ return - EINVAL ;
263144}
264145#endif
265146
0 commit comments