diff options
author | Michael Ellerman <mpe@ellerman.id.au> | 2016-03-02 23:26:54 -0500 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2016-03-06 22:53:53 -0500 |
commit | 136cd3450af8092f30d0e289806f08ac2aeee38f (patch) | |
tree | cd2a9d14ff7dcf8e80620aff347c1e303b881270 | |
parent | a5cab83cd3d2d75d3893276cb5f27e163484ef04 (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.h | 9 | ||||
-rw-r--r-- | arch/powerpc/kernel/module.c | 5 | ||||
-rw-r--r-- | arch/powerpc/kernel/module_32.c | 20 | ||||
-rw-r--r-- | arch/powerpc/kernel/module_64.c | 22 |
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); | |||
82 | int module_trampoline_target(struct module *mod, u32 *trampoline, | 82 | int module_trampoline_target(struct module *mod, u32 *trampoline, |
83 | unsigned long *target); | 83 | unsigned long *target); |
84 | 84 | ||
85 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
86 | int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sechdrs); | ||
87 | #else | ||
88 | static inline int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sechdrs) | ||
89 | { | ||
90 | return 0; | ||
91 | } | ||
92 | #endif | ||
93 | |||
85 | struct exception_table_entry; | 94 | struct exception_table_entry; |
86 | void sort_ex_table(struct exception_table_entry *start, | 95 | void 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 */ |
182 | static uint32_t do_plt_call(void *location, | 182 | static 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 = | 302 | int 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) */ |
416 | static inline unsigned long my_r2(Elf64_Shdr *sechdrs, struct module *me) | 416 | static 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. */ |
429 | static inline int create_stub(Elf64_Shdr *sechdrs, | 429 | static 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. */ |
455 | static unsigned long stub_for_addr(Elf64_Shdr *sechdrs, | 455 | static 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); | 700 | int 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 | ||