aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Ellerman <mpe@ellerman.id.au>2016-03-02 23:26:54 -0500
committerMichael Ellerman <mpe@ellerman.id.au>2016-03-06 22:53:53 -0500
commit136cd3450af8092f30d0e289806f08ac2aeee38f (patch)
treecd2a9d14ff7dcf8e80620aff347c1e303b881270
parenta5cab83cd3d2d75d3893276cb5f27e163484ef04 (diff)
powerpc/module: Only try to generate the ftrace_caller() stub once
Currently we generate the module stub for ftrace_caller() at the bottom of apply_relocate_add(). However apply_relocate_add() is potentially called more than once per module, which means we will try to generate the ftrace_caller() stub multiple times. Although the current code deals with that correctly, ie. it only generates a stub the first time, it would be clearer to only try to generate the stub once. Note also on first reading it may appear that we generate a different stub for each section that requires relocation, but that is not the case. The code in stub_for_addr() that searches for an existing stub uses sechdrs[me->arch.stubs_section], ie. the single stub section for this module. A cleaner approach is to only generate the ftrace_caller() stub once, from module_finalize(). Although the original code didn't check to see if the stub was actually generated correctly, it seems prudent to add a check, so do that. And an additional benefit is we can clean the ifdefs up a little. Finally we must propagate the const'ness of some of the pointers passed to module_finalize(), but that is also an improvement. Reviewed-by: Balbir Singh <bsingharora@gmail.com> Reviewed-by: Torsten Duwe <duwe@suse.de> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/include/asm/module.h9
-rw-r--r--arch/powerpc/kernel/module.c5
-rw-r--r--arch/powerpc/kernel/module_32.c20
-rw-r--r--arch/powerpc/kernel/module_64.c22
4 files changed, 42 insertions, 14 deletions
diff --git a/arch/powerpc/include/asm/module.h b/arch/powerpc/include/asm/module.h
index dcfcad139bcc..74d25a749018 100644
--- a/arch/powerpc/include/asm/module.h
+++ b/arch/powerpc/include/asm/module.h
@@ -82,6 +82,15 @@ bool is_module_trampoline(u32 *insns);
82int module_trampoline_target(struct module *mod, u32 *trampoline, 82int module_trampoline_target(struct module *mod, u32 *trampoline,
83 unsigned long *target); 83 unsigned long *target);
84 84
85#ifdef CONFIG_DYNAMIC_FTRACE
86int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sechdrs);
87#else
88static inline int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sechdrs)
89{
90 return 0;
91}
92#endif
93
85struct exception_table_entry; 94struct exception_table_entry;
86void sort_ex_table(struct exception_table_entry *start, 95void sort_ex_table(struct exception_table_entry *start,
87 struct exception_table_entry *finish); 96 struct exception_table_entry *finish);
diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c
index 9547381b631a..d1f1b35bf0c7 100644
--- a/arch/powerpc/kernel/module.c
+++ b/arch/powerpc/kernel/module.c
@@ -47,6 +47,11 @@ int module_finalize(const Elf_Ehdr *hdr,
47 const Elf_Shdr *sechdrs, struct module *me) 47 const Elf_Shdr *sechdrs, struct module *me)
48{ 48{
49 const Elf_Shdr *sect; 49 const Elf_Shdr *sect;
50 int rc;
51
52 rc = module_finalize_ftrace(me, sechdrs);
53 if (rc)
54 return rc;
50 55
51 /* Apply feature fixups */ 56 /* Apply feature fixups */
52 sect = find_section(hdr, sechdrs, "__ftr_fixup"); 57 sect = find_section(hdr, sechdrs, "__ftr_fixup");
diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c
index 2c01665eb410..5a7a78f12562 100644
--- a/arch/powerpc/kernel/module_32.c
+++ b/arch/powerpc/kernel/module_32.c
@@ -181,7 +181,7 @@ static inline int entry_matches(struct ppc_plt_entry *entry, Elf32_Addr val)
181/* Set up a trampoline in the PLT to bounce us to the distant function */ 181/* Set up a trampoline in the PLT to bounce us to the distant function */
182static uint32_t do_plt_call(void *location, 182static uint32_t do_plt_call(void *location,
183 Elf32_Addr val, 183 Elf32_Addr val,
184 Elf32_Shdr *sechdrs, 184 const Elf32_Shdr *sechdrs,
185 struct module *mod) 185 struct module *mod)
186{ 186{
187 struct ppc_plt_entry *entry; 187 struct ppc_plt_entry *entry;
@@ -294,11 +294,19 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
294 return -ENOEXEC; 294 return -ENOEXEC;
295 } 295 }
296 } 296 }
297
298 return 0;
299}
300
297#ifdef CONFIG_DYNAMIC_FTRACE 301#ifdef CONFIG_DYNAMIC_FTRACE
298 module->arch.tramp = 302int module_finalize_ftrace(struct module *module, const Elf_Shdr *sechdrs)
299 do_plt_call(module->core_layout.base, 303{
300 (unsigned long)ftrace_caller, 304 module->arch.tramp = do_plt_call(module->core_layout.base,
301 sechdrs, module); 305 (unsigned long)ftrace_caller,
302#endif 306 sechdrs, module);
307 if (!module->arch.tramp)
308 return -ENOENT;
309
303 return 0; 310 return 0;
304} 311}
312#endif
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index ac64ffdb52c8..599c753c7960 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -413,7 +413,7 @@ int module_frob_arch_sections(Elf64_Ehdr *hdr,
413/* r2 is the TOC pointer: it actually points 0x8000 into the TOC (this 413/* r2 is the TOC pointer: it actually points 0x8000 into the TOC (this
414 gives the value maximum span in an instruction which uses a signed 414 gives the value maximum span in an instruction which uses a signed
415 offset) */ 415 offset) */
416static inline unsigned long my_r2(Elf64_Shdr *sechdrs, struct module *me) 416static inline unsigned long my_r2(const Elf64_Shdr *sechdrs, struct module *me)
417{ 417{
418 return sechdrs[me->arch.toc_section].sh_addr + 0x8000; 418 return sechdrs[me->arch.toc_section].sh_addr + 0x8000;
419} 419}
@@ -426,7 +426,7 @@ static inline unsigned long my_r2(Elf64_Shdr *sechdrs, struct module *me)
426#define PPC_HA(v) PPC_HI ((v) + 0x8000) 426#define PPC_HA(v) PPC_HI ((v) + 0x8000)
427 427
428/* Patch stub to reference function and correct r2 value. */ 428/* Patch stub to reference function and correct r2 value. */
429static inline int create_stub(Elf64_Shdr *sechdrs, 429static inline int create_stub(const Elf64_Shdr *sechdrs,
430 struct ppc64_stub_entry *entry, 430 struct ppc64_stub_entry *entry,
431 unsigned long addr, 431 unsigned long addr,
432 struct module *me) 432 struct module *me)
@@ -452,7 +452,7 @@ static inline int create_stub(Elf64_Shdr *sechdrs,
452 452
453/* Create stub to jump to function described in this OPD/ptr: we need the 453/* Create stub to jump to function described in this OPD/ptr: we need the
454 stub to set up the TOC ptr (r2) for the function. */ 454 stub to set up the TOC ptr (r2) for the function. */
455static unsigned long stub_for_addr(Elf64_Shdr *sechdrs, 455static unsigned long stub_for_addr(const Elf64_Shdr *sechdrs,
456 unsigned long addr, 456 unsigned long addr,
457 struct module *me) 457 struct module *me)
458{ 458{
@@ -693,12 +693,18 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
693 } 693 }
694 } 694 }
695 695
696 return 0;
697}
698
696#ifdef CONFIG_DYNAMIC_FTRACE 699#ifdef CONFIG_DYNAMIC_FTRACE
697 me->arch.toc = my_r2(sechdrs, me); 700int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sechdrs)
698 me->arch.tramp = stub_for_addr(sechdrs, 701{
699 (unsigned long)ftrace_caller, 702 mod->arch.toc = my_r2(sechdrs, mod);
700 me); 703 mod->arch.tramp = stub_for_addr(sechdrs, (unsigned long)ftrace_caller, mod);
701#endif 704
705 if (!mod->arch.tramp)
706 return -ENOENT;
702 707
703 return 0; 708 return 0;
704} 709}
710#endif