From fbe9c9612930e0604dc99ef2da7e063fa3278817 Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Thu, 31 May 2007 00:40:50 -0700 Subject: 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 Signed-off-by: Geert Uytterhoeven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-m68k/module.h | 33 ++++++++++++++++++++++++++++++++- include/asm-m68k/page.h | 29 ++++++++++++++++++++++++++--- 2 files changed, 58 insertions(+), 4 deletions(-) (limited to 'include/asm-m68k') diff --git a/include/asm-m68k/module.h b/include/asm-m68k/module.h index c6d75af2d8d..71a1f76ac89 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 fcc165ddd09..7650b99dcae 100644 --- a/include/asm-m68k/page.h +++ b/include/asm-m68k/page.h @@ -27,6 +27,8 @@ #ifndef __ASSEMBLY__ +#include + #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)) -- cgit v1.2.3