diff options
author | Kumar Gala <galak@kernel.crashing.org> | 2008-06-20 12:31:01 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2008-06-30 21:28:05 -0400 |
commit | f0c426bc3557a93e9d2f2863fda1e2042f942a60 (patch) | |
tree | ad52a0ac08a47b46c3b2b7ccdab364042a73b67b | |
parent | 87e9ab13c36b838f7d557a6111dfdd29fcde85ad (diff) |
powerpc: Move common module code into its own file
Refactor common code between ppc32 and ppc64 module handling into a
shared filed.
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r-- | arch/powerpc/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/module.c | 110 | ||||
-rw-r--r-- | arch/powerpc/kernel/module_32.c | 72 | ||||
-rw-r--r-- | arch/powerpc/kernel/module_64.c | 78 |
4 files changed, 111 insertions, 151 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 0e8f928fef70..9ebeb2406b5b 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -44,7 +44,7 @@ obj-$(CONFIG_TAU) += tau_6xx.o | |||
44 | obj-$(CONFIG_HIBERNATION) += swsusp.o suspend.o \ | 44 | obj-$(CONFIG_HIBERNATION) += swsusp.o suspend.o \ |
45 | swsusp_$(CONFIG_WORD_SIZE).o | 45 | swsusp_$(CONFIG_WORD_SIZE).o |
46 | obj64-$(CONFIG_HIBERNATION) += swsusp_asm64.o | 46 | obj64-$(CONFIG_HIBERNATION) += swsusp_asm64.o |
47 | obj-$(CONFIG_MODULES) += module_$(CONFIG_WORD_SIZE).o | 47 | obj-$(CONFIG_MODULES) += module.o module_$(CONFIG_WORD_SIZE).o |
48 | obj-$(CONFIG_44x) += cpu_setup_44x.o | 48 | obj-$(CONFIG_44x) += cpu_setup_44x.o |
49 | 49 | ||
50 | ifeq ($(CONFIG_PPC_MERGE),y) | 50 | ifeq ($(CONFIG_PPC_MERGE),y) |
diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c new file mode 100644 index 000000000000..40dd52d81c18 --- /dev/null +++ b/arch/powerpc/kernel/module.c | |||
@@ -0,0 +1,110 @@ | |||
1 | /* Kernel module help for powerpc. | ||
2 | Copyright (C) 2001, 2003 Rusty Russell IBM Corporation. | ||
3 | Copyright (C) 2008 Freescale Semiconductor, Inc. | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/elf.h> | ||
21 | #include <linux/moduleloader.h> | ||
22 | #include <linux/err.h> | ||
23 | #include <linux/vmalloc.h> | ||
24 | #include <linux/bug.h> | ||
25 | #include <asm/module.h> | ||
26 | #include <asm/uaccess.h> | ||
27 | #include <asm/firmware.h> | ||
28 | #include <linux/sort.h> | ||
29 | |||
30 | #include "setup.h" | ||
31 | |||
32 | LIST_HEAD(module_bug_list); | ||
33 | |||
34 | void *module_alloc(unsigned long size) | ||
35 | { | ||
36 | if (size == 0) | ||
37 | return NULL; | ||
38 | |||
39 | return vmalloc_exec(size); | ||
40 | } | ||
41 | |||
42 | /* Free memory returned from module_alloc */ | ||
43 | void module_free(struct module *mod, void *module_region) | ||
44 | { | ||
45 | vfree(module_region); | ||
46 | /* FIXME: If module_region == mod->init_region, trim exception | ||
47 | table entries. */ | ||
48 | } | ||
49 | |||
50 | static const Elf_Shdr *find_section(const Elf_Ehdr *hdr, | ||
51 | const Elf_Shdr *sechdrs, | ||
52 | const char *name) | ||
53 | { | ||
54 | char *secstrings; | ||
55 | unsigned int i; | ||
56 | |||
57 | secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; | ||
58 | for (i = 1; i < hdr->e_shnum; i++) | ||
59 | if (strcmp(secstrings+sechdrs[i].sh_name, name) == 0) | ||
60 | return &sechdrs[i]; | ||
61 | return NULL; | ||
62 | } | ||
63 | |||
64 | int module_finalize(const Elf_Ehdr *hdr, | ||
65 | const Elf_Shdr *sechdrs, struct module *me) | ||
66 | { | ||
67 | const Elf_Shdr *sect; | ||
68 | int err; | ||
69 | |||
70 | err = module_bug_finalize(hdr, sechdrs, me); | ||
71 | if (err) | ||
72 | return err; | ||
73 | |||
74 | /* Apply feature fixups */ | ||
75 | sect = find_section(hdr, sechdrs, "__ftr_fixup"); | ||
76 | if (sect != NULL) | ||
77 | do_feature_fixups(cur_cpu_spec->cpu_features, | ||
78 | (void *)sect->sh_addr, | ||
79 | (void *)sect->sh_addr + sect->sh_size); | ||
80 | |||
81 | #ifdef CONFIG_PPC64 | ||
82 | sect = find_section(hdr, sechdrs, "__fw_ftr_fixup"); | ||
83 | if (sect != NULL) | ||
84 | do_feature_fixups(powerpc_firmware_features, | ||
85 | (void *)sect->sh_addr, | ||
86 | (void *)sect->sh_addr + sect->sh_size); | ||
87 | #endif | ||
88 | |||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | void module_arch_cleanup(struct module *mod) | ||
93 | { | ||
94 | module_bug_cleanup(mod); | ||
95 | } | ||
96 | |||
97 | struct bug_entry *module_find_bug(unsigned long bugaddr) | ||
98 | { | ||
99 | struct mod_arch_specific *mod; | ||
100 | unsigned int i; | ||
101 | struct bug_entry *bug; | ||
102 | |||
103 | list_for_each_entry(mod, &module_bug_list, bug_list) { | ||
104 | bug = mod->bug_table; | ||
105 | for (i = 0; i < mod->num_bugs; ++i, ++bug) | ||
106 | if (bugaddr == bug->bug_addr) | ||
107 | return bug; | ||
108 | } | ||
109 | return NULL; | ||
110 | } | ||
diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c index eab313858315..2df91a03462a 100644 --- a/arch/powerpc/kernel/module_32.c +++ b/arch/powerpc/kernel/module_32.c | |||
@@ -34,23 +34,6 @@ | |||
34 | #define DEBUGP(fmt , ...) | 34 | #define DEBUGP(fmt , ...) |
35 | #endif | 35 | #endif |
36 | 36 | ||
37 | LIST_HEAD(module_bug_list); | ||
38 | |||
39 | void *module_alloc(unsigned long size) | ||
40 | { | ||
41 | if (size == 0) | ||
42 | return NULL; | ||
43 | return vmalloc(size); | ||
44 | } | ||
45 | |||
46 | /* Free memory returned from module_alloc */ | ||
47 | void module_free(struct module *mod, void *module_region) | ||
48 | { | ||
49 | vfree(module_region); | ||
50 | /* FIXME: If module_region == mod->init_region, trim exception | ||
51 | table entries. */ | ||
52 | } | ||
53 | |||
54 | /* Count how many different relocations (different symbol, different | 37 | /* Count how many different relocations (different symbol, different |
55 | addend) */ | 38 | addend) */ |
56 | static unsigned int count_relocs(const Elf32_Rela *rela, unsigned int num) | 39 | static unsigned int count_relocs(const Elf32_Rela *rela, unsigned int num) |
@@ -325,58 +308,3 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, | |||
325 | } | 308 | } |
326 | return 0; | 309 | return 0; |
327 | } | 310 | } |
328 | |||
329 | static const Elf_Shdr *find_section(const Elf_Ehdr *hdr, | ||
330 | const Elf_Shdr *sechdrs, | ||
331 | const char *name) | ||
332 | { | ||
333 | char *secstrings; | ||
334 | unsigned int i; | ||
335 | |||
336 | secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; | ||
337 | for (i = 1; i < hdr->e_shnum; i++) | ||
338 | if (strcmp(secstrings+sechdrs[i].sh_name, name) == 0) | ||
339 | return &sechdrs[i]; | ||
340 | return NULL; | ||
341 | } | ||
342 | |||
343 | int module_finalize(const Elf_Ehdr *hdr, | ||
344 | const Elf_Shdr *sechdrs, | ||
345 | struct module *me) | ||
346 | { | ||
347 | const Elf_Shdr *sect; | ||
348 | int err; | ||
349 | |||
350 | err = module_bug_finalize(hdr, sechdrs, me); | ||
351 | if (err) /* never true, currently */ | ||
352 | return err; | ||
353 | |||
354 | /* Apply feature fixups */ | ||
355 | sect = find_section(hdr, sechdrs, "__ftr_fixup"); | ||
356 | if (sect != NULL) | ||
357 | do_feature_fixups(cur_cpu_spec->cpu_features, | ||
358 | (void *)sect->sh_addr, | ||
359 | (void *)sect->sh_addr + sect->sh_size); | ||
360 | |||
361 | return 0; | ||
362 | } | ||
363 | |||
364 | void module_arch_cleanup(struct module *mod) | ||
365 | { | ||
366 | module_bug_cleanup(mod); | ||
367 | } | ||
368 | |||
369 | struct bug_entry *module_find_bug(unsigned long bugaddr) | ||
370 | { | ||
371 | struct mod_arch_specific *mod; | ||
372 | unsigned int i; | ||
373 | struct bug_entry *bug; | ||
374 | |||
375 | list_for_each_entry(mod, &module_bug_list, bug_list) { | ||
376 | bug = mod->bug_table; | ||
377 | for (i = 0; i < mod->num_bugs; ++i, ++bug) | ||
378 | if (bugaddr == bug->bug_addr) | ||
379 | return bug; | ||
380 | } | ||
381 | return NULL; | ||
382 | } | ||
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index 3a82b02b784b..4803f2de98dd 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c | |||
@@ -101,22 +101,6 @@ static unsigned int count_relocs(const Elf64_Rela *rela, unsigned int num) | |||
101 | return _count_relocs; | 101 | return _count_relocs; |
102 | } | 102 | } |
103 | 103 | ||
104 | void *module_alloc(unsigned long size) | ||
105 | { | ||
106 | if (size == 0) | ||
107 | return NULL; | ||
108 | |||
109 | return vmalloc_exec(size); | ||
110 | } | ||
111 | |||
112 | /* Free memory returned from module_alloc */ | ||
113 | void module_free(struct module *mod, void *module_region) | ||
114 | { | ||
115 | vfree(module_region); | ||
116 | /* FIXME: If module_region == mod->init_region, trim exception | ||
117 | table entries. */ | ||
118 | } | ||
119 | |||
120 | static int relacmp(const void *_x, const void *_y) | 104 | static int relacmp(const void *_x, const void *_y) |
121 | { | 105 | { |
122 | const Elf64_Rela *x, *y; | 106 | const Elf64_Rela *x, *y; |
@@ -466,65 +450,3 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, | |||
466 | 450 | ||
467 | return 0; | 451 | return 0; |
468 | } | 452 | } |
469 | |||
470 | LIST_HEAD(module_bug_list); | ||
471 | |||
472 | static const Elf_Shdr *find_section(const Elf_Ehdr *hdr, | ||
473 | const Elf_Shdr *sechdrs, | ||
474 | const char *name) | ||
475 | { | ||
476 | char *secstrings; | ||
477 | unsigned int i; | ||
478 | |||
479 | secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; | ||
480 | for (i = 1; i < hdr->e_shnum; i++) | ||
481 | if (strcmp(secstrings+sechdrs[i].sh_name, name) == 0) | ||
482 | return &sechdrs[i]; | ||
483 | return NULL; | ||
484 | } | ||
485 | |||
486 | int module_finalize(const Elf_Ehdr *hdr, | ||
487 | const Elf_Shdr *sechdrs, struct module *me) | ||
488 | { | ||
489 | const Elf_Shdr *sect; | ||
490 | int err; | ||
491 | |||
492 | err = module_bug_finalize(hdr, sechdrs, me); | ||
493 | if (err) | ||
494 | return err; | ||
495 | |||
496 | /* Apply feature fixups */ | ||
497 | sect = find_section(hdr, sechdrs, "__ftr_fixup"); | ||
498 | if (sect != NULL) | ||
499 | do_feature_fixups(cur_cpu_spec->cpu_features, | ||
500 | (void *)sect->sh_addr, | ||
501 | (void *)sect->sh_addr + sect->sh_size); | ||
502 | |||
503 | sect = find_section(hdr, sechdrs, "__fw_ftr_fixup"); | ||
504 | if (sect != NULL) | ||
505 | do_feature_fixups(powerpc_firmware_features, | ||
506 | (void *)sect->sh_addr, | ||
507 | (void *)sect->sh_addr + sect->sh_size); | ||
508 | |||
509 | return 0; | ||
510 | } | ||
511 | |||
512 | void module_arch_cleanup(struct module *mod) | ||
513 | { | ||
514 | module_bug_cleanup(mod); | ||
515 | } | ||
516 | |||
517 | struct bug_entry *module_find_bug(unsigned long bugaddr) | ||
518 | { | ||
519 | struct mod_arch_specific *mod; | ||
520 | unsigned int i; | ||
521 | struct bug_entry *bug; | ||
522 | |||
523 | list_for_each_entry(mod, &module_bug_list, bug_list) { | ||
524 | bug = mod->bug_table; | ||
525 | for (i = 0; i < mod->num_bugs; ++i, ++bug) | ||
526 | if (bugaddr == bug->bug_addr) | ||
527 | return bug; | ||
528 | } | ||
529 | return NULL; | ||
530 | } | ||