aboutsummaryrefslogtreecommitdiffstats
path: root/debian/patches/bugfix/m68k/611-module_fixup.diff
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/bugfix/m68k/611-module_fixup.diff')
-rw-r--r--debian/patches/bugfix/m68k/611-module_fixup.diff214
1 files changed, 214 insertions, 0 deletions
diff --git a/debian/patches/bugfix/m68k/611-module_fixup.diff b/debian/patches/bugfix/m68k/611-module_fixup.diff
new file mode 100644
index 000000000000..94aa02f4698c
--- /dev/null
+++ b/debian/patches/bugfix/m68k/611-module_fixup.diff
@@ -0,0 +1,214 @@
+Subject: [PATCH] m68k: runtime patching infrastructure
+
+From: Roman Zippel <zippel@linux-m68k.org>
+
+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>
+---
+ arch/m68k/Makefile | 1 +
+ arch/m68k/kernel/module.c | 24 +++++++++++++++++++++++-
+ arch/m68k/kernel/module.lds | 7 +++++++
+ arch/m68k/kernel/vmlinux-std.lds | 5 +++++
+ arch/m68k/kernel/vmlinux-sun3.lds | 5 +++++
+ arch/m68k/mm/motorola.c | 3 +++
+ include/asm-m68k/module.h | 33 ++++++++++++++++++++++++++++++++-
+ include/asm-m68k/page.h | 29 ++++++++++++++++++++++++++---
+ 8 files changed, 102 insertions(+), 5 deletions(-)
+
+--- linux-m68k-2.6.21.orig/arch/m68k/Makefile
++++ linux-m68k-2.6.21/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-
+--- linux-m68k-2.6.21.orig/arch/m68k/kernel/module.c
++++ linux-m68k-2.6.21/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>
+@@ -116,10 +122,26 @@ int apply_relocate_add(Elf32_Shdr *sechd
+ return 0;
+ }
+
++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;
++ }
++ }
++}
++
+ 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;
+ }
+
+--- /dev/null
++++ linux-m68k-2.6.21/arch/m68k/kernel/module.lds
+@@ -0,0 +1,7 @@
++SECTIONS {
++ .m68k_fixup : {
++ __start_fixup = .;
++ *(.m68k_fixup)
++ __stop_fixup = .;
++ }
++}
+--- linux-m68k-2.6.21.orig/arch/m68k/kernel/vmlinux-std.lds
++++ linux-m68k-2.6.21/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);
+--- linux-m68k-2.6.21.orig/arch/m68k/kernel/vmlinux-sun3.lds
++++ linux-m68k-2.6.21/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);
+--- linux-m68k-2.6.21.orig/arch/m68k/mm/motorola.c
++++ linux-m68k-2.6.21/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
+--- linux-m68k-2.6.21.orig/include/asm-m68k/module.h
++++ linux-m68k-2.6.21/include/asm-m68k/module.h
+@@ -1,7 +1,38 @@
+ #ifndef _ASM_M68K_MODULE_H
+ #define _ASM_M68K_MODULE_H
+-struct mod_arch_specific { };
++
++struct mod_arch_specific {
++ struct m68k_fixup_info *fixup_start, *fixup_end;
++};
++
++#define MODULE_ARCH_INIT { \
++ .fixup_start = __start_fixup, \
++ .fixup_end = __stop_fixup, \
++}
++
+ #define Elf_Shdr Elf32_Shdr
+ #define Elf_Sym Elf32_Sym
+ #define Elf_Ehdr Elf32_Ehdr
++
++
++enum m68k_fixup_type {
++ m68k_fixup_memoffset,
++};
++
++struct m68k_fixup_info {
++ enum m68k_fixup_type type;
++ void *addr;
++};
++
++#define m68k_fixup(type, addr) \
++ " .section \".m68k_fixup\",\"aw\"\n" \
++ " .long " #type "," #addr "\n" \
++ " .previous\n"
++
++extern struct m68k_fixup_info __start_fixup[], __stop_fixup[];
++
++struct module;
++extern void module_fixup(struct module *mod, struct m68k_fixup_info *start,
++ struct m68k_fixup_info *end);
++
+ #endif /* _ASM_M68K_MODULE_H */
+--- linux-m68k-2.6.21.orig/include/asm-m68k/page.h
++++ linux-m68k-2.6.21/include/asm-m68k/page.h
+@@ -27,6 +27,8 @@
+
+ #ifndef __ASSEMBLY__
+
++#include <asm/module.h>
++
+ #define get_user_page(vaddr) __get_free_page(GFP_KERNEL)
+ #define free_user_page(page, addr) free_page(addr)
+
+@@ -114,14 +116,35 @@ typedef struct { unsigned long pgprot; }
+
+ #ifndef __ASSEMBLY__
+
++extern unsigned long m68k_memoffset;
++
+ #ifndef CONFIG_SUN3
+
+ #define WANT_PAGE_VIRTUAL
+ #ifdef CONFIG_SINGLE_MEMORY_CHUNK
+-extern unsigned long m68k_memoffset;
+
+-#define __pa(vaddr) ((unsigned long)(vaddr)+m68k_memoffset)
+-#define __va(paddr) ((void *)((unsigned long)(paddr)-m68k_memoffset))
++static inline unsigned long ___pa(void *vaddr)
++{
++ unsigned long paddr;
++ asm (
++ "1: addl #0,%0\n"
++ m68k_fixup(%c2, 1b+2)
++ : "=r" (paddr)
++ : "0" (vaddr), "i" (m68k_fixup_memoffset));
++ return paddr;
++}
++#define __pa(vaddr) ___pa((void *)(vaddr))
++static inline void *__va(unsigned long paddr)
++{
++ void *vaddr;
++ asm (
++ "1: subl #0,%0\n"
++ m68k_fixup(%c2, 1b+2)
++ : "=r" (vaddr)
++ : "0" (paddr), "i" (m68k_fixup_memoffset));
++ return vaddr;
++}
++
+ #else
+ #define __pa(vaddr) virt_to_phys((void *)(vaddr))
+ #define __va(paddr) phys_to_virt((unsigned long)(paddr))