summary refs log tree commit diff
path: root/include/asm-m68k
diff options
context:
space:
mode:
authorRoman Zippel <zippel@linux-m68k.org>2007-05-31 00:40:50 -0700
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-31 07:58:13 -0700
commitfbe9c9612930e0604dc99ef2da7e063fa3278817 (patch)
treeb11a5a03edd4a61fc5c71b2b38402cdfe914de22 /include/asm-m68k
parent1fc799e1b4efdbc405d87d9f154d64d9bc299e5c (diff)
downloadlinux-fbe9c9612930e0604dc99ef2da7e063fa3278817.tar.gz
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 'include/asm-m68k')
-rw-r--r--include/asm-m68k/module.h33
-rw-r--r--include/asm-m68k/page.h29
2 files changed, 58 insertions, 4 deletions
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 @@
 #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 */
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 @@
 
 #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; } pgprot_t;
 
 #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))