mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 20:51:44 +00:00
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>
This commit is contained in:
parent
1fc799e1b4
commit
fbe9c96129
@ -19,6 +19,7 @@ COMPILE_ARCH = $(shell uname -m)
|
|||||||
# override top level makefile
|
# override top level makefile
|
||||||
AS += -m68020
|
AS += -m68020
|
||||||
LDFLAGS := -m m68kelf
|
LDFLAGS := -m m68kelf
|
||||||
|
LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds
|
||||||
ifneq ($(COMPILE_ARCH),$(ARCH))
|
ifneq ($(COMPILE_ARCH),$(ARCH))
|
||||||
# prefix for cross-compiling binaries
|
# prefix for cross-compiling binaries
|
||||||
CROSS_COMPILE = m68k-linux-gnu-
|
CROSS_COMPILE = m68k-linux-gnu-
|
||||||
|
@ -9,13 +9,12 @@ else
|
|||||||
endif
|
endif
|
||||||
extra-y += vmlinux.lds
|
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
|
sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o devres.o
|
||||||
|
|
||||||
devres-y = ../../../kernel/irq/devres.o
|
devres-y = ../../../kernel/irq/devres.o
|
||||||
|
|
||||||
obj-$(CONFIG_PCI) += bios32.o
|
obj-$(CONFIG_PCI) += bios32.o
|
||||||
obj-$(CONFIG_MODULES) += module.o
|
|
||||||
obj-y$(CONFIG_MMU_SUN3) += dma.o # no, it's not a typo
|
obj-y$(CONFIG_MMU_SUN3) += dma.o # no, it's not a typo
|
||||||
|
|
||||||
EXTRA_AFLAGS := -traditional
|
EXTRA_AFLAGS := -traditional
|
||||||
|
@ -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/moduleloader.h>
|
||||||
#include <linux/elf.h>
|
#include <linux/elf.h>
|
||||||
#include <linux/vmalloc.h>
|
#include <linux/vmalloc.h>
|
||||||
@ -11,6 +17,8 @@
|
|||||||
#define DEBUGP(fmt...)
|
#define DEBUGP(fmt...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_MODULES
|
||||||
|
|
||||||
void *module_alloc(unsigned long size)
|
void *module_alloc(unsigned long size)
|
||||||
{
|
{
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
@ -118,11 +126,29 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
|
|||||||
|
|
||||||
int module_finalize(const Elf_Ehdr *hdr,
|
int module_finalize(const Elf_Ehdr *hdr,
|
||||||
const Elf_Shdr *sechdrs,
|
const Elf_Shdr *sechdrs,
|
||||||
struct module *me)
|
struct module *mod)
|
||||||
{
|
{
|
||||||
|
module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void module_arch_cleanup(struct module *mod)
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
7
arch/m68k/kernel/module.lds
Normal file
7
arch/m68k/kernel/module.lds
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
SECTIONS {
|
||||||
|
.m68k_fixup : {
|
||||||
|
__start_fixup = .;
|
||||||
|
*(.m68k_fixup)
|
||||||
|
__stop_fixup = .;
|
||||||
|
}
|
||||||
|
}
|
@ -60,6 +60,11 @@ SECTIONS
|
|||||||
__con_initcall_start = .;
|
__con_initcall_start = .;
|
||||||
.con_initcall.init : { *(.con_initcall.init) }
|
.con_initcall.init : { *(.con_initcall.init) }
|
||||||
__con_initcall_end = .;
|
__con_initcall_end = .;
|
||||||
|
.m68k_fixup : {
|
||||||
|
__start_fixup = .;
|
||||||
|
*(.m68k_fixup)
|
||||||
|
__stop_fixup = .;
|
||||||
|
}
|
||||||
SECURITY_INIT
|
SECURITY_INIT
|
||||||
#ifdef CONFIG_BLK_DEV_INITRD
|
#ifdef CONFIG_BLK_DEV_INITRD
|
||||||
. = ALIGN(8192);
|
. = ALIGN(8192);
|
||||||
|
@ -54,6 +54,11 @@ __init_begin = .;
|
|||||||
__con_initcall_start = .;
|
__con_initcall_start = .;
|
||||||
.con_initcall.init : { *(.con_initcall.init) }
|
.con_initcall.init : { *(.con_initcall.init) }
|
||||||
__con_initcall_end = .;
|
__con_initcall_end = .;
|
||||||
|
.m68k_fixup : {
|
||||||
|
__start_fixup = .;
|
||||||
|
*(.m68k_fixup)
|
||||||
|
__stop_fixup = .;
|
||||||
|
}
|
||||||
SECURITY_INIT
|
SECURITY_INIT
|
||||||
#ifdef CONFIG_BLK_DEV_INITRD
|
#ifdef CONFIG_BLK_DEV_INITRD
|
||||||
. = ALIGN(8192);
|
. = ALIGN(8192);
|
||||||
|
@ -222,6 +222,9 @@ void __init paging_init(void)
|
|||||||
pgprot_val(protection_map[i]) |= _PAGE_CACHE040;
|
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
|
* Map the physical memory available into the kernel virtual
|
||||||
* address space. It may allocate some memory for page
|
* address space. It may allocate some memory for page
|
||||||
|
@ -1,7 +1,38 @@
|
|||||||
#ifndef _ASM_M68K_MODULE_H
|
#ifndef _ASM_M68K_MODULE_H
|
||||||
#define _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_Shdr Elf32_Shdr
|
||||||
#define Elf_Sym Elf32_Sym
|
#define Elf_Sym Elf32_Sym
|
||||||
#define Elf_Ehdr Elf32_Ehdr
|
#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 */
|
#endif /* _ASM_M68K_MODULE_H */
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
#include <asm/module.h>
|
||||||
|
|
||||||
#define get_user_page(vaddr) __get_free_page(GFP_KERNEL)
|
#define get_user_page(vaddr) __get_free_page(GFP_KERNEL)
|
||||||
#define free_user_page(page, addr) free_page(addr)
|
#define free_user_page(page, addr) free_page(addr)
|
||||||
|
|
||||||
@ -114,14 +116,35 @@ typedef struct { unsigned long pgprot; } pgprot_t;
|
|||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
extern unsigned long m68k_memoffset;
|
||||||
|
|
||||||
#ifndef CONFIG_SUN3
|
#ifndef CONFIG_SUN3
|
||||||
|
|
||||||
#define WANT_PAGE_VIRTUAL
|
#define WANT_PAGE_VIRTUAL
|
||||||
#ifdef CONFIG_SINGLE_MEMORY_CHUNK
|
#ifdef CONFIG_SINGLE_MEMORY_CHUNK
|
||||||
extern unsigned long m68k_memoffset;
|
|
||||||
|
|
||||||
#define __pa(vaddr) ((unsigned long)(vaddr)+m68k_memoffset)
|
static inline unsigned long ___pa(void *vaddr)
|
||||||
#define __va(paddr) ((void *)((unsigned long)(paddr)-m68k_memoffset))
|
{
|
||||||
|
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
|
#else
|
||||||
#define __pa(vaddr) virt_to_phys((void *)(vaddr))
|
#define __pa(vaddr) virt_to_phys((void *)(vaddr))
|
||||||
#define __va(paddr) phys_to_virt((unsigned long)(paddr))
|
#define __va(paddr) phys_to_virt((unsigned long)(paddr))
|
||||||
|
Loading…
Reference in New Issue
Block a user