diff options
author | Roman Zippel <zippel@linux-m68k.org> | 2007-05-31 03:40:50 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-31 10:58:13 -0400 |
commit | fbe9c9612930e0604dc99ef2da7e063fa3278817 (patch) | |
tree | b11a5a03edd4a61fc5c71b2b38402cdfe914de22 | |
parent | 1fc799e1b4efdbc405d87d9f154d64d9bc299e5c (diff) |
m68k: runtime patching infrastructure
Add the basic infrastructure to allow runtime patching of kernel and modules
to optimize a few functions with parameters, which are only calculated once
during bootup and are otherwise constant. Use this for the conversion between
virtual and physical addresses.
Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | arch/m68k/Makefile | 1 | ||||
-rw-r--r-- | arch/m68k/kernel/Makefile | 3 | ||||
-rw-r--r-- | arch/m68k/kernel/module.c | 28 | ||||
-rw-r--r-- | arch/m68k/kernel/module.lds | 7 | ||||
-rw-r--r-- | arch/m68k/kernel/vmlinux-std.lds | 5 | ||||
-rw-r--r-- | arch/m68k/kernel/vmlinux-sun3.lds | 5 | ||||
-rw-r--r-- | arch/m68k/mm/motorola.c | 3 | ||||
-rw-r--r-- | include/asm-m68k/module.h | 33 | ||||
-rw-r--r-- | include/asm-m68k/page.h | 29 |
9 files changed, 107 insertions, 7 deletions
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile index c20831a7e1a9..aa383a5ea7ac 100644 --- a/arch/m68k/Makefile +++ b/arch/m68k/Makefile | |||
@@ -19,6 +19,7 @@ COMPILE_ARCH = $(shell uname -m) | |||
19 | # override top level makefile | 19 | # override top level makefile |
20 | AS += -m68020 | 20 | AS += -m68020 |
21 | LDFLAGS := -m m68kelf | 21 | LDFLAGS := -m m68kelf |
22 | LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds | ||
22 | ifneq ($(COMPILE_ARCH),$(ARCH)) | 23 | ifneq ($(COMPILE_ARCH),$(ARCH)) |
23 | # prefix for cross-compiling binaries | 24 | # prefix for cross-compiling binaries |
24 | CROSS_COMPILE = m68k-linux-gnu- | 25 | CROSS_COMPILE = m68k-linux-gnu- |
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile index 0b68ab8d63d1..a806208c7fb5 100644 --- a/arch/m68k/kernel/Makefile +++ b/arch/m68k/kernel/Makefile | |||
@@ -9,13 +9,12 @@ else | |||
9 | endif | 9 | endif |
10 | extra-y += vmlinux.lds | 10 | extra-y += vmlinux.lds |
11 | 11 | ||
12 | obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o \ | 12 | obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o module.o \ |
13 | sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o devres.o | 13 | sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o devres.o |
14 | 14 | ||
15 | devres-y = ../../../kernel/irq/devres.o | 15 | devres-y = ../../../kernel/irq/devres.o |
16 | 16 | ||
17 | obj-$(CONFIG_PCI) += bios32.o | 17 | obj-$(CONFIG_PCI) += bios32.o |
18 | obj-$(CONFIG_MODULES) += module.o | ||
19 | obj-y$(CONFIG_MMU_SUN3) += dma.o # no, it's not a typo | 18 | obj-y$(CONFIG_MMU_SUN3) += dma.o # no, it's not a typo |
20 | 19 | ||
21 | EXTRA_AFLAGS := -traditional | 20 | EXTRA_AFLAGS := -traditional |
diff --git a/arch/m68k/kernel/module.c b/arch/m68k/kernel/module.c index 3b1a2ff61ddc..32969d0cecc4 100644 --- a/arch/m68k/kernel/module.c +++ b/arch/m68k/kernel/module.c | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file COPYING in the main directory of this archive | ||
4 | * for more details. | ||
5 | */ | ||
6 | |||
1 | #include <linux/moduleloader.h> | 7 | #include <linux/moduleloader.h> |
2 | #include <linux/elf.h> | 8 | #include <linux/elf.h> |
3 | #include <linux/vmalloc.h> | 9 | #include <linux/vmalloc.h> |
@@ -11,6 +17,8 @@ | |||
11 | #define DEBUGP(fmt...) | 17 | #define DEBUGP(fmt...) |
12 | #endif | 18 | #endif |
13 | 19 | ||
20 | #ifdef CONFIG_MODULES | ||
21 | |||
14 | void *module_alloc(unsigned long size) | 22 | void *module_alloc(unsigned long size) |
15 | { | 23 | { |
16 | if (size == 0) | 24 | if (size == 0) |
@@ -118,11 +126,29 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, | |||
118 | 126 | ||
119 | int module_finalize(const Elf_Ehdr *hdr, | 127 | int module_finalize(const Elf_Ehdr *hdr, |
120 | const Elf_Shdr *sechdrs, | 128 | const Elf_Shdr *sechdrs, |
121 | struct module *me) | 129 | struct module *mod) |
122 | { | 130 | { |
131 | module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end); | ||
132 | |||
123 | return 0; | 133 | return 0; |
124 | } | 134 | } |
125 | 135 | ||
126 | void module_arch_cleanup(struct module *mod) | 136 | void module_arch_cleanup(struct module *mod) |
127 | { | 137 | { |
128 | } | 138 | } |
139 | |||
140 | #endif /* CONFIG_MODULES */ | ||
141 | |||
142 | void module_fixup(struct module *mod, struct m68k_fixup_info *start, | ||
143 | struct m68k_fixup_info *end) | ||
144 | { | ||
145 | struct m68k_fixup_info *fixup; | ||
146 | |||
147 | for (fixup = start; fixup < end; fixup++) { | ||
148 | switch (fixup->type) { | ||
149 | case m68k_fixup_memoffset: | ||
150 | *(u32 *)fixup->addr = m68k_memoffset; | ||
151 | break; | ||
152 | } | ||
153 | } | ||
154 | } | ||
diff --git a/arch/m68k/kernel/module.lds b/arch/m68k/kernel/module.lds new file mode 100644 index 000000000000..fda94fa38243 --- /dev/null +++ b/arch/m68k/kernel/module.lds | |||
@@ -0,0 +1,7 @@ | |||
1 | SECTIONS { | ||
2 | .m68k_fixup : { | ||
3 | __start_fixup = .; | ||
4 | *(.m68k_fixup) | ||
5 | __stop_fixup = .; | ||
6 | } | ||
7 | } | ||
diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds index 78f139226a1b..40f02b128f22 100644 --- a/arch/m68k/kernel/vmlinux-std.lds +++ b/arch/m68k/kernel/vmlinux-std.lds | |||
@@ -60,6 +60,11 @@ SECTIONS | |||
60 | __con_initcall_start = .; | 60 | __con_initcall_start = .; |
61 | .con_initcall.init : { *(.con_initcall.init) } | 61 | .con_initcall.init : { *(.con_initcall.init) } |
62 | __con_initcall_end = .; | 62 | __con_initcall_end = .; |
63 | .m68k_fixup : { | ||
64 | __start_fixup = .; | ||
65 | *(.m68k_fixup) | ||
66 | __stop_fixup = .; | ||
67 | } | ||
63 | SECURITY_INIT | 68 | SECURITY_INIT |
64 | #ifdef CONFIG_BLK_DEV_INITRD | 69 | #ifdef CONFIG_BLK_DEV_INITRD |
65 | . = ALIGN(8192); | 70 | . = ALIGN(8192); |
diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds index c8999b2db23b..f06425b6d206 100644 --- a/arch/m68k/kernel/vmlinux-sun3.lds +++ b/arch/m68k/kernel/vmlinux-sun3.lds | |||
@@ -54,6 +54,11 @@ __init_begin = .; | |||
54 | __con_initcall_start = .; | 54 | __con_initcall_start = .; |
55 | .con_initcall.init : { *(.con_initcall.init) } | 55 | .con_initcall.init : { *(.con_initcall.init) } |
56 | __con_initcall_end = .; | 56 | __con_initcall_end = .; |
57 | .m68k_fixup : { | ||
58 | __start_fixup = .; | ||
59 | *(.m68k_fixup) | ||
60 | __stop_fixup = .; | ||
61 | } | ||
57 | SECURITY_INIT | 62 | SECURITY_INIT |
58 | #ifdef CONFIG_BLK_DEV_INITRD | 63 | #ifdef CONFIG_BLK_DEV_INITRD |
59 | . = ALIGN(8192); | 64 | . = ALIGN(8192); |
diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c index afcccdc6ad45..98ef00547b37 100644 --- a/arch/m68k/mm/motorola.c +++ b/arch/m68k/mm/motorola.c | |||
@@ -222,6 +222,9 @@ void __init paging_init(void) | |||
222 | pgprot_val(protection_map[i]) |= _PAGE_CACHE040; | 222 | pgprot_val(protection_map[i]) |= _PAGE_CACHE040; |
223 | } | 223 | } |
224 | 224 | ||
225 | module_fixup(NULL, __start_fixup, __stop_fixup); | ||
226 | flush_icache(); | ||
227 | |||
225 | /* | 228 | /* |
226 | * Map the physical memory available into the kernel virtual | 229 | * Map the physical memory available into the kernel virtual |
227 | * address space. It may allocate some memory for page | 230 | * address space. It may allocate some memory for page |
diff --git a/include/asm-m68k/module.h b/include/asm-m68k/module.h index c6d75af2d8d3..71a1f76ac891 100644 --- a/include/asm-m68k/module.h +++ b/include/asm-m68k/module.h | |||
@@ -1,7 +1,38 @@ | |||
1 | #ifndef _ASM_M68K_MODULE_H | 1 | #ifndef _ASM_M68K_MODULE_H |
2 | #define _ASM_M68K_MODULE_H | 2 | #define _ASM_M68K_MODULE_H |
3 | struct mod_arch_specific { }; | 3 | |
4 | struct mod_arch_specific { | ||
5 | struct m68k_fixup_info *fixup_start, *fixup_end; | ||
6 | }; | ||
7 | |||
8 | #define MODULE_ARCH_INIT { \ | ||
9 | .fixup_start = __start_fixup, \ | ||
10 | .fixup_end = __stop_fixup, \ | ||
11 | } | ||
12 | |||
4 | #define Elf_Shdr Elf32_Shdr | 13 | #define Elf_Shdr Elf32_Shdr |
5 | #define Elf_Sym Elf32_Sym | 14 | #define Elf_Sym Elf32_Sym |
6 | #define Elf_Ehdr Elf32_Ehdr | 15 | #define Elf_Ehdr Elf32_Ehdr |
16 | |||
17 | |||
18 | enum m68k_fixup_type { | ||
19 | m68k_fixup_memoffset, | ||
20 | }; | ||
21 | |||
22 | struct m68k_fixup_info { | ||
23 | enum m68k_fixup_type type; | ||
24 | void *addr; | ||
25 | }; | ||
26 | |||
27 | #define m68k_fixup(type, addr) \ | ||
28 | " .section \".m68k_fixup\",\"aw\"\n" \ | ||
29 | " .long " #type "," #addr "\n" \ | ||
30 | " .previous\n" | ||
31 | |||
32 | extern struct m68k_fixup_info __start_fixup[], __stop_fixup[]; | ||
33 | |||
34 | struct module; | ||
35 | extern void module_fixup(struct module *mod, struct m68k_fixup_info *start, | ||
36 | struct m68k_fixup_info *end); | ||
37 | |||
7 | #endif /* _ASM_M68K_MODULE_H */ | 38 | #endif /* _ASM_M68K_MODULE_H */ |
diff --git a/include/asm-m68k/page.h b/include/asm-m68k/page.h index fcc165ddd09e..7650b99dcae6 100644 --- a/include/asm-m68k/page.h +++ b/include/asm-m68k/page.h | |||
@@ -27,6 +27,8 @@ | |||
27 | 27 | ||
28 | #ifndef __ASSEMBLY__ | 28 | #ifndef __ASSEMBLY__ |
29 | 29 | ||
30 | #include <asm/module.h> | ||
31 | |||
30 | #define get_user_page(vaddr) __get_free_page(GFP_KERNEL) | 32 | #define get_user_page(vaddr) __get_free_page(GFP_KERNEL) |
31 | #define free_user_page(page, addr) free_page(addr) | 33 | #define free_user_page(page, addr) free_page(addr) |
32 | 34 | ||
@@ -114,14 +116,35 @@ typedef struct { unsigned long pgprot; } pgprot_t; | |||
114 | 116 | ||
115 | #ifndef __ASSEMBLY__ | 117 | #ifndef __ASSEMBLY__ |
116 | 118 | ||
119 | extern unsigned long m68k_memoffset; | ||
120 | |||
117 | #ifndef CONFIG_SUN3 | 121 | #ifndef CONFIG_SUN3 |
118 | 122 | ||
119 | #define WANT_PAGE_VIRTUAL | 123 | #define WANT_PAGE_VIRTUAL |
120 | #ifdef CONFIG_SINGLE_MEMORY_CHUNK | 124 | #ifdef CONFIG_SINGLE_MEMORY_CHUNK |
121 | extern unsigned long m68k_memoffset; | ||
122 | 125 | ||
123 | #define __pa(vaddr) ((unsigned long)(vaddr)+m68k_memoffset) | 126 | static inline unsigned long ___pa(void *vaddr) |
124 | #define __va(paddr) ((void *)((unsigned long)(paddr)-m68k_memoffset)) | 127 | { |
128 | unsigned long paddr; | ||
129 | asm ( | ||
130 | "1: addl #0,%0\n" | ||
131 | m68k_fixup(%c2, 1b+2) | ||
132 | : "=r" (paddr) | ||
133 | : "0" (vaddr), "i" (m68k_fixup_memoffset)); | ||
134 | return paddr; | ||
135 | } | ||
136 | #define __pa(vaddr) ___pa((void *)(vaddr)) | ||
137 | static inline void *__va(unsigned long paddr) | ||
138 | { | ||
139 | void *vaddr; | ||
140 | asm ( | ||
141 | "1: subl #0,%0\n" | ||
142 | m68k_fixup(%c2, 1b+2) | ||
143 | : "=r" (vaddr) | ||
144 | : "0" (paddr), "i" (m68k_fixup_memoffset)); | ||
145 | return vaddr; | ||
146 | } | ||
147 | |||
125 | #else | 148 | #else |
126 | #define __pa(vaddr) virt_to_phys((void *)(vaddr)) | 149 | #define __pa(vaddr) virt_to_phys((void *)(vaddr)) |
127 | #define __va(paddr) phys_to_virt((unsigned long)(paddr)) | 150 | #define __va(paddr) phys_to_virt((unsigned long)(paddr)) |