diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/h8300/kernel |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/h8300/kernel')
-rw-r--r-- | arch/h8300/kernel/Makefile | 11 | ||||
-rw-r--r-- | arch/h8300/kernel/asm-offsets.c | 65 | ||||
-rw-r--r-- | arch/h8300/kernel/gpio.c | 174 | ||||
-rw-r--r-- | arch/h8300/kernel/h8300_ksyms.c | 112 | ||||
-rw-r--r-- | arch/h8300/kernel/init_task.c | 43 | ||||
-rw-r--r-- | arch/h8300/kernel/ints.c | 255 | ||||
-rw-r--r-- | arch/h8300/kernel/module.c | 122 | ||||
-rw-r--r-- | arch/h8300/kernel/process.c | 288 | ||||
-rw-r--r-- | arch/h8300/kernel/ptrace.c | 277 | ||||
-rw-r--r-- | arch/h8300/kernel/semaphore.c | 133 | ||||
-rw-r--r-- | arch/h8300/kernel/setup.c | 248 | ||||
-rw-r--r-- | arch/h8300/kernel/signal.c | 552 | ||||
-rw-r--r-- | arch/h8300/kernel/sys_h8300.c | 282 | ||||
-rw-r--r-- | arch/h8300/kernel/syscalls.S | 340 | ||||
-rw-r--r-- | arch/h8300/kernel/time.c | 134 | ||||
-rw-r--r-- | arch/h8300/kernel/traps.c | 169 | ||||
-rw-r--r-- | arch/h8300/kernel/vmlinux.lds.S | 172 |
17 files changed, 3377 insertions, 0 deletions
diff --git a/arch/h8300/kernel/Makefile b/arch/h8300/kernel/Makefile new file mode 100644 index 000000000000..71b6131e98b8 --- /dev/null +++ b/arch/h8300/kernel/Makefile | |||
@@ -0,0 +1,11 @@ | |||
1 | # | ||
2 | # Makefile for the linux kernel. | ||
3 | # | ||
4 | |||
5 | extra-y := vmlinux.lds | ||
6 | |||
7 | obj-y := process.o traps.o ptrace.o ints.o \ | ||
8 | sys_h8300.o time.o semaphore.o signal.o \ | ||
9 | setup.o gpio.o init_task.o syscalls.o | ||
10 | |||
11 | obj-$(CONFIG_MODULES) += module.o h8300_ksyms.o | ||
diff --git a/arch/h8300/kernel/asm-offsets.c b/arch/h8300/kernel/asm-offsets.c new file mode 100644 index 000000000000..b78b82ad28a3 --- /dev/null +++ b/arch/h8300/kernel/asm-offsets.c | |||
@@ -0,0 +1,65 @@ | |||
1 | /* | ||
2 | * This program is used to generate definitions needed by | ||
3 | * assembly language modules. | ||
4 | * | ||
5 | * We use the technique used in the OSF Mach kernel code: | ||
6 | * generate asm statements containing #defines, | ||
7 | * compile this file to assembler, and then extract the | ||
8 | * #defines from the assembly-language output. | ||
9 | */ | ||
10 | |||
11 | #include <linux/stddef.h> | ||
12 | #include <linux/sched.h> | ||
13 | #include <linux/kernel_stat.h> | ||
14 | #include <linux/ptrace.h> | ||
15 | #include <linux/hardirq.h> | ||
16 | #include <asm/bootinfo.h> | ||
17 | #include <asm/irq.h> | ||
18 | #include <asm/ptrace.h> | ||
19 | |||
20 | #define DEFINE(sym, val) \ | ||
21 | asm volatile("\n->" #sym " %0 " #val : : "i" (val)) | ||
22 | |||
23 | #define BLANK() asm volatile("\n->" : : ) | ||
24 | |||
25 | int main(void) | ||
26 | { | ||
27 | /* offsets into the task struct */ | ||
28 | DEFINE(TASK_STATE, offsetof(struct task_struct, state)); | ||
29 | DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags)); | ||
30 | DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace)); | ||
31 | DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked)); | ||
32 | DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); | ||
33 | DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info)); | ||
34 | DEFINE(TASK_MM, offsetof(struct task_struct, mm)); | ||
35 | DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); | ||
36 | |||
37 | /* offsets into the irq_cpustat_t struct */ | ||
38 | DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending)); | ||
39 | |||
40 | /* offsets into the thread struct */ | ||
41 | DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); | ||
42 | DEFINE(THREAD_USP, offsetof(struct thread_struct, usp)); | ||
43 | DEFINE(THREAD_CCR, offsetof(struct thread_struct, ccr)); | ||
44 | |||
45 | /* offsets into the pt_regs struct */ | ||
46 | DEFINE(LER0, offsetof(struct pt_regs, er0) - sizeof(long)); | ||
47 | DEFINE(LER1, offsetof(struct pt_regs, er1) - sizeof(long)); | ||
48 | DEFINE(LER2, offsetof(struct pt_regs, er2) - sizeof(long)); | ||
49 | DEFINE(LER3, offsetof(struct pt_regs, er3) - sizeof(long)); | ||
50 | DEFINE(LER4, offsetof(struct pt_regs, er4) - sizeof(long)); | ||
51 | DEFINE(LER5, offsetof(struct pt_regs, er5) - sizeof(long)); | ||
52 | DEFINE(LER6, offsetof(struct pt_regs, er6) - sizeof(long)); | ||
53 | DEFINE(LORIG, offsetof(struct pt_regs, orig_er0) - sizeof(long)); | ||
54 | DEFINE(LCCR, offsetof(struct pt_regs, ccr) - sizeof(long)); | ||
55 | DEFINE(LVEC, offsetof(struct pt_regs, vector) - sizeof(long)); | ||
56 | #if defined(__H8300S__) | ||
57 | DEFINE(LEXR, offsetof(struct pt_regs, exr) - sizeof(long)); | ||
58 | #endif | ||
59 | DEFINE(LRET, offsetof(struct pt_regs, pc) - sizeof(long)); | ||
60 | |||
61 | DEFINE(PT_PTRACED, PT_PTRACED); | ||
62 | DEFINE(PT_DTRACE, PT_DTRACE); | ||
63 | |||
64 | return 0; | ||
65 | } | ||
diff --git a/arch/h8300/kernel/gpio.c b/arch/h8300/kernel/gpio.c new file mode 100644 index 000000000000..795682b873e2 --- /dev/null +++ b/arch/h8300/kernel/gpio.c | |||
@@ -0,0 +1,174 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/kernel/gpio.c | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * Internal I/O Port Management | ||
10 | */ | ||
11 | |||
12 | #include <linux/config.h> | ||
13 | #include <linux/stddef.h> | ||
14 | #include <linux/proc_fs.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/string.h> | ||
17 | #include <linux/fs.h> | ||
18 | #include <linux/init.h> | ||
19 | |||
20 | #define _(addr) (volatile unsigned char *)(addr) | ||
21 | #if defined(CONFIG_H83007) || defined(CONFIG_H83068) | ||
22 | #include <asm/regs306x.h> | ||
23 | static volatile unsigned char *ddrs[] = { | ||
24 | _(P1DDR),_(P2DDR),_(P3DDR),_(P4DDR),_(P5DDR),_(P6DDR), | ||
25 | NULL, _(P8DDR),_(P9DDR),_(PADDR),_(PBDDR), | ||
26 | }; | ||
27 | #define MAX_PORT 11 | ||
28 | #endif | ||
29 | |||
30 | #if defined(CONFIG_H83002) || defined(CONFIG_H8048) | ||
31 | /* Fix me!! */ | ||
32 | #include <asm/regs306x.h> | ||
33 | static volatile unsigned char *ddrs[] = { | ||
34 | _(P1DDR),_(P2DDR),_(P3DDR),_(P4DDR),_(P5DDR),_(P6DDR), | ||
35 | NULL, _(P8DDR),_(P9DDR),_(PADDR),_(PBDDR), | ||
36 | }; | ||
37 | #define MAX_PORT 11 | ||
38 | #endif | ||
39 | |||
40 | #if defined(CONFIG_H8S2678) | ||
41 | #include <asm/regs267x.h> | ||
42 | static volatile unsigned char *ddrs[] = { | ||
43 | _(P1DDR),_(P2DDR),_(P3DDR),NULL ,_(P5DDR),_(P6DDR), | ||
44 | _(P7DDR),_(P8DDR),NULL, _(PADDR),_(PBDDR),_(PCDDR), | ||
45 | _(PDDDR),_(PEDDR),_(PFDDR),_(PGDDR),_(PHDDR), | ||
46 | _(PADDR),_(PBDDR),_(PCDDR),_(PDDDR),_(PEDDR),_(PFDDR), | ||
47 | _(PGDDR),_(PHDDR) | ||
48 | }; | ||
49 | #define MAX_PORT 17 | ||
50 | #endif | ||
51 | #undef _ | ||
52 | |||
53 | #if !defined(P1DDR) | ||
54 | #error Unsuppoted CPU Selection | ||
55 | #endif | ||
56 | |||
57 | static struct { | ||
58 | unsigned char used; | ||
59 | unsigned char ddr; | ||
60 | } gpio_regs[MAX_PORT]; | ||
61 | |||
62 | extern char *_platform_gpio_table(int length); | ||
63 | |||
64 | int h8300_reserved_gpio(int port, unsigned int bits) | ||
65 | { | ||
66 | unsigned char *used; | ||
67 | |||
68 | if (port < 0 || port >= MAX_PORT) | ||
69 | return -1; | ||
70 | used = &(gpio_regs[port].used); | ||
71 | if ((*used & bits) != 0) | ||
72 | return 0; | ||
73 | *used |= bits; | ||
74 | return 1; | ||
75 | } | ||
76 | |||
77 | int h8300_free_gpio(int port, unsigned int bits) | ||
78 | { | ||
79 | unsigned char *used; | ||
80 | |||
81 | if (port < 0 || port >= MAX_PORT) | ||
82 | return -1; | ||
83 | used = &(gpio_regs[port].used); | ||
84 | if ((*used & bits) != bits) | ||
85 | return 0; | ||
86 | *used &= (~bits); | ||
87 | return 1; | ||
88 | } | ||
89 | |||
90 | int h8300_set_gpio_dir(int port_bit,int dir) | ||
91 | { | ||
92 | int port = (port_bit >> 8) & 0xff; | ||
93 | int bit = port_bit & 0xff; | ||
94 | |||
95 | if (ddrs[port] == NULL) | ||
96 | return 0; | ||
97 | if (gpio_regs[port].used & bit) { | ||
98 | if (dir) | ||
99 | gpio_regs[port].ddr |= bit; | ||
100 | else | ||
101 | gpio_regs[port].ddr &= ~bit; | ||
102 | *ddrs[port] = gpio_regs[port].ddr; | ||
103 | return 1; | ||
104 | } else | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | int h8300_get_gpio_dir(int port_bit) | ||
109 | { | ||
110 | int port = (port_bit >> 8) & 0xff; | ||
111 | int bit = port_bit & 0xff; | ||
112 | |||
113 | if (ddrs[port] == NULL) | ||
114 | return 0; | ||
115 | if (gpio_regs[port].used & bit) { | ||
116 | return (gpio_regs[port].ddr & bit) != 0; | ||
117 | } else | ||
118 | return -1; | ||
119 | } | ||
120 | |||
121 | #if defined(CONFIG_PROC_FS) | ||
122 | static char *port_status(int portno) | ||
123 | { | ||
124 | static char result[10]; | ||
125 | const static char io[2]={'I','O'}; | ||
126 | char *rp; | ||
127 | int c; | ||
128 | unsigned char used,ddr; | ||
129 | |||
130 | used = gpio_regs[portno].used; | ||
131 | ddr = gpio_regs[portno].ddr; | ||
132 | result[8]='\0'; | ||
133 | rp = result + 7; | ||
134 | for (c = 8; c > 0; c--,rp--,used >>= 1, ddr >>= 1) | ||
135 | if (used & 0x01) | ||
136 | *rp = io[ ddr & 0x01]; | ||
137 | else | ||
138 | *rp = '-'; | ||
139 | return result; | ||
140 | } | ||
141 | |||
142 | static int gpio_proc_read(char *buf, char **start, off_t offset, | ||
143 | int len, int *unused_i, void *unused_v) | ||
144 | { | ||
145 | int c,outlen; | ||
146 | const static char port_name[]="123456789ABCDEFGH"; | ||
147 | outlen = 0; | ||
148 | for (c = 0; c < MAX_PORT; c++) { | ||
149 | if (ddrs[c] == NULL) | ||
150 | continue ; | ||
151 | len = sprintf(buf,"P%c: %s\n",port_name[c],port_status(c)); | ||
152 | buf += len; | ||
153 | outlen += len; | ||
154 | } | ||
155 | return outlen; | ||
156 | } | ||
157 | |||
158 | static __init int register_proc(void) | ||
159 | { | ||
160 | struct proc_dir_entry *proc_gpio; | ||
161 | |||
162 | proc_gpio = create_proc_entry("gpio", S_IRUGO, NULL); | ||
163 | if (proc_gpio) | ||
164 | proc_gpio->read_proc = gpio_proc_read; | ||
165 | return proc_gpio != NULL; | ||
166 | } | ||
167 | |||
168 | __initcall(register_proc); | ||
169 | #endif | ||
170 | |||
171 | void __init h8300_gpio_init(void) | ||
172 | { | ||
173 | memcpy(gpio_regs,_platform_gpio_table(sizeof(gpio_regs)),sizeof(gpio_regs)); | ||
174 | } | ||
diff --git a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c new file mode 100644 index 000000000000..5a630233112f --- /dev/null +++ b/arch/h8300/kernel/h8300_ksyms.c | |||
@@ -0,0 +1,112 @@ | |||
1 | #include <linux/module.h> | ||
2 | #include <linux/linkage.h> | ||
3 | #include <linux/sched.h> | ||
4 | #include <linux/string.h> | ||
5 | #include <linux/mm.h> | ||
6 | #include <linux/user.h> | ||
7 | #include <linux/elfcore.h> | ||
8 | #include <linux/in6.h> | ||
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/config.h> | ||
11 | |||
12 | #include <asm/setup.h> | ||
13 | #include <asm/pgalloc.h> | ||
14 | #include <asm/irq.h> | ||
15 | #include <asm/io.h> | ||
16 | #include <asm/semaphore.h> | ||
17 | #include <asm/checksum.h> | ||
18 | #include <asm/current.h> | ||
19 | #include <asm/gpio.h> | ||
20 | |||
21 | //asmlinkage long long __ashrdi3 (long long, int); | ||
22 | //asmlinkage long long __lshrdi3 (long long, int); | ||
23 | extern char h8300_debug_device[]; | ||
24 | |||
25 | extern void dump_thread(struct pt_regs *, struct user *); | ||
26 | |||
27 | /* platform dependent support */ | ||
28 | |||
29 | EXPORT_SYMBOL(dump_thread); | ||
30 | EXPORT_SYMBOL(strnlen); | ||
31 | EXPORT_SYMBOL(strrchr); | ||
32 | EXPORT_SYMBOL(strstr); | ||
33 | EXPORT_SYMBOL(strchr); | ||
34 | EXPORT_SYMBOL(strcat); | ||
35 | EXPORT_SYMBOL(strlen); | ||
36 | EXPORT_SYMBOL(strcmp); | ||
37 | EXPORT_SYMBOL(strncmp); | ||
38 | |||
39 | EXPORT_SYMBOL(ip_fast_csum); | ||
40 | |||
41 | EXPORT_SYMBOL(kernel_thread); | ||
42 | EXPORT_SYMBOL(enable_irq); | ||
43 | EXPORT_SYMBOL(disable_irq); | ||
44 | |||
45 | /* Networking helper routines. */ | ||
46 | EXPORT_SYMBOL(csum_partial_copy); | ||
47 | |||
48 | /* The following are special because they're not called | ||
49 | explicitly (the C compiler generates them). Fortunately, | ||
50 | their interface isn't gonna change any time soon now, so | ||
51 | it's OK to leave it out of version control. */ | ||
52 | //EXPORT_SYMBOL(__ashrdi3); | ||
53 | //EXPORT_SYMBOL(__lshrdi3); | ||
54 | EXPORT_SYMBOL(memcpy); | ||
55 | EXPORT_SYMBOL(memset); | ||
56 | EXPORT_SYMBOL(memcmp); | ||
57 | EXPORT_SYMBOL(memscan); | ||
58 | EXPORT_SYMBOL(memmove); | ||
59 | |||
60 | EXPORT_SYMBOL(get_wchan); | ||
61 | |||
62 | /* | ||
63 | * libgcc functions - functions that are used internally by the | ||
64 | * compiler... (prototypes are not correct though, but that | ||
65 | * doesn't really matter since they're not versioned). | ||
66 | */ | ||
67 | extern void __gcc_bcmp(void); | ||
68 | extern void __ashldi3(void); | ||
69 | extern void __ashrdi3(void); | ||
70 | extern void __cmpdi2(void); | ||
71 | extern void __divdi3(void); | ||
72 | extern void __divsi3(void); | ||
73 | extern void __lshrdi3(void); | ||
74 | extern void __moddi3(void); | ||
75 | extern void __modsi3(void); | ||
76 | extern void __muldi3(void); | ||
77 | extern void __mulsi3(void); | ||
78 | extern void __negdi2(void); | ||
79 | extern void __ucmpdi2(void); | ||
80 | extern void __udivdi3(void); | ||
81 | extern void __udivmoddi4(void); | ||
82 | extern void __udivsi3(void); | ||
83 | extern void __umoddi3(void); | ||
84 | extern void __umodsi3(void); | ||
85 | |||
86 | /* gcc lib functions */ | ||
87 | EXPORT_SYMBOL(__gcc_bcmp); | ||
88 | EXPORT_SYMBOL(__ashldi3); | ||
89 | EXPORT_SYMBOL(__ashrdi3); | ||
90 | EXPORT_SYMBOL(__cmpdi2); | ||
91 | EXPORT_SYMBOL(__divdi3); | ||
92 | EXPORT_SYMBOL(__divsi3); | ||
93 | EXPORT_SYMBOL(__lshrdi3); | ||
94 | EXPORT_SYMBOL(__moddi3); | ||
95 | EXPORT_SYMBOL(__modsi3); | ||
96 | EXPORT_SYMBOL(__muldi3); | ||
97 | EXPORT_SYMBOL(__mulsi3); | ||
98 | EXPORT_SYMBOL(__negdi2); | ||
99 | EXPORT_SYMBOL(__ucmpdi2); | ||
100 | EXPORT_SYMBOL(__udivdi3); | ||
101 | EXPORT_SYMBOL(__udivmoddi4); | ||
102 | EXPORT_SYMBOL(__udivsi3); | ||
103 | EXPORT_SYMBOL(__umoddi3); | ||
104 | EXPORT_SYMBOL(__umodsi3); | ||
105 | |||
106 | #ifdef MAGIC_ROM_PTR | ||
107 | EXPORT_SYMBOL(is_in_rom); | ||
108 | #endif | ||
109 | |||
110 | EXPORT_SYMBOL(h8300_reserved_gpio); | ||
111 | EXPORT_SYMBOL(h8300_free_gpio); | ||
112 | EXPORT_SYMBOL(h8300_set_gpio_dir); | ||
diff --git a/arch/h8300/kernel/init_task.c b/arch/h8300/kernel/init_task.c new file mode 100644 index 000000000000..19272c2ac56a --- /dev/null +++ b/arch/h8300/kernel/init_task.c | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/kernel/init_task.c | ||
3 | */ | ||
4 | #include <linux/mm.h> | ||
5 | #include <linux/module.h> | ||
6 | #include <linux/sched.h> | ||
7 | #include <linux/init.h> | ||
8 | #include <linux/init_task.h> | ||
9 | #include <linux/fs.h> | ||
10 | #include <linux/mqueue.h> | ||
11 | |||
12 | #include <asm/uaccess.h> | ||
13 | #include <asm/pgtable.h> | ||
14 | |||
15 | static struct fs_struct init_fs = INIT_FS; | ||
16 | static struct files_struct init_files = INIT_FILES; | ||
17 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | ||
18 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | ||
19 | struct mm_struct init_mm = INIT_MM(init_mm); | ||
20 | |||
21 | EXPORT_SYMBOL(init_mm); | ||
22 | |||
23 | /* | ||
24 | * Initial task structure. | ||
25 | * | ||
26 | * All other task structs will be allocated on slabs in fork.c | ||
27 | */ | ||
28 | __asm__(".align 4"); | ||
29 | struct task_struct init_task = INIT_TASK(init_task); | ||
30 | |||
31 | EXPORT_SYMBOL(init_task); | ||
32 | |||
33 | /* | ||
34 | * Initial thread structure. | ||
35 | * | ||
36 | * We need to make sure that this is 8192-byte aligned due to the | ||
37 | * way process stacks are handled. This is done by having a special | ||
38 | * "init_task" linker map entry.. | ||
39 | */ | ||
40 | union thread_union init_thread_union | ||
41 | __attribute__((__section__(".data.init_task"))) = | ||
42 | { INIT_THREAD_INFO(init_task) }; | ||
43 | |||
diff --git a/arch/h8300/kernel/ints.c b/arch/h8300/kernel/ints.c new file mode 100644 index 000000000000..edb3c4170013 --- /dev/null +++ b/arch/h8300/kernel/ints.c | |||
@@ -0,0 +1,255 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/platform/h8300h/ints.c | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
5 | * | ||
6 | * Based on linux/arch/$(ARCH)/platform/$(PLATFORM)/ints.c | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General Public | ||
9 | * License. See the file COPYING in the main directory of this archive | ||
10 | * for more details. | ||
11 | * | ||
12 | * Copyright 1996 Roman Zippel | ||
13 | * Copyright 1999 D. Jeff Dionne <jeff@rt-control.com> | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/types.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/kernel_stat.h> | ||
21 | #include <linux/seq_file.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/random.h> | ||
24 | #include <linux/bootmem.h> | ||
25 | #include <linux/hardirq.h> | ||
26 | |||
27 | #include <asm/system.h> | ||
28 | #include <asm/irq.h> | ||
29 | #include <asm/traps.h> | ||
30 | #include <asm/io.h> | ||
31 | #include <asm/setup.h> | ||
32 | #include <asm/errno.h> | ||
33 | |||
34 | /* | ||
35 | * This structure has only 4 elements for speed reasons | ||
36 | */ | ||
37 | typedef struct irq_handler { | ||
38 | irqreturn_t (*handler)(int, void *, struct pt_regs *); | ||
39 | int flags; | ||
40 | int count; | ||
41 | void *dev_id; | ||
42 | const char *devname; | ||
43 | } irq_handler_t; | ||
44 | |||
45 | static irq_handler_t *irq_list[NR_IRQS]; | ||
46 | static int use_kmalloc; | ||
47 | |||
48 | extern unsigned long *interrupt_redirect_table; | ||
49 | extern const int h8300_saved_vectors[]; | ||
50 | extern const unsigned long h8300_trap_table[]; | ||
51 | int h8300_enable_irq_pin(unsigned int irq); | ||
52 | void h8300_disable_irq_pin(unsigned int irq); | ||
53 | |||
54 | #define CPU_VECTOR ((unsigned long *)0x000000) | ||
55 | #define ADDR_MASK (0xffffff) | ||
56 | |||
57 | #if defined(CONFIG_RAMKERNEL) | ||
58 | static unsigned long __init *get_vector_address(void) | ||
59 | { | ||
60 | unsigned long *rom_vector = CPU_VECTOR; | ||
61 | unsigned long base,tmp; | ||
62 | int vec_no; | ||
63 | |||
64 | base = rom_vector[EXT_IRQ0] & ADDR_MASK; | ||
65 | |||
66 | /* check romvector format */ | ||
67 | for (vec_no = EXT_IRQ1; vec_no <= EXT_IRQ0+EXT_IRQS; vec_no++) { | ||
68 | if ((base+(vec_no - EXT_IRQ0)*4) != (rom_vector[vec_no] & ADDR_MASK)) | ||
69 | return NULL; | ||
70 | } | ||
71 | |||
72 | /* ramvector base address */ | ||
73 | base -= EXT_IRQ0*4; | ||
74 | |||
75 | /* writerble check */ | ||
76 | tmp = ~(*(volatile unsigned long *)base); | ||
77 | (*(volatile unsigned long *)base) = tmp; | ||
78 | if ((*(volatile unsigned long *)base) != tmp) | ||
79 | return NULL; | ||
80 | return (unsigned long *)base; | ||
81 | } | ||
82 | #endif | ||
83 | |||
84 | void __init init_IRQ(void) | ||
85 | { | ||
86 | #if defined(CONFIG_RAMKERNEL) | ||
87 | int i; | ||
88 | unsigned long *ramvec,*ramvec_p; | ||
89 | const unsigned long *trap_entry; | ||
90 | const int *saved_vector; | ||
91 | |||
92 | ramvec = get_vector_address(); | ||
93 | if (ramvec == NULL) | ||
94 | panic("interrupt vector serup failed."); | ||
95 | else | ||
96 | printk(KERN_INFO "virtual vector at 0x%08lx\n",(unsigned long)ramvec); | ||
97 | |||
98 | /* create redirect table */ | ||
99 | ramvec_p = ramvec; | ||
100 | trap_entry = h8300_trap_table; | ||
101 | saved_vector = h8300_saved_vectors; | ||
102 | for ( i = 0; i < NR_IRQS; i++) { | ||
103 | if (i == *saved_vector) { | ||
104 | ramvec_p++; | ||
105 | saved_vector++; | ||
106 | } else { | ||
107 | if ( i < NR_TRAPS ) { | ||
108 | if (*trap_entry) | ||
109 | *ramvec_p = VECTOR(*trap_entry); | ||
110 | ramvec_p++; | ||
111 | trap_entry++; | ||
112 | } else | ||
113 | *ramvec_p++ = REDIRECT(interrupt_entry); | ||
114 | } | ||
115 | } | ||
116 | interrupt_redirect_table = ramvec; | ||
117 | #ifdef DUMP_VECTOR | ||
118 | ramvec_p = ramvec; | ||
119 | for (i = 0; i < NR_IRQS; i++) { | ||
120 | if ((i % 8) == 0) | ||
121 | printk(KERN_DEBUG "\n%p: ",ramvec_p); | ||
122 | printk(KERN_DEBUG "%p ",*ramvec_p); | ||
123 | ramvec_p++; | ||
124 | } | ||
125 | printk(KERN_DEBUG "\n"); | ||
126 | #endif | ||
127 | #endif | ||
128 | } | ||
129 | |||
130 | int request_irq(unsigned int irq, | ||
131 | irqreturn_t (*handler)(int, void *, struct pt_regs *), | ||
132 | unsigned long flags, const char *devname, void *dev_id) | ||
133 | { | ||
134 | irq_handler_t *irq_handle; | ||
135 | if (irq < 0 || irq >= NR_IRQS) { | ||
136 | printk(KERN_ERR "Incorrect IRQ %d from %s\n", irq, devname); | ||
137 | return -EINVAL; | ||
138 | } | ||
139 | |||
140 | if (irq_list[irq] || (h8300_enable_irq_pin(irq) == -EBUSY)) | ||
141 | return -EBUSY; | ||
142 | |||
143 | if (use_kmalloc) | ||
144 | irq_handle = (irq_handler_t *)kmalloc(sizeof(irq_handler_t), GFP_ATOMIC); | ||
145 | else { | ||
146 | /* use bootmem allocater */ | ||
147 | irq_handle = (irq_handler_t *)alloc_bootmem(sizeof(irq_handler_t)); | ||
148 | irq_handle = (irq_handler_t *)((unsigned long)irq_handle | 0x80000000); | ||
149 | } | ||
150 | |||
151 | if (irq_handle == NULL) | ||
152 | return -ENOMEM; | ||
153 | |||
154 | irq_handle->handler = handler; | ||
155 | irq_handle->flags = flags; | ||
156 | irq_handle->count = 0; | ||
157 | irq_handle->dev_id = dev_id; | ||
158 | irq_handle->devname = devname; | ||
159 | irq_list[irq] = irq_handle; | ||
160 | |||
161 | if (irq_handle->flags & SA_SAMPLE_RANDOM) | ||
162 | rand_initialize_irq(irq); | ||
163 | |||
164 | enable_irq(irq); | ||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | EXPORT_SYMBOL(request_irq); | ||
169 | |||
170 | void free_irq(unsigned int irq, void *dev_id) | ||
171 | { | ||
172 | if (irq >= NR_IRQS) | ||
173 | return; | ||
174 | |||
175 | if (!irq_list[irq] || irq_list[irq]->dev_id != dev_id) | ||
176 | printk(KERN_WARNING "Removing probably wrong IRQ %d from %s\n", | ||
177 | irq, irq_list[irq]->devname); | ||
178 | disable_irq(irq); | ||
179 | h8300_disable_irq_pin(irq); | ||
180 | if (((unsigned long)irq_list[irq] & 0x80000000) == 0) { | ||
181 | kfree(irq_list[irq]); | ||
182 | irq_list[irq] = NULL; | ||
183 | } | ||
184 | } | ||
185 | |||
186 | EXPORT_SYMBOL(free_irq); | ||
187 | |||
188 | /* | ||
189 | * Do we need these probe functions on the m68k? | ||
190 | */ | ||
191 | unsigned long probe_irq_on (void) | ||
192 | { | ||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | EXPORT_SYMBOL(probe_irq_on); | ||
197 | |||
198 | int probe_irq_off (unsigned long irqs) | ||
199 | { | ||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | EXPORT_SYMBOL(probe_irq_off); | ||
204 | |||
205 | void enable_irq(unsigned int irq) | ||
206 | { | ||
207 | if (irq >= EXT_IRQ0 && irq <= (EXT_IRQ0 + EXT_IRQS)) | ||
208 | IER_REGS |= 1 << (irq - EXT_IRQ0); | ||
209 | } | ||
210 | |||
211 | void disable_irq(unsigned int irq) | ||
212 | { | ||
213 | if (irq >= EXT_IRQ0 && irq <= (EXT_IRQ0 + EXT_IRQS)) | ||
214 | IER_REGS &= ~(1 << (irq - EXT_IRQ0)); | ||
215 | } | ||
216 | |||
217 | asmlinkage void process_int(int irq, struct pt_regs *fp) | ||
218 | { | ||
219 | irq_enter(); | ||
220 | h8300_clear_isr(irq); | ||
221 | if (irq >= NR_TRAPS && irq < NR_IRQS) { | ||
222 | if (irq_list[irq]) { | ||
223 | irq_list[irq]->handler(irq, irq_list[irq]->dev_id, fp); | ||
224 | irq_list[irq]->count++; | ||
225 | if (irq_list[irq]->flags & SA_SAMPLE_RANDOM) | ||
226 | add_interrupt_randomness(irq); | ||
227 | } | ||
228 | } else { | ||
229 | BUG(); | ||
230 | } | ||
231 | irq_exit(); | ||
232 | } | ||
233 | |||
234 | int show_interrupts(struct seq_file *p, void *v) | ||
235 | { | ||
236 | int i = *(loff_t *) v; | ||
237 | |||
238 | if ((i < NR_IRQS) && (irq_list[i]!=NULL)) { | ||
239 | seq_printf(p, "%3d: %10u ",i,irq_list[i]->count); | ||
240 | seq_printf(p, "%s\n", irq_list[i]->devname); | ||
241 | } | ||
242 | |||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | void init_irq_proc(void) | ||
247 | { | ||
248 | } | ||
249 | |||
250 | static int __init enable_kmalloc(void) | ||
251 | { | ||
252 | use_kmalloc = 1; | ||
253 | return 0; | ||
254 | } | ||
255 | core_initcall(enable_kmalloc); | ||
diff --git a/arch/h8300/kernel/module.c b/arch/h8300/kernel/module.c new file mode 100644 index 000000000000..4fd7138a6e03 --- /dev/null +++ b/arch/h8300/kernel/module.c | |||
@@ -0,0 +1,122 @@ | |||
1 | #include <linux/moduleloader.h> | ||
2 | #include <linux/elf.h> | ||
3 | #include <linux/vmalloc.h> | ||
4 | #include <linux/fs.h> | ||
5 | #include <linux/string.h> | ||
6 | #include <linux/kernel.h> | ||
7 | |||
8 | #if 0 | ||
9 | #define DEBUGP printk | ||
10 | #else | ||
11 | #define DEBUGP(fmt...) | ||
12 | #endif | ||
13 | |||
14 | void *module_alloc(unsigned long size) | ||
15 | { | ||
16 | if (size == 0) | ||
17 | return NULL; | ||
18 | return vmalloc(size); | ||
19 | } | ||
20 | |||
21 | |||
22 | /* Free memory returned from module_alloc */ | ||
23 | void module_free(struct module *mod, void *module_region) | ||
24 | { | ||
25 | vfree(module_region); | ||
26 | /* FIXME: If module_region == mod->init_region, trim exception | ||
27 | table entries. */ | ||
28 | } | ||
29 | |||
30 | /* We don't need anything special. */ | ||
31 | int module_frob_arch_sections(Elf_Ehdr *hdr, | ||
32 | Elf_Shdr *sechdrs, | ||
33 | char *secstrings, | ||
34 | struct module *mod) | ||
35 | { | ||
36 | return 0; | ||
37 | } | ||
38 | |||
39 | int apply_relocate(Elf32_Shdr *sechdrs, | ||
40 | const char *strtab, | ||
41 | unsigned int symindex, | ||
42 | unsigned int relsec, | ||
43 | struct module *me) | ||
44 | { | ||
45 | printk(KERN_ERR "module %s: RELOCATION unsupported\n", | ||
46 | me->name); | ||
47 | return -ENOEXEC; | ||
48 | } | ||
49 | |||
50 | int apply_relocate_add(Elf32_Shdr *sechdrs, | ||
51 | const char *strtab, | ||
52 | unsigned int symindex, | ||
53 | unsigned int relsec, | ||
54 | struct module *me) | ||
55 | { | ||
56 | unsigned int i; | ||
57 | Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; | ||
58 | |||
59 | DEBUGP("Applying relocate section %u to %u\n", relsec, | ||
60 | sechdrs[relsec].sh_info); | ||
61 | for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) { | ||
62 | /* This is where to make the change */ | ||
63 | uint32_t *loc = (uint32_t *)(sechdrs[sechdrs[relsec].sh_info].sh_addr | ||
64 | + rela[i].r_offset); | ||
65 | /* This is the symbol it is referring to. Note that all | ||
66 | undefined symbols have been resolved. */ | ||
67 | Elf32_Sym *sym = (Elf32_Sym *)sechdrs[symindex].sh_addr | ||
68 | + ELF32_R_SYM(rela[i].r_info); | ||
69 | uint32_t v = sym->st_value + rela[i].r_addend; | ||
70 | |||
71 | switch (ELF32_R_TYPE(rela[i].r_info)) { | ||
72 | case R_H8_DIR24R8: | ||
73 | loc = (uint32_t *)((uint32_t)loc - 1); | ||
74 | *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v); | ||
75 | break; | ||
76 | case R_H8_DIR24A8: | ||
77 | if (ELF32_R_SYM(rela[i].r_info)) | ||
78 | *loc += v; | ||
79 | break; | ||
80 | case R_H8_DIR32: | ||
81 | case R_H8_DIR32A16: | ||
82 | *loc += v; | ||
83 | break; | ||
84 | case R_H8_PCREL16: | ||
85 | v -= (unsigned long)loc + 2; | ||
86 | if ((Elf32_Sword)v > 0x7fff || | ||
87 | (Elf32_Sword)v < -(Elf32_Sword)0x8000) | ||
88 | goto overflow; | ||
89 | else | ||
90 | *(unsigned short *)loc = v; | ||
91 | break; | ||
92 | case R_H8_PCREL8: | ||
93 | v -= (unsigned long)loc + 1; | ||
94 | if ((Elf32_Sword)v > 0x7f || | ||
95 | (Elf32_Sword)v < -(Elf32_Sword)0x80) | ||
96 | goto overflow; | ||
97 | else | ||
98 | *(unsigned char *)loc = v; | ||
99 | break; | ||
100 | default: | ||
101 | printk(KERN_ERR "module %s: Unknown relocation: %u\n", | ||
102 | me->name, ELF32_R_TYPE(rela[i].r_info)); | ||
103 | return -ENOEXEC; | ||
104 | } | ||
105 | } | ||
106 | return 0; | ||
107 | overflow: | ||
108 | printk(KERN_ERR "module %s: relocation offset overflow: %08x\n", | ||
109 | me->name, rela[i].r_offset); | ||
110 | return -ENOEXEC; | ||
111 | } | ||
112 | |||
113 | int module_finalize(const Elf_Ehdr *hdr, | ||
114 | const Elf_Shdr *sechdrs, | ||
115 | struct module *me) | ||
116 | { | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | void module_arch_cleanup(struct module *mod) | ||
121 | { | ||
122 | } | ||
diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c new file mode 100644 index 000000000000..134aec1c6d19 --- /dev/null +++ b/arch/h8300/kernel/process.c | |||
@@ -0,0 +1,288 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/kernel/process.c | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
5 | * | ||
6 | * Based on: | ||
7 | * | ||
8 | * linux/arch/m68knommu/kernel/process.c | ||
9 | * | ||
10 | * Copyright (C) 1998 D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca>, | ||
11 | * Kenneth Albanowski <kjahds@kjahds.com>, | ||
12 | * The Silver Hammer Group, Ltd. | ||
13 | * | ||
14 | * linux/arch/m68k/kernel/process.c | ||
15 | * | ||
16 | * Copyright (C) 1995 Hamish Macdonald | ||
17 | * | ||
18 | * 68060 fixes by Jesper Skov | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | * This file handles the architecture-dependent parts of process handling.. | ||
23 | */ | ||
24 | |||
25 | #include <linux/config.h> | ||
26 | #include <linux/errno.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/sched.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/mm.h> | ||
31 | #include <linux/smp.h> | ||
32 | #include <linux/smp_lock.h> | ||
33 | #include <linux/stddef.h> | ||
34 | #include <linux/unistd.h> | ||
35 | #include <linux/ptrace.h> | ||
36 | #include <linux/slab.h> | ||
37 | #include <linux/user.h> | ||
38 | #include <linux/a.out.h> | ||
39 | #include <linux/interrupt.h> | ||
40 | #include <linux/reboot.h> | ||
41 | |||
42 | #include <asm/uaccess.h> | ||
43 | #include <asm/system.h> | ||
44 | #include <asm/traps.h> | ||
45 | #include <asm/setup.h> | ||
46 | #include <asm/pgtable.h> | ||
47 | |||
48 | asmlinkage void ret_from_fork(void); | ||
49 | |||
50 | /* | ||
51 | * The idle loop on an H8/300.. | ||
52 | */ | ||
53 | #if !defined(CONFIG_H8300H_SIM) && !defined(CONFIG_H8S_SIM) | ||
54 | void default_idle(void) | ||
55 | { | ||
56 | while(1) { | ||
57 | if (need_resched()) { | ||
58 | local_irq_enable(); | ||
59 | __asm__("sleep"); | ||
60 | local_irq_disable(); | ||
61 | } | ||
62 | schedule(); | ||
63 | } | ||
64 | } | ||
65 | #else | ||
66 | void default_idle(void) | ||
67 | { | ||
68 | while(1) { | ||
69 | if (need_resched()) | ||
70 | schedule(); | ||
71 | } | ||
72 | } | ||
73 | #endif | ||
74 | void (*idle)(void) = default_idle; | ||
75 | |||
76 | /* | ||
77 | * The idle thread. There's no useful work to be | ||
78 | * done, so just try to conserve power and have a | ||
79 | * low exit latency (ie sit in a loop waiting for | ||
80 | * somebody to say that they'd like to reschedule) | ||
81 | */ | ||
82 | void cpu_idle(void) | ||
83 | { | ||
84 | idle(); | ||
85 | } | ||
86 | |||
87 | void machine_restart(char * __unused) | ||
88 | { | ||
89 | local_irq_disable(); | ||
90 | __asm__("jmp @@0"); | ||
91 | } | ||
92 | |||
93 | EXPORT_SYMBOL(machine_restart); | ||
94 | |||
95 | void machine_halt(void) | ||
96 | { | ||
97 | local_irq_disable(); | ||
98 | __asm__("sleep"); | ||
99 | for (;;); | ||
100 | } | ||
101 | |||
102 | EXPORT_SYMBOL(machine_halt); | ||
103 | |||
104 | void machine_power_off(void) | ||
105 | { | ||
106 | local_irq_disable(); | ||
107 | __asm__("sleep"); | ||
108 | for (;;); | ||
109 | } | ||
110 | |||
111 | EXPORT_SYMBOL(machine_power_off); | ||
112 | |||
113 | void show_regs(struct pt_regs * regs) | ||
114 | { | ||
115 | printk("\nPC: %08lx Status: %02x", | ||
116 | regs->pc, regs->ccr); | ||
117 | printk("\nORIG_ER0: %08lx ER0: %08lx ER1: %08lx", | ||
118 | regs->orig_er0, regs->er0, regs->er1); | ||
119 | printk("\nER2: %08lx ER3: %08lx ER4: %08lx ER5: %08lx", | ||
120 | regs->er2, regs->er3, regs->er4, regs->er5); | ||
121 | printk("\nER6' %08lx ",regs->er6); | ||
122 | if (user_mode(regs)) | ||
123 | printk("USP: %08lx\n", rdusp()); | ||
124 | else | ||
125 | printk("\n"); | ||
126 | } | ||
127 | |||
128 | /* | ||
129 | * Create a kernel thread | ||
130 | */ | ||
131 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
132 | { | ||
133 | long retval; | ||
134 | long clone_arg; | ||
135 | mm_segment_t fs; | ||
136 | |||
137 | fs = get_fs(); | ||
138 | set_fs (KERNEL_DS); | ||
139 | clone_arg = flags | CLONE_VM; | ||
140 | __asm__("mov.l sp,er3\n\t" | ||
141 | "sub.l er2,er2\n\t" | ||
142 | "mov.l %2,er1\n\t" | ||
143 | "mov.l %1,er0\n\t" | ||
144 | "trapa #0\n\t" | ||
145 | "cmp.l sp,er3\n\t" | ||
146 | "beq 1f\n\t" | ||
147 | "mov.l %4,er0\n\t" | ||
148 | "mov.l %3,er1\n\t" | ||
149 | "jsr @er1\n\t" | ||
150 | "mov.l %5,er0\n\t" | ||
151 | "trapa #0\n" | ||
152 | "1:\n\t" | ||
153 | "mov.l er0,%0" | ||
154 | :"=r"(retval) | ||
155 | :"i"(__NR_clone),"g"(clone_arg),"g"(fn),"g"(arg),"i"(__NR_exit) | ||
156 | :"er0","er1","er2","er3"); | ||
157 | set_fs (fs); | ||
158 | return retval; | ||
159 | } | ||
160 | |||
161 | void flush_thread(void) | ||
162 | { | ||
163 | } | ||
164 | |||
165 | /* | ||
166 | * "h8300_fork()".. By the time we get here, the | ||
167 | * non-volatile registers have also been saved on the | ||
168 | * stack. We do some ugly pointer stuff here.. (see | ||
169 | * also copy_thread) | ||
170 | */ | ||
171 | |||
172 | asmlinkage int h8300_fork(struct pt_regs *regs) | ||
173 | { | ||
174 | return -EINVAL; | ||
175 | } | ||
176 | |||
177 | asmlinkage int h8300_vfork(struct pt_regs *regs) | ||
178 | { | ||
179 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL); | ||
180 | } | ||
181 | |||
182 | asmlinkage int h8300_clone(struct pt_regs *regs) | ||
183 | { | ||
184 | unsigned long clone_flags; | ||
185 | unsigned long newsp; | ||
186 | |||
187 | /* syscall2 puts clone_flags in er1 and usp in er2 */ | ||
188 | clone_flags = regs->er1; | ||
189 | newsp = regs->er2; | ||
190 | if (!newsp) | ||
191 | newsp = rdusp(); | ||
192 | return do_fork(clone_flags, newsp, regs, 0, NULL, NULL); | ||
193 | |||
194 | } | ||
195 | |||
196 | int copy_thread(int nr, unsigned long clone_flags, | ||
197 | unsigned long usp, unsigned long topstk, | ||
198 | struct task_struct * p, struct pt_regs * regs) | ||
199 | { | ||
200 | struct pt_regs * childregs; | ||
201 | |||
202 | childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1; | ||
203 | |||
204 | *childregs = *regs; | ||
205 | childregs->retpc = (unsigned long) ret_from_fork; | ||
206 | childregs->er0 = 0; | ||
207 | |||
208 | p->thread.usp = usp; | ||
209 | p->thread.ksp = (unsigned long)childregs; | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | /* | ||
215 | * fill in the user structure for a core dump.. | ||
216 | */ | ||
217 | void dump_thread(struct pt_regs * regs, struct user * dump) | ||
218 | { | ||
219 | /* changed the size calculations - should hopefully work better. lbt */ | ||
220 | dump->magic = CMAGIC; | ||
221 | dump->start_code = 0; | ||
222 | dump->start_stack = rdusp() & ~(PAGE_SIZE - 1); | ||
223 | dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT; | ||
224 | dump->u_dsize = ((unsigned long) (current->mm->brk + | ||
225 | (PAGE_SIZE-1))) >> PAGE_SHIFT; | ||
226 | dump->u_dsize -= dump->u_tsize; | ||
227 | dump->u_ssize = 0; | ||
228 | |||
229 | dump->u_ar0 = (struct user_regs_struct *)(((int)(&dump->regs)) -((int)(dump))); | ||
230 | dump->regs.er0 = regs->er0; | ||
231 | dump->regs.er1 = regs->er1; | ||
232 | dump->regs.er2 = regs->er2; | ||
233 | dump->regs.er3 = regs->er3; | ||
234 | dump->regs.er4 = regs->er4; | ||
235 | dump->regs.er5 = regs->er5; | ||
236 | dump->regs.er6 = regs->er6; | ||
237 | dump->regs.orig_er0 = regs->orig_er0; | ||
238 | dump->regs.ccr = regs->ccr; | ||
239 | dump->regs.pc = regs->pc; | ||
240 | } | ||
241 | |||
242 | /* | ||
243 | * sys_execve() executes a new program. | ||
244 | */ | ||
245 | asmlinkage int sys_execve(char *name, char **argv, char **envp,int dummy,...) | ||
246 | { | ||
247 | int error; | ||
248 | char * filename; | ||
249 | struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4); | ||
250 | |||
251 | lock_kernel(); | ||
252 | filename = getname(name); | ||
253 | error = PTR_ERR(filename); | ||
254 | if (IS_ERR(filename)) | ||
255 | goto out; | ||
256 | error = do_execve(filename, argv, envp, regs); | ||
257 | putname(filename); | ||
258 | out: | ||
259 | unlock_kernel(); | ||
260 | return error; | ||
261 | } | ||
262 | |||
263 | unsigned long thread_saved_pc(struct task_struct *tsk) | ||
264 | { | ||
265 | return ((struct pt_regs *)tsk->thread.esp0)->pc; | ||
266 | } | ||
267 | |||
268 | unsigned long get_wchan(struct task_struct *p) | ||
269 | { | ||
270 | unsigned long fp, pc; | ||
271 | unsigned long stack_page; | ||
272 | int count = 0; | ||
273 | if (!p || p == current || p->state == TASK_RUNNING) | ||
274 | return 0; | ||
275 | |||
276 | stack_page = (unsigned long)p; | ||
277 | fp = ((struct pt_regs *)p->thread.ksp)->er6; | ||
278 | do { | ||
279 | if (fp < stack_page+sizeof(struct thread_info) || | ||
280 | fp >= 8184+stack_page) | ||
281 | return 0; | ||
282 | pc = ((unsigned long *)fp)[1]; | ||
283 | if (!in_sched_functions(pc)) | ||
284 | return pc; | ||
285 | fp = *(unsigned long *) fp; | ||
286 | } while (count++ < 16); | ||
287 | return 0; | ||
288 | } | ||
diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c new file mode 100644 index 000000000000..5f19d774a288 --- /dev/null +++ b/arch/h8300/kernel/ptrace.c | |||
@@ -0,0 +1,277 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/kernel/ptrace.c | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
5 | * | ||
6 | * Based on: | ||
7 | * linux/arch/m68k/kernel/ptrace.c | ||
8 | * | ||
9 | * Copyright (C) 1994 by Hamish Macdonald | ||
10 | * Taken from linux/kernel/ptrace.c and modified for M680x0. | ||
11 | * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds | ||
12 | * | ||
13 | * This file is subject to the terms and conditions of the GNU General | ||
14 | * Public License. See the file COPYING in the main directory of | ||
15 | * this archive for more details. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/mm.h> | ||
21 | #include <linux/smp.h> | ||
22 | #include <linux/smp_lock.h> | ||
23 | #include <linux/errno.h> | ||
24 | #include <linux/ptrace.h> | ||
25 | #include <linux/user.h> | ||
26 | #include <linux/config.h> | ||
27 | |||
28 | #include <asm/uaccess.h> | ||
29 | #include <asm/page.h> | ||
30 | #include <asm/pgtable.h> | ||
31 | #include <asm/system.h> | ||
32 | #include <asm/processor.h> | ||
33 | #include <asm/signal.h> | ||
34 | |||
35 | /* cpu depend functions */ | ||
36 | extern long h8300_get_reg(struct task_struct *task, int regno); | ||
37 | extern int h8300_put_reg(struct task_struct *task, int regno, unsigned long data); | ||
38 | extern void h8300_disable_trace(struct task_struct *child); | ||
39 | extern void h8300_enable_trace(struct task_struct *child); | ||
40 | |||
41 | /* | ||
42 | * does not yet catch signals sent when the child dies. | ||
43 | * in exit.c or in signal.c. | ||
44 | */ | ||
45 | |||
46 | inline | ||
47 | static int read_long(struct task_struct * tsk, unsigned long addr, | ||
48 | unsigned long * result) | ||
49 | { | ||
50 | *result = *(unsigned long *)addr; | ||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | void ptrace_disable(struct task_struct *child) | ||
55 | { | ||
56 | h8300_disable_trace(child); | ||
57 | } | ||
58 | |||
59 | asmlinkage int sys_ptrace(long request, long pid, long addr, long data) | ||
60 | { | ||
61 | struct task_struct *child; | ||
62 | int ret; | ||
63 | |||
64 | lock_kernel(); | ||
65 | ret = -EPERM; | ||
66 | if (request == PTRACE_TRACEME) { | ||
67 | /* are we already being traced? */ | ||
68 | if (current->ptrace & PT_PTRACED) | ||
69 | goto out; | ||
70 | /* set the ptrace bit in the process flags. */ | ||
71 | current->ptrace |= PT_PTRACED; | ||
72 | ret = 0; | ||
73 | goto out; | ||
74 | } | ||
75 | ret = -ESRCH; | ||
76 | read_lock(&tasklist_lock); | ||
77 | child = find_task_by_pid(pid); | ||
78 | if (child) | ||
79 | get_task_struct(child); | ||
80 | read_unlock(&tasklist_lock); | ||
81 | if (!child) | ||
82 | goto out; | ||
83 | |||
84 | ret = -EPERM; | ||
85 | if (pid == 1) /* you may not mess with init */ | ||
86 | goto out_tsk; | ||
87 | |||
88 | if (request == PTRACE_ATTACH) { | ||
89 | ret = ptrace_attach(child); | ||
90 | goto out_tsk; | ||
91 | } | ||
92 | ret = ptrace_check_attach(child, request == PTRACE_KILL); | ||
93 | if (ret < 0) | ||
94 | goto out_tsk; | ||
95 | |||
96 | switch (request) { | ||
97 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | ||
98 | case PTRACE_PEEKDATA: { | ||
99 | unsigned long tmp; | ||
100 | |||
101 | ret = read_long(child, addr, &tmp); | ||
102 | if (ret < 0) | ||
103 | break ; | ||
104 | ret = put_user(tmp, (unsigned long *) data); | ||
105 | break ; | ||
106 | } | ||
107 | |||
108 | /* read the word at location addr in the USER area. */ | ||
109 | case PTRACE_PEEKUSR: { | ||
110 | unsigned long tmp = 0; | ||
111 | |||
112 | if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) { | ||
113 | ret = -EIO; | ||
114 | break ; | ||
115 | } | ||
116 | |||
117 | ret = 0; /* Default return condition */ | ||
118 | addr = addr >> 2; /* temporary hack. */ | ||
119 | |||
120 | if (addr < H8300_REGS_NO) | ||
121 | tmp = h8300_get_reg(child, addr); | ||
122 | else { | ||
123 | switch(addr) { | ||
124 | case 49: | ||
125 | tmp = child->mm->start_code; | ||
126 | break ; | ||
127 | case 50: | ||
128 | tmp = child->mm->start_data; | ||
129 | break ; | ||
130 | case 51: | ||
131 | tmp = child->mm->end_code; | ||
132 | break ; | ||
133 | case 52: | ||
134 | tmp = child->mm->end_data; | ||
135 | break ; | ||
136 | default: | ||
137 | ret = -EIO; | ||
138 | } | ||
139 | } | ||
140 | if (!ret) | ||
141 | ret = put_user(tmp,(unsigned long *) data); | ||
142 | break ; | ||
143 | } | ||
144 | |||
145 | /* when I and D space are separate, this will have to be fixed. */ | ||
146 | case PTRACE_POKETEXT: /* write the word at location addr. */ | ||
147 | case PTRACE_POKEDATA: | ||
148 | ret = 0; | ||
149 | if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) | ||
150 | break; | ||
151 | ret = -EIO; | ||
152 | break; | ||
153 | |||
154 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ | ||
155 | if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) { | ||
156 | ret = -EIO; | ||
157 | break ; | ||
158 | } | ||
159 | addr = addr >> 2; /* temporary hack. */ | ||
160 | |||
161 | if (addr == PT_ORIG_ER0) { | ||
162 | ret = -EIO; | ||
163 | break ; | ||
164 | } | ||
165 | if (addr < H8300_REGS_NO) { | ||
166 | ret = h8300_put_reg(child, addr, data); | ||
167 | break ; | ||
168 | } | ||
169 | ret = -EIO; | ||
170 | break ; | ||
171 | case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ | ||
172 | case PTRACE_CONT: { /* restart after signal. */ | ||
173 | ret = -EIO; | ||
174 | if ((unsigned long) data >= _NSIG) | ||
175 | break ; | ||
176 | if (request == PTRACE_SYSCALL) | ||
177 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
178 | else | ||
179 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
180 | child->exit_code = data; | ||
181 | wake_up_process(child); | ||
182 | /* make sure the single step bit is not set. */ | ||
183 | h8300_disable_trace(child); | ||
184 | ret = 0; | ||
185 | } | ||
186 | |||
187 | /* | ||
188 | * make the child exit. Best I can do is send it a sigkill. | ||
189 | * perhaps it should be put in the status that it wants to | ||
190 | * exit. | ||
191 | */ | ||
192 | case PTRACE_KILL: { | ||
193 | |||
194 | ret = 0; | ||
195 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ | ||
196 | break; | ||
197 | child->exit_code = SIGKILL; | ||
198 | h8300_disable_trace(child); | ||
199 | wake_up_process(child); | ||
200 | break; | ||
201 | } | ||
202 | |||
203 | case PTRACE_SINGLESTEP: { /* set the trap flag. */ | ||
204 | ret = -EIO; | ||
205 | if ((unsigned long) data > _NSIG) | ||
206 | break; | ||
207 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
208 | child->exit_code = data; | ||
209 | h8300_enable_trace(child); | ||
210 | wake_up_process(child); | ||
211 | ret = 0; | ||
212 | break; | ||
213 | } | ||
214 | |||
215 | case PTRACE_DETACH: /* detach a process that was attached. */ | ||
216 | ret = ptrace_detach(child, data); | ||
217 | break; | ||
218 | |||
219 | case PTRACE_GETREGS: { /* Get all gp regs from the child. */ | ||
220 | int i; | ||
221 | unsigned long tmp; | ||
222 | for (i = 0; i < H8300_REGS_NO; i++) { | ||
223 | tmp = h8300_get_reg(child, i); | ||
224 | if (put_user(tmp, (unsigned long *) data)) { | ||
225 | ret = -EFAULT; | ||
226 | break; | ||
227 | } | ||
228 | data += sizeof(long); | ||
229 | } | ||
230 | ret = 0; | ||
231 | break; | ||
232 | } | ||
233 | |||
234 | case PTRACE_SETREGS: { /* Set all gp regs in the child. */ | ||
235 | int i; | ||
236 | unsigned long tmp; | ||
237 | for (i = 0; i < H8300_REGS_NO; i++) { | ||
238 | if (get_user(tmp, (unsigned long *) data)) { | ||
239 | ret = -EFAULT; | ||
240 | break; | ||
241 | } | ||
242 | h8300_put_reg(child, i, tmp); | ||
243 | data += sizeof(long); | ||
244 | } | ||
245 | ret = 0; | ||
246 | break; | ||
247 | } | ||
248 | |||
249 | default: | ||
250 | ret = -EIO; | ||
251 | break; | ||
252 | } | ||
253 | out_tsk: | ||
254 | put_task_struct(child); | ||
255 | out: | ||
256 | unlock_kernel(); | ||
257 | return ret; | ||
258 | } | ||
259 | |||
260 | asmlinkage void syscall_trace(void) | ||
261 | { | ||
262 | if (!test_thread_flag(TIF_SYSCALL_TRACE)) | ||
263 | return; | ||
264 | if (!(current->ptrace & PT_PTRACED)) | ||
265 | return; | ||
266 | ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) | ||
267 | ? 0x80 : 0)); | ||
268 | /* | ||
269 | * this isn't the same as continuing with a signal, but it will do | ||
270 | * for normal use. strace only continues with a signal if the | ||
271 | * stopping signal is not SIGTRAP. -brl | ||
272 | */ | ||
273 | if (current->exit_code) { | ||
274 | send_sig(current->exit_code, current, 1); | ||
275 | current->exit_code = 0; | ||
276 | } | ||
277 | } | ||
diff --git a/arch/h8300/kernel/semaphore.c b/arch/h8300/kernel/semaphore.c new file mode 100644 index 000000000000..1ebb79baaa8c --- /dev/null +++ b/arch/h8300/kernel/semaphore.c | |||
@@ -0,0 +1,133 @@ | |||
1 | /* | ||
2 | * Generic semaphore code. Buyer beware. Do your own | ||
3 | * specific changes in <asm/semaphore-helper.h> | ||
4 | */ | ||
5 | |||
6 | #include <linux/config.h> | ||
7 | #include <linux/sched.h> | ||
8 | #include <linux/init.h> | ||
9 | #include <asm/semaphore-helper.h> | ||
10 | |||
11 | #ifndef CONFIG_RMW_INSNS | ||
12 | spinlock_t semaphore_wake_lock; | ||
13 | #endif | ||
14 | |||
15 | /* | ||
16 | * Semaphores are implemented using a two-way counter: | ||
17 | * The "count" variable is decremented for each process | ||
18 | * that tries to sleep, while the "waking" variable is | ||
19 | * incremented when the "up()" code goes to wake up waiting | ||
20 | * processes. | ||
21 | * | ||
22 | * Notably, the inline "up()" and "down()" functions can | ||
23 | * efficiently test if they need to do any extra work (up | ||
24 | * needs to do something only if count was negative before | ||
25 | * the increment operation. | ||
26 | * | ||
27 | * waking_non_zero() (from asm/semaphore.h) must execute | ||
28 | * atomically. | ||
29 | * | ||
30 | * When __up() is called, the count was negative before | ||
31 | * incrementing it, and we need to wake up somebody. | ||
32 | * | ||
33 | * This routine adds one to the count of processes that need to | ||
34 | * wake up and exit. ALL waiting processes actually wake up but | ||
35 | * only the one that gets to the "waking" field first will gate | ||
36 | * through and acquire the semaphore. The others will go back | ||
37 | * to sleep. | ||
38 | * | ||
39 | * Note that these functions are only called when there is | ||
40 | * contention on the lock, and as such all this is the | ||
41 | * "non-critical" part of the whole semaphore business. The | ||
42 | * critical part is the inline stuff in <asm/semaphore.h> | ||
43 | * where we want to avoid any extra jumps and calls. | ||
44 | */ | ||
45 | void __up(struct semaphore *sem) | ||
46 | { | ||
47 | wake_one_more(sem); | ||
48 | wake_up(&sem->wait); | ||
49 | } | ||
50 | |||
51 | /* | ||
52 | * Perform the "down" function. Return zero for semaphore acquired, | ||
53 | * return negative for signalled out of the function. | ||
54 | * | ||
55 | * If called from __down, the return is ignored and the wait loop is | ||
56 | * not interruptible. This means that a task waiting on a semaphore | ||
57 | * using "down()" cannot be killed until someone does an "up()" on | ||
58 | * the semaphore. | ||
59 | * | ||
60 | * If called from __down_interruptible, the return value gets checked | ||
61 | * upon return. If the return value is negative then the task continues | ||
62 | * with the negative value in the return register (it can be tested by | ||
63 | * the caller). | ||
64 | * | ||
65 | * Either form may be used in conjunction with "up()". | ||
66 | * | ||
67 | */ | ||
68 | |||
69 | |||
70 | #define DOWN_HEAD(task_state) \ | ||
71 | \ | ||
72 | \ | ||
73 | current->state = (task_state); \ | ||
74 | add_wait_queue(&sem->wait, &wait); \ | ||
75 | \ | ||
76 | /* \ | ||
77 | * Ok, we're set up. sem->count is known to be less than zero \ | ||
78 | * so we must wait. \ | ||
79 | * \ | ||
80 | * We can let go the lock for purposes of waiting. \ | ||
81 | * We re-acquire it after awaking so as to protect \ | ||
82 | * all semaphore operations. \ | ||
83 | * \ | ||
84 | * If "up()" is called before we call waking_non_zero() then \ | ||
85 | * we will catch it right away. If it is called later then \ | ||
86 | * we will have to go through a wakeup cycle to catch it. \ | ||
87 | * \ | ||
88 | * Multiple waiters contend for the semaphore lock to see \ | ||
89 | * who gets to gate through and who has to wait some more. \ | ||
90 | */ \ | ||
91 | for (;;) { | ||
92 | |||
93 | #define DOWN_TAIL(task_state) \ | ||
94 | current->state = (task_state); \ | ||
95 | } \ | ||
96 | current->state = TASK_RUNNING; \ | ||
97 | remove_wait_queue(&sem->wait, &wait); | ||
98 | |||
99 | void __sched __down(struct semaphore * sem) | ||
100 | { | ||
101 | DECLARE_WAITQUEUE(wait, current); | ||
102 | |||
103 | DOWN_HEAD(TASK_UNINTERRUPTIBLE) | ||
104 | if (waking_non_zero(sem)) | ||
105 | break; | ||
106 | schedule(); | ||
107 | DOWN_TAIL(TASK_UNINTERRUPTIBLE) | ||
108 | } | ||
109 | |||
110 | int __sched __down_interruptible(struct semaphore * sem) | ||
111 | { | ||
112 | DECLARE_WAITQUEUE(wait, current); | ||
113 | int ret = 0; | ||
114 | |||
115 | DOWN_HEAD(TASK_INTERRUPTIBLE) | ||
116 | |||
117 | ret = waking_non_zero_interruptible(sem, current); | ||
118 | if (ret) | ||
119 | { | ||
120 | if (ret == 1) | ||
121 | /* ret != 0 only if we get interrupted -arca */ | ||
122 | ret = 0; | ||
123 | break; | ||
124 | } | ||
125 | schedule(); | ||
126 | DOWN_TAIL(TASK_INTERRUPTIBLE) | ||
127 | return ret; | ||
128 | } | ||
129 | |||
130 | int __down_trylock(struct semaphore * sem) | ||
131 | { | ||
132 | return waking_non_zero_trylock(sem); | ||
133 | } | ||
diff --git a/arch/h8300/kernel/setup.c b/arch/h8300/kernel/setup.c new file mode 100644 index 000000000000..f469d9160730 --- /dev/null +++ b/arch/h8300/kernel/setup.c | |||
@@ -0,0 +1,248 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/kernel/setup.c | ||
3 | * | ||
4 | * Copyleft ()) 2000 James D. Schettine {james@telos-systems.com} | ||
5 | * Copyright (C) 1999,2000 Greg Ungerer (gerg@snapgear.com) | ||
6 | * Copyright (C) 1998,1999 D. Jeff Dionne <jeff@lineo.ca> | ||
7 | * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com> | ||
8 | * Copyright (C) 1995 Hamish Macdonald | ||
9 | * Copyright (C) 2000 Lineo Inc. (www.lineo.com) | ||
10 | * Copyright (C) 2001 Lineo, Inc. <www.lineo.com> | ||
11 | * | ||
12 | * H8/300 porting Yoshinori Sato <ysato@users.sourceforge.jp> | ||
13 | */ | ||
14 | |||
15 | /* | ||
16 | * This file handles the architecture-dependent parts of system setup | ||
17 | */ | ||
18 | |||
19 | #include <linux/config.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/sched.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/fs.h> | ||
25 | #include <linux/fb.h> | ||
26 | #include <linux/console.h> | ||
27 | #include <linux/genhd.h> | ||
28 | #include <linux/errno.h> | ||
29 | #include <linux/string.h> | ||
30 | #include <linux/major.h> | ||
31 | #include <linux/bootmem.h> | ||
32 | #include <linux/seq_file.h> | ||
33 | #include <linux/init.h> | ||
34 | |||
35 | #include <asm/setup.h> | ||
36 | #include <asm/irq.h> | ||
37 | |||
38 | #ifdef CONFIG_BLK_DEV_INITRD | ||
39 | #include <asm/pgtable.h> | ||
40 | #endif | ||
41 | |||
42 | #if defined(__H8300H__) | ||
43 | #define CPU "H8/300H" | ||
44 | #include <asm/regs306x.h> | ||
45 | #endif | ||
46 | |||
47 | #if defined(__H8300S__) | ||
48 | #define CPU "H8S" | ||
49 | #include <asm/regs267x.h> | ||
50 | #endif | ||
51 | |||
52 | #define STUBSIZE 0xc000; | ||
53 | |||
54 | unsigned long rom_length; | ||
55 | unsigned long memory_start; | ||
56 | unsigned long memory_end; | ||
57 | |||
58 | char command_line[COMMAND_LINE_SIZE]; | ||
59 | |||
60 | extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end; | ||
61 | extern int _ramstart, _ramend; | ||
62 | extern char _target_name[]; | ||
63 | extern void h8300_gpio_init(void); | ||
64 | |||
65 | #if (defined(CONFIG_H8300H_SIM) || defined(CONFIG_H8S_SIM)) \ | ||
66 | && defined(CONFIG_GDB_MAGICPRINT) | ||
67 | /* printk with gdb service */ | ||
68 | static void gdb_console_output(struct console *c, const char *msg, unsigned len) | ||
69 | { | ||
70 | for (; len > 0; len--) { | ||
71 | asm("mov.w %0,r2\n\t" | ||
72 | "jsr @0xc4"::"r"(*msg++):"er2"); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | /* | ||
77 | * Setup initial baud/bits/parity. We do two things here: | ||
78 | * - construct a cflag setting for the first rs_open() | ||
79 | * - initialize the serial port | ||
80 | * Return non-zero if we didn't find a serial port. | ||
81 | */ | ||
82 | static int __init gdb_console_setup(struct console *co, char *options) | ||
83 | { | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static const struct console gdb_console = { | ||
88 | .name = "gdb_con", | ||
89 | .write = gdb_console_output, | ||
90 | .device = NULL, | ||
91 | .setup = gdb_console_setup, | ||
92 | .flags = CON_PRINTBUFFER, | ||
93 | .index = -1, | ||
94 | }; | ||
95 | #endif | ||
96 | |||
97 | void __init setup_arch(char **cmdline_p) | ||
98 | { | ||
99 | int bootmap_size; | ||
100 | |||
101 | memory_start = (unsigned long) &_ramstart; | ||
102 | |||
103 | /* allow for ROMFS on the end of the kernel */ | ||
104 | if (memcmp((void *)memory_start, "-rom1fs-", 8) == 0) { | ||
105 | #if defined(CONFIG_BLK_DEV_INITRD) | ||
106 | initrd_start = memory_start; | ||
107 | initrd_end = memory_start += be32_to_cpu(((unsigned long *) (memory_start))[2]); | ||
108 | #else | ||
109 | memory_start += be32_to_cpu(((unsigned long *) memory_start)[2]); | ||
110 | #endif | ||
111 | } | ||
112 | memory_start = PAGE_ALIGN(memory_start); | ||
113 | #if !defined(CONFIG_BLKDEV_RESERVE) | ||
114 | memory_end = (unsigned long) &_ramend; /* by now the stack is part of the init task */ | ||
115 | #if defined(CONFIG_GDB_DEBUG) | ||
116 | memory_end -= STUBSIZE; | ||
117 | #endif | ||
118 | #else | ||
119 | if ((memory_end < CONFIG_BLKDEV_RESERVE_ADDRESS) && | ||
120 | (memory_end > CONFIG_BLKDEV_RESERVE_ADDRESS) | ||
121 | /* overlap userarea */ | ||
122 | memory_end = CONFIG_BLKDEV_RESERVE_ADDRESS; | ||
123 | #endif | ||
124 | |||
125 | init_mm.start_code = (unsigned long) &_stext; | ||
126 | init_mm.end_code = (unsigned long) &_etext; | ||
127 | init_mm.end_data = (unsigned long) &_edata; | ||
128 | init_mm.brk = (unsigned long) 0; | ||
129 | |||
130 | #if (defined(CONFIG_H8300H_SIM) || defined(CONFIG_H8S_SIM)) && defined(CONFIG_GDB_MAGICPRINT) | ||
131 | register_console((struct console *)&gdb_console); | ||
132 | #endif | ||
133 | |||
134 | printk(KERN_INFO "\r\n\nuClinux " CPU "\n"); | ||
135 | printk(KERN_INFO "Target Hardware: %s\n",_target_name); | ||
136 | printk(KERN_INFO "Flat model support (C) 1998,1999 Kenneth Albanowski, D. Jeff Dionne\n"); | ||
137 | printk(KERN_INFO "H8/300 series support by Yoshinori Sato <ysato@users.sourceforge.jp>\n"); | ||
138 | |||
139 | #ifdef DEBUG | ||
140 | printk(KERN_DEBUG "KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x " | ||
141 | "BSS=0x%06x-0x%06x\n", (int) &_stext, (int) &_etext, | ||
142 | (int) &_sdata, (int) &_edata, | ||
143 | (int) &_sbss, (int) &_ebss); | ||
144 | printk(KERN_DEBUG "KERNEL -> ROMFS=0x%06x-0x%06x MEM=0x%06x-0x%06x " | ||
145 | "STACK=0x%06x-0x%06x\n", | ||
146 | (int) &_ebss, (int) memory_start, | ||
147 | (int) memory_start, (int) memory_end, | ||
148 | (int) memory_end, (int) &_ramend); | ||
149 | #endif | ||
150 | |||
151 | #ifdef CONFIG_DEFAULT_CMDLINE | ||
152 | /* set from default command line */ | ||
153 | if (*command_line == '\0') | ||
154 | strcpy(command_line,CONFIG_KERNEL_COMMAND); | ||
155 | #endif | ||
156 | /* Keep a copy of command line */ | ||
157 | *cmdline_p = &command_line[0]; | ||
158 | memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE); | ||
159 | saved_command_line[COMMAND_LINE_SIZE-1] = 0; | ||
160 | |||
161 | #ifdef DEBUG | ||
162 | if (strlen(*cmdline_p)) | ||
163 | printk(KERN_DEBUG "Command line: '%s'\n", *cmdline_p); | ||
164 | #endif | ||
165 | |||
166 | /* | ||
167 | * give all the memory to the bootmap allocator, tell it to put the | ||
168 | * boot mem_map at the start of memory | ||
169 | */ | ||
170 | bootmap_size = init_bootmem_node( | ||
171 | NODE_DATA(0), | ||
172 | memory_start >> PAGE_SHIFT, /* map goes here */ | ||
173 | PAGE_OFFSET >> PAGE_SHIFT, /* 0 on coldfire */ | ||
174 | memory_end >> PAGE_SHIFT); | ||
175 | /* | ||
176 | * free the usable memory, we have to make sure we do not free | ||
177 | * the bootmem bitmap so we then reserve it after freeing it :-) | ||
178 | */ | ||
179 | free_bootmem(memory_start, memory_end - memory_start); | ||
180 | reserve_bootmem(memory_start, bootmap_size); | ||
181 | /* | ||
182 | * get kmalloc into gear | ||
183 | */ | ||
184 | paging_init(); | ||
185 | h8300_gpio_init(); | ||
186 | #if defined(CONFIG_H8300_AKI3068NET) && defined(CONFIG_IDE) | ||
187 | { | ||
188 | #define AREABIT(addr) (1 << (((addr) >> 21) & 7)) | ||
189 | /* setup BSC */ | ||
190 | volatile unsigned char *abwcr = (volatile unsigned char *)ABWCR; | ||
191 | volatile unsigned char *cscr = (volatile unsigned char *)CSCR; | ||
192 | *abwcr &= ~(AREABIT(CONFIG_H8300_IDE_BASE) | AREABIT(CONFIG_H8300_IDE_ALT)); | ||
193 | *cscr |= (AREABIT(CONFIG_H8300_IDE_BASE) | AREABIT(CONFIG_H8300_IDE_ALT)) | 0x0f; | ||
194 | } | ||
195 | #endif | ||
196 | #ifdef DEBUG | ||
197 | printk(KERN_DEBUG "Done setup_arch\n"); | ||
198 | #endif | ||
199 | } | ||
200 | |||
201 | /* | ||
202 | * Get CPU information for use by the procfs. | ||
203 | */ | ||
204 | |||
205 | static int show_cpuinfo(struct seq_file *m, void *v) | ||
206 | { | ||
207 | char *cpu; | ||
208 | int mode; | ||
209 | u_long clockfreq; | ||
210 | |||
211 | cpu = CPU; | ||
212 | mode = *(volatile unsigned char *)MDCR & 0x07; | ||
213 | |||
214 | clockfreq = CONFIG_CPU_CLOCK; | ||
215 | |||
216 | seq_printf(m, "CPU:\t\t%s (mode:%d)\n" | ||
217 | "Clock:\t\t%lu.%1luMHz\n" | ||
218 | "BogoMips:\t%lu.%02lu\n" | ||
219 | "Calibration:\t%lu loops\n", | ||
220 | cpu,mode, | ||
221 | clockfreq/1000,clockfreq%1000, | ||
222 | (loops_per_jiffy*HZ)/500000,((loops_per_jiffy*HZ)/5000)%100, | ||
223 | (loops_per_jiffy*HZ)); | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | static void *c_start(struct seq_file *m, loff_t *pos) | ||
229 | { | ||
230 | return *pos < NR_CPUS ? ((void *) 0x12345678) : NULL; | ||
231 | } | ||
232 | |||
233 | static void *c_next(struct seq_file *m, void *v, loff_t *pos) | ||
234 | { | ||
235 | ++*pos; | ||
236 | return c_start(m, pos); | ||
237 | } | ||
238 | |||
239 | static void c_stop(struct seq_file *m, void *v) | ||
240 | { | ||
241 | } | ||
242 | |||
243 | struct seq_operations cpuinfo_op = { | ||
244 | .start = c_start, | ||
245 | .next = c_next, | ||
246 | .stop = c_stop, | ||
247 | .show = show_cpuinfo, | ||
248 | }; | ||
diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c new file mode 100644 index 000000000000..a4799d633ef4 --- /dev/null +++ b/arch/h8300/kernel/signal.c | |||
@@ -0,0 +1,552 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/kernel/signal.c | ||
3 | * | ||
4 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file COPYING in the main directory of this archive | ||
8 | * for more details. | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * uClinux H8/300 support by Yoshinori Sato <ysato@users.sourceforge.jp> | ||
13 | * and David McCullough <davidm@snapgear.com> | ||
14 | * | ||
15 | * Based on | ||
16 | * Linux/m68k by Hamish Macdonald | ||
17 | */ | ||
18 | |||
19 | /* | ||
20 | * ++roman (07/09/96): implemented signal stacks (specially for tosemu on | ||
21 | * Atari :-) Current limitation: Only one sigstack can be active at one time. | ||
22 | * If a second signal with SA_ONSTACK set arrives while working on a sigstack, | ||
23 | * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested | ||
24 | * signal handlers! | ||
25 | */ | ||
26 | |||
27 | #include <linux/sched.h> | ||
28 | #include <linux/mm.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/signal.h> | ||
31 | #include <linux/syscalls.h> | ||
32 | #include <linux/errno.h> | ||
33 | #include <linux/wait.h> | ||
34 | #include <linux/ptrace.h> | ||
35 | #include <linux/unistd.h> | ||
36 | #include <linux/stddef.h> | ||
37 | #include <linux/highuid.h> | ||
38 | #include <linux/personality.h> | ||
39 | #include <linux/tty.h> | ||
40 | #include <linux/binfmts.h> | ||
41 | #include <linux/suspend.h> | ||
42 | |||
43 | #include <asm/setup.h> | ||
44 | #include <asm/uaccess.h> | ||
45 | #include <asm/pgtable.h> | ||
46 | #include <asm/traps.h> | ||
47 | #include <asm/ucontext.h> | ||
48 | |||
49 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | ||
50 | |||
51 | asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); | ||
52 | |||
53 | /* | ||
54 | * Atomically swap in the new signal mask, and wait for a signal. | ||
55 | */ | ||
56 | asmlinkage int do_sigsuspend(struct pt_regs *regs) | ||
57 | { | ||
58 | old_sigset_t mask = regs->er3; | ||
59 | sigset_t saveset; | ||
60 | |||
61 | mask &= _BLOCKABLE; | ||
62 | spin_lock_irq(¤t->sighand->siglock); | ||
63 | saveset = current->blocked; | ||
64 | siginitset(¤t->blocked, mask); | ||
65 | recalc_sigpending(); | ||
66 | spin_unlock_irq(¤t->sighand->siglock); | ||
67 | |||
68 | regs->er0 = -EINTR; | ||
69 | while (1) { | ||
70 | current->state = TASK_INTERRUPTIBLE; | ||
71 | schedule(); | ||
72 | if (do_signal(regs, &saveset)) | ||
73 | return -EINTR; | ||
74 | } | ||
75 | } | ||
76 | |||
77 | asmlinkage int | ||
78 | do_rt_sigsuspend(struct pt_regs *regs) | ||
79 | { | ||
80 | sigset_t *unewset = (sigset_t *)regs->er1; | ||
81 | size_t sigsetsize = (size_t)regs->er2; | ||
82 | sigset_t saveset, newset; | ||
83 | |||
84 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
85 | if (sigsetsize != sizeof(sigset_t)) | ||
86 | return -EINVAL; | ||
87 | |||
88 | if (copy_from_user(&newset, unewset, sizeof(newset))) | ||
89 | return -EFAULT; | ||
90 | sigdelsetmask(&newset, ~_BLOCKABLE); | ||
91 | |||
92 | spin_lock_irq(¤t->sighand->siglock); | ||
93 | saveset = current->blocked; | ||
94 | current->blocked = newset; | ||
95 | recalc_sigpending(); | ||
96 | spin_unlock_irq(¤t->sighand->siglock); | ||
97 | |||
98 | regs->er0 = -EINTR; | ||
99 | while (1) { | ||
100 | current->state = TASK_INTERRUPTIBLE; | ||
101 | schedule(); | ||
102 | if (do_signal(regs, &saveset)) | ||
103 | return -EINTR; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | asmlinkage int | ||
108 | sys_sigaction(int sig, const struct old_sigaction *act, | ||
109 | struct old_sigaction *oact) | ||
110 | { | ||
111 | struct k_sigaction new_ka, old_ka; | ||
112 | int ret; | ||
113 | |||
114 | if (act) { | ||
115 | old_sigset_t mask; | ||
116 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || | ||
117 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || | ||
118 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) | ||
119 | return -EFAULT; | ||
120 | __get_user(new_ka.sa.sa_flags, &act->sa_flags); | ||
121 | __get_user(mask, &act->sa_mask); | ||
122 | siginitset(&new_ka.sa.sa_mask, mask); | ||
123 | } | ||
124 | |||
125 | ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); | ||
126 | |||
127 | if (!ret && oact) { | ||
128 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || | ||
129 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || | ||
130 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) | ||
131 | return -EFAULT; | ||
132 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags); | ||
133 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); | ||
134 | } | ||
135 | |||
136 | return ret; | ||
137 | } | ||
138 | |||
139 | asmlinkage int | ||
140 | sys_sigaltstack(const stack_t *uss, stack_t *uoss) | ||
141 | { | ||
142 | return do_sigaltstack(uss, uoss, rdusp()); | ||
143 | } | ||
144 | |||
145 | |||
146 | /* | ||
147 | * Do a signal return; undo the signal stack. | ||
148 | * | ||
149 | * Keep the return code on the stack quadword aligned! | ||
150 | * That makes the cache flush below easier. | ||
151 | */ | ||
152 | |||
153 | struct sigframe | ||
154 | { | ||
155 | long dummy_er0; | ||
156 | long dummy_vector; | ||
157 | #if defined(CONFIG_CPU_H8S) | ||
158 | short dummy_exr; | ||
159 | #endif | ||
160 | long dummy_pc; | ||
161 | char *pretcode; | ||
162 | unsigned char retcode[8]; | ||
163 | unsigned long extramask[_NSIG_WORDS-1]; | ||
164 | struct sigcontext sc; | ||
165 | int sig; | ||
166 | } __attribute__((aligned(2),packed)); | ||
167 | |||
168 | struct rt_sigframe | ||
169 | { | ||
170 | long dummy_er0; | ||
171 | long dummy_vector; | ||
172 | #if defined(CONFIG_CPU_H8S) | ||
173 | short dummy_exr; | ||
174 | #endif | ||
175 | long dummy_pc; | ||
176 | char *pretcode; | ||
177 | struct siginfo *pinfo; | ||
178 | void *puc; | ||
179 | unsigned char retcode[8]; | ||
180 | struct siginfo info; | ||
181 | struct ucontext uc; | ||
182 | int sig; | ||
183 | } __attribute__((aligned(2),packed)); | ||
184 | |||
185 | static inline int | ||
186 | restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, | ||
187 | int *pd0) | ||
188 | { | ||
189 | int err = 0; | ||
190 | unsigned int ccr; | ||
191 | unsigned int usp; | ||
192 | unsigned int er0; | ||
193 | |||
194 | /* Always make any pending restarted system calls return -EINTR */ | ||
195 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
196 | |||
197 | #define COPY(r) err |= __get_user(regs->r, &usc->sc_##r) /* restore passed registers */ | ||
198 | COPY(er1); | ||
199 | COPY(er2); | ||
200 | COPY(er3); | ||
201 | COPY(er5); | ||
202 | COPY(pc); | ||
203 | ccr = regs->ccr & 0x10; | ||
204 | COPY(ccr); | ||
205 | #undef COPY | ||
206 | regs->ccr &= 0xef; | ||
207 | regs->ccr |= ccr; | ||
208 | regs->orig_er0 = -1; /* disable syscall checks */ | ||
209 | err |= __get_user(usp, &usc->sc_usp); | ||
210 | wrusp(usp); | ||
211 | |||
212 | err |= __get_user(er0, &usc->sc_er0); | ||
213 | *pd0 = er0; | ||
214 | return err; | ||
215 | } | ||
216 | |||
217 | asmlinkage int do_sigreturn(unsigned long __unused,...) | ||
218 | { | ||
219 | struct pt_regs *regs = (struct pt_regs *) (&__unused - 1); | ||
220 | unsigned long usp = rdusp(); | ||
221 | struct sigframe *frame = (struct sigframe *)(usp - 4); | ||
222 | sigset_t set; | ||
223 | int er0; | ||
224 | |||
225 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | ||
226 | goto badframe; | ||
227 | if (__get_user(set.sig[0], &frame->sc.sc_mask) || | ||
228 | (_NSIG_WORDS > 1 && | ||
229 | __copy_from_user(&set.sig[1], &frame->extramask, | ||
230 | sizeof(frame->extramask)))) | ||
231 | goto badframe; | ||
232 | |||
233 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
234 | spin_lock_irq(¤t->sighand->siglock); | ||
235 | current->blocked = set; | ||
236 | recalc_sigpending(); | ||
237 | spin_unlock_irq(¤t->sighand->siglock); | ||
238 | |||
239 | if (restore_sigcontext(regs, &frame->sc, &er0)) | ||
240 | goto badframe; | ||
241 | return er0; | ||
242 | |||
243 | badframe: | ||
244 | force_sig(SIGSEGV, current); | ||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | asmlinkage int do_rt_sigreturn(unsigned long __unused,...) | ||
249 | { | ||
250 | struct pt_regs *regs = (struct pt_regs *) &__unused; | ||
251 | unsigned long usp = rdusp(); | ||
252 | struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4); | ||
253 | sigset_t set; | ||
254 | int er0; | ||
255 | |||
256 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | ||
257 | goto badframe; | ||
258 | if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) | ||
259 | goto badframe; | ||
260 | |||
261 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
262 | spin_unlock_irq(¤t->sighand->siglock); | ||
263 | current->blocked = set; | ||
264 | recalc_sigpending(); | ||
265 | spin_lock_irq(¤t->sighand->siglock); | ||
266 | |||
267 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0)) | ||
268 | goto badframe; | ||
269 | |||
270 | if (do_sigaltstack(&frame->uc.uc_stack, NULL, usp) == -EFAULT) | ||
271 | goto badframe; | ||
272 | |||
273 | return er0; | ||
274 | |||
275 | badframe: | ||
276 | force_sig(SIGSEGV, current); | ||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, | ||
281 | unsigned long mask) | ||
282 | { | ||
283 | int err = 0; | ||
284 | |||
285 | err |= __put_user(regs->er0, &sc->sc_er0); | ||
286 | err |= __put_user(regs->er1, &sc->sc_er1); | ||
287 | err |= __put_user(regs->er2, &sc->sc_er2); | ||
288 | err |= __put_user(regs->er3, &sc->sc_er3); | ||
289 | err |= __put_user(regs->er4, &sc->sc_er4); | ||
290 | err |= __put_user(regs->er5, &sc->sc_er5); | ||
291 | err |= __put_user(regs->er6, &sc->sc_er6); | ||
292 | err |= __put_user(rdusp(), &sc->sc_usp); | ||
293 | err |= __put_user(regs->pc, &sc->sc_pc); | ||
294 | err |= __put_user(regs->ccr, &sc->sc_ccr); | ||
295 | err |= __put_user(mask, &sc->sc_mask); | ||
296 | |||
297 | return err; | ||
298 | } | ||
299 | |||
300 | static inline void * | ||
301 | get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) | ||
302 | { | ||
303 | unsigned long usp; | ||
304 | |||
305 | /* Default to using normal stack. */ | ||
306 | usp = rdusp(); | ||
307 | |||
308 | /* This is the X/Open sanctioned signal stack switching. */ | ||
309 | if (ka->sa.sa_flags & SA_ONSTACK) { | ||
310 | if (!on_sig_stack(usp)) | ||
311 | usp = current->sas_ss_sp + current->sas_ss_size; | ||
312 | } | ||
313 | return (void *)((usp - frame_size) & -8UL); | ||
314 | } | ||
315 | |||
316 | static void setup_frame (int sig, struct k_sigaction *ka, | ||
317 | sigset_t *set, struct pt_regs *regs) | ||
318 | { | ||
319 | struct sigframe *frame; | ||
320 | int err = 0; | ||
321 | int usig; | ||
322 | unsigned char *ret; | ||
323 | |||
324 | frame = get_sigframe(ka, regs, sizeof(*frame)); | ||
325 | |||
326 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | ||
327 | goto give_sigsegv; | ||
328 | |||
329 | usig = current_thread_info()->exec_domain | ||
330 | && current_thread_info()->exec_domain->signal_invmap | ||
331 | && sig < 32 | ||
332 | ? current_thread_info()->exec_domain->signal_invmap[sig] | ||
333 | : sig; | ||
334 | |||
335 | err |= __put_user(usig, &frame->sig); | ||
336 | if (err) | ||
337 | goto give_sigsegv; | ||
338 | |||
339 | err |= setup_sigcontext(&frame->sc, regs, set->sig[0]); | ||
340 | if (err) | ||
341 | goto give_sigsegv; | ||
342 | |||
343 | if (_NSIG_WORDS > 1) { | ||
344 | err |= copy_to_user(frame->extramask, &set->sig[1], | ||
345 | sizeof(frame->extramask)); | ||
346 | if (err) | ||
347 | goto give_sigsegv; | ||
348 | } | ||
349 | |||
350 | ret = frame->retcode; | ||
351 | if (ka->sa.sa_flags & SA_RESTORER) | ||
352 | ret = (unsigned char *)(ka->sa.sa_restorer); | ||
353 | else { | ||
354 | /* sub.l er0,er0; mov.b #__NR_sigreturn,r0l; trapa #0 */ | ||
355 | err != __put_user(0x1a80f800 + (__NR_sigreturn & 0xff), | ||
356 | (unsigned long *)(frame->retcode + 0)); | ||
357 | err |= __put_user(0x5700, (unsigned short *)(frame->retcode + 4)); | ||
358 | } | ||
359 | |||
360 | /* Set up to return from userspace. */ | ||
361 | err |= __put_user(ret, &frame->pretcode); | ||
362 | |||
363 | if (err) | ||
364 | goto give_sigsegv; | ||
365 | |||
366 | /* Set up registers for signal handler */ | ||
367 | wrusp ((unsigned long) frame); | ||
368 | regs->pc = (unsigned long) ka->sa.sa_handler; | ||
369 | regs->er0 = (current_thread_info()->exec_domain | ||
370 | && current_thread_info()->exec_domain->signal_invmap | ||
371 | && sig < 32 | ||
372 | ? current_thread_info()->exec_domain->signal_invmap[sig] | ||
373 | : sig); | ||
374 | regs->er1 = (unsigned long)&(frame->sc); | ||
375 | regs->er5 = current->mm->start_data; /* GOT base */ | ||
376 | |||
377 | return; | ||
378 | |||
379 | give_sigsegv: | ||
380 | force_sigsegv(sig, current); | ||
381 | } | ||
382 | |||
383 | static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, | ||
384 | sigset_t *set, struct pt_regs *regs) | ||
385 | { | ||
386 | struct rt_sigframe *frame; | ||
387 | int err = 0; | ||
388 | int usig; | ||
389 | unsigned char *ret; | ||
390 | |||
391 | frame = get_sigframe(ka, regs, sizeof(*frame)); | ||
392 | |||
393 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | ||
394 | goto give_sigsegv; | ||
395 | |||
396 | usig = current_thread_info()->exec_domain | ||
397 | && current_thread_info()->exec_domain->signal_invmap | ||
398 | && sig < 32 | ||
399 | ? current_thread_info()->exec_domain->signal_invmap[sig] | ||
400 | : sig; | ||
401 | |||
402 | err |= __put_user(usig, &frame->sig); | ||
403 | if (err) | ||
404 | goto give_sigsegv; | ||
405 | |||
406 | err |= __put_user(&frame->info, &frame->pinfo); | ||
407 | err |= __put_user(&frame->uc, &frame->puc); | ||
408 | err |= copy_siginfo_to_user(&frame->info, info); | ||
409 | if (err) | ||
410 | goto give_sigsegv; | ||
411 | |||
412 | /* Create the ucontext. */ | ||
413 | err |= __put_user(0, &frame->uc.uc_flags); | ||
414 | err |= __put_user(0, &frame->uc.uc_link); | ||
415 | err |= __put_user((void *)current->sas_ss_sp, | ||
416 | &frame->uc.uc_stack.ss_sp); | ||
417 | err |= __put_user(sas_ss_flags(rdusp()), | ||
418 | &frame->uc.uc_stack.ss_flags); | ||
419 | err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); | ||
420 | err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); | ||
421 | err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set)); | ||
422 | if (err) | ||
423 | goto give_sigsegv; | ||
424 | |||
425 | /* Set up to return from userspace. */ | ||
426 | ret = frame->retcode; | ||
427 | if (ka->sa.sa_flags & SA_RESTORER) | ||
428 | ret = (unsigned char *)(ka->sa.sa_restorer); | ||
429 | else { | ||
430 | /* sub.l er0,er0; mov.b #__NR_sigreturn,r0l; trapa #0 */ | ||
431 | err != __put_user(0x1a80f800 + (__NR_sigreturn & 0xff), | ||
432 | (unsigned long *)(frame->retcode + 0)); | ||
433 | err |= __put_user(0x5700, (unsigned short *)(frame->retcode + 4)); | ||
434 | } | ||
435 | err |= __put_user(ret, &frame->pretcode); | ||
436 | |||
437 | if (err) | ||
438 | goto give_sigsegv; | ||
439 | |||
440 | /* Set up registers for signal handler */ | ||
441 | wrusp ((unsigned long) frame); | ||
442 | regs->pc = (unsigned long) ka->sa.sa_handler; | ||
443 | regs->er0 = (current_thread_info()->exec_domain | ||
444 | && current_thread_info()->exec_domain->signal_invmap | ||
445 | && sig < 32 | ||
446 | ? current_thread_info()->exec_domain->signal_invmap[sig] | ||
447 | : sig); | ||
448 | regs->er1 = (unsigned long)&(frame->info); | ||
449 | regs->er2 = (unsigned long)&frame->uc; | ||
450 | regs->er5 = current->mm->start_data; /* GOT base */ | ||
451 | |||
452 | return; | ||
453 | |||
454 | give_sigsegv: | ||
455 | force_sigsegv(sig, current); | ||
456 | } | ||
457 | |||
458 | /* | ||
459 | * OK, we're invoking a handler | ||
460 | */ | ||
461 | static void | ||
462 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | ||
463 | sigset_t *oldset, struct pt_regs * regs) | ||
464 | { | ||
465 | /* are we from a system call? */ | ||
466 | if (regs->orig_er0 >= 0) { | ||
467 | switch (regs->er0) { | ||
468 | case -ERESTART_RESTARTBLOCK: | ||
469 | case -ERESTARTNOHAND: | ||
470 | regs->er0 = -EINTR; | ||
471 | break; | ||
472 | |||
473 | case -ERESTARTSYS: | ||
474 | if (!(ka->sa.sa_flags & SA_RESTART)) { | ||
475 | regs->er0 = -EINTR; | ||
476 | break; | ||
477 | } | ||
478 | /* fallthrough */ | ||
479 | case -ERESTARTNOINTR: | ||
480 | regs->er0 = regs->orig_er0; | ||
481 | regs->pc -= 2; | ||
482 | } | ||
483 | } | ||
484 | |||
485 | /* set up the stack frame */ | ||
486 | if (ka->sa.sa_flags & SA_SIGINFO) | ||
487 | setup_rt_frame(sig, ka, info, oldset, regs); | ||
488 | else | ||
489 | setup_frame(sig, ka, oldset, regs); | ||
490 | |||
491 | if (!(ka->sa.sa_flags & SA_NODEFER)) { | ||
492 | spin_lock_irq(¤t->sighand->siglock); | ||
493 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | ||
494 | sigaddset(¤t->blocked,sig); | ||
495 | recalc_sigpending(); | ||
496 | spin_unlock_irq(¤t->sighand->siglock); | ||
497 | } | ||
498 | } | ||
499 | |||
500 | /* | ||
501 | * Note that 'init' is a special process: it doesn't get signals it doesn't | ||
502 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | ||
503 | * mistake. | ||
504 | */ | ||
505 | asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset) | ||
506 | { | ||
507 | siginfo_t info; | ||
508 | int signr; | ||
509 | struct k_sigaction ka; | ||
510 | |||
511 | /* | ||
512 | * We want the common case to go fast, which | ||
513 | * is why we may in certain cases get here from | ||
514 | * kernel mode. Just return without doing anything | ||
515 | * if so. | ||
516 | */ | ||
517 | if ((regs->ccr & 0x10)) | ||
518 | return 1; | ||
519 | |||
520 | if (current->flags & PF_FREEZE) { | ||
521 | refrigerator(0); | ||
522 | goto no_signal; | ||
523 | } | ||
524 | |||
525 | current->thread.esp0 = (unsigned long) regs; | ||
526 | |||
527 | if (!oldset) | ||
528 | oldset = ¤t->blocked; | ||
529 | |||
530 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | ||
531 | if (signr > 0) { | ||
532 | /* Whee! Actually deliver the signal. */ | ||
533 | handle_signal(signr, &info, &ka, oldset, regs); | ||
534 | return 1; | ||
535 | } | ||
536 | no_signal: | ||
537 | /* Did we come from a system call? */ | ||
538 | if (regs->orig_er0 >= 0) { | ||
539 | /* Restart the system call - no handlers present */ | ||
540 | if (regs->er0 == -ERESTARTNOHAND || | ||
541 | regs->er0 == -ERESTARTSYS || | ||
542 | regs->er0 == -ERESTARTNOINTR) { | ||
543 | regs->er0 = regs->orig_er0; | ||
544 | regs->pc -= 2; | ||
545 | } | ||
546 | if (regs->er0 == -ERESTART_RESTARTBLOCK){ | ||
547 | regs->er0 = __NR_restart_syscall; | ||
548 | regs->pc -= 2; | ||
549 | } | ||
550 | } | ||
551 | return 0; | ||
552 | } | ||
diff --git a/arch/h8300/kernel/sys_h8300.c b/arch/h8300/kernel/sys_h8300.c new file mode 100644 index 000000000000..0f61b7ad69ab --- /dev/null +++ b/arch/h8300/kernel/sys_h8300.c | |||
@@ -0,0 +1,282 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/kernel/sys_h8300.c | ||
3 | * | ||
4 | * This file contains various random system calls that | ||
5 | * have a non-standard calling sequence on the H8/300 | ||
6 | * platform. | ||
7 | */ | ||
8 | |||
9 | #include <linux/errno.h> | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/mm.h> | ||
12 | #include <linux/smp.h> | ||
13 | #include <linux/smp_lock.h> | ||
14 | #include <linux/sem.h> | ||
15 | #include <linux/msg.h> | ||
16 | #include <linux/shm.h> | ||
17 | #include <linux/stat.h> | ||
18 | #include <linux/syscalls.h> | ||
19 | #include <linux/mman.h> | ||
20 | #include <linux/file.h> | ||
21 | #include <linux/utsname.h> | ||
22 | |||
23 | #include <asm/setup.h> | ||
24 | #include <asm/uaccess.h> | ||
25 | #include <asm/cachectl.h> | ||
26 | #include <asm/traps.h> | ||
27 | #include <asm/ipc.h> | ||
28 | |||
29 | /* | ||
30 | * sys_pipe() is the normal C calling standard for creating | ||
31 | * a pipe. It's not the way unix traditionally does this, though. | ||
32 | */ | ||
33 | asmlinkage int sys_pipe(unsigned long * fildes) | ||
34 | { | ||
35 | int fd[2]; | ||
36 | int error; | ||
37 | |||
38 | error = do_pipe(fd); | ||
39 | if (!error) { | ||
40 | if (copy_to_user(fildes, fd, 2*sizeof(int))) | ||
41 | error = -EFAULT; | ||
42 | } | ||
43 | return error; | ||
44 | } | ||
45 | |||
46 | /* common code for old and new mmaps */ | ||
47 | static inline long do_mmap2( | ||
48 | unsigned long addr, unsigned long len, | ||
49 | unsigned long prot, unsigned long flags, | ||
50 | unsigned long fd, unsigned long pgoff) | ||
51 | { | ||
52 | int error = -EBADF; | ||
53 | struct file * file = NULL; | ||
54 | |||
55 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | ||
56 | if (!(flags & MAP_ANONYMOUS)) { | ||
57 | file = fget(fd); | ||
58 | if (!file) | ||
59 | goto out; | ||
60 | } | ||
61 | |||
62 | down_write(¤t->mm->mmap_sem); | ||
63 | error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); | ||
64 | up_write(¤t->mm->mmap_sem); | ||
65 | |||
66 | if (file) | ||
67 | fput(file); | ||
68 | out: | ||
69 | return error; | ||
70 | } | ||
71 | |||
72 | asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, | ||
73 | unsigned long prot, unsigned long flags, | ||
74 | unsigned long fd, unsigned long pgoff) | ||
75 | { | ||
76 | return do_mmap2(addr, len, prot, flags, fd, pgoff); | ||
77 | } | ||
78 | |||
79 | /* | ||
80 | * Perform the select(nd, in, out, ex, tv) and mmap() system | ||
81 | * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to | ||
82 | * handle more than 4 system call parameters, so these system calls | ||
83 | * used a memory block for parameter passing.. | ||
84 | */ | ||
85 | |||
86 | struct mmap_arg_struct { | ||
87 | unsigned long addr; | ||
88 | unsigned long len; | ||
89 | unsigned long prot; | ||
90 | unsigned long flags; | ||
91 | unsigned long fd; | ||
92 | unsigned long offset; | ||
93 | }; | ||
94 | |||
95 | asmlinkage int old_mmap(struct mmap_arg_struct *arg) | ||
96 | { | ||
97 | struct mmap_arg_struct a; | ||
98 | int error = -EFAULT; | ||
99 | |||
100 | if (copy_from_user(&a, arg, sizeof(a))) | ||
101 | goto out; | ||
102 | |||
103 | error = -EINVAL; | ||
104 | if (a.offset & ~PAGE_MASK) | ||
105 | goto out; | ||
106 | |||
107 | a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | ||
108 | |||
109 | error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); | ||
110 | out: | ||
111 | return error; | ||
112 | } | ||
113 | |||
114 | #if 0 /* DAVIDM - do we want this */ | ||
115 | struct mmap_arg_struct64 { | ||
116 | __u32 addr; | ||
117 | __u32 len; | ||
118 | __u32 prot; | ||
119 | __u32 flags; | ||
120 | __u64 offset; /* 64 bits */ | ||
121 | __u32 fd; | ||
122 | }; | ||
123 | |||
124 | asmlinkage long sys_mmap64(struct mmap_arg_struct64 *arg) | ||
125 | { | ||
126 | int error = -EFAULT; | ||
127 | struct file * file = NULL; | ||
128 | struct mmap_arg_struct64 a; | ||
129 | unsigned long pgoff; | ||
130 | |||
131 | if (copy_from_user(&a, arg, sizeof(a))) | ||
132 | return -EFAULT; | ||
133 | |||
134 | if ((long)a.offset & ~PAGE_MASK) | ||
135 | return -EINVAL; | ||
136 | |||
137 | pgoff = a.offset >> PAGE_SHIFT; | ||
138 | if ((a.offset >> PAGE_SHIFT) != pgoff) | ||
139 | return -EINVAL; | ||
140 | |||
141 | if (!(a.flags & MAP_ANONYMOUS)) { | ||
142 | error = -EBADF; | ||
143 | file = fget(a.fd); | ||
144 | if (!file) | ||
145 | goto out; | ||
146 | } | ||
147 | a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | ||
148 | |||
149 | down_write(¤t->mm->mmap_sem); | ||
150 | error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff); | ||
151 | up_write(¤t->mm->mmap_sem); | ||
152 | if (file) | ||
153 | fput(file); | ||
154 | out: | ||
155 | return error; | ||
156 | } | ||
157 | #endif | ||
158 | |||
159 | struct sel_arg_struct { | ||
160 | unsigned long n; | ||
161 | fd_set *inp, *outp, *exp; | ||
162 | struct timeval *tvp; | ||
163 | }; | ||
164 | |||
165 | asmlinkage int old_select(struct sel_arg_struct *arg) | ||
166 | { | ||
167 | struct sel_arg_struct a; | ||
168 | |||
169 | if (copy_from_user(&a, arg, sizeof(a))) | ||
170 | return -EFAULT; | ||
171 | /* sys_select() does the appropriate kernel locking */ | ||
172 | return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); | ||
173 | } | ||
174 | |||
175 | /* | ||
176 | * sys_ipc() is the de-multiplexer for the SysV IPC calls.. | ||
177 | * | ||
178 | * This is really horribly ugly. | ||
179 | */ | ||
180 | asmlinkage int sys_ipc (uint call, int first, int second, | ||
181 | int third, void *ptr, long fifth) | ||
182 | { | ||
183 | int version, ret; | ||
184 | |||
185 | version = call >> 16; /* hack for backward compatibility */ | ||
186 | call &= 0xffff; | ||
187 | |||
188 | if (call <= SEMCTL) | ||
189 | switch (call) { | ||
190 | case SEMOP: | ||
191 | return sys_semop (first, (struct sembuf *)ptr, second); | ||
192 | case SEMGET: | ||
193 | return sys_semget (first, second, third); | ||
194 | case SEMCTL: { | ||
195 | union semun fourth; | ||
196 | if (!ptr) | ||
197 | return -EINVAL; | ||
198 | if (get_user(fourth.__pad, (void **) ptr)) | ||
199 | return -EFAULT; | ||
200 | return sys_semctl (first, second, third, fourth); | ||
201 | } | ||
202 | default: | ||
203 | return -EINVAL; | ||
204 | } | ||
205 | if (call <= MSGCTL) | ||
206 | switch (call) { | ||
207 | case MSGSND: | ||
208 | return sys_msgsnd (first, (struct msgbuf *) ptr, | ||
209 | second, third); | ||
210 | case MSGRCV: | ||
211 | switch (version) { | ||
212 | case 0: { | ||
213 | struct ipc_kludge tmp; | ||
214 | if (!ptr) | ||
215 | return -EINVAL; | ||
216 | if (copy_from_user (&tmp, | ||
217 | (struct ipc_kludge *)ptr, | ||
218 | sizeof (tmp))) | ||
219 | return -EFAULT; | ||
220 | return sys_msgrcv (first, tmp.msgp, second, | ||
221 | tmp.msgtyp, third); | ||
222 | } | ||
223 | default: | ||
224 | return sys_msgrcv (first, | ||
225 | (struct msgbuf *) ptr, | ||
226 | second, fifth, third); | ||
227 | } | ||
228 | case MSGGET: | ||
229 | return sys_msgget ((key_t) first, second); | ||
230 | case MSGCTL: | ||
231 | return sys_msgctl (first, second, | ||
232 | (struct msqid_ds *) ptr); | ||
233 | default: | ||
234 | return -EINVAL; | ||
235 | } | ||
236 | if (call <= SHMCTL) | ||
237 | switch (call) { | ||
238 | case SHMAT: | ||
239 | switch (version) { | ||
240 | default: { | ||
241 | ulong raddr; | ||
242 | ret = do_shmat (first, (char *) ptr, | ||
243 | second, &raddr); | ||
244 | if (ret) | ||
245 | return ret; | ||
246 | return put_user (raddr, (ulong *) third); | ||
247 | } | ||
248 | } | ||
249 | case SHMDT: | ||
250 | return sys_shmdt ((char *)ptr); | ||
251 | case SHMGET: | ||
252 | return sys_shmget (first, second, third); | ||
253 | case SHMCTL: | ||
254 | return sys_shmctl (first, second, | ||
255 | (struct shmid_ds *) ptr); | ||
256 | default: | ||
257 | return -EINVAL; | ||
258 | } | ||
259 | |||
260 | return -EINVAL; | ||
261 | } | ||
262 | |||
263 | /* sys_cacheflush -- no support. */ | ||
264 | asmlinkage int | ||
265 | sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) | ||
266 | { | ||
267 | return -EINVAL; | ||
268 | } | ||
269 | |||
270 | asmlinkage int sys_getpagesize(void) | ||
271 | { | ||
272 | return PAGE_SIZE; | ||
273 | } | ||
274 | |||
275 | #if defined(CONFIG_SYSCALL_PRINT) | ||
276 | asmlinkage void syscall_print(void *dummy,...) | ||
277 | { | ||
278 | struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4); | ||
279 | printk("call %06lx:%ld 1:%08lx,2:%08lx,3:%08lx,ret:%08lx\n", | ||
280 | ((regs->pc)&0xffffff)-2,regs->orig_er0,regs->er1,regs->er2,regs->er3,regs->er0); | ||
281 | } | ||
282 | #endif | ||
diff --git a/arch/h8300/kernel/syscalls.S b/arch/h8300/kernel/syscalls.S new file mode 100644 index 000000000000..79b3bda5c6e3 --- /dev/null +++ b/arch/h8300/kernel/syscalls.S | |||
@@ -0,0 +1,340 @@ | |||
1 | /* Systemcall Entry Table */ | ||
2 | #include <linux/config.h> | ||
3 | #include <linux/sys.h> | ||
4 | #include <asm/linkage.h> | ||
5 | #include <asm/unistd.h> | ||
6 | |||
7 | .globl SYMBOL_NAME(sys_call_table) | ||
8 | |||
9 | #if defined(CONFIG_CPU_H8300H) | ||
10 | .h8300h | ||
11 | #endif | ||
12 | #if defined(CONFIG_CPU_H8S) | ||
13 | .h8300s | ||
14 | #endif | ||
15 | .section .text | ||
16 | .align 2 | ||
17 | SYMBOL_NAME_LABEL(sys_call_table) | ||
18 | .long SYMBOL_NAME(sys_ni_syscall) /* 0 - old "setup()" system call*/ | ||
19 | .long SYMBOL_NAME(sys_exit) | ||
20 | .long SYMBOL_NAME(sys_fork) | ||
21 | .long SYMBOL_NAME(sys_read) | ||
22 | .long SYMBOL_NAME(sys_write) | ||
23 | .long SYMBOL_NAME(sys_open) /* 5 */ | ||
24 | .long SYMBOL_NAME(sys_close) | ||
25 | .long SYMBOL_NAME(sys_waitpid) | ||
26 | .long SYMBOL_NAME(sys_creat) | ||
27 | .long SYMBOL_NAME(sys_link) | ||
28 | .long SYMBOL_NAME(sys_unlink) /* 10 */ | ||
29 | .long SYMBOL_NAME(sys_execve) | ||
30 | .long SYMBOL_NAME(sys_chdir) | ||
31 | .long SYMBOL_NAME(sys_time) | ||
32 | .long SYMBOL_NAME(sys_mknod) | ||
33 | .long SYMBOL_NAME(sys_chmod) /* 15 */ | ||
34 | .long SYMBOL_NAME(sys_chown16) | ||
35 | .long SYMBOL_NAME(sys_ni_syscall) /* old break syscall holder */ | ||
36 | .long SYMBOL_NAME(sys_stat) | ||
37 | .long SYMBOL_NAME(sys_lseek) | ||
38 | .long SYMBOL_NAME(sys_getpid) /* 20 */ | ||
39 | .long SYMBOL_NAME(sys_mount) | ||
40 | .long SYMBOL_NAME(sys_oldumount) | ||
41 | .long SYMBOL_NAME(sys_setuid16) | ||
42 | .long SYMBOL_NAME(sys_getuid16) | ||
43 | .long SYMBOL_NAME(sys_stime) /* 25 */ | ||
44 | .long SYMBOL_NAME(sys_ptrace) | ||
45 | .long SYMBOL_NAME(sys_alarm) | ||
46 | .long SYMBOL_NAME(sys_fstat) | ||
47 | .long SYMBOL_NAME(sys_pause) | ||
48 | .long SYMBOL_NAME(sys_utime) /* 30 */ | ||
49 | .long SYMBOL_NAME(sys_ni_syscall) /* old stty syscall holder */ | ||
50 | .long SYMBOL_NAME(sys_ni_syscall) /* old gtty syscall holder */ | ||
51 | .long SYMBOL_NAME(sys_access) | ||
52 | .long SYMBOL_NAME(sys_nice) | ||
53 | .long SYMBOL_NAME(sys_ni_syscall) /* 35 */ /* old ftime syscall holder */ | ||
54 | .long SYMBOL_NAME(sys_sync) | ||
55 | .long SYMBOL_NAME(sys_kill) | ||
56 | .long SYMBOL_NAME(sys_rename) | ||
57 | .long SYMBOL_NAME(sys_mkdir) | ||
58 | .long SYMBOL_NAME(sys_rmdir) /* 40 */ | ||
59 | .long SYMBOL_NAME(sys_dup) | ||
60 | .long SYMBOL_NAME(sys_pipe) | ||
61 | .long SYMBOL_NAME(sys_times) | ||
62 | .long SYMBOL_NAME(sys_ni_syscall) /* old prof syscall holder */ | ||
63 | .long SYMBOL_NAME(sys_brk) /* 45 */ | ||
64 | .long SYMBOL_NAME(sys_setgid16) | ||
65 | .long SYMBOL_NAME(sys_getgid16) | ||
66 | .long SYMBOL_NAME(sys_signal) | ||
67 | .long SYMBOL_NAME(sys_geteuid16) | ||
68 | .long SYMBOL_NAME(sys_getegid16) /* 50 */ | ||
69 | .long SYMBOL_NAME(sys_acct) | ||
70 | .long SYMBOL_NAME(sys_umount) /* recycled never used phys() */ | ||
71 | .long SYMBOL_NAME(sys_ni_syscall) /* old lock syscall holder */ | ||
72 | .long SYMBOL_NAME(sys_ioctl) | ||
73 | .long SYMBOL_NAME(sys_fcntl) /* 55 */ | ||
74 | .long SYMBOL_NAME(sys_ni_syscall) /* old mpx syscall holder */ | ||
75 | .long SYMBOL_NAME(sys_setpgid) | ||
76 | .long SYMBOL_NAME(sys_ni_syscall) /* old ulimit syscall holder */ | ||
77 | .long SYMBOL_NAME(sys_ni_syscall) | ||
78 | .long SYMBOL_NAME(sys_umask) /* 60 */ | ||
79 | .long SYMBOL_NAME(sys_chroot) | ||
80 | .long SYMBOL_NAME(sys_ustat) | ||
81 | .long SYMBOL_NAME(sys_dup2) | ||
82 | .long SYMBOL_NAME(sys_getppid) | ||
83 | .long SYMBOL_NAME(sys_getpgrp) /* 65 */ | ||
84 | .long SYMBOL_NAME(sys_setsid) | ||
85 | .long SYMBOL_NAME(sys_sigaction) | ||
86 | .long SYMBOL_NAME(sys_sgetmask) | ||
87 | .long SYMBOL_NAME(sys_ssetmask) | ||
88 | .long SYMBOL_NAME(sys_setreuid16) /* 70 */ | ||
89 | .long SYMBOL_NAME(sys_setregid16) | ||
90 | .long SYMBOL_NAME(sys_sigsuspend) | ||
91 | .long SYMBOL_NAME(sys_sigpending) | ||
92 | .long SYMBOL_NAME(sys_sethostname) | ||
93 | .long SYMBOL_NAME(sys_setrlimit) /* 75 */ | ||
94 | .long SYMBOL_NAME(sys_old_getrlimit) | ||
95 | .long SYMBOL_NAME(sys_getrusage) | ||
96 | .long SYMBOL_NAME(sys_gettimeofday) | ||
97 | .long SYMBOL_NAME(sys_settimeofday) | ||
98 | .long SYMBOL_NAME(sys_getgroups16) /* 80 */ | ||
99 | .long SYMBOL_NAME(sys_setgroups16) | ||
100 | .long SYMBOL_NAME(old_select) | ||
101 | .long SYMBOL_NAME(sys_symlink) | ||
102 | .long SYMBOL_NAME(sys_lstat) | ||
103 | .long SYMBOL_NAME(sys_readlink) /* 85 */ | ||
104 | .long SYMBOL_NAME(sys_uselib) | ||
105 | .long SYMBOL_NAME(sys_swapon) | ||
106 | .long SYMBOL_NAME(sys_reboot) | ||
107 | .long SYMBOL_NAME(old_readdir) | ||
108 | .long SYMBOL_NAME(old_mmap) /* 90 */ | ||
109 | .long SYMBOL_NAME(sys_munmap) | ||
110 | .long SYMBOL_NAME(sys_truncate) | ||
111 | .long SYMBOL_NAME(sys_ftruncate) | ||
112 | .long SYMBOL_NAME(sys_fchmod) | ||
113 | .long SYMBOL_NAME(sys_fchown16) /* 95 */ | ||
114 | .long SYMBOL_NAME(sys_getpriority) | ||
115 | .long SYMBOL_NAME(sys_setpriority) | ||
116 | .long SYMBOL_NAME(sys_ni_syscall) /* old profil syscall holder */ | ||
117 | .long SYMBOL_NAME(sys_statfs) | ||
118 | .long SYMBOL_NAME(sys_fstatfs) /* 100 */ | ||
119 | .long SYMBOL_NAME(sys_ni_syscall) /* ioperm for i386 */ | ||
120 | .long SYMBOL_NAME(sys_socketcall) | ||
121 | .long SYMBOL_NAME(sys_syslog) | ||
122 | .long SYMBOL_NAME(sys_setitimer) | ||
123 | .long SYMBOL_NAME(sys_getitimer) /* 105 */ | ||
124 | .long SYMBOL_NAME(sys_newstat) | ||
125 | .long SYMBOL_NAME(sys_newlstat) | ||
126 | .long SYMBOL_NAME(sys_newfstat) | ||
127 | .long SYMBOL_NAME(sys_ni_syscall) | ||
128 | .long SYMBOL_NAME(sys_ni_syscall) /* iopl for i386 */ /* 110 */ | ||
129 | .long SYMBOL_NAME(sys_vhangup) | ||
130 | .long SYMBOL_NAME(sys_ni_syscall) /* obsolete idle() syscall */ | ||
131 | .long SYMBOL_NAME(sys_ni_syscall) /* vm86old for i386 */ | ||
132 | .long SYMBOL_NAME(sys_wait4) | ||
133 | .long SYMBOL_NAME(sys_swapoff) /* 115 */ | ||
134 | .long SYMBOL_NAME(sys_sysinfo) | ||
135 | .long SYMBOL_NAME(sys_ipc) | ||
136 | .long SYMBOL_NAME(sys_fsync) | ||
137 | .long SYMBOL_NAME(sys_sigreturn) | ||
138 | .long SYMBOL_NAME(sys_clone) /* 120 */ | ||
139 | .long SYMBOL_NAME(sys_setdomainname) | ||
140 | .long SYMBOL_NAME(sys_newuname) | ||
141 | .long SYMBOL_NAME(sys_cacheflush) /* modify_ldt for i386 */ | ||
142 | .long SYMBOL_NAME(sys_adjtimex) | ||
143 | .long SYMBOL_NAME(sys_ni_syscall) /* 125 sys_mprotect */ | ||
144 | .long SYMBOL_NAME(sys_sigprocmask) | ||
145 | .long SYMBOL_NAME(sys_ni_syscall) /* sys_create_module */ | ||
146 | .long SYMBOL_NAME(sys_init_module) | ||
147 | .long SYMBOL_NAME(sys_delete_module) | ||
148 | .long SYMBOL_NAME(sys_ni_syscall) /* 130 sys_get_kernel_syms */ | ||
149 | .long SYMBOL_NAME(sys_quotactl) | ||
150 | .long SYMBOL_NAME(sys_getpgid) | ||
151 | .long SYMBOL_NAME(sys_fchdir) | ||
152 | .long SYMBOL_NAME(sys_bdflush) | ||
153 | .long SYMBOL_NAME(sys_sysfs) /* 135 */ | ||
154 | .long SYMBOL_NAME(sys_personality) | ||
155 | .long SYMBOL_NAME(sys_ni_syscall) /* for afs_syscall */ | ||
156 | .long SYMBOL_NAME(sys_setfsuid16) | ||
157 | .long SYMBOL_NAME(sys_setfsgid16) | ||
158 | .long SYMBOL_NAME(sys_llseek) /* 140 */ | ||
159 | .long SYMBOL_NAME(sys_getdents) | ||
160 | .long SYMBOL_NAME(sys_select) | ||
161 | .long SYMBOL_NAME(sys_flock) | ||
162 | .long SYMBOL_NAME(sys_ni_syscall) /* sys_msync */ | ||
163 | .long SYMBOL_NAME(sys_readv) /* 145 */ | ||
164 | .long SYMBOL_NAME(sys_writev) | ||
165 | .long SYMBOL_NAME(sys_getsid) | ||
166 | .long SYMBOL_NAME(sys_fdatasync) | ||
167 | .long SYMBOL_NAME(sys_sysctl) | ||
168 | .long SYMBOL_NAME(sys_ni_syscall) /* 150 sys_mlock */ | ||
169 | .long SYMBOL_NAME(sys_ni_syscall) /* sys_munlock */ | ||
170 | .long SYMBOL_NAME(sys_ni_syscall) /* sys_mlockall */ | ||
171 | .long SYMBOL_NAME(sys_ni_syscall) /* sys_munlockall */ | ||
172 | .long SYMBOL_NAME(sys_sched_setparam) | ||
173 | .long SYMBOL_NAME(sys_sched_getparam) /* 155 */ | ||
174 | .long SYMBOL_NAME(sys_sched_setscheduler) | ||
175 | .long SYMBOL_NAME(sys_sched_getscheduler) | ||
176 | .long SYMBOL_NAME(sys_sched_yield) | ||
177 | .long SYMBOL_NAME(sys_sched_get_priority_max) | ||
178 | .long SYMBOL_NAME(sys_sched_get_priority_min) /* 160 */ | ||
179 | .long SYMBOL_NAME(sys_sched_rr_get_interval) | ||
180 | .long SYMBOL_NAME(sys_nanosleep) | ||
181 | .long SYMBOL_NAME(sys_ni_syscall) /* sys_mremap */ | ||
182 | .long SYMBOL_NAME(sys_setresuid16) | ||
183 | .long SYMBOL_NAME(sys_getresuid16) /* 165 */ | ||
184 | .long SYMBOL_NAME(sys_ni_syscall) /* for vm86 */ | ||
185 | .long SYMBOL_NAME(sys_ni_syscall) /* sys_query_module */ | ||
186 | .long SYMBOL_NAME(sys_poll) | ||
187 | .long SYMBOL_NAME(sys_nfsservctl) | ||
188 | .long SYMBOL_NAME(sys_setresgid16) /* 170 */ | ||
189 | .long SYMBOL_NAME(sys_getresgid16) | ||
190 | .long SYMBOL_NAME(sys_prctl) | ||
191 | .long SYMBOL_NAME(sys_rt_sigreturn) | ||
192 | .long SYMBOL_NAME(sys_rt_sigaction) | ||
193 | .long SYMBOL_NAME(sys_rt_sigprocmask) /* 175 */ | ||
194 | .long SYMBOL_NAME(sys_rt_sigpending) | ||
195 | .long SYMBOL_NAME(sys_rt_sigtimedwait) | ||
196 | .long SYMBOL_NAME(sys_rt_sigqueueinfo) | ||
197 | .long SYMBOL_NAME(sys_rt_sigsuspend) | ||
198 | .long SYMBOL_NAME(sys_pread64) /* 180 */ | ||
199 | .long SYMBOL_NAME(sys_pwrite64) | ||
200 | .long SYMBOL_NAME(sys_lchown16); | ||
201 | .long SYMBOL_NAME(sys_getcwd) | ||
202 | .long SYMBOL_NAME(sys_capget) | ||
203 | .long SYMBOL_NAME(sys_capset) /* 185 */ | ||
204 | .long SYMBOL_NAME(sys_sigaltstack) | ||
205 | .long SYMBOL_NAME(sys_sendfile) | ||
206 | .long SYMBOL_NAME(sys_ni_syscall) /* streams1 */ | ||
207 | .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */ | ||
208 | .long SYMBOL_NAME(sys_vfork) /* 190 */ | ||
209 | .long SYMBOL_NAME(sys_getrlimit) | ||
210 | .long SYMBOL_NAME(sys_mmap2) | ||
211 | .long SYMBOL_NAME(sys_truncate64) | ||
212 | .long SYMBOL_NAME(sys_ftruncate64) | ||
213 | .long SYMBOL_NAME(sys_stat64) /* 195 */ | ||
214 | .long SYMBOL_NAME(sys_lstat64) | ||
215 | .long SYMBOL_NAME(sys_fstat64) | ||
216 | .long SYMBOL_NAME(sys_chown) | ||
217 | .long SYMBOL_NAME(sys_getuid) | ||
218 | .long SYMBOL_NAME(sys_getgid) /* 200 */ | ||
219 | .long SYMBOL_NAME(sys_geteuid) | ||
220 | .long SYMBOL_NAME(sys_getegid) | ||
221 | .long SYMBOL_NAME(sys_setreuid) | ||
222 | .long SYMBOL_NAME(sys_setregid) | ||
223 | .long SYMBOL_NAME(sys_getgroups) /* 205 */ | ||
224 | .long SYMBOL_NAME(sys_setgroups) | ||
225 | .long SYMBOL_NAME(sys_fchown) | ||
226 | .long SYMBOL_NAME(sys_setresuid) | ||
227 | .long SYMBOL_NAME(sys_getresuid) | ||
228 | .long SYMBOL_NAME(sys_setresgid) /* 210 */ | ||
229 | .long SYMBOL_NAME(sys_getresgid) | ||
230 | .long SYMBOL_NAME(sys_lchown) | ||
231 | .long SYMBOL_NAME(sys_setuid) | ||
232 | .long SYMBOL_NAME(sys_setgid) | ||
233 | .long SYMBOL_NAME(sys_setfsuid) /* 215 */ | ||
234 | .long SYMBOL_NAME(sys_setfsgid) | ||
235 | .long SYMBOL_NAME(sys_pivot_root) | ||
236 | .long SYMBOL_NAME(sys_ni_syscall) | ||
237 | .long SYMBOL_NAME(sys_ni_syscall) | ||
238 | .long SYMBOL_NAME(sys_getdents64) /* 220 */ | ||
239 | .long SYMBOL_NAME(sys_fcntl64) | ||
240 | .long SYMBOL_NAME(sys_ni_syscall) /* reserved for TUX */ | ||
241 | .long SYMBOL_NAME(sys_ni_syscall) | ||
242 | .long SYMBOL_NAME(sys_gettid) | ||
243 | .long SYMBOL_NAME(sys_ni_syscall) /* 225 */ /* sys_readahead */ | ||
244 | .long SYMBOL_NAME(sys_setxattr) | ||
245 | .long SYMBOL_NAME(sys_lsetxattr) | ||
246 | .long SYMBOL_NAME(sys_fsetxattr) | ||
247 | .long SYMBOL_NAME(sys_getxattr) | ||
248 | .long SYMBOL_NAME(sys_lgetxattr) /* 230 */ | ||
249 | .long SYMBOL_NAME(sys_fgetxattr) | ||
250 | .long SYMBOL_NAME(sys_listxattr) | ||
251 | .long SYMBOL_NAME(sys_llistxattr) | ||
252 | .long SYMBOL_NAME(sys_flistxattr) | ||
253 | .long SYMBOL_NAME(sys_removexattr) /* 235 */ | ||
254 | .long SYMBOL_NAME(sys_lremovexattr) | ||
255 | .long SYMBOL_NAME(sys_fremovexattr) | ||
256 | .long SYMBOL_NAME(sys_tkill) | ||
257 | .long SYMBOL_NAME(sys_sendfile64) | ||
258 | .long SYMBOL_NAME(sys_futex) /* 240 */ | ||
259 | .long SYMBOL_NAME(sys_sched_setaffinity) | ||
260 | .long SYMBOL_NAME(sys_sched_getaffinity) | ||
261 | .long SYMBOL_NAME(sys_ni_syscall) /* sys_set_thread_area */ | ||
262 | .long SYMBOL_NAME(sys_ni_syscall) /* sys_get_thread_area */ | ||
263 | .long SYMBOL_NAME(sys_io_setup) /* 245 */ | ||
264 | .long SYMBOL_NAME(sys_io_destroy) | ||
265 | .long SYMBOL_NAME(sys_io_getevents) | ||
266 | .long SYMBOL_NAME(sys_io_submit) | ||
267 | .long SYMBOL_NAME(sys_io_cancel) | ||
268 | .long SYMBOL_NAME(sys_fadvise64) /* 250 */ | ||
269 | .long SYMBOL_NAME(sys_ni_syscall) | ||
270 | .long SYMBOL_NAME(sys_exit_group) | ||
271 | .long SYMBOL_NAME(sys_lookup_dcookie) | ||
272 | .long SYMBOL_NAME(sys_epoll_create) | ||
273 | .long SYMBOL_NAME(sys_epoll_ctl) /* 255 */ | ||
274 | .long SYMBOL_NAME(sys_epoll_wait) | ||
275 | .long SYMBOL_NAME(sys_ni_syscall) /* sys_remap_file_pages */ | ||
276 | .long SYMBOL_NAME(sys_set_tid_address) | ||
277 | .long SYMBOL_NAME(sys_timer_create) | ||
278 | .long SYMBOL_NAME(sys_timer_settime) /* 260 */ | ||
279 | .long SYMBOL_NAME(sys_timer_gettime) | ||
280 | .long SYMBOL_NAME(sys_timer_getoverrun) | ||
281 | .long SYMBOL_NAME(sys_timer_delete) | ||
282 | .long SYMBOL_NAME(sys_clock_settime) | ||
283 | .long SYMBOL_NAME(sys_clock_gettime) /* 265 */ | ||
284 | .long SYMBOL_NAME(sys_clock_getres) | ||
285 | .long SYMBOL_NAME(sys_clock_nanosleep) | ||
286 | .long SYMBOL_NAME(sys_statfs64) | ||
287 | .long SYMBOL_NAME(sys_fstatfs64) | ||
288 | .long SYMBOL_NAME(sys_tgkill) /* 270 */ | ||
289 | .long SYMBOL_NAME(sys_utimes) | ||
290 | .long SYMBOL_NAME(sys_fadvise64_64) | ||
291 | .long SYMBOL_NAME(sys_ni_syscall) /* sys_vserver */ | ||
292 | .long SYMBOL_NAME(sys_mbind) | ||
293 | .long SYMBOL_NAME(sys_get_mempolicy) | ||
294 | .long SYMBOL_NAME(sys_set_mempolicy) | ||
295 | .long SYMBOL_NAME(sys_mq_open) | ||
296 | .long SYMBOL_NAME(sys_mq_unlink) | ||
297 | .long SYMBOL_NAME(sys_mq_timedsend) | ||
298 | .long SYMBOL_NAME(sys_mq_timedreceive) /* 280 */ | ||
299 | .long SYMBOL_NAME(sys_mq_notify) | ||
300 | .long SYMBOL_NAME(sys_mq_getsetattr) | ||
301 | .long SYMBOL_NAME(sys_ni_syscall) /* reserved for kexec */ | ||
302 | .long SYMBOL_NAME(sys_waitid) | ||
303 | .long SYMBOL_NAME(sys_ni_syscall) /* 285 */ /* available */ | ||
304 | .long SYMBOL_NAME(sys_add_key) | ||
305 | .long SYMBOL_NAME(sys_request_key) | ||
306 | .long SYMBOL_NAME(sys_keyctl) | ||
307 | |||
308 | .rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4 | ||
309 | .long SYMBOL_NAME(sys_ni_syscall) | ||
310 | .endr | ||
311 | |||
312 | .macro call_sp addr | ||
313 | mov.l #SYMBOL_NAME(\addr),er6 | ||
314 | bra SYMBOL_NAME(syscall_trampoline):8 | ||
315 | .endm | ||
316 | |||
317 | SYMBOL_NAME_LABEL(sys_clone) | ||
318 | call_sp h8300_clone | ||
319 | |||
320 | SYMBOL_NAME_LABEL(sys_sigsuspend) | ||
321 | call_sp do_sigsuspend | ||
322 | |||
323 | SYMBOL_NAME_LABEL(sys_rt_sigsuspend) | ||
324 | call_sp do_rt_sigsuspend | ||
325 | |||
326 | SYMBOL_NAME_LABEL(sys_sigreturn) | ||
327 | call_sp do_sigreturn | ||
328 | |||
329 | SYMBOL_NAME_LABEL(sys_rt_sigreturn) | ||
330 | call_sp do_rt_sigreturn | ||
331 | |||
332 | SYMBOL_NAME_LABEL(sys_fork) | ||
333 | call_sp h8300_fork | ||
334 | |||
335 | SYMBOL_NAME_LABEL(sys_vfork) | ||
336 | call_sp h8300_vfork | ||
337 | |||
338 | SYMBOL_NAME_LABEL(syscall_trampoline) | ||
339 | mov.l sp,er0 | ||
340 | jmp @er6 | ||
diff --git a/arch/h8300/kernel/time.c b/arch/h8300/kernel/time.c new file mode 100644 index 000000000000..8a600218334d --- /dev/null +++ b/arch/h8300/kernel/time.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/kernel/time.c | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
5 | * | ||
6 | * Copied/hacked from: | ||
7 | * | ||
8 | * linux/arch/m68k/kernel/time.c | ||
9 | * | ||
10 | * Copyright (C) 1991, 1992, 1995 Linus Torvalds | ||
11 | * | ||
12 | * This file contains the m68k-specific time handling details. | ||
13 | * Most of the stuff is located in the machine specific files. | ||
14 | * | ||
15 | * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 | ||
16 | * "A Kernel Model for Precision Timekeeping" by Dave Mills | ||
17 | */ | ||
18 | |||
19 | #include <linux/config.h> /* CONFIG_HEARTBEAT */ | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/param.h> | ||
25 | #include <linux/string.h> | ||
26 | #include <linux/mm.h> | ||
27 | #include <linux/timex.h> | ||
28 | #include <linux/profile.h> | ||
29 | |||
30 | #include <asm/io.h> | ||
31 | #include <asm/target_time.h> | ||
32 | |||
33 | #define TICK_SIZE (tick_nsec / 1000) | ||
34 | |||
35 | u64 jiffies_64; | ||
36 | |||
37 | EXPORT_SYMBOL(jiffies_64); | ||
38 | |||
39 | /* | ||
40 | * timer_interrupt() needs to keep up the real-time clock, | ||
41 | * as well as call the "do_timer()" routine every clocktick | ||
42 | */ | ||
43 | static void timer_interrupt(int irq, void *dummy, struct pt_regs * regs) | ||
44 | { | ||
45 | /* may need to kick the hardware timer */ | ||
46 | platform_timer_eoi(); | ||
47 | |||
48 | do_timer(regs); | ||
49 | #ifndef CONFIG_SMP | ||
50 | update_process_times(user_mode(regs)); | ||
51 | #endif | ||
52 | profile_tick(CPU_PROFILING, regs); | ||
53 | } | ||
54 | |||
55 | void time_init(void) | ||
56 | { | ||
57 | unsigned int year, mon, day, hour, min, sec; | ||
58 | |||
59 | /* FIX by dqg : Set to zero for platforms that don't have tod */ | ||
60 | /* without this time is undefined and can overflow time_t, causing */ | ||
61 | /* very stange errors */ | ||
62 | year = 1980; | ||
63 | mon = day = 1; | ||
64 | hour = min = sec = 0; | ||
65 | platform_gettod (&year, &mon, &day, &hour, &min, &sec); | ||
66 | |||
67 | if ((year += 1900) < 1970) | ||
68 | year += 100; | ||
69 | xtime.tv_sec = mktime(year, mon, day, hour, min, sec); | ||
70 | xtime.tv_nsec = 0; | ||
71 | |||
72 | platform_timer_setup(timer_interrupt); | ||
73 | } | ||
74 | |||
75 | /* | ||
76 | * This version of gettimeofday has near microsecond resolution. | ||
77 | */ | ||
78 | void do_gettimeofday(struct timeval *tv) | ||
79 | { | ||
80 | unsigned long flags; | ||
81 | unsigned long usec, sec; | ||
82 | |||
83 | read_lock_irqsave(&xtime_lock, flags); | ||
84 | usec = 0; | ||
85 | sec = xtime.tv_sec; | ||
86 | usec += (xtime.tv_nsec / 1000); | ||
87 | read_unlock_irqrestore(&xtime_lock, flags); | ||
88 | |||
89 | while (usec >= 1000000) { | ||
90 | usec -= 1000000; | ||
91 | sec++; | ||
92 | } | ||
93 | |||
94 | tv->tv_sec = sec; | ||
95 | tv->tv_usec = usec; | ||
96 | } | ||
97 | |||
98 | EXPORT_SYMBOL(do_gettimeofday); | ||
99 | |||
100 | int do_settimeofday(struct timespec *tv) | ||
101 | { | ||
102 | if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) | ||
103 | return -EINVAL; | ||
104 | |||
105 | write_lock_irq(&xtime_lock); | ||
106 | /* This is revolting. We need to set the xtime.tv_usec | ||
107 | * correctly. However, the value in this location is | ||
108 | * is value at the last tick. | ||
109 | * Discover what correction gettimeofday | ||
110 | * would have done, and then undo it! | ||
111 | */ | ||
112 | while (tv->tv_nsec < 0) { | ||
113 | tv->tv_nsec += NSEC_PER_SEC; | ||
114 | tv->tv_sec--; | ||
115 | } | ||
116 | |||
117 | xtime.tv_sec = tv->tv_sec; | ||
118 | xtime.tv_nsec = tv->tv_nsec; | ||
119 | time_adjust = 0; /* stop active adjtime() */ | ||
120 | time_status |= STA_UNSYNC; | ||
121 | time_maxerror = NTP_PHASE_LIMIT; | ||
122 | time_esterror = NTP_PHASE_LIMIT; | ||
123 | write_sequnlock_irq(&xtime_lock); | ||
124 | clock_was_set(); | ||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | EXPORT_SYMBOL(do_settimeofday); | ||
129 | |||
130 | unsigned long long sched_clock(void) | ||
131 | { | ||
132 | return (unsigned long long)jiffies * (1000000000 / HZ); | ||
133 | |||
134 | } | ||
diff --git a/arch/h8300/kernel/traps.c b/arch/h8300/kernel/traps.c new file mode 100644 index 000000000000..300e3279ca5a --- /dev/null +++ b/arch/h8300/kernel/traps.c | |||
@@ -0,0 +1,169 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/boot/traps.c -- general exception handling code | ||
3 | * H8/300 support Yoshinori Sato <ysato@users.sourceforge.jp> | ||
4 | * | ||
5 | * Cloned from Linux/m68k. | ||
6 | * | ||
7 | * No original Copyright holder listed, | ||
8 | * Probabily original (C) Roman Zippel (assigned DJD, 1999) | ||
9 | * | ||
10 | * Copyright 1999-2000 D. Jeff Dionne, <jeff@rt-control.com> | ||
11 | * | ||
12 | * This file is subject to the terms and conditions of the GNU General Public | ||
13 | * License. See the file COPYING in the main directory of this archive | ||
14 | * for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/types.h> | ||
18 | #include <linux/sched.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/module.h> | ||
23 | |||
24 | #include <asm/system.h> | ||
25 | #include <asm/irq.h> | ||
26 | #include <asm/traps.h> | ||
27 | #include <asm/page.h> | ||
28 | #include <asm/gpio.h> | ||
29 | |||
30 | /* | ||
31 | * this must be called very early as the kernel might | ||
32 | * use some instruction that are emulated on the 060 | ||
33 | */ | ||
34 | |||
35 | void __init base_trap_init(void) | ||
36 | { | ||
37 | } | ||
38 | |||
39 | void __init trap_init (void) | ||
40 | { | ||
41 | } | ||
42 | |||
43 | asmlinkage void set_esp0 (unsigned long ssp) | ||
44 | { | ||
45 | current->thread.esp0 = ssp; | ||
46 | } | ||
47 | |||
48 | /* | ||
49 | * Generic dumping code. Used for panic and debug. | ||
50 | */ | ||
51 | |||
52 | static void dump(struct pt_regs *fp) | ||
53 | { | ||
54 | unsigned long *sp; | ||
55 | unsigned char *tp; | ||
56 | int i; | ||
57 | |||
58 | printk("\nCURRENT PROCESS:\n\n"); | ||
59 | printk("COMM=%s PID=%d\n", current->comm, current->pid); | ||
60 | if (current->mm) { | ||
61 | printk("TEXT=%08x-%08x DATA=%08x-%08x BSS=%08x-%08x\n", | ||
62 | (int) current->mm->start_code, | ||
63 | (int) current->mm->end_code, | ||
64 | (int) current->mm->start_data, | ||
65 | (int) current->mm->end_data, | ||
66 | (int) current->mm->end_data, | ||
67 | (int) current->mm->brk); | ||
68 | printk("USER-STACK=%08x KERNEL-STACK=%08lx\n\n", | ||
69 | (int) current->mm->start_stack, | ||
70 | (int) PAGE_SIZE+(unsigned long)current); | ||
71 | } | ||
72 | |||
73 | show_regs(fp); | ||
74 | printk("\nCODE:"); | ||
75 | tp = ((unsigned char *) fp->pc) - 0x20; | ||
76 | for (sp = (unsigned long *) tp, i = 0; (i < 0x40); i += 4) { | ||
77 | if ((i % 0x10) == 0) | ||
78 | printk("\n%08x: ", (int) (tp + i)); | ||
79 | printk("%08x ", (int) *sp++); | ||
80 | } | ||
81 | printk("\n"); | ||
82 | |||
83 | printk("\nKERNEL STACK:"); | ||
84 | tp = ((unsigned char *) fp) - 0x40; | ||
85 | for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) { | ||
86 | if ((i % 0x10) == 0) | ||
87 | printk("\n%08x: ", (int) (tp + i)); | ||
88 | printk("%08x ", (int) *sp++); | ||
89 | } | ||
90 | printk("\n"); | ||
91 | if (STACK_MAGIC != *(unsigned long *)((unsigned long)current+PAGE_SIZE)) | ||
92 | printk("(Possibly corrupted stack page??)\n"); | ||
93 | |||
94 | printk("\n\n"); | ||
95 | } | ||
96 | |||
97 | void die_if_kernel (char *str, struct pt_regs *fp, int nr) | ||
98 | { | ||
99 | extern int console_loglevel; | ||
100 | |||
101 | if (!(fp->ccr & PS_S)) | ||
102 | return; | ||
103 | |||
104 | console_loglevel = 15; | ||
105 | dump(fp); | ||
106 | |||
107 | do_exit(SIGSEGV); | ||
108 | } | ||
109 | |||
110 | extern char _start, _etext; | ||
111 | #define check_kernel_text(addr) \ | ||
112 | ((addr >= (unsigned long)(&_start)) && \ | ||
113 | (addr < (unsigned long)(&_etext))) | ||
114 | |||
115 | static int kstack_depth_to_print = 24; | ||
116 | |||
117 | void show_stack(struct task_struct *task, unsigned long *esp) | ||
118 | { | ||
119 | unsigned long *stack, addr; | ||
120 | int i; | ||
121 | |||
122 | if (esp == NULL) | ||
123 | esp = (unsigned long *) &esp; | ||
124 | |||
125 | stack = esp; | ||
126 | |||
127 | printk("Stack from %08lx:", (unsigned long)stack); | ||
128 | for (i = 0; i < kstack_depth_to_print; i++) { | ||
129 | if (((unsigned long)stack & (THREAD_SIZE - 1)) == 0) | ||
130 | break; | ||
131 | if (i % 8 == 0) | ||
132 | printk("\n "); | ||
133 | printk(" %08lx", *stack++); | ||
134 | } | ||
135 | |||
136 | printk("\nCall Trace:"); | ||
137 | i = 0; | ||
138 | stack = esp; | ||
139 | while (((unsigned long)stack & (THREAD_SIZE - 1)) == 0) { | ||
140 | addr = *stack++; | ||
141 | /* | ||
142 | * If the address is either in the text segment of the | ||
143 | * kernel, or in the region which contains vmalloc'ed | ||
144 | * memory, it *may* be the address of a calling | ||
145 | * routine; if so, print it so that someone tracing | ||
146 | * down the cause of the crash will be able to figure | ||
147 | * out the call path that was taken. | ||
148 | */ | ||
149 | if (check_kernel_text(addr)) { | ||
150 | if (i % 4 == 0) | ||
151 | printk("\n "); | ||
152 | printk(" [<%08lx>]", addr); | ||
153 | i++; | ||
154 | } | ||
155 | } | ||
156 | printk("\n"); | ||
157 | } | ||
158 | |||
159 | void show_trace_task(struct task_struct *tsk) | ||
160 | { | ||
161 | show_stack(tsk,(unsigned long *)tsk->thread.esp0); | ||
162 | } | ||
163 | |||
164 | void dump_stack(void) | ||
165 | { | ||
166 | show_stack(NULL,NULL); | ||
167 | } | ||
168 | |||
169 | EXPORT_SYMBOL(dump_stack); | ||
diff --git a/arch/h8300/kernel/vmlinux.lds.S b/arch/h8300/kernel/vmlinux.lds.S new file mode 100644 index 000000000000..17fa11da1e4a --- /dev/null +++ b/arch/h8300/kernel/vmlinux.lds.S | |||
@@ -0,0 +1,172 @@ | |||
1 | #define VMLINUX_SYMBOL(_sym_) _##_sym_ | ||
2 | #include <asm-generic/vmlinux.lds.h> | ||
3 | #include <linux/config.h> | ||
4 | |||
5 | /* target memory map */ | ||
6 | #ifdef CONFIG_H8300H_GENERIC | ||
7 | #define ROMTOP 0x000000 | ||
8 | #define ROMSIZE 0x400000 | ||
9 | #define RAMTOP 0x400000 | ||
10 | #define RAMSIZE 0x400000 | ||
11 | #endif | ||
12 | |||
13 | #ifdef CONFIG_H8300H_AKI3068NET | ||
14 | #define ROMTOP 0x000000 | ||
15 | #define ROMSIZE 0x080000 | ||
16 | #define RAMTOP 0x400000 | ||
17 | #define RAMSIZE 0x200000 | ||
18 | #endif | ||
19 | |||
20 | #ifdef CONFIG_H8300H_H8MAX | ||
21 | #define ROMTOP 0x000000 | ||
22 | #define ROMSIZE 0x080000 | ||
23 | #define RAMTOP 0x400000 | ||
24 | #define RAMSIZE 0x200000 | ||
25 | #endif | ||
26 | |||
27 | #ifdef CONFIG_H8300H_SIM | ||
28 | #define ROMTOP 0x000000 | ||
29 | #define ROMSIZE 0x400000 | ||
30 | #define RAMTOP 0x400000 | ||
31 | #define RAMSIZE 0x400000 | ||
32 | #endif | ||
33 | |||
34 | #ifdef CONFIG_H8S_SIM | ||
35 | #define ROMTOP 0x000000 | ||
36 | #define ROMSIZE 0x400000 | ||
37 | #define RAMTOP 0x400000 | ||
38 | #define RAMSIZE 0x800000 | ||
39 | #endif | ||
40 | |||
41 | #ifdef CONFIG_H8S_EDOSK2674 | ||
42 | #define ROMTOP 0x000000 | ||
43 | #define ROMSIZE 0x400000 | ||
44 | #define RAMTOP 0x400000 | ||
45 | #define RAMSIZE 0x800000 | ||
46 | #endif | ||
47 | |||
48 | #if defined(CONFIG_H8300H_SIM) || defined(CONFIG_H8S_SIM) | ||
49 | INPUT(romfs.o) | ||
50 | #endif | ||
51 | |||
52 | _jiffies = _jiffies_64 + 4; | ||
53 | |||
54 | ENTRY(__start) | ||
55 | |||
56 | SECTIONS | ||
57 | { | ||
58 | #if defined(CONFIG_ROMKERNEL) | ||
59 | . = ROMTOP; | ||
60 | .vectors : | ||
61 | { | ||
62 | __vector = . ; | ||
63 | *(.vectors*) | ||
64 | } | ||
65 | #else | ||
66 | . = RAMTOP; | ||
67 | .bootvec : | ||
68 | { | ||
69 | *(.bootvec) | ||
70 | } | ||
71 | #endif | ||
72 | .text : | ||
73 | { | ||
74 | #if defined(CONFIG_ROMKERNEL) | ||
75 | *(.int_redirect) | ||
76 | #endif | ||
77 | __stext = . ; | ||
78 | *(.text) | ||
79 | SCHED_TEXT | ||
80 | LOCK_TEXT | ||
81 | __etext = . ; | ||
82 | . = ALIGN(16); /* Exception table */ | ||
83 | ___start___ex_table = .; | ||
84 | *(__ex_table) | ||
85 | ___stop___ex_table = .; | ||
86 | } | ||
87 | |||
88 | RODATA | ||
89 | #if defined(CONFIG_ROMKERNEL) | ||
90 | SECURITY_INIT | ||
91 | #endif | ||
92 | ROEND = .; | ||
93 | #if defined(CONFIG_ROMKERNEL) | ||
94 | . = RAMTOP; | ||
95 | .data : AT(ROEND) | ||
96 | #else | ||
97 | .data : | ||
98 | #endif | ||
99 | { | ||
100 | __sdata = . ; | ||
101 | ___data_start = . ; | ||
102 | |||
103 | . = ALIGN(0x2000) ; | ||
104 | *(.data.init_task) | ||
105 | . = ALIGN(0x4) ; | ||
106 | *(.data) | ||
107 | . = ALIGN(0x4) ; | ||
108 | *(.data.*) | ||
109 | |||
110 | . = ALIGN(0x4) ; | ||
111 | ___init_begin = .; | ||
112 | __sinittext = .; | ||
113 | *(.init.text) | ||
114 | __einittext = .; | ||
115 | *(.init.data) | ||
116 | . = ALIGN(0x4) ; | ||
117 | ___setup_start = .; | ||
118 | *(.init.setup) | ||
119 | . = ALIGN(0x4) ; | ||
120 | ___setup_end = .; | ||
121 | ___initcall_start = .; | ||
122 | *(.initcall1.init) | ||
123 | *(.initcall2.init) | ||
124 | *(.initcall3.init) | ||
125 | *(.initcall4.init) | ||
126 | *(.initcall5.init) | ||
127 | *(.initcall6.init) | ||
128 | *(.initcall7.init) | ||
129 | ___initcall_end = .; | ||
130 | ___con_initcall_start = .; | ||
131 | *(.con_initcall.init) | ||
132 | ___con_initcall_end = .; | ||
133 | *(.exit.text) | ||
134 | *(.exit.data) | ||
135 | . = ALIGN(4); | ||
136 | ___initramfs_start = .; | ||
137 | *(.init.ramfs) | ||
138 | ___initramfs_end = .; | ||
139 | . = ALIGN(0x4) ; | ||
140 | ___init_end = .; | ||
141 | __edata = . ; | ||
142 | } | ||
143 | #if defined(CONFIG_RAMKERNEL) | ||
144 | SECURITY_INIT | ||
145 | #endif | ||
146 | __begin_data = LOADADDR(.data); | ||
147 | .bss : | ||
148 | { | ||
149 | . = ALIGN(0x4) ; | ||
150 | __sbss = . ; | ||
151 | *(.bss*) | ||
152 | . = ALIGN(0x4) ; | ||
153 | *(COMMON) | ||
154 | . = ALIGN(0x4) ; | ||
155 | __ebss = . ; | ||
156 | __end = . ; | ||
157 | __ramstart = .; | ||
158 | } | ||
159 | /DISCARD/ : { | ||
160 | *(.exitcall.exit) | ||
161 | } | ||
162 | .romfs : | ||
163 | { | ||
164 | *(.romfs*) | ||
165 | } | ||
166 | . = RAMTOP+RAMSIZE; | ||
167 | .dummy : | ||
168 | { | ||
169 | COMMAND_START = . - 0x200 ; | ||
170 | __ramend = . ; | ||
171 | } | ||
172 | } | ||