diff options
author | GuanXuetao <gxt@mprc.pku.edu.cn> | 2011-01-15 05:13:50 -0500 |
---|---|---|
committer | GuanXuetao <gxt@mprc.pku.edu.cn> | 2011-03-16 21:19:05 -0400 |
commit | 87c1a3fb7c07322dfd63a63dd6d42339ad52ddee (patch) | |
tree | c090cce270aa4ca455bbfadb975f35f3eb01ccab /arch/unicore32 | |
parent | 790edb61c0d87d1f1daafcaaa8f7c66b7b82bdad (diff) |
unicore32 core architecture: generic elf and ksyms stuff
This patch includes some generic stuff including elf and ksyms.
Because all one-line asm-generic headers are auto-generated by ASM_GENERIC_HEADERS
in arch/unicore32/Makefile, so the rest seems very little.
ELF handling functions and module handling functions are also here.
Signed-off-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/unicore32')
-rw-r--r-- | arch/unicore32/include/asm/elf.h | 94 | ||||
-rw-r--r-- | arch/unicore32/include/asm/string.h | 38 | ||||
-rw-r--r-- | arch/unicore32/kernel/asm-offsets.c | 112 | ||||
-rw-r--r-- | arch/unicore32/kernel/elf.c | 38 | ||||
-rw-r--r-- | arch/unicore32/kernel/ksyms.c | 99 | ||||
-rw-r--r-- | arch/unicore32/kernel/ksyms.h | 15 | ||||
-rw-r--r-- | arch/unicore32/kernel/module.c | 152 | ||||
-rw-r--r-- | arch/unicore32/mm/proc-syms.c | 23 |
8 files changed, 571 insertions, 0 deletions
diff --git a/arch/unicore32/include/asm/elf.h b/arch/unicore32/include/asm/elf.h new file mode 100644 index 000000000000..829042d07722 --- /dev/null +++ b/arch/unicore32/include/asm/elf.h | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | * linux/arch/unicore32/include/asm/elf.h | ||
3 | * | ||
4 | * Code specific to PKUnity SoC and UniCore ISA | ||
5 | * | ||
6 | * Copyright (C) 2001-2010 GUAN Xue-tao | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __UNICORE_ELF_H__ | ||
14 | #define __UNICORE_ELF_H__ | ||
15 | |||
16 | #include <asm/hwcap.h> | ||
17 | |||
18 | /* | ||
19 | * ELF register definitions.. | ||
20 | */ | ||
21 | #include <asm/ptrace.h> | ||
22 | |||
23 | typedef unsigned long elf_greg_t; | ||
24 | typedef unsigned long elf_freg_t[3]; | ||
25 | |||
26 | #define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t)) | ||
27 | typedef elf_greg_t elf_gregset_t[ELF_NGREG]; | ||
28 | |||
29 | typedef struct fp_state elf_fpregset_t; | ||
30 | |||
31 | #define EM_UNICORE 110 | ||
32 | |||
33 | #define R_UNICORE_NONE 0 | ||
34 | #define R_UNICORE_PC24 1 | ||
35 | #define R_UNICORE_ABS32 2 | ||
36 | #define R_UNICORE_CALL 28 | ||
37 | #define R_UNICORE_JUMP24 29 | ||
38 | |||
39 | /* | ||
40 | * These are used to set parameters in the core dumps. | ||
41 | */ | ||
42 | #define ELF_CLASS ELFCLASS32 | ||
43 | #define ELF_DATA ELFDATA2LSB | ||
44 | #define ELF_ARCH EM_UNICORE | ||
45 | |||
46 | /* | ||
47 | * This yields a string that ld.so will use to load implementation | ||
48 | * specific libraries for optimization. This is more specific in | ||
49 | * intent than poking at uname or /proc/cpuinfo. | ||
50 | * | ||
51 | */ | ||
52 | #define ELF_PLATFORM_SIZE 8 | ||
53 | #define ELF_PLATFORM (elf_platform) | ||
54 | |||
55 | extern char elf_platform[]; | ||
56 | |||
57 | struct elf32_hdr; | ||
58 | |||
59 | /* | ||
60 | * This is used to ensure we don't load something for the wrong architecture. | ||
61 | */ | ||
62 | extern int elf_check_arch(const struct elf32_hdr *); | ||
63 | #define elf_check_arch elf_check_arch | ||
64 | |||
65 | struct task_struct; | ||
66 | int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs); | ||
67 | #define ELF_CORE_COPY_TASK_REGS dump_task_regs | ||
68 | |||
69 | #define ELF_EXEC_PAGESIZE 4096 | ||
70 | |||
71 | /* This is the location that an ET_DYN program is loaded if exec'ed. Typical | ||
72 | use of this is to invoke "./ld.so someprog" to test out a new version of | ||
73 | the loader. We need to make sure that it is out of the way of the program | ||
74 | that it will "exec", and that there is sufficient room for the brk. */ | ||
75 | |||
76 | #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) | ||
77 | |||
78 | /* When the program starts, a1 contains a pointer to a function to be | ||
79 | registered with atexit, as per the SVR4 ABI. A value of 0 means we | ||
80 | have no such handler. */ | ||
81 | #define ELF_PLAT_INIT(_r, load_addr) {(_r)->UCreg_00 = 0; } | ||
82 | |||
83 | extern void elf_set_personality(const struct elf32_hdr *); | ||
84 | #define SET_PERSONALITY(ex) elf_set_personality(&(ex)) | ||
85 | |||
86 | struct mm_struct; | ||
87 | extern unsigned long arch_randomize_brk(struct mm_struct *mm); | ||
88 | #define arch_randomize_brk arch_randomize_brk | ||
89 | |||
90 | extern int vectors_user_mapping(void); | ||
91 | #define arch_setup_additional_pages(bprm, uses_interp) vectors_user_mapping() | ||
92 | #define ARCH_HAS_SETUP_ADDITIONAL_PAGES | ||
93 | |||
94 | #endif | ||
diff --git a/arch/unicore32/include/asm/string.h b/arch/unicore32/include/asm/string.h new file mode 100644 index 000000000000..55264c84369a --- /dev/null +++ b/arch/unicore32/include/asm/string.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * linux/arch/unicore32/include/asm/string.h | ||
3 | * | ||
4 | * Code specific to PKUnity SoC and UniCore ISA | ||
5 | * | ||
6 | * Copyright (C) 2001-2010 GUAN Xue-tao | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #ifndef __UNICORE_STRING_H__ | ||
13 | #define __UNICORE_STRING_H__ | ||
14 | |||
15 | /* | ||
16 | * We don't do inline string functions, since the | ||
17 | * optimised inline asm versions are not small. | ||
18 | */ | ||
19 | |||
20 | #define __HAVE_ARCH_STRRCHR | ||
21 | extern char *strrchr(const char *s, int c); | ||
22 | |||
23 | #define __HAVE_ARCH_STRCHR | ||
24 | extern char *strchr(const char *s, int c); | ||
25 | |||
26 | #define __HAVE_ARCH_MEMCPY | ||
27 | extern void *memcpy(void *, const void *, __kernel_size_t); | ||
28 | |||
29 | #define __HAVE_ARCH_MEMMOVE | ||
30 | extern void *memmove(void *, const void *, __kernel_size_t); | ||
31 | |||
32 | #define __HAVE_ARCH_MEMCHR | ||
33 | extern void *memchr(const void *, int, __kernel_size_t); | ||
34 | |||
35 | #define __HAVE_ARCH_MEMSET | ||
36 | extern void *memset(void *, int, __kernel_size_t); | ||
37 | |||
38 | #endif | ||
diff --git a/arch/unicore32/kernel/asm-offsets.c b/arch/unicore32/kernel/asm-offsets.c new file mode 100644 index 000000000000..ffcbe7536ca7 --- /dev/null +++ b/arch/unicore32/kernel/asm-offsets.c | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * linux/arch/unicore32/kernel/asm-offsets.c | ||
3 | * | ||
4 | * Code specific to PKUnity SoC and UniCore ISA | ||
5 | * | ||
6 | * Copyright (C) 2001-2010 GUAN Xue-tao | ||
7 | * | ||
8 | * Generate definitions needed by assembly language modules. | ||
9 | * This code generates raw asm output which is post-processed to extract | ||
10 | * and format the required data. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 as | ||
14 | * published by the Free Software Foundation. | ||
15 | */ | ||
16 | #include <linux/sched.h> | ||
17 | #include <linux/mm.h> | ||
18 | #include <linux/dma-mapping.h> | ||
19 | #include <linux/kbuild.h> | ||
20 | #include <linux/suspend.h> | ||
21 | #include <linux/thread_info.h> | ||
22 | #include <asm/memory.h> | ||
23 | #include <asm/suspend.h> | ||
24 | |||
25 | /* | ||
26 | * GCC 3.0, 3.1: general bad code generation. | ||
27 | * GCC 3.2.0: incorrect function argument offset calculation. | ||
28 | * GCC 3.2.x: miscompiles NEW_AUX_ENT in fs/binfmt_elf.c | ||
29 | * (http://gcc.gnu.org/PR8896) and incorrect structure | ||
30 | * initialisation in fs/jffs2/erase.c | ||
31 | */ | ||
32 | #if (__GNUC__ < 4) | ||
33 | #error Your compiler should upgrade to uc4 | ||
34 | #error Known good compilers: 4.2.2 | ||
35 | #endif | ||
36 | |||
37 | int main(void) | ||
38 | { | ||
39 | DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); | ||
40 | BLANK(); | ||
41 | DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); | ||
42 | DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); | ||
43 | DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit)); | ||
44 | DEFINE(TI_TASK, offsetof(struct thread_info, task)); | ||
45 | DEFINE(TI_EXEC_DOMAIN, offsetof(struct thread_info, exec_domain)); | ||
46 | DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); | ||
47 | DEFINE(TI_CPU_SAVE, offsetof(struct thread_info, cpu_context)); | ||
48 | DEFINE(TI_USED_CP, offsetof(struct thread_info, used_cp)); | ||
49 | #ifdef CONFIG_UNICORE_FPU_F64 | ||
50 | DEFINE(TI_FPSTATE, offsetof(struct thread_info, fpstate)); | ||
51 | #endif | ||
52 | BLANK(); | ||
53 | DEFINE(S_R0, offsetof(struct pt_regs, UCreg_00)); | ||
54 | DEFINE(S_R1, offsetof(struct pt_regs, UCreg_01)); | ||
55 | DEFINE(S_R2, offsetof(struct pt_regs, UCreg_02)); | ||
56 | DEFINE(S_R3, offsetof(struct pt_regs, UCreg_03)); | ||
57 | DEFINE(S_R4, offsetof(struct pt_regs, UCreg_04)); | ||
58 | DEFINE(S_R5, offsetof(struct pt_regs, UCreg_05)); | ||
59 | DEFINE(S_R6, offsetof(struct pt_regs, UCreg_06)); | ||
60 | DEFINE(S_R7, offsetof(struct pt_regs, UCreg_07)); | ||
61 | DEFINE(S_R8, offsetof(struct pt_regs, UCreg_08)); | ||
62 | DEFINE(S_R9, offsetof(struct pt_regs, UCreg_09)); | ||
63 | DEFINE(S_R10, offsetof(struct pt_regs, UCreg_10)); | ||
64 | DEFINE(S_R11, offsetof(struct pt_regs, UCreg_11)); | ||
65 | DEFINE(S_R12, offsetof(struct pt_regs, UCreg_12)); | ||
66 | DEFINE(S_R13, offsetof(struct pt_regs, UCreg_13)); | ||
67 | DEFINE(S_R14, offsetof(struct pt_regs, UCreg_14)); | ||
68 | DEFINE(S_R15, offsetof(struct pt_regs, UCreg_15)); | ||
69 | DEFINE(S_R16, offsetof(struct pt_regs, UCreg_16)); | ||
70 | DEFINE(S_R17, offsetof(struct pt_regs, UCreg_17)); | ||
71 | DEFINE(S_R18, offsetof(struct pt_regs, UCreg_18)); | ||
72 | DEFINE(S_R19, offsetof(struct pt_regs, UCreg_19)); | ||
73 | DEFINE(S_R20, offsetof(struct pt_regs, UCreg_20)); | ||
74 | DEFINE(S_R21, offsetof(struct pt_regs, UCreg_21)); | ||
75 | DEFINE(S_R22, offsetof(struct pt_regs, UCreg_22)); | ||
76 | DEFINE(S_R23, offsetof(struct pt_regs, UCreg_23)); | ||
77 | DEFINE(S_R24, offsetof(struct pt_regs, UCreg_24)); | ||
78 | DEFINE(S_R25, offsetof(struct pt_regs, UCreg_25)); | ||
79 | DEFINE(S_R26, offsetof(struct pt_regs, UCreg_26)); | ||
80 | DEFINE(S_FP, offsetof(struct pt_regs, UCreg_fp)); | ||
81 | DEFINE(S_IP, offsetof(struct pt_regs, UCreg_ip)); | ||
82 | DEFINE(S_SP, offsetof(struct pt_regs, UCreg_sp)); | ||
83 | DEFINE(S_LR, offsetof(struct pt_regs, UCreg_lr)); | ||
84 | DEFINE(S_PC, offsetof(struct pt_regs, UCreg_pc)); | ||
85 | DEFINE(S_PSR, offsetof(struct pt_regs, UCreg_asr)); | ||
86 | DEFINE(S_OLD_R0, offsetof(struct pt_regs, UCreg_ORIG_00)); | ||
87 | DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs)); | ||
88 | BLANK(); | ||
89 | DEFINE(VMA_VM_MM, offsetof(struct vm_area_struct, vm_mm)); | ||
90 | DEFINE(VMA_VM_FLAGS, offsetof(struct vm_area_struct, vm_flags)); | ||
91 | BLANK(); | ||
92 | DEFINE(VM_EXEC, VM_EXEC); | ||
93 | BLANK(); | ||
94 | DEFINE(PAGE_SZ, PAGE_SIZE); | ||
95 | BLANK(); | ||
96 | DEFINE(SYS_ERROR0, 0x9f0000); | ||
97 | BLANK(); | ||
98 | DEFINE(PBE_ADDRESS, offsetof(struct pbe, address)); | ||
99 | DEFINE(PBE_ORIN_ADDRESS, offsetof(struct pbe, orig_address)); | ||
100 | DEFINE(PBE_NEXT, offsetof(struct pbe, next)); | ||
101 | DEFINE(SWSUSP_CPU, offsetof(struct swsusp_arch_regs, \ | ||
102 | cpu_context)); | ||
103 | #ifdef CONFIG_UNICORE_FPU_F64 | ||
104 | DEFINE(SWSUSP_FPSTATE, offsetof(struct swsusp_arch_regs, \ | ||
105 | fpstate)); | ||
106 | #endif | ||
107 | BLANK(); | ||
108 | DEFINE(DMA_BIDIRECTIONAL, DMA_BIDIRECTIONAL); | ||
109 | DEFINE(DMA_TO_DEVICE, DMA_TO_DEVICE); | ||
110 | DEFINE(DMA_FROM_DEVICE, DMA_FROM_DEVICE); | ||
111 | return 0; | ||
112 | } | ||
diff --git a/arch/unicore32/kernel/elf.c b/arch/unicore32/kernel/elf.c new file mode 100644 index 000000000000..0a176734fefa --- /dev/null +++ b/arch/unicore32/kernel/elf.c | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * linux/arch/unicore32/kernel/elf.c | ||
3 | * | ||
4 | * Code specific to PKUnity SoC and UniCore ISA | ||
5 | * | ||
6 | * Copyright (C) 2001-2010 GUAN Xue-tao | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/personality.h> | ||
15 | #include <linux/binfmts.h> | ||
16 | #include <linux/elf.h> | ||
17 | |||
18 | int elf_check_arch(const struct elf32_hdr *x) | ||
19 | { | ||
20 | /* Make sure it's an UniCore executable */ | ||
21 | if (x->e_machine != EM_UNICORE) | ||
22 | return 0; | ||
23 | |||
24 | /* Make sure the entry address is reasonable */ | ||
25 | if (x->e_entry & 3) | ||
26 | return 0; | ||
27 | |||
28 | return 1; | ||
29 | } | ||
30 | EXPORT_SYMBOL(elf_check_arch); | ||
31 | |||
32 | void elf_set_personality(const struct elf32_hdr *x) | ||
33 | { | ||
34 | unsigned int personality = PER_LINUX; | ||
35 | |||
36 | set_personality(personality); | ||
37 | } | ||
38 | EXPORT_SYMBOL(elf_set_personality); | ||
diff --git a/arch/unicore32/kernel/ksyms.c b/arch/unicore32/kernel/ksyms.c new file mode 100644 index 000000000000..a8970809428a --- /dev/null +++ b/arch/unicore32/kernel/ksyms.c | |||
@@ -0,0 +1,99 @@ | |||
1 | /* | ||
2 | * linux/arch/unicore32/kernel/ksyms.c | ||
3 | * | ||
4 | * Code specific to PKUnity SoC and UniCore ISA | ||
5 | * | ||
6 | * Copyright (C) 2001-2010 GUAN Xue-tao | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/string.h> | ||
15 | #include <linux/cryptohash.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/in6.h> | ||
18 | #include <linux/syscalls.h> | ||
19 | #include <linux/uaccess.h> | ||
20 | #include <linux/io.h> | ||
21 | |||
22 | #include <asm/checksum.h> | ||
23 | #include <asm/system.h> | ||
24 | |||
25 | #include "ksyms.h" | ||
26 | |||
27 | EXPORT_SYMBOL(__uc32_find_next_zero_bit); | ||
28 | EXPORT_SYMBOL(__uc32_find_next_bit); | ||
29 | |||
30 | EXPORT_SYMBOL(__backtrace); | ||
31 | |||
32 | /* platform dependent support */ | ||
33 | EXPORT_SYMBOL(__udelay); | ||
34 | EXPORT_SYMBOL(__const_udelay); | ||
35 | |||
36 | /* networking */ | ||
37 | EXPORT_SYMBOL(csum_partial); | ||
38 | EXPORT_SYMBOL(csum_partial_copy_from_user); | ||
39 | EXPORT_SYMBOL(csum_partial_copy_nocheck); | ||
40 | EXPORT_SYMBOL(__csum_ipv6_magic); | ||
41 | |||
42 | /* io */ | ||
43 | #ifndef __raw_readsb | ||
44 | EXPORT_SYMBOL(__raw_readsb); | ||
45 | #endif | ||
46 | #ifndef __raw_readsw | ||
47 | EXPORT_SYMBOL(__raw_readsw); | ||
48 | #endif | ||
49 | #ifndef __raw_readsl | ||
50 | EXPORT_SYMBOL(__raw_readsl); | ||
51 | #endif | ||
52 | #ifndef __raw_writesb | ||
53 | EXPORT_SYMBOL(__raw_writesb); | ||
54 | #endif | ||
55 | #ifndef __raw_writesw | ||
56 | EXPORT_SYMBOL(__raw_writesw); | ||
57 | #endif | ||
58 | #ifndef __raw_writesl | ||
59 | EXPORT_SYMBOL(__raw_writesl); | ||
60 | #endif | ||
61 | |||
62 | /* string / mem functions */ | ||
63 | EXPORT_SYMBOL(strchr); | ||
64 | EXPORT_SYMBOL(strrchr); | ||
65 | EXPORT_SYMBOL(memset); | ||
66 | EXPORT_SYMBOL(memcpy); | ||
67 | EXPORT_SYMBOL(memmove); | ||
68 | EXPORT_SYMBOL(memchr); | ||
69 | |||
70 | /* user mem (segment) */ | ||
71 | EXPORT_SYMBOL(__strnlen_user); | ||
72 | EXPORT_SYMBOL(__strncpy_from_user); | ||
73 | |||
74 | EXPORT_SYMBOL(copy_page); | ||
75 | |||
76 | EXPORT_SYMBOL(__copy_from_user); | ||
77 | EXPORT_SYMBOL(__copy_to_user); | ||
78 | EXPORT_SYMBOL(__clear_user); | ||
79 | |||
80 | EXPORT_SYMBOL(__get_user_1); | ||
81 | EXPORT_SYMBOL(__get_user_2); | ||
82 | EXPORT_SYMBOL(__get_user_4); | ||
83 | |||
84 | EXPORT_SYMBOL(__put_user_1); | ||
85 | EXPORT_SYMBOL(__put_user_2); | ||
86 | EXPORT_SYMBOL(__put_user_4); | ||
87 | EXPORT_SYMBOL(__put_user_8); | ||
88 | |||
89 | EXPORT_SYMBOL(__ashldi3); | ||
90 | EXPORT_SYMBOL(__ashrdi3); | ||
91 | EXPORT_SYMBOL(__divsi3); | ||
92 | EXPORT_SYMBOL(__lshrdi3); | ||
93 | EXPORT_SYMBOL(__modsi3); | ||
94 | EXPORT_SYMBOL(__muldi3); | ||
95 | EXPORT_SYMBOL(__ucmpdi2); | ||
96 | EXPORT_SYMBOL(__udivsi3); | ||
97 | EXPORT_SYMBOL(__umodsi3); | ||
98 | EXPORT_SYMBOL(__bswapsi2); | ||
99 | |||
diff --git a/arch/unicore32/kernel/ksyms.h b/arch/unicore32/kernel/ksyms.h new file mode 100644 index 000000000000..185cdc712d03 --- /dev/null +++ b/arch/unicore32/kernel/ksyms.h | |||
@@ -0,0 +1,15 @@ | |||
1 | /* | ||
2 | * libgcc functions - functions that are used internally by the | ||
3 | * compiler... (prototypes are not correct though, but that | ||
4 | * doesn't really matter since they're not versioned). | ||
5 | */ | ||
6 | extern void __ashldi3(void); | ||
7 | extern void __ashrdi3(void); | ||
8 | extern void __divsi3(void); | ||
9 | extern void __lshrdi3(void); | ||
10 | extern void __modsi3(void); | ||
11 | extern void __muldi3(void); | ||
12 | extern void __ucmpdi2(void); | ||
13 | extern void __udivsi3(void); | ||
14 | extern void __umodsi3(void); | ||
15 | extern void __bswapsi2(void); | ||
diff --git a/arch/unicore32/kernel/module.c b/arch/unicore32/kernel/module.c new file mode 100644 index 000000000000..3e5a38d71a1e --- /dev/null +++ b/arch/unicore32/kernel/module.c | |||
@@ -0,0 +1,152 @@ | |||
1 | /* | ||
2 | * linux/arch/unicore32/kernel/module.c | ||
3 | * | ||
4 | * Code specific to PKUnity SoC and UniCore ISA | ||
5 | * | ||
6 | * Copyright (C) 2001-2010 GUAN Xue-tao | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/moduleloader.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/mm.h> | ||
16 | #include <linux/elf.h> | ||
17 | #include <linux/vmalloc.h> | ||
18 | #include <linux/fs.h> | ||
19 | #include <linux/string.h> | ||
20 | #include <linux/gfp.h> | ||
21 | |||
22 | #include <asm/pgtable.h> | ||
23 | #include <asm/sections.h> | ||
24 | |||
25 | void *module_alloc(unsigned long size) | ||
26 | { | ||
27 | struct vm_struct *area; | ||
28 | |||
29 | size = PAGE_ALIGN(size); | ||
30 | if (!size) | ||
31 | return NULL; | ||
32 | |||
33 | area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END); | ||
34 | if (!area) | ||
35 | return NULL; | ||
36 | |||
37 | return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL_EXEC); | ||
38 | } | ||
39 | |||
40 | void module_free(struct module *module, void *region) | ||
41 | { | ||
42 | vfree(region); | ||
43 | } | ||
44 | |||
45 | int module_frob_arch_sections(Elf_Ehdr *hdr, | ||
46 | Elf_Shdr *sechdrs, | ||
47 | char *secstrings, | ||
48 | struct module *mod) | ||
49 | { | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | int | ||
54 | apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, | ||
55 | unsigned int relindex, struct module *module) | ||
56 | { | ||
57 | Elf32_Shdr *symsec = sechdrs + symindex; | ||
58 | Elf32_Shdr *relsec = sechdrs + relindex; | ||
59 | Elf32_Shdr *dstsec = sechdrs + relsec->sh_info; | ||
60 | Elf32_Rel *rel = (void *)relsec->sh_addr; | ||
61 | unsigned int i; | ||
62 | |||
63 | for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++, rel++) { | ||
64 | unsigned long loc; | ||
65 | Elf32_Sym *sym; | ||
66 | s32 offset; | ||
67 | |||
68 | offset = ELF32_R_SYM(rel->r_info); | ||
69 | if (offset < 0 || offset > | ||
70 | (symsec->sh_size / sizeof(Elf32_Sym))) { | ||
71 | printk(KERN_ERR "%s: bad relocation, " | ||
72 | "section %d reloc %d\n", | ||
73 | module->name, relindex, i); | ||
74 | return -ENOEXEC; | ||
75 | } | ||
76 | |||
77 | sym = ((Elf32_Sym *)symsec->sh_addr) + offset; | ||
78 | |||
79 | if (rel->r_offset < 0 || rel->r_offset > | ||
80 | dstsec->sh_size - sizeof(u32)) { | ||
81 | printk(KERN_ERR "%s: out of bounds relocation, " | ||
82 | "section %d reloc %d offset %d size %d\n", | ||
83 | module->name, relindex, i, rel->r_offset, | ||
84 | dstsec->sh_size); | ||
85 | return -ENOEXEC; | ||
86 | } | ||
87 | |||
88 | loc = dstsec->sh_addr + rel->r_offset; | ||
89 | |||
90 | switch (ELF32_R_TYPE(rel->r_info)) { | ||
91 | case R_UNICORE_NONE: | ||
92 | /* ignore */ | ||
93 | break; | ||
94 | |||
95 | case R_UNICORE_ABS32: | ||
96 | *(u32 *)loc += sym->st_value; | ||
97 | break; | ||
98 | |||
99 | case R_UNICORE_PC24: | ||
100 | case R_UNICORE_CALL: | ||
101 | case R_UNICORE_JUMP24: | ||
102 | offset = (*(u32 *)loc & 0x00ffffff) << 2; | ||
103 | if (offset & 0x02000000) | ||
104 | offset -= 0x04000000; | ||
105 | |||
106 | offset += sym->st_value - loc; | ||
107 | if (offset & 3 || | ||
108 | offset <= (s32)0xfe000000 || | ||
109 | offset >= (s32)0x02000000) { | ||
110 | printk(KERN_ERR | ||
111 | "%s: relocation out of range, section " | ||
112 | "%d reloc %d sym '%s'\n", module->name, | ||
113 | relindex, i, strtab + sym->st_name); | ||
114 | return -ENOEXEC; | ||
115 | } | ||
116 | |||
117 | offset >>= 2; | ||
118 | |||
119 | *(u32 *)loc &= 0xff000000; | ||
120 | *(u32 *)loc |= offset & 0x00ffffff; | ||
121 | break; | ||
122 | |||
123 | default: | ||
124 | printk(KERN_ERR "%s: unknown relocation: %u\n", | ||
125 | module->name, ELF32_R_TYPE(rel->r_info)); | ||
126 | return -ENOEXEC; | ||
127 | } | ||
128 | } | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | int | ||
133 | apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab, | ||
134 | unsigned int symindex, unsigned int relsec, | ||
135 | struct module *module) | ||
136 | { | ||
137 | printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", | ||
138 | module->name); | ||
139 | return -ENOEXEC; | ||
140 | } | ||
141 | |||
142 | int | ||
143 | module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, | ||
144 | struct module *module) | ||
145 | { | ||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | void | ||
150 | module_arch_cleanup(struct module *mod) | ||
151 | { | ||
152 | } | ||
diff --git a/arch/unicore32/mm/proc-syms.c b/arch/unicore32/mm/proc-syms.c new file mode 100644 index 000000000000..f30071e3665d --- /dev/null +++ b/arch/unicore32/mm/proc-syms.c | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * linux/arch/unicore32/mm/proc-syms.c | ||
3 | * | ||
4 | * Code specific to PKUnity SoC and UniCore ISA | ||
5 | * | ||
6 | * Copyright (C) 2001-2010 GUAN Xue-tao | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/mm.h> | ||
14 | |||
15 | #include <asm/cacheflush.h> | ||
16 | #include <asm/tlbflush.h> | ||
17 | #include <asm/page.h> | ||
18 | |||
19 | EXPORT_SYMBOL(cpu_dcache_clean_area); | ||
20 | EXPORT_SYMBOL(cpu_set_pte); | ||
21 | |||
22 | EXPORT_SYMBOL(__cpuc_dma_flush_range); | ||
23 | EXPORT_SYMBOL(__cpuc_dma_clean_range); | ||