diff options
author | Roman Zippel <zippel@linux-m68k.org> | 2007-05-31 00:40:50 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-31 07:58:13 -0700 |
commit | fbe9c9612930e0604dc99ef2da7e063fa3278817 (patch) | |
tree | b11a5a03edd4a61fc5c71b2b38402cdfe914de22 /arch/m68k | |
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>
Diffstat (limited to 'arch/m68k')
-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 |
7 files changed, 49 insertions, 3 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) # override top level makefile AS += -m68020 LDFLAGS := -m m68kelf +LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds ifneq ($(COMPILE_ARCH),$(ARCH)) # prefix for cross-compiling binaries 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 endif extra-y += vmlinux.lds -obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o \ +obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o module.o \ sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o devres.o devres-y = ../../../kernel/irq/devres.o obj-$(CONFIG_PCI) += bios32.o -obj-$(CONFIG_MODULES) += module.o obj-y$(CONFIG_MMU_SUN3) += dma.o # no, it's not a typo 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 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + #include <linux/moduleloader.h> #include <linux/elf.h> #include <linux/vmalloc.h> @@ -11,6 +17,8 @@ #define DEBUGP(fmt...) #endif +#ifdef CONFIG_MODULES + void *module_alloc(unsigned long size) { if (size == 0) @@ -118,11 +126,29 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, - struct module *me) + struct module *mod) { + module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end); + return 0; } void module_arch_cleanup(struct module *mod) { } + +#endif /* CONFIG_MODULES */ + +void module_fixup(struct module *mod, struct m68k_fixup_info *start, + struct m68k_fixup_info *end) +{ + struct m68k_fixup_info *fixup; + + for (fixup = start; fixup < end; fixup++) { + switch (fixup->type) { + case m68k_fixup_memoffset: + *(u32 *)fixup->addr = m68k_memoffset; + break; + } + } +} 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 @@ +SECTIONS { + .m68k_fixup : { + __start_fixup = .; + *(.m68k_fixup) + __stop_fixup = .; + } +} 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 __con_initcall_start = .; .con_initcall.init : { *(.con_initcall.init) } __con_initcall_end = .; + .m68k_fixup : { + __start_fixup = .; + *(.m68k_fixup) + __stop_fixup = .; + } SECURITY_INIT #ifdef CONFIG_BLK_DEV_INITRD . = 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 = .; __con_initcall_start = .; .con_initcall.init : { *(.con_initcall.init) } __con_initcall_end = .; + .m68k_fixup : { + __start_fixup = .; + *(.m68k_fixup) + __stop_fixup = .; + } SECURITY_INIT #ifdef CONFIG_BLK_DEV_INITRD . = 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) pgprot_val(protection_map[i]) |= _PAGE_CACHE040; } + module_fixup(NULL, __start_fixup, __stop_fixup); + flush_icache(); + /* * Map the physical memory available into the kernel virtual * address space. It may allocate some memory for page |