@@ -205,7 +205,9 @@ static int relacmp(const void *_x, const void *_y)
205
205
206
206
/* Get size of potential trampolines required. */
207
207
static unsigned long get_stubs_size (const Elf64_Ehdr * hdr ,
208
- const Elf64_Shdr * sechdrs )
208
+ const Elf64_Shdr * sechdrs ,
209
+ char * secstrings ,
210
+ struct module * me )
209
211
{
210
212
/* One extra reloc so it's always 0-addr terminated */
211
213
unsigned long relocs = 1 ;
@@ -241,13 +243,25 @@ static unsigned long get_stubs_size(const Elf64_Ehdr *hdr,
241
243
}
242
244
}
243
245
244
- #ifdef CONFIG_DYNAMIC_FTRACE
245
- /* make the trampoline to the ftrace_caller */
246
- relocs ++ ;
247
- #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
248
- /* an additional one for ftrace_regs_caller */
249
- relocs ++ ;
250
- #endif
246
+ /* stubs for ftrace_caller and ftrace_regs_caller */
247
+ relocs += IS_ENABLED (CONFIG_DYNAMIC_FTRACE ) + IS_ENABLED (CONFIG_DYNAMIC_FTRACE_WITH_REGS );
248
+
249
+ #ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
250
+ /* stubs for the function tracer */
251
+ for (i = 1 ; i < hdr -> e_shnum ; i ++ ) {
252
+ if (!strcmp (secstrings + sechdrs [i ].sh_name , "__patchable_function_entries" )) {
253
+ me -> arch .ool_stub_count = sechdrs [i ].sh_size / sizeof (unsigned long );
254
+ me -> arch .ool_stub_index = 0 ;
255
+ relocs += roundup (me -> arch .ool_stub_count * sizeof (struct ftrace_ool_stub ),
256
+ sizeof (struct ppc64_stub_entry )) /
257
+ sizeof (struct ppc64_stub_entry );
258
+ break ;
259
+ }
260
+ }
261
+ if (i == hdr -> e_shnum ) {
262
+ pr_err ("%s: doesn't contain __patchable_function_entries.\n" , me -> name );
263
+ return - ENOEXEC ;
264
+ }
251
265
#endif
252
266
253
267
pr_debug ("Looks like a total of %lu stubs, max\n" , relocs );
@@ -460,7 +474,7 @@ int module_frob_arch_sections(Elf64_Ehdr *hdr,
460
474
#endif
461
475
462
476
/* Override the stubs size */
463
- sechdrs [me -> arch .stubs_section ].sh_size = get_stubs_size (hdr , sechdrs );
477
+ sechdrs [me -> arch .stubs_section ].sh_size = get_stubs_size (hdr , sechdrs , secstrings , me );
464
478
465
479
return 0 ;
466
480
}
@@ -1085,6 +1099,37 @@ int module_trampoline_target(struct module *mod, unsigned long addr,
1085
1099
return 0 ;
1086
1100
}
1087
1101
1102
+ static int setup_ftrace_ool_stubs (const Elf64_Shdr * sechdrs , unsigned long addr , struct module * me )
1103
+ {
1104
+ #ifdef CONFIG_PPC_FTRACE_OUT_OF_LINE
1105
+ unsigned int i , total_stubs , num_stubs ;
1106
+ struct ppc64_stub_entry * stub ;
1107
+
1108
+ total_stubs = sechdrs [me -> arch .stubs_section ].sh_size / sizeof (* stub );
1109
+ num_stubs = roundup (me -> arch .ool_stub_count * sizeof (struct ftrace_ool_stub ),
1110
+ sizeof (struct ppc64_stub_entry )) / sizeof (struct ppc64_stub_entry );
1111
+
1112
+ /* Find the next available entry */
1113
+ stub = (void * )sechdrs [me -> arch .stubs_section ].sh_addr ;
1114
+ for (i = 0 ; stub_func_addr (stub [i ].funcdata ); i ++ )
1115
+ if (WARN_ON (i >= total_stubs ))
1116
+ return -1 ;
1117
+
1118
+ if (WARN_ON (i + num_stubs > total_stubs ))
1119
+ return -1 ;
1120
+
1121
+ stub += i ;
1122
+ me -> arch .ool_stubs = (struct ftrace_ool_stub * )stub ;
1123
+
1124
+ /* reserve stubs */
1125
+ for (i = 0 ; i < num_stubs ; i ++ )
1126
+ if (patch_u32 ((void * )& stub -> funcdata , PPC_RAW_NOP ()))
1127
+ return -1 ;
1128
+ #endif
1129
+
1130
+ return 0 ;
1131
+ }
1132
+
1088
1133
int module_finalize_ftrace (struct module * mod , const Elf_Shdr * sechdrs )
1089
1134
{
1090
1135
mod -> arch .tramp = stub_for_addr (sechdrs ,
@@ -1103,6 +1148,9 @@ int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sechdrs)
1103
1148
if (!mod -> arch .tramp )
1104
1149
return - ENOENT ;
1105
1150
1151
+ if (setup_ftrace_ool_stubs (sechdrs , mod -> arch .tramp , mod ))
1152
+ return - ENOENT ;
1153
+
1106
1154
return 0 ;
1107
1155
}
1108
1156
#endif
0 commit comments