diff options
Diffstat (limited to 'arch/m68k/kernel')
-rw-r--r-- | arch/m68k/kernel/ints.c | 1 | ||||
-rw-r--r-- | arch/m68k/kernel/irq.c | 1 | ||||
-rw-r--r-- | arch/m68k/kernel/process.c | 376 | ||||
-rw-r--r-- | arch/m68k/kernel/process_mm.c | 369 | ||||
-rw-r--r-- | arch/m68k/kernel/process_no.c | 406 | ||||
-rw-r--r-- | arch/m68k/kernel/ptrace.c | 305 | ||||
-rw-r--r-- | arch/m68k/kernel/ptrace_mm.c | 295 | ||||
-rw-r--r-- | arch/m68k/kernel/ptrace_no.c | 255 | ||||
-rw-r--r-- | arch/m68k/kernel/setup_no.c | 3 | ||||
-rw-r--r-- | arch/m68k/kernel/time.c | 116 | ||||
-rw-r--r-- | arch/m68k/kernel/time_mm.c | 114 | ||||
-rw-r--r-- | arch/m68k/kernel/time_no.c | 90 | ||||
-rw-r--r-- | arch/m68k/kernel/traps.c | 1 | ||||
-rw-r--r-- | arch/m68k/kernel/vectors.c | 1 | ||||
-rw-r--r-- | arch/m68k/kernel/vmlinux-nommu.lds | 200 |
15 files changed, 839 insertions, 1694 deletions
diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index 74fefac00899..6b32b64bac35 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | 16 | ||
17 | #include <asm/setup.h> | 17 | #include <asm/setup.h> |
18 | #include <asm/system.h> | ||
19 | #include <asm/irq.h> | 18 | #include <asm/irq.h> |
20 | #include <asm/traps.h> | 19 | #include <asm/traps.h> |
21 | #include <asm/page.h> | 20 | #include <asm/page.h> |
diff --git a/arch/m68k/kernel/irq.c b/arch/m68k/kernel/irq.c index c73988cfa90f..9ab4f550342e 100644 --- a/arch/m68k/kernel/irq.c +++ b/arch/m68k/kernel/irq.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
16 | #include <linux/irq.h> | 16 | #include <linux/irq.h> |
17 | #include <linux/seq_file.h> | 17 | #include <linux/seq_file.h> |
18 | #include <asm/system.h> | ||
19 | #include <asm/traps.h> | 18 | #include <asm/traps.h> |
20 | 19 | ||
21 | asmlinkage void do_IRQ(int irq, struct pt_regs *regs) | 20 | asmlinkage void do_IRQ(int irq, struct pt_regs *regs) |
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index 6cf4bd6e34f8..c488e3cfab53 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c | |||
@@ -1,5 +1,377 @@ | |||
1 | /* | ||
2 | * linux/arch/m68k/kernel/process.c | ||
3 | * | ||
4 | * Copyright (C) 1995 Hamish Macdonald | ||
5 | * | ||
6 | * 68060 fixes by Jesper Skov | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * This file handles the architecture-dependent parts of process handling.. | ||
11 | */ | ||
12 | |||
13 | #include <linux/errno.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/sched.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/mm.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/fs.h> | ||
20 | #include <linux/smp.h> | ||
21 | #include <linux/stddef.h> | ||
22 | #include <linux/unistd.h> | ||
23 | #include <linux/ptrace.h> | ||
24 | #include <linux/user.h> | ||
25 | #include <linux/reboot.h> | ||
26 | #include <linux/init_task.h> | ||
27 | #include <linux/mqueue.h> | ||
28 | |||
29 | #include <asm/uaccess.h> | ||
30 | #include <asm/traps.h> | ||
31 | #include <asm/machdep.h> | ||
32 | #include <asm/setup.h> | ||
33 | #include <asm/pgtable.h> | ||
34 | |||
35 | |||
36 | asmlinkage void ret_from_fork(void); | ||
37 | |||
38 | |||
39 | /* | ||
40 | * Return saved PC from a blocked thread | ||
41 | */ | ||
42 | unsigned long thread_saved_pc(struct task_struct *tsk) | ||
43 | { | ||
44 | struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp; | ||
45 | /* Check whether the thread is blocked in resume() */ | ||
46 | if (in_sched_functions(sw->retpc)) | ||
47 | return ((unsigned long *)sw->a6)[1]; | ||
48 | else | ||
49 | return sw->retpc; | ||
50 | } | ||
51 | |||
52 | /* | ||
53 | * The idle loop on an m68k.. | ||
54 | */ | ||
55 | static void default_idle(void) | ||
56 | { | ||
57 | if (!need_resched()) | ||
58 | #if defined(MACH_ATARI_ONLY) | ||
59 | /* block out HSYNC on the atari (falcon) */ | ||
60 | __asm__("stop #0x2200" : : : "cc"); | ||
61 | #else | ||
62 | __asm__("stop #0x2000" : : : "cc"); | ||
63 | #endif | ||
64 | } | ||
65 | |||
66 | void (*idle)(void) = default_idle; | ||
67 | |||
68 | /* | ||
69 | * The idle thread. There's no useful work to be | ||
70 | * done, so just try to conserve power and have a | ||
71 | * low exit latency (ie sit in a loop waiting for | ||
72 | * somebody to say that they'd like to reschedule) | ||
73 | */ | ||
74 | void cpu_idle(void) | ||
75 | { | ||
76 | /* endless idle loop with no priority at all */ | ||
77 | while (1) { | ||
78 | while (!need_resched()) | ||
79 | idle(); | ||
80 | schedule_preempt_disabled(); | ||
81 | } | ||
82 | } | ||
83 | |||
84 | void machine_restart(char * __unused) | ||
85 | { | ||
86 | if (mach_reset) | ||
87 | mach_reset(); | ||
88 | for (;;); | ||
89 | } | ||
90 | |||
91 | void machine_halt(void) | ||
92 | { | ||
93 | if (mach_halt) | ||
94 | mach_halt(); | ||
95 | for (;;); | ||
96 | } | ||
97 | |||
98 | void machine_power_off(void) | ||
99 | { | ||
100 | if (mach_power_off) | ||
101 | mach_power_off(); | ||
102 | for (;;); | ||
103 | } | ||
104 | |||
105 | void (*pm_power_off)(void) = machine_power_off; | ||
106 | EXPORT_SYMBOL(pm_power_off); | ||
107 | |||
108 | void show_regs(struct pt_regs * regs) | ||
109 | { | ||
110 | printk("\n"); | ||
111 | printk("Format %02x Vector: %04x PC: %08lx Status: %04x %s\n", | ||
112 | regs->format, regs->vector, regs->pc, regs->sr, print_tainted()); | ||
113 | printk("ORIG_D0: %08lx D0: %08lx A2: %08lx A1: %08lx\n", | ||
114 | regs->orig_d0, regs->d0, regs->a2, regs->a1); | ||
115 | printk("A0: %08lx D5: %08lx D4: %08lx\n", | ||
116 | regs->a0, regs->d5, regs->d4); | ||
117 | printk("D3: %08lx D2: %08lx D1: %08lx\n", | ||
118 | regs->d3, regs->d2, regs->d1); | ||
119 | if (!(regs->sr & PS_S)) | ||
120 | printk("USP: %08lx\n", rdusp()); | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | * Create a kernel thread | ||
125 | */ | ||
126 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
127 | { | ||
128 | int pid; | ||
129 | mm_segment_t fs; | ||
130 | |||
131 | fs = get_fs(); | ||
132 | set_fs (KERNEL_DS); | ||
133 | |||
134 | { | ||
135 | register long retval __asm__ ("d0"); | ||
136 | register long clone_arg __asm__ ("d1") = flags | CLONE_VM | CLONE_UNTRACED; | ||
137 | |||
138 | retval = __NR_clone; | ||
139 | __asm__ __volatile__ | ||
140 | ("clrl %%d2\n\t" | ||
141 | "trap #0\n\t" /* Linux/m68k system call */ | ||
142 | "tstl %0\n\t" /* child or parent */ | ||
143 | "jne 1f\n\t" /* parent - jump */ | ||
144 | #ifdef CONFIG_MMU | ||
145 | "lea %%sp@(%c7),%6\n\t" /* reload current */ | ||
146 | "movel %6@,%6\n\t" | ||
147 | #endif | ||
148 | "movel %3,%%sp@-\n\t" /* push argument */ | ||
149 | "jsr %4@\n\t" /* call fn */ | ||
150 | "movel %0,%%d1\n\t" /* pass exit value */ | ||
151 | "movel %2,%%d0\n\t" /* exit */ | ||
152 | "trap #0\n" | ||
153 | "1:" | ||
154 | : "+d" (retval) | ||
155 | : "i" (__NR_clone), "i" (__NR_exit), | ||
156 | "r" (arg), "a" (fn), "d" (clone_arg), "r" (current), | ||
157 | "i" (-THREAD_SIZE) | ||
158 | : "d2"); | ||
159 | |||
160 | pid = retval; | ||
161 | } | ||
162 | |||
163 | set_fs (fs); | ||
164 | return pid; | ||
165 | } | ||
166 | EXPORT_SYMBOL(kernel_thread); | ||
167 | |||
168 | void flush_thread(void) | ||
169 | { | ||
170 | current->thread.fs = __USER_DS; | ||
171 | #ifdef CONFIG_FPU | ||
172 | if (!FPU_IS_EMU) { | ||
173 | unsigned long zero = 0; | ||
174 | asm volatile("frestore %0": :"m" (zero)); | ||
175 | } | ||
176 | #endif | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * "m68k_fork()".. By the time we get here, the | ||
181 | * non-volatile registers have also been saved on the | ||
182 | * stack. We do some ugly pointer stuff here.. (see | ||
183 | * also copy_thread) | ||
184 | */ | ||
185 | |||
186 | asmlinkage int m68k_fork(struct pt_regs *regs) | ||
187 | { | ||
1 | #ifdef CONFIG_MMU | 188 | #ifdef CONFIG_MMU |
2 | #include "process_mm.c" | 189 | return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL); |
3 | #else | 190 | #else |
4 | #include "process_no.c" | 191 | return -EINVAL; |
5 | #endif | 192 | #endif |
193 | } | ||
194 | |||
195 | asmlinkage int m68k_vfork(struct pt_regs *regs) | ||
196 | { | ||
197 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, | ||
198 | NULL, NULL); | ||
199 | } | ||
200 | |||
201 | asmlinkage int m68k_clone(struct pt_regs *regs) | ||
202 | { | ||
203 | unsigned long clone_flags; | ||
204 | unsigned long newsp; | ||
205 | int __user *parent_tidptr, *child_tidptr; | ||
206 | |||
207 | /* syscall2 puts clone_flags in d1 and usp in d2 */ | ||
208 | clone_flags = regs->d1; | ||
209 | newsp = regs->d2; | ||
210 | parent_tidptr = (int __user *)regs->d3; | ||
211 | child_tidptr = (int __user *)regs->d4; | ||
212 | if (!newsp) | ||
213 | newsp = rdusp(); | ||
214 | return do_fork(clone_flags, newsp, regs, 0, | ||
215 | parent_tidptr, child_tidptr); | ||
216 | } | ||
217 | |||
218 | int copy_thread(unsigned long clone_flags, unsigned long usp, | ||
219 | unsigned long unused, | ||
220 | struct task_struct * p, struct pt_regs * regs) | ||
221 | { | ||
222 | struct pt_regs * childregs; | ||
223 | struct switch_stack * childstack, *stack; | ||
224 | unsigned long *retp; | ||
225 | |||
226 | childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; | ||
227 | |||
228 | *childregs = *regs; | ||
229 | childregs->d0 = 0; | ||
230 | |||
231 | retp = ((unsigned long *) regs); | ||
232 | stack = ((struct switch_stack *) retp) - 1; | ||
233 | |||
234 | childstack = ((struct switch_stack *) childregs) - 1; | ||
235 | *childstack = *stack; | ||
236 | childstack->retpc = (unsigned long)ret_from_fork; | ||
237 | |||
238 | p->thread.usp = usp; | ||
239 | p->thread.ksp = (unsigned long)childstack; | ||
240 | |||
241 | if (clone_flags & CLONE_SETTLS) | ||
242 | task_thread_info(p)->tp_value = regs->d5; | ||
243 | |||
244 | /* | ||
245 | * Must save the current SFC/DFC value, NOT the value when | ||
246 | * the parent was last descheduled - RGH 10-08-96 | ||
247 | */ | ||
248 | p->thread.fs = get_fs().seg; | ||
249 | |||
250 | #ifdef CONFIG_FPU | ||
251 | if (!FPU_IS_EMU) { | ||
252 | /* Copy the current fpu state */ | ||
253 | asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory"); | ||
254 | |||
255 | if (!CPU_IS_060 ? p->thread.fpstate[0] : p->thread.fpstate[2]) { | ||
256 | if (CPU_IS_COLDFIRE) { | ||
257 | asm volatile ("fmovemd %/fp0-%/fp7,%0\n\t" | ||
258 | "fmovel %/fpiar,%1\n\t" | ||
259 | "fmovel %/fpcr,%2\n\t" | ||
260 | "fmovel %/fpsr,%3" | ||
261 | : | ||
262 | : "m" (p->thread.fp[0]), | ||
263 | "m" (p->thread.fpcntl[0]), | ||
264 | "m" (p->thread.fpcntl[1]), | ||
265 | "m" (p->thread.fpcntl[2]) | ||
266 | : "memory"); | ||
267 | } else { | ||
268 | asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t" | ||
269 | "fmoveml %/fpiar/%/fpcr/%/fpsr,%1" | ||
270 | : | ||
271 | : "m" (p->thread.fp[0]), | ||
272 | "m" (p->thread.fpcntl[0]) | ||
273 | : "memory"); | ||
274 | } | ||
275 | } | ||
276 | |||
277 | /* Restore the state in case the fpu was busy */ | ||
278 | asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0])); | ||
279 | } | ||
280 | #endif /* CONFIG_FPU */ | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | /* Fill in the fpu structure for a core dump. */ | ||
286 | #ifdef CONFIG_FPU | ||
287 | int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu) | ||
288 | { | ||
289 | char fpustate[216]; | ||
290 | |||
291 | if (FPU_IS_EMU) { | ||
292 | int i; | ||
293 | |||
294 | memcpy(fpu->fpcntl, current->thread.fpcntl, 12); | ||
295 | memcpy(fpu->fpregs, current->thread.fp, 96); | ||
296 | /* Convert internal fpu reg representation | ||
297 | * into long double format | ||
298 | */ | ||
299 | for (i = 0; i < 24; i += 3) | ||
300 | fpu->fpregs[i] = ((fpu->fpregs[i] & 0xffff0000) << 15) | | ||
301 | ((fpu->fpregs[i] & 0x0000ffff) << 16); | ||
302 | return 1; | ||
303 | } | ||
304 | |||
305 | /* First dump the fpu context to avoid protocol violation. */ | ||
306 | asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory"); | ||
307 | if (!CPU_IS_060 ? !fpustate[0] : !fpustate[2]) | ||
308 | return 0; | ||
309 | |||
310 | if (CPU_IS_COLDFIRE) { | ||
311 | asm volatile ("fmovel %/fpiar,%0\n\t" | ||
312 | "fmovel %/fpcr,%1\n\t" | ||
313 | "fmovel %/fpsr,%2\n\t" | ||
314 | "fmovemd %/fp0-%/fp7,%3" | ||
315 | : | ||
316 | : "m" (fpu->fpcntl[0]), | ||
317 | "m" (fpu->fpcntl[1]), | ||
318 | "m" (fpu->fpcntl[2]), | ||
319 | "m" (fpu->fpregs[0]) | ||
320 | : "memory"); | ||
321 | } else { | ||
322 | asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0" | ||
323 | : | ||
324 | : "m" (fpu->fpcntl[0]) | ||
325 | : "memory"); | ||
326 | asm volatile ("fmovemx %/fp0-%/fp7,%0" | ||
327 | : | ||
328 | : "m" (fpu->fpregs[0]) | ||
329 | : "memory"); | ||
330 | } | ||
331 | |||
332 | return 1; | ||
333 | } | ||
334 | EXPORT_SYMBOL(dump_fpu); | ||
335 | #endif /* CONFIG_FPU */ | ||
336 | |||
337 | /* | ||
338 | * sys_execve() executes a new program. | ||
339 | */ | ||
340 | asmlinkage int sys_execve(const char __user *name, | ||
341 | const char __user *const __user *argv, | ||
342 | const char __user *const __user *envp) | ||
343 | { | ||
344 | int error; | ||
345 | char * filename; | ||
346 | struct pt_regs *regs = (struct pt_regs *) &name; | ||
347 | |||
348 | filename = getname(name); | ||
349 | error = PTR_ERR(filename); | ||
350 | if (IS_ERR(filename)) | ||
351 | return error; | ||
352 | error = do_execve(filename, argv, envp, regs); | ||
353 | putname(filename); | ||
354 | return error; | ||
355 | } | ||
356 | |||
357 | unsigned long get_wchan(struct task_struct *p) | ||
358 | { | ||
359 | unsigned long fp, pc; | ||
360 | unsigned long stack_page; | ||
361 | int count = 0; | ||
362 | if (!p || p == current || p->state == TASK_RUNNING) | ||
363 | return 0; | ||
364 | |||
365 | stack_page = (unsigned long)task_stack_page(p); | ||
366 | fp = ((struct switch_stack *)p->thread.ksp)->a6; | ||
367 | do { | ||
368 | if (fp < stack_page+sizeof(struct thread_info) || | ||
369 | fp >= 8184+stack_page) | ||
370 | return 0; | ||
371 | pc = ((unsigned long *)fp)[1]; | ||
372 | if (!in_sched_functions(pc)) | ||
373 | return pc; | ||
374 | fp = *(unsigned long *) fp; | ||
375 | } while (count++ < 16); | ||
376 | return 0; | ||
377 | } | ||
diff --git a/arch/m68k/kernel/process_mm.c b/arch/m68k/kernel/process_mm.c deleted file mode 100644 index 099283ee1a8f..000000000000 --- a/arch/m68k/kernel/process_mm.c +++ /dev/null | |||
@@ -1,369 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/m68k/kernel/process.c | ||
3 | * | ||
4 | * Copyright (C) 1995 Hamish Macdonald | ||
5 | * | ||
6 | * 68060 fixes by Jesper Skov | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * This file handles the architecture-dependent parts of process handling.. | ||
11 | */ | ||
12 | |||
13 | #include <linux/errno.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/sched.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/mm.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/fs.h> | ||
20 | #include <linux/smp.h> | ||
21 | #include <linux/stddef.h> | ||
22 | #include <linux/unistd.h> | ||
23 | #include <linux/ptrace.h> | ||
24 | #include <linux/user.h> | ||
25 | #include <linux/reboot.h> | ||
26 | #include <linux/init_task.h> | ||
27 | #include <linux/mqueue.h> | ||
28 | |||
29 | #include <asm/uaccess.h> | ||
30 | #include <asm/system.h> | ||
31 | #include <asm/traps.h> | ||
32 | #include <asm/machdep.h> | ||
33 | #include <asm/setup.h> | ||
34 | #include <asm/pgtable.h> | ||
35 | |||
36 | |||
37 | asmlinkage void ret_from_fork(void); | ||
38 | |||
39 | |||
40 | /* | ||
41 | * Return saved PC from a blocked thread | ||
42 | */ | ||
43 | unsigned long thread_saved_pc(struct task_struct *tsk) | ||
44 | { | ||
45 | struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp; | ||
46 | /* Check whether the thread is blocked in resume() */ | ||
47 | if (in_sched_functions(sw->retpc)) | ||
48 | return ((unsigned long *)sw->a6)[1]; | ||
49 | else | ||
50 | return sw->retpc; | ||
51 | } | ||
52 | |||
53 | /* | ||
54 | * The idle loop on an m68k.. | ||
55 | */ | ||
56 | static void default_idle(void) | ||
57 | { | ||
58 | if (!need_resched()) | ||
59 | #if defined(MACH_ATARI_ONLY) | ||
60 | /* block out HSYNC on the atari (falcon) */ | ||
61 | __asm__("stop #0x2200" : : : "cc"); | ||
62 | #else | ||
63 | __asm__("stop #0x2000" : : : "cc"); | ||
64 | #endif | ||
65 | } | ||
66 | |||
67 | void (*idle)(void) = default_idle; | ||
68 | |||
69 | /* | ||
70 | * The idle thread. There's no useful work to be | ||
71 | * done, so just try to conserve power and have a | ||
72 | * low exit latency (ie sit in a loop waiting for | ||
73 | * somebody to say that they'd like to reschedule) | ||
74 | */ | ||
75 | void cpu_idle(void) | ||
76 | { | ||
77 | /* endless idle loop with no priority at all */ | ||
78 | while (1) { | ||
79 | while (!need_resched()) | ||
80 | idle(); | ||
81 | preempt_enable_no_resched(); | ||
82 | schedule(); | ||
83 | preempt_disable(); | ||
84 | } | ||
85 | } | ||
86 | |||
87 | void machine_restart(char * __unused) | ||
88 | { | ||
89 | if (mach_reset) | ||
90 | mach_reset(); | ||
91 | for (;;); | ||
92 | } | ||
93 | |||
94 | void machine_halt(void) | ||
95 | { | ||
96 | if (mach_halt) | ||
97 | mach_halt(); | ||
98 | for (;;); | ||
99 | } | ||
100 | |||
101 | void machine_power_off(void) | ||
102 | { | ||
103 | if (mach_power_off) | ||
104 | mach_power_off(); | ||
105 | for (;;); | ||
106 | } | ||
107 | |||
108 | void (*pm_power_off)(void) = machine_power_off; | ||
109 | EXPORT_SYMBOL(pm_power_off); | ||
110 | |||
111 | void show_regs(struct pt_regs * regs) | ||
112 | { | ||
113 | printk("\n"); | ||
114 | printk("Format %02x Vector: %04x PC: %08lx Status: %04x %s\n", | ||
115 | regs->format, regs->vector, regs->pc, regs->sr, print_tainted()); | ||
116 | printk("ORIG_D0: %08lx D0: %08lx A2: %08lx A1: %08lx\n", | ||
117 | regs->orig_d0, regs->d0, regs->a2, regs->a1); | ||
118 | printk("A0: %08lx D5: %08lx D4: %08lx\n", | ||
119 | regs->a0, regs->d5, regs->d4); | ||
120 | printk("D3: %08lx D2: %08lx D1: %08lx\n", | ||
121 | regs->d3, regs->d2, regs->d1); | ||
122 | if (!(regs->sr & PS_S)) | ||
123 | printk("USP: %08lx\n", rdusp()); | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * Create a kernel thread | ||
128 | */ | ||
129 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
130 | { | ||
131 | int pid; | ||
132 | mm_segment_t fs; | ||
133 | |||
134 | fs = get_fs(); | ||
135 | set_fs (KERNEL_DS); | ||
136 | |||
137 | { | ||
138 | register long retval __asm__ ("d0"); | ||
139 | register long clone_arg __asm__ ("d1") = flags | CLONE_VM | CLONE_UNTRACED; | ||
140 | |||
141 | retval = __NR_clone; | ||
142 | __asm__ __volatile__ | ||
143 | ("clrl %%d2\n\t" | ||
144 | "trap #0\n\t" /* Linux/m68k system call */ | ||
145 | "tstl %0\n\t" /* child or parent */ | ||
146 | "jne 1f\n\t" /* parent - jump */ | ||
147 | "lea %%sp@(%c7),%6\n\t" /* reload current */ | ||
148 | "movel %6@,%6\n\t" | ||
149 | "movel %3,%%sp@-\n\t" /* push argument */ | ||
150 | "jsr %4@\n\t" /* call fn */ | ||
151 | "movel %0,%%d1\n\t" /* pass exit value */ | ||
152 | "movel %2,%%d0\n\t" /* exit */ | ||
153 | "trap #0\n" | ||
154 | "1:" | ||
155 | : "+d" (retval) | ||
156 | : "i" (__NR_clone), "i" (__NR_exit), | ||
157 | "r" (arg), "a" (fn), "d" (clone_arg), "r" (current), | ||
158 | "i" (-THREAD_SIZE) | ||
159 | : "d2"); | ||
160 | |||
161 | pid = retval; | ||
162 | } | ||
163 | |||
164 | set_fs (fs); | ||
165 | return pid; | ||
166 | } | ||
167 | EXPORT_SYMBOL(kernel_thread); | ||
168 | |||
169 | void flush_thread(void) | ||
170 | { | ||
171 | unsigned long zero = 0; | ||
172 | |||
173 | current->thread.fs = __USER_DS; | ||
174 | if (!FPU_IS_EMU) | ||
175 | asm volatile("frestore %0": :"m" (zero)); | ||
176 | } | ||
177 | |||
178 | /* | ||
179 | * "m68k_fork()".. By the time we get here, the | ||
180 | * non-volatile registers have also been saved on the | ||
181 | * stack. We do some ugly pointer stuff here.. (see | ||
182 | * also copy_thread) | ||
183 | */ | ||
184 | |||
185 | asmlinkage int m68k_fork(struct pt_regs *regs) | ||
186 | { | ||
187 | return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL); | ||
188 | } | ||
189 | |||
190 | asmlinkage int m68k_vfork(struct pt_regs *regs) | ||
191 | { | ||
192 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, | ||
193 | NULL, NULL); | ||
194 | } | ||
195 | |||
196 | asmlinkage int m68k_clone(struct pt_regs *regs) | ||
197 | { | ||
198 | unsigned long clone_flags; | ||
199 | unsigned long newsp; | ||
200 | int __user *parent_tidptr, *child_tidptr; | ||
201 | |||
202 | /* syscall2 puts clone_flags in d1 and usp in d2 */ | ||
203 | clone_flags = regs->d1; | ||
204 | newsp = regs->d2; | ||
205 | parent_tidptr = (int __user *)regs->d3; | ||
206 | child_tidptr = (int __user *)regs->d4; | ||
207 | if (!newsp) | ||
208 | newsp = rdusp(); | ||
209 | return do_fork(clone_flags, newsp, regs, 0, | ||
210 | parent_tidptr, child_tidptr); | ||
211 | } | ||
212 | |||
213 | int copy_thread(unsigned long clone_flags, unsigned long usp, | ||
214 | unsigned long unused, | ||
215 | struct task_struct * p, struct pt_regs * regs) | ||
216 | { | ||
217 | struct pt_regs * childregs; | ||
218 | struct switch_stack * childstack, *stack; | ||
219 | unsigned long *retp; | ||
220 | |||
221 | childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; | ||
222 | |||
223 | *childregs = *regs; | ||
224 | childregs->d0 = 0; | ||
225 | |||
226 | retp = ((unsigned long *) regs); | ||
227 | stack = ((struct switch_stack *) retp) - 1; | ||
228 | |||
229 | childstack = ((struct switch_stack *) childregs) - 1; | ||
230 | *childstack = *stack; | ||
231 | childstack->retpc = (unsigned long)ret_from_fork; | ||
232 | |||
233 | p->thread.usp = usp; | ||
234 | p->thread.ksp = (unsigned long)childstack; | ||
235 | |||
236 | if (clone_flags & CLONE_SETTLS) | ||
237 | task_thread_info(p)->tp_value = regs->d5; | ||
238 | |||
239 | /* | ||
240 | * Must save the current SFC/DFC value, NOT the value when | ||
241 | * the parent was last descheduled - RGH 10-08-96 | ||
242 | */ | ||
243 | p->thread.fs = get_fs().seg; | ||
244 | |||
245 | if (!FPU_IS_EMU) { | ||
246 | /* Copy the current fpu state */ | ||
247 | asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory"); | ||
248 | |||
249 | if (!CPU_IS_060 ? p->thread.fpstate[0] : p->thread.fpstate[2]) { | ||
250 | if (CPU_IS_COLDFIRE) { | ||
251 | asm volatile ("fmovemd %/fp0-%/fp7,%0\n\t" | ||
252 | "fmovel %/fpiar,%1\n\t" | ||
253 | "fmovel %/fpcr,%2\n\t" | ||
254 | "fmovel %/fpsr,%3" | ||
255 | : | ||
256 | : "m" (p->thread.fp[0]), | ||
257 | "m" (p->thread.fpcntl[0]), | ||
258 | "m" (p->thread.fpcntl[1]), | ||
259 | "m" (p->thread.fpcntl[2]) | ||
260 | : "memory"); | ||
261 | } else { | ||
262 | asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t" | ||
263 | "fmoveml %/fpiar/%/fpcr/%/fpsr,%1" | ||
264 | : | ||
265 | : "m" (p->thread.fp[0]), | ||
266 | "m" (p->thread.fpcntl[0]) | ||
267 | : "memory"); | ||
268 | } | ||
269 | } | ||
270 | |||
271 | /* Restore the state in case the fpu was busy */ | ||
272 | asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0])); | ||
273 | } | ||
274 | |||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | /* Fill in the fpu structure for a core dump. */ | ||
279 | |||
280 | int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu) | ||
281 | { | ||
282 | char fpustate[216]; | ||
283 | |||
284 | if (FPU_IS_EMU) { | ||
285 | int i; | ||
286 | |||
287 | memcpy(fpu->fpcntl, current->thread.fpcntl, 12); | ||
288 | memcpy(fpu->fpregs, current->thread.fp, 96); | ||
289 | /* Convert internal fpu reg representation | ||
290 | * into long double format | ||
291 | */ | ||
292 | for (i = 0; i < 24; i += 3) | ||
293 | fpu->fpregs[i] = ((fpu->fpregs[i] & 0xffff0000) << 15) | | ||
294 | ((fpu->fpregs[i] & 0x0000ffff) << 16); | ||
295 | return 1; | ||
296 | } | ||
297 | |||
298 | /* First dump the fpu context to avoid protocol violation. */ | ||
299 | asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory"); | ||
300 | if (!CPU_IS_060 ? !fpustate[0] : !fpustate[2]) | ||
301 | return 0; | ||
302 | |||
303 | if (CPU_IS_COLDFIRE) { | ||
304 | asm volatile ("fmovel %/fpiar,%0\n\t" | ||
305 | "fmovel %/fpcr,%1\n\t" | ||
306 | "fmovel %/fpsr,%2\n\t" | ||
307 | "fmovemd %/fp0-%/fp7,%3" | ||
308 | : | ||
309 | : "m" (fpu->fpcntl[0]), | ||
310 | "m" (fpu->fpcntl[1]), | ||
311 | "m" (fpu->fpcntl[2]), | ||
312 | "m" (fpu->fpregs[0]) | ||
313 | : "memory"); | ||
314 | } else { | ||
315 | asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0" | ||
316 | : | ||
317 | : "m" (fpu->fpcntl[0]) | ||
318 | : "memory"); | ||
319 | asm volatile ("fmovemx %/fp0-%/fp7,%0" | ||
320 | : | ||
321 | : "m" (fpu->fpregs[0]) | ||
322 | : "memory"); | ||
323 | } | ||
324 | |||
325 | return 1; | ||
326 | } | ||
327 | EXPORT_SYMBOL(dump_fpu); | ||
328 | |||
329 | /* | ||
330 | * sys_execve() executes a new program. | ||
331 | */ | ||
332 | asmlinkage int sys_execve(const char __user *name, | ||
333 | const char __user *const __user *argv, | ||
334 | const char __user *const __user *envp) | ||
335 | { | ||
336 | int error; | ||
337 | char * filename; | ||
338 | struct pt_regs *regs = (struct pt_regs *) &name; | ||
339 | |||
340 | filename = getname(name); | ||
341 | error = PTR_ERR(filename); | ||
342 | if (IS_ERR(filename)) | ||
343 | return error; | ||
344 | error = do_execve(filename, argv, envp, regs); | ||
345 | putname(filename); | ||
346 | return error; | ||
347 | } | ||
348 | |||
349 | unsigned long get_wchan(struct task_struct *p) | ||
350 | { | ||
351 | unsigned long fp, pc; | ||
352 | unsigned long stack_page; | ||
353 | int count = 0; | ||
354 | if (!p || p == current || p->state == TASK_RUNNING) | ||
355 | return 0; | ||
356 | |||
357 | stack_page = (unsigned long)task_stack_page(p); | ||
358 | fp = ((struct switch_stack *)p->thread.ksp)->a6; | ||
359 | do { | ||
360 | if (fp < stack_page+sizeof(struct thread_info) || | ||
361 | fp >= 8184+stack_page) | ||
362 | return 0; | ||
363 | pc = ((unsigned long *)fp)[1]; | ||
364 | if (!in_sched_functions(pc)) | ||
365 | return pc; | ||
366 | fp = *(unsigned long *) fp; | ||
367 | } while (count++ < 16); | ||
368 | return 0; | ||
369 | } | ||
diff --git a/arch/m68k/kernel/process_no.c b/arch/m68k/kernel/process_no.c deleted file mode 100644 index 5e1078cabe0e..000000000000 --- a/arch/m68k/kernel/process_no.c +++ /dev/null | |||
@@ -1,406 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/m68knommu/kernel/process.c | ||
3 | * | ||
4 | * Copyright (C) 1995 Hamish Macdonald | ||
5 | * | ||
6 | * 68060 fixes by Jesper Skov | ||
7 | * | ||
8 | * uClinux changes | ||
9 | * Copyright (C) 2000-2002, David McCullough <davidm@snapgear.com> | ||
10 | */ | ||
11 | |||
12 | /* | ||
13 | * This file handles the architecture-dependent parts of process handling.. | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/errno.h> | ||
18 | #include <linux/sched.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/mm.h> | ||
21 | #include <linux/smp.h> | ||
22 | #include <linux/stddef.h> | ||
23 | #include <linux/unistd.h> | ||
24 | #include <linux/ptrace.h> | ||
25 | #include <linux/user.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/reboot.h> | ||
28 | #include <linux/fs.h> | ||
29 | #include <linux/slab.h> | ||
30 | |||
31 | #include <asm/uaccess.h> | ||
32 | #include <asm/system.h> | ||
33 | #include <asm/traps.h> | ||
34 | #include <asm/machdep.h> | ||
35 | #include <asm/setup.h> | ||
36 | #include <asm/pgtable.h> | ||
37 | |||
38 | asmlinkage void ret_from_fork(void); | ||
39 | |||
40 | /* | ||
41 | * The following aren't currently used. | ||
42 | */ | ||
43 | void (*pm_idle)(void); | ||
44 | EXPORT_SYMBOL(pm_idle); | ||
45 | |||
46 | void (*pm_power_off)(void); | ||
47 | EXPORT_SYMBOL(pm_power_off); | ||
48 | |||
49 | /* | ||
50 | * The idle loop on an m68knommu.. | ||
51 | */ | ||
52 | static void default_idle(void) | ||
53 | { | ||
54 | local_irq_disable(); | ||
55 | while (!need_resched()) { | ||
56 | /* This stop will re-enable interrupts */ | ||
57 | __asm__("stop #0x2000" : : : "cc"); | ||
58 | local_irq_disable(); | ||
59 | } | ||
60 | local_irq_enable(); | ||
61 | } | ||
62 | |||
63 | void (*idle)(void) = default_idle; | ||
64 | |||
65 | /* | ||
66 | * The idle thread. There's no useful work to be | ||
67 | * done, so just try to conserve power and have a | ||
68 | * low exit latency (ie sit in a loop waiting for | ||
69 | * somebody to say that they'd like to reschedule) | ||
70 | */ | ||
71 | void cpu_idle(void) | ||
72 | { | ||
73 | /* endless idle loop with no priority at all */ | ||
74 | while (1) { | ||
75 | idle(); | ||
76 | preempt_enable_no_resched(); | ||
77 | schedule(); | ||
78 | preempt_disable(); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | void machine_restart(char * __unused) | ||
83 | { | ||
84 | if (mach_reset) | ||
85 | mach_reset(); | ||
86 | for (;;); | ||
87 | } | ||
88 | |||
89 | void machine_halt(void) | ||
90 | { | ||
91 | if (mach_halt) | ||
92 | mach_halt(); | ||
93 | for (;;); | ||
94 | } | ||
95 | |||
96 | void machine_power_off(void) | ||
97 | { | ||
98 | if (mach_power_off) | ||
99 | mach_power_off(); | ||
100 | for (;;); | ||
101 | } | ||
102 | |||
103 | void show_regs(struct pt_regs * regs) | ||
104 | { | ||
105 | printk(KERN_NOTICE "\n"); | ||
106 | printk(KERN_NOTICE "Format %02x Vector: %04x PC: %08lx Status: %04x %s\n", | ||
107 | regs->format, regs->vector, regs->pc, regs->sr, print_tainted()); | ||
108 | printk(KERN_NOTICE "ORIG_D0: %08lx D0: %08lx A2: %08lx A1: %08lx\n", | ||
109 | regs->orig_d0, regs->d0, regs->a2, regs->a1); | ||
110 | printk(KERN_NOTICE "A0: %08lx D5: %08lx D4: %08lx\n", | ||
111 | regs->a0, regs->d5, regs->d4); | ||
112 | printk(KERN_NOTICE "D3: %08lx D2: %08lx D1: %08lx\n", | ||
113 | regs->d3, regs->d2, regs->d1); | ||
114 | if (!(regs->sr & PS_S)) | ||
115 | printk(KERN_NOTICE "USP: %08lx\n", rdusp()); | ||
116 | } | ||
117 | |||
118 | /* | ||
119 | * Create a kernel thread | ||
120 | */ | ||
121 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
122 | { | ||
123 | int retval; | ||
124 | long clone_arg = flags | CLONE_VM; | ||
125 | mm_segment_t fs; | ||
126 | |||
127 | fs = get_fs(); | ||
128 | set_fs(KERNEL_DS); | ||
129 | |||
130 | __asm__ __volatile__ ( | ||
131 | "movel %%sp, %%d2\n\t" | ||
132 | "movel %5, %%d1\n\t" | ||
133 | "movel %1, %%d0\n\t" | ||
134 | "trap #0\n\t" | ||
135 | "cmpl %%sp, %%d2\n\t" | ||
136 | "jeq 1f\n\t" | ||
137 | "movel %3, %%sp@-\n\t" | ||
138 | "jsr %4@\n\t" | ||
139 | "movel %2, %%d0\n\t" | ||
140 | "trap #0\n" | ||
141 | "1:\n\t" | ||
142 | "movel %%d0, %0\n" | ||
143 | : "=d" (retval) | ||
144 | : "i" (__NR_clone), | ||
145 | "i" (__NR_exit), | ||
146 | "a" (arg), | ||
147 | "a" (fn), | ||
148 | "a" (clone_arg) | ||
149 | : "cc", "%d0", "%d1", "%d2"); | ||
150 | |||
151 | set_fs(fs); | ||
152 | return retval; | ||
153 | } | ||
154 | EXPORT_SYMBOL(kernel_thread); | ||
155 | |||
156 | void flush_thread(void) | ||
157 | { | ||
158 | #ifdef CONFIG_FPU | ||
159 | unsigned long zero = 0; | ||
160 | #endif | ||
161 | |||
162 | current->thread.fs = __USER_DS; | ||
163 | #ifdef CONFIG_FPU | ||
164 | if (!FPU_IS_EMU) | ||
165 | asm volatile (".chip 68k/68881\n\t" | ||
166 | "frestore %0\n\t" | ||
167 | ".chip 68k" : : "m" (zero)); | ||
168 | #endif | ||
169 | } | ||
170 | |||
171 | /* | ||
172 | * "m68k_fork()".. By the time we get here, the | ||
173 | * non-volatile registers have also been saved on the | ||
174 | * stack. We do some ugly pointer stuff here.. (see | ||
175 | * also copy_thread) | ||
176 | */ | ||
177 | |||
178 | asmlinkage int m68k_fork(struct pt_regs *regs) | ||
179 | { | ||
180 | /* fork almost works, enough to trick you into looking elsewhere :-( */ | ||
181 | return(-EINVAL); | ||
182 | } | ||
183 | |||
184 | asmlinkage int m68k_vfork(struct pt_regs *regs) | ||
185 | { | ||
186 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL); | ||
187 | } | ||
188 | |||
189 | asmlinkage int m68k_clone(struct pt_regs *regs) | ||
190 | { | ||
191 | unsigned long clone_flags; | ||
192 | unsigned long newsp; | ||
193 | |||
194 | /* syscall2 puts clone_flags in d1 and usp in d2 */ | ||
195 | clone_flags = regs->d1; | ||
196 | newsp = regs->d2; | ||
197 | if (!newsp) | ||
198 | newsp = rdusp(); | ||
199 | return do_fork(clone_flags, newsp, regs, 0, NULL, NULL); | ||
200 | } | ||
201 | |||
202 | int copy_thread(unsigned long clone_flags, | ||
203 | unsigned long usp, unsigned long topstk, | ||
204 | struct task_struct * p, struct pt_regs * regs) | ||
205 | { | ||
206 | struct pt_regs * childregs; | ||
207 | struct switch_stack * childstack, *stack; | ||
208 | unsigned long *retp; | ||
209 | |||
210 | childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; | ||
211 | |||
212 | *childregs = *regs; | ||
213 | childregs->d0 = 0; | ||
214 | |||
215 | retp = ((unsigned long *) regs); | ||
216 | stack = ((struct switch_stack *) retp) - 1; | ||
217 | |||
218 | childstack = ((struct switch_stack *) childregs) - 1; | ||
219 | *childstack = *stack; | ||
220 | childstack->retpc = (unsigned long)ret_from_fork; | ||
221 | |||
222 | p->thread.usp = usp; | ||
223 | p->thread.ksp = (unsigned long)childstack; | ||
224 | |||
225 | if (clone_flags & CLONE_SETTLS) | ||
226 | task_thread_info(p)->tp_value = regs->d5; | ||
227 | |||
228 | /* | ||
229 | * Must save the current SFC/DFC value, NOT the value when | ||
230 | * the parent was last descheduled - RGH 10-08-96 | ||
231 | */ | ||
232 | p->thread.fs = get_fs().seg; | ||
233 | |||
234 | #ifdef CONFIG_FPU | ||
235 | if (!FPU_IS_EMU) { | ||
236 | /* Copy the current fpu state */ | ||
237 | asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory"); | ||
238 | |||
239 | if (p->thread.fpstate[0]) | ||
240 | asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t" | ||
241 | "fmoveml %/fpiar/%/fpcr/%/fpsr,%1" | ||
242 | : : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0]) | ||
243 | : "memory"); | ||
244 | /* Restore the state in case the fpu was busy */ | ||
245 | asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0])); | ||
246 | } | ||
247 | #endif | ||
248 | |||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | /* Fill in the fpu structure for a core dump. */ | ||
253 | |||
254 | int dump_fpu(struct pt_regs *regs, struct user_m68kfp_struct *fpu) | ||
255 | { | ||
256 | #ifdef CONFIG_FPU | ||
257 | char fpustate[216]; | ||
258 | |||
259 | if (FPU_IS_EMU) { | ||
260 | int i; | ||
261 | |||
262 | memcpy(fpu->fpcntl, current->thread.fpcntl, 12); | ||
263 | memcpy(fpu->fpregs, current->thread.fp, 96); | ||
264 | /* Convert internal fpu reg representation | ||
265 | * into long double format | ||
266 | */ | ||
267 | for (i = 0; i < 24; i += 3) | ||
268 | fpu->fpregs[i] = ((fpu->fpregs[i] & 0xffff0000) << 15) | | ||
269 | ((fpu->fpregs[i] & 0x0000ffff) << 16); | ||
270 | return 1; | ||
271 | } | ||
272 | |||
273 | /* First dump the fpu context to avoid protocol violation. */ | ||
274 | asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory"); | ||
275 | if (!fpustate[0]) | ||
276 | return 0; | ||
277 | |||
278 | asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0" | ||
279 | :: "m" (fpu->fpcntl[0]) | ||
280 | : "memory"); | ||
281 | asm volatile ("fmovemx %/fp0-%/fp7,%0" | ||
282 | :: "m" (fpu->fpregs[0]) | ||
283 | : "memory"); | ||
284 | #endif | ||
285 | return 1; | ||
286 | } | ||
287 | EXPORT_SYMBOL(dump_fpu); | ||
288 | |||
289 | /* | ||
290 | * Generic dumping code. Used for panic and debug. | ||
291 | */ | ||
292 | void dump(struct pt_regs *fp) | ||
293 | { | ||
294 | unsigned long *sp; | ||
295 | unsigned char *tp; | ||
296 | int i; | ||
297 | |||
298 | printk(KERN_EMERG "\nCURRENT PROCESS:\n\n"); | ||
299 | printk(KERN_EMERG "COMM=%s PID=%d\n", current->comm, current->pid); | ||
300 | |||
301 | if (current->mm) { | ||
302 | printk(KERN_EMERG "TEXT=%08x-%08x DATA=%08x-%08x BSS=%08x-%08x\n", | ||
303 | (int) current->mm->start_code, | ||
304 | (int) current->mm->end_code, | ||
305 | (int) current->mm->start_data, | ||
306 | (int) current->mm->end_data, | ||
307 | (int) current->mm->end_data, | ||
308 | (int) current->mm->brk); | ||
309 | printk(KERN_EMERG "USER-STACK=%08x KERNEL-STACK=%08x\n\n", | ||
310 | (int) current->mm->start_stack, | ||
311 | (int)(((unsigned long) current) + THREAD_SIZE)); | ||
312 | } | ||
313 | |||
314 | printk(KERN_EMERG "PC: %08lx\n", fp->pc); | ||
315 | printk(KERN_EMERG "SR: %08lx SP: %08lx\n", (long) fp->sr, (long) fp); | ||
316 | printk(KERN_EMERG "d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", | ||
317 | fp->d0, fp->d1, fp->d2, fp->d3); | ||
318 | printk(KERN_EMERG "d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", | ||
319 | fp->d4, fp->d5, fp->a0, fp->a1); | ||
320 | printk(KERN_EMERG "\nUSP: %08x TRAPFRAME: %p\n", | ||
321 | (unsigned int) rdusp(), fp); | ||
322 | |||
323 | printk(KERN_EMERG "\nCODE:"); | ||
324 | tp = ((unsigned char *) fp->pc) - 0x20; | ||
325 | for (sp = (unsigned long *) tp, i = 0; (i < 0x40); i += 4) { | ||
326 | if ((i % 0x10) == 0) | ||
327 | printk(KERN_EMERG "%p: ", tp + i); | ||
328 | printk("%08x ", (int) *sp++); | ||
329 | } | ||
330 | printk(KERN_EMERG "\n"); | ||
331 | |||
332 | printk(KERN_EMERG "KERNEL STACK:"); | ||
333 | tp = ((unsigned char *) fp) - 0x40; | ||
334 | for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) { | ||
335 | if ((i % 0x10) == 0) | ||
336 | printk(KERN_EMERG "%p: ", tp + i); | ||
337 | printk("%08x ", (int) *sp++); | ||
338 | } | ||
339 | printk(KERN_EMERG "\n"); | ||
340 | |||
341 | printk(KERN_EMERG "USER STACK:"); | ||
342 | tp = (unsigned char *) (rdusp() - 0x10); | ||
343 | for (sp = (unsigned long *) tp, i = 0; (i < 0x80); i += 4) { | ||
344 | if ((i % 0x10) == 0) | ||
345 | printk(KERN_EMERG "%p: ", tp + i); | ||
346 | printk("%08x ", (int) *sp++); | ||
347 | } | ||
348 | printk(KERN_EMERG "\n"); | ||
349 | } | ||
350 | |||
351 | /* | ||
352 | * sys_execve() executes a new program. | ||
353 | */ | ||
354 | asmlinkage int sys_execve(const char *name, | ||
355 | const char *const *argv, | ||
356 | const char *const *envp) | ||
357 | { | ||
358 | int error; | ||
359 | char * filename; | ||
360 | struct pt_regs *regs = (struct pt_regs *) &name; | ||
361 | |||
362 | filename = getname(name); | ||
363 | error = PTR_ERR(filename); | ||
364 | if (IS_ERR(filename)) | ||
365 | return error; | ||
366 | error = do_execve(filename, argv, envp, regs); | ||
367 | putname(filename); | ||
368 | return error; | ||
369 | } | ||
370 | |||
371 | unsigned long get_wchan(struct task_struct *p) | ||
372 | { | ||
373 | unsigned long fp, pc; | ||
374 | unsigned long stack_page; | ||
375 | int count = 0; | ||
376 | if (!p || p == current || p->state == TASK_RUNNING) | ||
377 | return 0; | ||
378 | |||
379 | stack_page = (unsigned long)p; | ||
380 | fp = ((struct switch_stack *)p->thread.ksp)->a6; | ||
381 | do { | ||
382 | if (fp < stack_page+sizeof(struct thread_info) || | ||
383 | fp >= THREAD_SIZE-8+stack_page) | ||
384 | return 0; | ||
385 | pc = ((unsigned long *)fp)[1]; | ||
386 | if (!in_sched_functions(pc)) | ||
387 | return pc; | ||
388 | fp = *(unsigned long *) fp; | ||
389 | } while (count++ < 16); | ||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | /* | ||
394 | * Return saved PC of a blocked thread. | ||
395 | */ | ||
396 | unsigned long thread_saved_pc(struct task_struct *tsk) | ||
397 | { | ||
398 | struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp; | ||
399 | |||
400 | /* Check whether the thread is blocked in resume() */ | ||
401 | if (in_sched_functions(sw->retpc)) | ||
402 | return ((unsigned long *)sw->a6)[1]; | ||
403 | else | ||
404 | return sw->retpc; | ||
405 | } | ||
406 | |||
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index 07a417550e94..8b4a2222e658 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c | |||
@@ -1,5 +1,304 @@ | |||
1 | /* | ||
2 | * linux/arch/m68k/kernel/ptrace.c | ||
3 | * | ||
4 | * Copyright (C) 1994 by Hamish Macdonald | ||
5 | * Taken from linux/kernel/ptrace.c and modified for M680x0. | ||
6 | * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General | ||
9 | * Public License. See the file COPYING in the main directory of | ||
10 | * this archive for more details. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/sched.h> | ||
15 | #include <linux/mm.h> | ||
16 | #include <linux/smp.h> | ||
17 | #include <linux/errno.h> | ||
18 | #include <linux/ptrace.h> | ||
19 | #include <linux/user.h> | ||
20 | #include <linux/signal.h> | ||
21 | #include <linux/tracehook.h> | ||
22 | |||
23 | #include <asm/uaccess.h> | ||
24 | #include <asm/page.h> | ||
25 | #include <asm/pgtable.h> | ||
26 | #include <asm/processor.h> | ||
27 | |||
28 | /* | ||
29 | * does not yet catch signals sent when the child dies. | ||
30 | * in exit.c or in signal.c. | ||
31 | */ | ||
32 | |||
33 | /* determines which bits in the SR the user has access to. */ | ||
34 | /* 1 = access 0 = no access */ | ||
35 | #define SR_MASK 0x001f | ||
36 | |||
37 | /* sets the trace bits. */ | ||
38 | #define TRACE_BITS 0xC000 | ||
39 | #define T1_BIT 0x8000 | ||
40 | #define T0_BIT 0x4000 | ||
41 | |||
42 | /* Find the stack offset for a register, relative to thread.esp0. */ | ||
43 | #define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg) | ||
44 | #define SW_REG(reg) ((long)&((struct switch_stack *)0)->reg \ | ||
45 | - sizeof(struct switch_stack)) | ||
46 | /* Mapping from PT_xxx to the stack offset at which the register is | ||
47 | saved. Notice that usp has no stack-slot and needs to be treated | ||
48 | specially (see get_reg/put_reg below). */ | ||
49 | static const int regoff[] = { | ||
50 | [0] = PT_REG(d1), | ||
51 | [1] = PT_REG(d2), | ||
52 | [2] = PT_REG(d3), | ||
53 | [3] = PT_REG(d4), | ||
54 | [4] = PT_REG(d5), | ||
55 | [5] = SW_REG(d6), | ||
56 | [6] = SW_REG(d7), | ||
57 | [7] = PT_REG(a0), | ||
58 | [8] = PT_REG(a1), | ||
59 | [9] = PT_REG(a2), | ||
60 | [10] = SW_REG(a3), | ||
61 | [11] = SW_REG(a4), | ||
62 | [12] = SW_REG(a5), | ||
63 | [13] = SW_REG(a6), | ||
64 | [14] = PT_REG(d0), | ||
65 | [15] = -1, | ||
66 | [16] = PT_REG(orig_d0), | ||
67 | [17] = PT_REG(sr), | ||
68 | [18] = PT_REG(pc), | ||
69 | }; | ||
70 | |||
71 | /* | ||
72 | * Get contents of register REGNO in task TASK. | ||
73 | */ | ||
74 | static inline long get_reg(struct task_struct *task, int regno) | ||
75 | { | ||
76 | unsigned long *addr; | ||
77 | |||
78 | if (regno == PT_USP) | ||
79 | addr = &task->thread.usp; | ||
80 | else if (regno < ARRAY_SIZE(regoff)) | ||
81 | addr = (unsigned long *)(task->thread.esp0 + regoff[regno]); | ||
82 | else | ||
83 | return 0; | ||
84 | /* Need to take stkadj into account. */ | ||
85 | if (regno == PT_SR || regno == PT_PC) { | ||
86 | long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj)); | ||
87 | addr = (unsigned long *) ((unsigned long)addr + stkadj); | ||
88 | /* The sr is actually a 16 bit register. */ | ||
89 | if (regno == PT_SR) | ||
90 | return *(unsigned short *)addr; | ||
91 | } | ||
92 | return *addr; | ||
93 | } | ||
94 | |||
95 | /* | ||
96 | * Write contents of register REGNO in task TASK. | ||
97 | */ | ||
98 | static inline int put_reg(struct task_struct *task, int regno, | ||
99 | unsigned long data) | ||
100 | { | ||
101 | unsigned long *addr; | ||
102 | |||
103 | if (regno == PT_USP) | ||
104 | addr = &task->thread.usp; | ||
105 | else if (regno < ARRAY_SIZE(regoff)) | ||
106 | addr = (unsigned long *)(task->thread.esp0 + regoff[regno]); | ||
107 | else | ||
108 | return -1; | ||
109 | /* Need to take stkadj into account. */ | ||
110 | if (regno == PT_SR || regno == PT_PC) { | ||
111 | long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj)); | ||
112 | addr = (unsigned long *) ((unsigned long)addr + stkadj); | ||
113 | /* The sr is actually a 16 bit register. */ | ||
114 | if (regno == PT_SR) { | ||
115 | *(unsigned short *)addr = data; | ||
116 | return 0; | ||
117 | } | ||
118 | } | ||
119 | *addr = data; | ||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | * Make sure the single step bit is not set. | ||
125 | */ | ||
126 | static inline void singlestep_disable(struct task_struct *child) | ||
127 | { | ||
128 | unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS; | ||
129 | put_reg(child, PT_SR, tmp); | ||
130 | clear_tsk_thread_flag(child, TIF_DELAYED_TRACE); | ||
131 | } | ||
132 | |||
133 | /* | ||
134 | * Called by kernel/ptrace.c when detaching.. | ||
135 | */ | ||
136 | void ptrace_disable(struct task_struct *child) | ||
137 | { | ||
138 | singlestep_disable(child); | ||
139 | } | ||
140 | |||
141 | void user_enable_single_step(struct task_struct *child) | ||
142 | { | ||
143 | unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS; | ||
144 | put_reg(child, PT_SR, tmp | T1_BIT); | ||
145 | set_tsk_thread_flag(child, TIF_DELAYED_TRACE); | ||
146 | } | ||
147 | |||
1 | #ifdef CONFIG_MMU | 148 | #ifdef CONFIG_MMU |
2 | #include "ptrace_mm.c" | 149 | void user_enable_block_step(struct task_struct *child) |
3 | #else | 150 | { |
4 | #include "ptrace_no.c" | 151 | unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS; |
152 | put_reg(child, PT_SR, tmp | T0_BIT); | ||
153 | } | ||
5 | #endif | 154 | #endif |
155 | |||
156 | void user_disable_single_step(struct task_struct *child) | ||
157 | { | ||
158 | singlestep_disable(child); | ||
159 | } | ||
160 | |||
161 | long arch_ptrace(struct task_struct *child, long request, | ||
162 | unsigned long addr, unsigned long data) | ||
163 | { | ||
164 | unsigned long tmp; | ||
165 | int i, ret = 0; | ||
166 | int regno = addr >> 2; /* temporary hack. */ | ||
167 | unsigned long __user *datap = (unsigned long __user *) data; | ||
168 | |||
169 | switch (request) { | ||
170 | /* read the word at location addr in the USER area. */ | ||
171 | case PTRACE_PEEKUSR: | ||
172 | if (addr & 3) | ||
173 | goto out_eio; | ||
174 | |||
175 | if (regno >= 0 && regno < 19) { | ||
176 | tmp = get_reg(child, regno); | ||
177 | } else if (regno >= 21 && regno < 49) { | ||
178 | tmp = child->thread.fp[regno - 21]; | ||
179 | /* Convert internal fpu reg representation | ||
180 | * into long double format | ||
181 | */ | ||
182 | if (FPU_IS_EMU && (regno < 45) && !(regno % 3)) | ||
183 | tmp = ((tmp & 0xffff0000) << 15) | | ||
184 | ((tmp & 0x0000ffff) << 16); | ||
185 | #ifndef CONFIG_MMU | ||
186 | } else if (regno == 49) { | ||
187 | tmp = child->mm->start_code; | ||
188 | } else if (regno == 50) { | ||
189 | tmp = child->mm->start_data; | ||
190 | } else if (regno == 51) { | ||
191 | tmp = child->mm->end_code; | ||
192 | #endif | ||
193 | } else | ||
194 | goto out_eio; | ||
195 | ret = put_user(tmp, datap); | ||
196 | break; | ||
197 | |||
198 | case PTRACE_POKEUSR: | ||
199 | /* write the word at location addr in the USER area */ | ||
200 | if (addr & 3) | ||
201 | goto out_eio; | ||
202 | |||
203 | if (regno == PT_SR) { | ||
204 | data &= SR_MASK; | ||
205 | data |= get_reg(child, PT_SR) & ~SR_MASK; | ||
206 | } | ||
207 | if (regno >= 0 && regno < 19) { | ||
208 | if (put_reg(child, regno, data)) | ||
209 | goto out_eio; | ||
210 | } else if (regno >= 21 && regno < 48) { | ||
211 | /* Convert long double format | ||
212 | * into internal fpu reg representation | ||
213 | */ | ||
214 | if (FPU_IS_EMU && (regno < 45) && !(regno % 3)) { | ||
215 | data <<= 15; | ||
216 | data = (data & 0xffff0000) | | ||
217 | ((data & 0x0000ffff) >> 1); | ||
218 | } | ||
219 | child->thread.fp[regno - 21] = data; | ||
220 | } else | ||
221 | goto out_eio; | ||
222 | break; | ||
223 | |||
224 | case PTRACE_GETREGS: /* Get all gp regs from the child. */ | ||
225 | for (i = 0; i < 19; i++) { | ||
226 | tmp = get_reg(child, i); | ||
227 | ret = put_user(tmp, datap); | ||
228 | if (ret) | ||
229 | break; | ||
230 | datap++; | ||
231 | } | ||
232 | break; | ||
233 | |||
234 | case PTRACE_SETREGS: /* Set all gp regs in the child. */ | ||
235 | for (i = 0; i < 19; i++) { | ||
236 | ret = get_user(tmp, datap); | ||
237 | if (ret) | ||
238 | break; | ||
239 | if (i == PT_SR) { | ||
240 | tmp &= SR_MASK; | ||
241 | tmp |= get_reg(child, PT_SR) & ~SR_MASK; | ||
242 | } | ||
243 | put_reg(child, i, tmp); | ||
244 | datap++; | ||
245 | } | ||
246 | break; | ||
247 | |||
248 | case PTRACE_GETFPREGS: /* Get the child FPU state. */ | ||
249 | if (copy_to_user(datap, &child->thread.fp, | ||
250 | sizeof(struct user_m68kfp_struct))) | ||
251 | ret = -EFAULT; | ||
252 | break; | ||
253 | |||
254 | case PTRACE_SETFPREGS: /* Set the child FPU state. */ | ||
255 | if (copy_from_user(&child->thread.fp, datap, | ||
256 | sizeof(struct user_m68kfp_struct))) | ||
257 | ret = -EFAULT; | ||
258 | break; | ||
259 | |||
260 | case PTRACE_GET_THREAD_AREA: | ||
261 | ret = put_user(task_thread_info(child)->tp_value, datap); | ||
262 | break; | ||
263 | |||
264 | default: | ||
265 | ret = ptrace_request(child, request, addr, data); | ||
266 | break; | ||
267 | } | ||
268 | |||
269 | return ret; | ||
270 | out_eio: | ||
271 | return -EIO; | ||
272 | } | ||
273 | |||
274 | asmlinkage void syscall_trace(void) | ||
275 | { | ||
276 | ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) | ||
277 | ? 0x80 : 0)); | ||
278 | /* | ||
279 | * this isn't the same as continuing with a signal, but it will do | ||
280 | * for normal use. strace only continues with a signal if the | ||
281 | * stopping signal is not SIGTRAP. -brl | ||
282 | */ | ||
283 | if (current->exit_code) { | ||
284 | send_sig(current->exit_code, current, 1); | ||
285 | current->exit_code = 0; | ||
286 | } | ||
287 | } | ||
288 | |||
289 | #ifdef CONFIG_COLDFIRE | ||
290 | asmlinkage int syscall_trace_enter(void) | ||
291 | { | ||
292 | int ret = 0; | ||
293 | |||
294 | if (test_thread_flag(TIF_SYSCALL_TRACE)) | ||
295 | ret = tracehook_report_syscall_entry(task_pt_regs(current)); | ||
296 | return ret; | ||
297 | } | ||
298 | |||
299 | asmlinkage void syscall_trace_leave(void) | ||
300 | { | ||
301 | if (test_thread_flag(TIF_SYSCALL_TRACE)) | ||
302 | tracehook_report_syscall_exit(task_pt_regs(current), 0); | ||
303 | } | ||
304 | #endif /* CONFIG_COLDFIRE */ | ||
diff --git a/arch/m68k/kernel/ptrace_mm.c b/arch/m68k/kernel/ptrace_mm.c deleted file mode 100644 index 7bc999b73529..000000000000 --- a/arch/m68k/kernel/ptrace_mm.c +++ /dev/null | |||
@@ -1,295 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/m68k/kernel/ptrace.c | ||
3 | * | ||
4 | * Copyright (C) 1994 by Hamish Macdonald | ||
5 | * Taken from linux/kernel/ptrace.c and modified for M680x0. | ||
6 | * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General | ||
9 | * Public License. See the file COPYING in the main directory of | ||
10 | * this archive for more details. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/sched.h> | ||
15 | #include <linux/mm.h> | ||
16 | #include <linux/smp.h> | ||
17 | #include <linux/errno.h> | ||
18 | #include <linux/ptrace.h> | ||
19 | #include <linux/user.h> | ||
20 | #include <linux/signal.h> | ||
21 | #include <linux/tracehook.h> | ||
22 | |||
23 | #include <asm/uaccess.h> | ||
24 | #include <asm/page.h> | ||
25 | #include <asm/pgtable.h> | ||
26 | #include <asm/system.h> | ||
27 | #include <asm/processor.h> | ||
28 | |||
29 | /* | ||
30 | * does not yet catch signals sent when the child dies. | ||
31 | * in exit.c or in signal.c. | ||
32 | */ | ||
33 | |||
34 | /* determines which bits in the SR the user has access to. */ | ||
35 | /* 1 = access 0 = no access */ | ||
36 | #define SR_MASK 0x001f | ||
37 | |||
38 | /* sets the trace bits. */ | ||
39 | #define TRACE_BITS 0xC000 | ||
40 | #define T1_BIT 0x8000 | ||
41 | #define T0_BIT 0x4000 | ||
42 | |||
43 | /* Find the stack offset for a register, relative to thread.esp0. */ | ||
44 | #define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg) | ||
45 | #define SW_REG(reg) ((long)&((struct switch_stack *)0)->reg \ | ||
46 | - sizeof(struct switch_stack)) | ||
47 | /* Mapping from PT_xxx to the stack offset at which the register is | ||
48 | saved. Notice that usp has no stack-slot and needs to be treated | ||
49 | specially (see get_reg/put_reg below). */ | ||
50 | static const int regoff[] = { | ||
51 | [0] = PT_REG(d1), | ||
52 | [1] = PT_REG(d2), | ||
53 | [2] = PT_REG(d3), | ||
54 | [3] = PT_REG(d4), | ||
55 | [4] = PT_REG(d5), | ||
56 | [5] = SW_REG(d6), | ||
57 | [6] = SW_REG(d7), | ||
58 | [7] = PT_REG(a0), | ||
59 | [8] = PT_REG(a1), | ||
60 | [9] = PT_REG(a2), | ||
61 | [10] = SW_REG(a3), | ||
62 | [11] = SW_REG(a4), | ||
63 | [12] = SW_REG(a5), | ||
64 | [13] = SW_REG(a6), | ||
65 | [14] = PT_REG(d0), | ||
66 | [15] = -1, | ||
67 | [16] = PT_REG(orig_d0), | ||
68 | [17] = PT_REG(sr), | ||
69 | [18] = PT_REG(pc), | ||
70 | }; | ||
71 | |||
72 | /* | ||
73 | * Get contents of register REGNO in task TASK. | ||
74 | */ | ||
75 | static inline long get_reg(struct task_struct *task, int regno) | ||
76 | { | ||
77 | unsigned long *addr; | ||
78 | |||
79 | if (regno == PT_USP) | ||
80 | addr = &task->thread.usp; | ||
81 | else if (regno < ARRAY_SIZE(regoff)) | ||
82 | addr = (unsigned long *)(task->thread.esp0 + regoff[regno]); | ||
83 | else | ||
84 | return 0; | ||
85 | /* Need to take stkadj into account. */ | ||
86 | if (regno == PT_SR || regno == PT_PC) { | ||
87 | long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj)); | ||
88 | addr = (unsigned long *) ((unsigned long)addr + stkadj); | ||
89 | /* The sr is actually a 16 bit register. */ | ||
90 | if (regno == PT_SR) | ||
91 | return *(unsigned short *)addr; | ||
92 | } | ||
93 | return *addr; | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * Write contents of register REGNO in task TASK. | ||
98 | */ | ||
99 | static inline int put_reg(struct task_struct *task, int regno, | ||
100 | unsigned long data) | ||
101 | { | ||
102 | unsigned long *addr; | ||
103 | |||
104 | if (regno == PT_USP) | ||
105 | addr = &task->thread.usp; | ||
106 | else if (regno < ARRAY_SIZE(regoff)) | ||
107 | addr = (unsigned long *)(task->thread.esp0 + regoff[regno]); | ||
108 | else | ||
109 | return -1; | ||
110 | /* Need to take stkadj into account. */ | ||
111 | if (regno == PT_SR || regno == PT_PC) { | ||
112 | long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj)); | ||
113 | addr = (unsigned long *) ((unsigned long)addr + stkadj); | ||
114 | /* The sr is actually a 16 bit register. */ | ||
115 | if (regno == PT_SR) { | ||
116 | *(unsigned short *)addr = data; | ||
117 | return 0; | ||
118 | } | ||
119 | } | ||
120 | *addr = data; | ||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | /* | ||
125 | * Make sure the single step bit is not set. | ||
126 | */ | ||
127 | static inline void singlestep_disable(struct task_struct *child) | ||
128 | { | ||
129 | unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS; | ||
130 | put_reg(child, PT_SR, tmp); | ||
131 | clear_tsk_thread_flag(child, TIF_DELAYED_TRACE); | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * Called by kernel/ptrace.c when detaching.. | ||
136 | */ | ||
137 | void ptrace_disable(struct task_struct *child) | ||
138 | { | ||
139 | singlestep_disable(child); | ||
140 | } | ||
141 | |||
142 | void user_enable_single_step(struct task_struct *child) | ||
143 | { | ||
144 | unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS; | ||
145 | put_reg(child, PT_SR, tmp | T1_BIT); | ||
146 | set_tsk_thread_flag(child, TIF_DELAYED_TRACE); | ||
147 | } | ||
148 | |||
149 | void user_enable_block_step(struct task_struct *child) | ||
150 | { | ||
151 | unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS; | ||
152 | put_reg(child, PT_SR, tmp | T0_BIT); | ||
153 | } | ||
154 | |||
155 | void user_disable_single_step(struct task_struct *child) | ||
156 | { | ||
157 | singlestep_disable(child); | ||
158 | } | ||
159 | |||
160 | long arch_ptrace(struct task_struct *child, long request, | ||
161 | unsigned long addr, unsigned long data) | ||
162 | { | ||
163 | unsigned long tmp; | ||
164 | int i, ret = 0; | ||
165 | int regno = addr >> 2; /* temporary hack. */ | ||
166 | unsigned long __user *datap = (unsigned long __user *) data; | ||
167 | |||
168 | switch (request) { | ||
169 | /* read the word at location addr in the USER area. */ | ||
170 | case PTRACE_PEEKUSR: | ||
171 | if (addr & 3) | ||
172 | goto out_eio; | ||
173 | |||
174 | if (regno >= 0 && regno < 19) { | ||
175 | tmp = get_reg(child, regno); | ||
176 | } else if (regno >= 21 && regno < 49) { | ||
177 | tmp = child->thread.fp[regno - 21]; | ||
178 | /* Convert internal fpu reg representation | ||
179 | * into long double format | ||
180 | */ | ||
181 | if (FPU_IS_EMU && (regno < 45) && !(regno % 3)) | ||
182 | tmp = ((tmp & 0xffff0000) << 15) | | ||
183 | ((tmp & 0x0000ffff) << 16); | ||
184 | } else | ||
185 | goto out_eio; | ||
186 | ret = put_user(tmp, datap); | ||
187 | break; | ||
188 | |||
189 | case PTRACE_POKEUSR: | ||
190 | /* write the word at location addr in the USER area */ | ||
191 | if (addr & 3) | ||
192 | goto out_eio; | ||
193 | |||
194 | if (regno == PT_SR) { | ||
195 | data &= SR_MASK; | ||
196 | data |= get_reg(child, PT_SR) & ~SR_MASK; | ||
197 | } | ||
198 | if (regno >= 0 && regno < 19) { | ||
199 | if (put_reg(child, regno, data)) | ||
200 | goto out_eio; | ||
201 | } else if (regno >= 21 && regno < 48) { | ||
202 | /* Convert long double format | ||
203 | * into internal fpu reg representation | ||
204 | */ | ||
205 | if (FPU_IS_EMU && (regno < 45) && !(regno % 3)) { | ||
206 | data <<= 15; | ||
207 | data = (data & 0xffff0000) | | ||
208 | ((data & 0x0000ffff) >> 1); | ||
209 | } | ||
210 | child->thread.fp[regno - 21] = data; | ||
211 | } else | ||
212 | goto out_eio; | ||
213 | break; | ||
214 | |||
215 | case PTRACE_GETREGS: /* Get all gp regs from the child. */ | ||
216 | for (i = 0; i < 19; i++) { | ||
217 | tmp = get_reg(child, i); | ||
218 | ret = put_user(tmp, datap); | ||
219 | if (ret) | ||
220 | break; | ||
221 | datap++; | ||
222 | } | ||
223 | break; | ||
224 | |||
225 | case PTRACE_SETREGS: /* Set all gp regs in the child. */ | ||
226 | for (i = 0; i < 19; i++) { | ||
227 | ret = get_user(tmp, datap); | ||
228 | if (ret) | ||
229 | break; | ||
230 | if (i == PT_SR) { | ||
231 | tmp &= SR_MASK; | ||
232 | tmp |= get_reg(child, PT_SR) & ~SR_MASK; | ||
233 | } | ||
234 | put_reg(child, i, tmp); | ||
235 | datap++; | ||
236 | } | ||
237 | break; | ||
238 | |||
239 | case PTRACE_GETFPREGS: /* Get the child FPU state. */ | ||
240 | if (copy_to_user(datap, &child->thread.fp, | ||
241 | sizeof(struct user_m68kfp_struct))) | ||
242 | ret = -EFAULT; | ||
243 | break; | ||
244 | |||
245 | case PTRACE_SETFPREGS: /* Set the child FPU state. */ | ||
246 | if (copy_from_user(&child->thread.fp, datap, | ||
247 | sizeof(struct user_m68kfp_struct))) | ||
248 | ret = -EFAULT; | ||
249 | break; | ||
250 | |||
251 | case PTRACE_GET_THREAD_AREA: | ||
252 | ret = put_user(task_thread_info(child)->tp_value, datap); | ||
253 | break; | ||
254 | |||
255 | default: | ||
256 | ret = ptrace_request(child, request, addr, data); | ||
257 | break; | ||
258 | } | ||
259 | |||
260 | return ret; | ||
261 | out_eio: | ||
262 | return -EIO; | ||
263 | } | ||
264 | |||
265 | asmlinkage void syscall_trace(void) | ||
266 | { | ||
267 | ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) | ||
268 | ? 0x80 : 0)); | ||
269 | /* | ||
270 | * this isn't the same as continuing with a signal, but it will do | ||
271 | * for normal use. strace only continues with a signal if the | ||
272 | * stopping signal is not SIGTRAP. -brl | ||
273 | */ | ||
274 | if (current->exit_code) { | ||
275 | send_sig(current->exit_code, current, 1); | ||
276 | current->exit_code = 0; | ||
277 | } | ||
278 | } | ||
279 | |||
280 | #ifdef CONFIG_COLDFIRE | ||
281 | asmlinkage int syscall_trace_enter(void) | ||
282 | { | ||
283 | int ret = 0; | ||
284 | |||
285 | if (test_thread_flag(TIF_SYSCALL_TRACE)) | ||
286 | ret = tracehook_report_syscall_entry(task_pt_regs(current)); | ||
287 | return ret; | ||
288 | } | ||
289 | |||
290 | asmlinkage void syscall_trace_leave(void) | ||
291 | { | ||
292 | if (test_thread_flag(TIF_SYSCALL_TRACE)) | ||
293 | tracehook_report_syscall_exit(task_pt_regs(current), 0); | ||
294 | } | ||
295 | #endif /* CONFIG_COLDFIRE */ | ||
diff --git a/arch/m68k/kernel/ptrace_no.c b/arch/m68k/kernel/ptrace_no.c deleted file mode 100644 index 6709fb707335..000000000000 --- a/arch/m68k/kernel/ptrace_no.c +++ /dev/null | |||
@@ -1,255 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/m68knommu/kernel/ptrace.c | ||
3 | * | ||
4 | * Copyright (C) 1994 by Hamish Macdonald | ||
5 | * Taken from linux/kernel/ptrace.c and modified for M680x0. | ||
6 | * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General | ||
9 | * Public License. See the file COPYING in the main directory of | ||
10 | * this archive for more details. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/sched.h> | ||
15 | #include <linux/mm.h> | ||
16 | #include <linux/smp.h> | ||
17 | #include <linux/errno.h> | ||
18 | #include <linux/ptrace.h> | ||
19 | #include <linux/user.h> | ||
20 | #include <linux/signal.h> | ||
21 | #include <linux/tracehook.h> | ||
22 | |||
23 | #include <asm/uaccess.h> | ||
24 | #include <asm/page.h> | ||
25 | #include <asm/pgtable.h> | ||
26 | #include <asm/system.h> | ||
27 | #include <asm/processor.h> | ||
28 | |||
29 | /* | ||
30 | * does not yet catch signals sent when the child dies. | ||
31 | * in exit.c or in signal.c. | ||
32 | */ | ||
33 | |||
34 | /* determines which bits in the SR the user has access to. */ | ||
35 | /* 1 = access 0 = no access */ | ||
36 | #define SR_MASK 0x001f | ||
37 | |||
38 | /* sets the trace bits. */ | ||
39 | #define TRACE_BITS 0x8000 | ||
40 | |||
41 | /* Find the stack offset for a register, relative to thread.esp0. */ | ||
42 | #define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg) | ||
43 | #define SW_REG(reg) ((long)&((struct switch_stack *)0)->reg \ | ||
44 | - sizeof(struct switch_stack)) | ||
45 | /* Mapping from PT_xxx to the stack offset at which the register is | ||
46 | saved. Notice that usp has no stack-slot and needs to be treated | ||
47 | specially (see get_reg/put_reg below). */ | ||
48 | static int regoff[] = { | ||
49 | PT_REG(d1), PT_REG(d2), PT_REG(d3), PT_REG(d4), | ||
50 | PT_REG(d5), SW_REG(d6), SW_REG(d7), PT_REG(a0), | ||
51 | PT_REG(a1), PT_REG(a2), SW_REG(a3), SW_REG(a4), | ||
52 | SW_REG(a5), SW_REG(a6), PT_REG(d0), -1, | ||
53 | PT_REG(orig_d0), PT_REG(sr), PT_REG(pc), | ||
54 | }; | ||
55 | |||
56 | /* | ||
57 | * Get contents of register REGNO in task TASK. | ||
58 | */ | ||
59 | static inline long get_reg(struct task_struct *task, int regno) | ||
60 | { | ||
61 | unsigned long *addr; | ||
62 | |||
63 | if (regno == PT_USP) | ||
64 | addr = &task->thread.usp; | ||
65 | else if (regno < ARRAY_SIZE(regoff)) | ||
66 | addr = (unsigned long *)(task->thread.esp0 + regoff[regno]); | ||
67 | else | ||
68 | return 0; | ||
69 | return *addr; | ||
70 | } | ||
71 | |||
72 | /* | ||
73 | * Write contents of register REGNO in task TASK. | ||
74 | */ | ||
75 | static inline int put_reg(struct task_struct *task, int regno, | ||
76 | unsigned long data) | ||
77 | { | ||
78 | unsigned long *addr; | ||
79 | |||
80 | if (regno == PT_USP) | ||
81 | addr = &task->thread.usp; | ||
82 | else if (regno < ARRAY_SIZE(regoff)) | ||
83 | addr = (unsigned long *) (task->thread.esp0 + regoff[regno]); | ||
84 | else | ||
85 | return -1; | ||
86 | *addr = data; | ||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | void user_enable_single_step(struct task_struct *task) | ||
91 | { | ||
92 | unsigned long srflags; | ||
93 | srflags = get_reg(task, PT_SR) | (TRACE_BITS << 16); | ||
94 | put_reg(task, PT_SR, srflags); | ||
95 | } | ||
96 | |||
97 | void user_disable_single_step(struct task_struct *task) | ||
98 | { | ||
99 | unsigned long srflags; | ||
100 | srflags = get_reg(task, PT_SR) & ~(TRACE_BITS << 16); | ||
101 | put_reg(task, PT_SR, srflags); | ||
102 | } | ||
103 | |||
104 | /* | ||
105 | * Called by kernel/ptrace.c when detaching.. | ||
106 | * | ||
107 | * Make sure the single step bit is not set. | ||
108 | */ | ||
109 | void ptrace_disable(struct task_struct *child) | ||
110 | { | ||
111 | /* make sure the single step bit is not set. */ | ||
112 | user_disable_single_step(child); | ||
113 | } | ||
114 | |||
115 | long arch_ptrace(struct task_struct *child, long request, | ||
116 | unsigned long addr, unsigned long data) | ||
117 | { | ||
118 | int ret; | ||
119 | int regno = addr >> 2; | ||
120 | unsigned long __user *datap = (unsigned long __user *) data; | ||
121 | |||
122 | switch (request) { | ||
123 | /* read the word at location addr in the USER area. */ | ||
124 | case PTRACE_PEEKUSR: { | ||
125 | unsigned long tmp; | ||
126 | |||
127 | ret = -EIO; | ||
128 | if ((addr & 3) || addr > sizeof(struct user) - 3) | ||
129 | break; | ||
130 | |||
131 | tmp = 0; /* Default return condition */ | ||
132 | ret = -EIO; | ||
133 | if (regno < 19) { | ||
134 | tmp = get_reg(child, regno); | ||
135 | if (regno == PT_SR) | ||
136 | tmp >>= 16; | ||
137 | } else if (regno >= 21 && regno < 49) { | ||
138 | tmp = child->thread.fp[regno - 21]; | ||
139 | } else if (regno == 49) { | ||
140 | tmp = child->mm->start_code; | ||
141 | } else if (regno == 50) { | ||
142 | tmp = child->mm->start_data; | ||
143 | } else if (regno == 51) { | ||
144 | tmp = child->mm->end_code; | ||
145 | } else | ||
146 | break; | ||
147 | ret = put_user(tmp, datap); | ||
148 | break; | ||
149 | } | ||
150 | |||
151 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ | ||
152 | ret = -EIO; | ||
153 | if ((addr & 3) || addr > sizeof(struct user) - 3) | ||
154 | break; | ||
155 | |||
156 | if (regno == PT_SR) { | ||
157 | data &= SR_MASK; | ||
158 | data <<= 16; | ||
159 | data |= get_reg(child, PT_SR) & ~(SR_MASK << 16); | ||
160 | } | ||
161 | if (regno < 19) { | ||
162 | if (put_reg(child, regno, data)) | ||
163 | break; | ||
164 | ret = 0; | ||
165 | break; | ||
166 | } | ||
167 | if (regno >= 21 && regno < 48) | ||
168 | { | ||
169 | child->thread.fp[regno - 21] = data; | ||
170 | ret = 0; | ||
171 | } | ||
172 | break; | ||
173 | |||
174 | case PTRACE_GETREGS: { /* Get all gp regs from the child. */ | ||
175 | int i; | ||
176 | unsigned long tmp; | ||
177 | for (i = 0; i < 19; i++) { | ||
178 | tmp = get_reg(child, i); | ||
179 | if (i == PT_SR) | ||
180 | tmp >>= 16; | ||
181 | if (put_user(tmp, datap)) { | ||
182 | ret = -EFAULT; | ||
183 | break; | ||
184 | } | ||
185 | datap++; | ||
186 | } | ||
187 | ret = 0; | ||
188 | break; | ||
189 | } | ||
190 | |||
191 | case PTRACE_SETREGS: { /* Set all gp regs in the child. */ | ||
192 | int i; | ||
193 | unsigned long tmp; | ||
194 | for (i = 0; i < 19; i++) { | ||
195 | if (get_user(tmp, datap)) { | ||
196 | ret = -EFAULT; | ||
197 | break; | ||
198 | } | ||
199 | if (i == PT_SR) { | ||
200 | tmp &= SR_MASK; | ||
201 | tmp <<= 16; | ||
202 | tmp |= get_reg(child, PT_SR) & ~(SR_MASK << 16); | ||
203 | } | ||
204 | put_reg(child, i, tmp); | ||
205 | datap++; | ||
206 | } | ||
207 | ret = 0; | ||
208 | break; | ||
209 | } | ||
210 | |||
211 | #ifdef PTRACE_GETFPREGS | ||
212 | case PTRACE_GETFPREGS: { /* Get the child FPU state. */ | ||
213 | ret = 0; | ||
214 | if (copy_to_user(datap, &child->thread.fp, | ||
215 | sizeof(struct user_m68kfp_struct))) | ||
216 | ret = -EFAULT; | ||
217 | break; | ||
218 | } | ||
219 | #endif | ||
220 | |||
221 | #ifdef PTRACE_SETFPREGS | ||
222 | case PTRACE_SETFPREGS: { /* Set the child FPU state. */ | ||
223 | ret = 0; | ||
224 | if (copy_from_user(&child->thread.fp, datap, | ||
225 | sizeof(struct user_m68kfp_struct))) | ||
226 | ret = -EFAULT; | ||
227 | break; | ||
228 | } | ||
229 | #endif | ||
230 | |||
231 | case PTRACE_GET_THREAD_AREA: | ||
232 | ret = put_user(task_thread_info(child)->tp_value, datap); | ||
233 | break; | ||
234 | |||
235 | default: | ||
236 | ret = ptrace_request(child, request, addr, data); | ||
237 | break; | ||
238 | } | ||
239 | return ret; | ||
240 | } | ||
241 | |||
242 | asmlinkage int syscall_trace_enter(void) | ||
243 | { | ||
244 | int ret = 0; | ||
245 | |||
246 | if (test_thread_flag(TIF_SYSCALL_TRACE)) | ||
247 | ret = tracehook_report_syscall_entry(task_pt_regs(current)); | ||
248 | return ret; | ||
249 | } | ||
250 | |||
251 | asmlinkage void syscall_trace_leave(void) | ||
252 | { | ||
253 | if (test_thread_flag(TIF_SYSCALL_TRACE)) | ||
254 | tracehook_report_syscall_exit(task_pt_regs(current), 0); | ||
255 | } | ||
diff --git a/arch/m68k/kernel/setup_no.c b/arch/m68k/kernel/setup_no.c index ca3df0dc7e88..7dc186b7a85f 100644 --- a/arch/m68k/kernel/setup_no.c +++ b/arch/m68k/kernel/setup_no.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/initrd.h> | 32 | #include <linux/initrd.h> |
33 | #include <linux/root_dev.h> | 33 | #include <linux/root_dev.h> |
34 | #include <linux/rtc.h> | ||
34 | 35 | ||
35 | #include <asm/setup.h> | 36 | #include <asm/setup.h> |
36 | #include <asm/irq.h> | 37 | #include <asm/irq.h> |
@@ -47,7 +48,9 @@ EXPORT_SYMBOL(memory_end); | |||
47 | char __initdata command_line[COMMAND_LINE_SIZE]; | 48 | char __initdata command_line[COMMAND_LINE_SIZE]; |
48 | 49 | ||
49 | /* machine dependent timer functions */ | 50 | /* machine dependent timer functions */ |
51 | void (*mach_sched_init)(irq_handler_t handler) __initdata = NULL; | ||
50 | int (*mach_set_clock_mmss)(unsigned long); | 52 | int (*mach_set_clock_mmss)(unsigned long); |
53 | int (*mach_hwclk) (int, struct rtc_time*); | ||
51 | 54 | ||
52 | /* machine dependent reboot functions */ | 55 | /* machine dependent reboot functions */ |
53 | void (*mach_reset)(void); | 56 | void (*mach_reset)(void); |
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c index 75ab79b3bdeb..d7deb7fc7eb5 100644 --- a/arch/m68k/kernel/time.c +++ b/arch/m68k/kernel/time.c | |||
@@ -1,5 +1,111 @@ | |||
1 | #if defined(CONFIG_MMU) && !defined(CONFIG_COLDFIRE) | 1 | /* |
2 | #include "time_mm.c" | 2 | * linux/arch/m68k/kernel/time.c |
3 | #else | 3 | * |
4 | #include "time_no.c" | 4 | * Copyright (C) 1991, 1992, 1995 Linus Torvalds |
5 | #endif | 5 | * |
6 | * This file contains the m68k-specific time handling details. | ||
7 | * Most of the stuff is located in the machine specific files. | ||
8 | * | ||
9 | * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 | ||
10 | * "A Kernel Model for Precision Timekeeping" by Dave Mills | ||
11 | */ | ||
12 | |||
13 | #include <linux/errno.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/sched.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/param.h> | ||
18 | #include <linux/string.h> | ||
19 | #include <linux/mm.h> | ||
20 | #include <linux/rtc.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | |||
23 | #include <asm/machdep.h> | ||
24 | #include <asm/io.h> | ||
25 | #include <asm/irq_regs.h> | ||
26 | |||
27 | #include <linux/time.h> | ||
28 | #include <linux/timex.h> | ||
29 | #include <linux/profile.h> | ||
30 | |||
31 | /* | ||
32 | * timer_interrupt() needs to keep up the real-time clock, | ||
33 | * as well as call the "xtime_update()" routine every clocktick | ||
34 | */ | ||
35 | static irqreturn_t timer_interrupt(int irq, void *dummy) | ||
36 | { | ||
37 | xtime_update(1); | ||
38 | update_process_times(user_mode(get_irq_regs())); | ||
39 | profile_tick(CPU_PROFILING); | ||
40 | |||
41 | #ifdef CONFIG_HEARTBEAT | ||
42 | /* use power LED as a heartbeat instead -- much more useful | ||
43 | for debugging -- based on the version for PReP by Cort */ | ||
44 | /* acts like an actual heart beat -- ie thump-thump-pause... */ | ||
45 | if (mach_heartbeat) { | ||
46 | static unsigned cnt = 0, period = 0, dist = 0; | ||
47 | |||
48 | if (cnt == 0 || cnt == dist) | ||
49 | mach_heartbeat( 1 ); | ||
50 | else if (cnt == 7 || cnt == dist+7) | ||
51 | mach_heartbeat( 0 ); | ||
52 | |||
53 | if (++cnt > period) { | ||
54 | cnt = 0; | ||
55 | /* The hyperbolic function below modifies the heartbeat period | ||
56 | * length in dependency of the current (5min) load. It goes | ||
57 | * through the points f(0)=126, f(1)=86, f(5)=51, | ||
58 | * f(inf)->30. */ | ||
59 | period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30; | ||
60 | dist = period / 4; | ||
61 | } | ||
62 | } | ||
63 | #endif /* CONFIG_HEARTBEAT */ | ||
64 | return IRQ_HANDLED; | ||
65 | } | ||
66 | |||
67 | void read_persistent_clock(struct timespec *ts) | ||
68 | { | ||
69 | struct rtc_time time; | ||
70 | ts->tv_sec = 0; | ||
71 | ts->tv_nsec = 0; | ||
72 | |||
73 | if (mach_hwclk) { | ||
74 | mach_hwclk(0, &time); | ||
75 | |||
76 | if ((time.tm_year += 1900) < 1970) | ||
77 | time.tm_year += 100; | ||
78 | ts->tv_sec = mktime(time.tm_year, time.tm_mon, time.tm_mday, | ||
79 | time.tm_hour, time.tm_min, time.tm_sec); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | void __init time_init(void) | ||
84 | { | ||
85 | mach_sched_init(timer_interrupt); | ||
86 | } | ||
87 | |||
88 | #ifdef CONFIG_M68KCLASSIC | ||
89 | |||
90 | u32 arch_gettimeoffset(void) | ||
91 | { | ||
92 | return mach_gettimeoffset() * 1000; | ||
93 | } | ||
94 | |||
95 | static int __init rtc_init(void) | ||
96 | { | ||
97 | struct platform_device *pdev; | ||
98 | |||
99 | if (!mach_hwclk) | ||
100 | return -ENODEV; | ||
101 | |||
102 | pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0); | ||
103 | if (IS_ERR(pdev)) | ||
104 | return PTR_ERR(pdev); | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | module_init(rtc_init); | ||
110 | |||
111 | #endif /* CONFIG_M68KCLASSIC */ | ||
diff --git a/arch/m68k/kernel/time_mm.c b/arch/m68k/kernel/time_mm.c deleted file mode 100644 index 18b34ee5db3b..000000000000 --- a/arch/m68k/kernel/time_mm.c +++ /dev/null | |||
@@ -1,114 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/m68k/kernel/time.c | ||
3 | * | ||
4 | * Copyright (C) 1991, 1992, 1995 Linus Torvalds | ||
5 | * | ||
6 | * This file contains the m68k-specific time handling details. | ||
7 | * Most of the stuff is located in the machine specific files. | ||
8 | * | ||
9 | * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 | ||
10 | * "A Kernel Model for Precision Timekeeping" by Dave Mills | ||
11 | */ | ||
12 | |||
13 | #include <linux/errno.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/sched.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/param.h> | ||
18 | #include <linux/string.h> | ||
19 | #include <linux/mm.h> | ||
20 | #include <linux/rtc.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | |||
23 | #include <asm/machdep.h> | ||
24 | #include <asm/io.h> | ||
25 | #include <asm/irq_regs.h> | ||
26 | |||
27 | #include <linux/time.h> | ||
28 | #include <linux/timex.h> | ||
29 | #include <linux/profile.h> | ||
30 | |||
31 | static inline int set_rtc_mmss(unsigned long nowtime) | ||
32 | { | ||
33 | if (mach_set_clock_mmss) | ||
34 | return mach_set_clock_mmss (nowtime); | ||
35 | return -1; | ||
36 | } | ||
37 | |||
38 | /* | ||
39 | * timer_interrupt() needs to keep up the real-time clock, | ||
40 | * as well as call the "xtime_update()" routine every clocktick | ||
41 | */ | ||
42 | static irqreturn_t timer_interrupt(int irq, void *dummy) | ||
43 | { | ||
44 | xtime_update(1); | ||
45 | update_process_times(user_mode(get_irq_regs())); | ||
46 | profile_tick(CPU_PROFILING); | ||
47 | |||
48 | #ifdef CONFIG_HEARTBEAT | ||
49 | /* use power LED as a heartbeat instead -- much more useful | ||
50 | for debugging -- based on the version for PReP by Cort */ | ||
51 | /* acts like an actual heart beat -- ie thump-thump-pause... */ | ||
52 | if (mach_heartbeat) { | ||
53 | static unsigned cnt = 0, period = 0, dist = 0; | ||
54 | |||
55 | if (cnt == 0 || cnt == dist) | ||
56 | mach_heartbeat( 1 ); | ||
57 | else if (cnt == 7 || cnt == dist+7) | ||
58 | mach_heartbeat( 0 ); | ||
59 | |||
60 | if (++cnt > period) { | ||
61 | cnt = 0; | ||
62 | /* The hyperbolic function below modifies the heartbeat period | ||
63 | * length in dependency of the current (5min) load. It goes | ||
64 | * through the points f(0)=126, f(1)=86, f(5)=51, | ||
65 | * f(inf)->30. */ | ||
66 | period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30; | ||
67 | dist = period / 4; | ||
68 | } | ||
69 | } | ||
70 | #endif /* CONFIG_HEARTBEAT */ | ||
71 | return IRQ_HANDLED; | ||
72 | } | ||
73 | |||
74 | void read_persistent_clock(struct timespec *ts) | ||
75 | { | ||
76 | struct rtc_time time; | ||
77 | ts->tv_sec = 0; | ||
78 | ts->tv_nsec = 0; | ||
79 | |||
80 | if (mach_hwclk) { | ||
81 | mach_hwclk(0, &time); | ||
82 | |||
83 | if ((time.tm_year += 1900) < 1970) | ||
84 | time.tm_year += 100; | ||
85 | ts->tv_sec = mktime(time.tm_year, time.tm_mon, time.tm_mday, | ||
86 | time.tm_hour, time.tm_min, time.tm_sec); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | void __init time_init(void) | ||
91 | { | ||
92 | mach_sched_init(timer_interrupt); | ||
93 | } | ||
94 | |||
95 | u32 arch_gettimeoffset(void) | ||
96 | { | ||
97 | return mach_gettimeoffset() * 1000; | ||
98 | } | ||
99 | |||
100 | static int __init rtc_init(void) | ||
101 | { | ||
102 | struct platform_device *pdev; | ||
103 | |||
104 | if (!mach_hwclk) | ||
105 | return -ENODEV; | ||
106 | |||
107 | pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0); | ||
108 | if (IS_ERR(pdev)) | ||
109 | return PTR_ERR(pdev); | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | module_init(rtc_init); | ||
diff --git a/arch/m68k/kernel/time_no.c b/arch/m68k/kernel/time_no.c deleted file mode 100644 index 3ef0f7768dcd..000000000000 --- a/arch/m68k/kernel/time_no.c +++ /dev/null | |||
@@ -1,90 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/m68knommu/kernel/time.c | ||
3 | * | ||
4 | * Copyright (C) 1991, 1992, 1995 Linus Torvalds | ||
5 | * | ||
6 | * This file contains the m68k-specific time handling details. | ||
7 | * Most of the stuff is located in the machine specific files. | ||
8 | * | ||
9 | * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 | ||
10 | * "A Kernel Model for Precision Timekeeping" by Dave Mills | ||
11 | */ | ||
12 | |||
13 | #include <linux/errno.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/sched.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/param.h> | ||
18 | #include <linux/string.h> | ||
19 | #include <linux/mm.h> | ||
20 | #include <linux/profile.h> | ||
21 | #include <linux/time.h> | ||
22 | #include <linux/timex.h> | ||
23 | |||
24 | #include <asm/machdep.h> | ||
25 | #include <asm/irq_regs.h> | ||
26 | |||
27 | #define TICK_SIZE (tick_nsec / 1000) | ||
28 | |||
29 | /* machine dependent timer functions */ | ||
30 | void (*mach_gettod)(int*, int*, int*, int*, int*, int*); | ||
31 | |||
32 | static inline int set_rtc_mmss(unsigned long nowtime) | ||
33 | { | ||
34 | if (mach_set_clock_mmss) | ||
35 | return mach_set_clock_mmss (nowtime); | ||
36 | return -1; | ||
37 | } | ||
38 | |||
39 | #ifndef CONFIG_GENERIC_CLOCKEVENTS | ||
40 | /* | ||
41 | * timer_interrupt() needs to keep up the real-time clock, | ||
42 | * as well as call the "xtime_update()" routine every clocktick | ||
43 | */ | ||
44 | irqreturn_t arch_timer_interrupt(int irq, void *dummy) | ||
45 | { | ||
46 | |||
47 | if (current->pid) | ||
48 | profile_tick(CPU_PROFILING); | ||
49 | |||
50 | xtime_update(1); | ||
51 | |||
52 | update_process_times(user_mode(get_irq_regs())); | ||
53 | |||
54 | return(IRQ_HANDLED); | ||
55 | } | ||
56 | #endif | ||
57 | |||
58 | static unsigned long read_rtc_mmss(void) | ||
59 | { | ||
60 | unsigned int year, mon, day, hour, min, sec; | ||
61 | |||
62 | if (mach_gettod) { | ||
63 | mach_gettod(&year, &mon, &day, &hour, &min, &sec); | ||
64 | if ((year += 1900) < 1970) | ||
65 | year += 100; | ||
66 | } else { | ||
67 | year = 1970; | ||
68 | mon = day = 1; | ||
69 | hour = min = sec = 0; | ||
70 | } | ||
71 | |||
72 | |||
73 | return mktime(year, mon, day, hour, min, sec); | ||
74 | } | ||
75 | |||
76 | void read_persistent_clock(struct timespec *ts) | ||
77 | { | ||
78 | ts->tv_sec = read_rtc_mmss(); | ||
79 | ts->tv_nsec = 0; | ||
80 | } | ||
81 | |||
82 | int update_persistent_clock(struct timespec now) | ||
83 | { | ||
84 | return set_rtc_mmss(now.tv_sec); | ||
85 | } | ||
86 | |||
87 | void time_init(void) | ||
88 | { | ||
89 | hw_timer_init(); | ||
90 | } | ||
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c index daaa9187654c..388e5cc89599 100644 --- a/arch/m68k/kernel/traps.c +++ b/arch/m68k/kernel/traps.c | |||
@@ -32,7 +32,6 @@ | |||
32 | 32 | ||
33 | #include <asm/setup.h> | 33 | #include <asm/setup.h> |
34 | #include <asm/fpu.h> | 34 | #include <asm/fpu.h> |
35 | #include <asm/system.h> | ||
36 | #include <asm/uaccess.h> | 35 | #include <asm/uaccess.h> |
37 | #include <asm/traps.h> | 36 | #include <asm/traps.h> |
38 | #include <asm/pgalloc.h> | 37 | #include <asm/pgalloc.h> |
diff --git a/arch/m68k/kernel/vectors.c b/arch/m68k/kernel/vectors.c index 147b03fbc71e..322c977bb9ec 100644 --- a/arch/m68k/kernel/vectors.c +++ b/arch/m68k/kernel/vectors.c | |||
@@ -25,7 +25,6 @@ | |||
25 | 25 | ||
26 | #include <asm/setup.h> | 26 | #include <asm/setup.h> |
27 | #include <asm/fpu.h> | 27 | #include <asm/fpu.h> |
28 | #include <asm/system.h> | ||
29 | #include <asm/traps.h> | 28 | #include <asm/traps.h> |
30 | 29 | ||
31 | /* assembler routines */ | 30 | /* assembler routines */ |
diff --git a/arch/m68k/kernel/vmlinux-nommu.lds b/arch/m68k/kernel/vmlinux-nommu.lds index 8e66ccb0935e..40e02d9c38b4 100644 --- a/arch/m68k/kernel/vmlinux-nommu.lds +++ b/arch/m68k/kernel/vmlinux-nommu.lds | |||
@@ -1,195 +1,93 @@ | |||
1 | /* | 1 | /* |
2 | * vmlinux.lds.S -- master linker script for m68knommu arch | 2 | * vmlinux.lds.S -- master linker script for m68knommu arch |
3 | * | 3 | * |
4 | * (C) Copyright 2002-2006, Greg Ungerer <gerg@snapgear.com> | 4 | * (C) Copyright 2002-2012, Greg Ungerer <gerg@snapgear.com> |
5 | * | 5 | * |
6 | * This linker script is equipped to build either ROM loaded or RAM | 6 | * This linker script is equipped to build either ROM loaded or RAM |
7 | * run kernels. | 7 | * run kernels. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <asm-generic/vmlinux.lds.h> | ||
11 | #include <asm/page.h> | ||
12 | #include <asm/thread_info.h> | ||
13 | |||
14 | #if defined(CONFIG_RAMKERNEL) | 10 | #if defined(CONFIG_RAMKERNEL) |
15 | #define RAM_START CONFIG_KERNELBASE | 11 | #define KTEXT_ADDR CONFIG_KERNELBASE |
16 | #define RAM_LENGTH (CONFIG_RAMBASE + CONFIG_RAMSIZE - CONFIG_KERNELBASE) | ||
17 | #define TEXT ram | ||
18 | #define DATA ram | ||
19 | #define INIT ram | ||
20 | #define BSSS ram | ||
21 | #endif | ||
22 | #if defined(CONFIG_ROMKERNEL) || defined(CONFIG_HIMEMKERNEL) | ||
23 | #define RAM_START CONFIG_RAMBASE | ||
24 | #define RAM_LENGTH CONFIG_RAMSIZE | ||
25 | #define ROMVEC_START CONFIG_ROMVEC | ||
26 | #define ROMVEC_LENGTH CONFIG_ROMVECSIZE | ||
27 | #define ROM_START CONFIG_ROMSTART | ||
28 | #define ROM_LENGTH CONFIG_ROMSIZE | ||
29 | #define TEXT rom | ||
30 | #define DATA ram | ||
31 | #define INIT ram | ||
32 | #define BSSS ram | ||
33 | #endif | 12 | #endif |
34 | 13 | #if defined(CONFIG_ROMKERNEL) | |
35 | #ifndef DATA_ADDR | 14 | #define KTEXT_ADDR CONFIG_ROMSTART |
36 | #define DATA_ADDR | 15 | #define KDATA_ADDR CONFIG_KERNELBASE |
16 | #define LOAD_OFFSET KDATA_ADDR + (ADDR(.text) + SIZEOF(.text)) | ||
37 | #endif | 17 | #endif |
38 | 18 | ||
19 | #include <asm/page.h> | ||
20 | #include <asm/thread_info.h> | ||
21 | #include <asm-generic/vmlinux.lds.h> | ||
39 | 22 | ||
40 | OUTPUT_ARCH(m68k) | 23 | OUTPUT_ARCH(m68k) |
41 | ENTRY(_start) | 24 | ENTRY(_start) |
42 | 25 | ||
43 | MEMORY { | ||
44 | ram : ORIGIN = RAM_START, LENGTH = RAM_LENGTH | ||
45 | #ifdef ROM_START | ||
46 | romvec : ORIGIN = ROMVEC_START, LENGTH = ROMVEC_LENGTH | ||
47 | rom : ORIGIN = ROM_START, LENGTH = ROM_LENGTH | ||
48 | #endif | ||
49 | } | ||
50 | |||
51 | jiffies = jiffies_64 + 4; | 26 | jiffies = jiffies_64 + 4; |
52 | 27 | ||
53 | SECTIONS { | 28 | SECTIONS { |
54 | 29 | ||
55 | #ifdef ROMVEC_START | 30 | #ifdef CONFIG_ROMVEC |
56 | . = ROMVEC_START ; | 31 | . = CONFIG_ROMVEC; |
57 | .romvec : { | 32 | .romvec : { |
58 | __rom_start = . ; | 33 | __rom_start = .; |
59 | _romvec = .; | 34 | _romvec = .; |
35 | *(.romvec) | ||
60 | *(.data..initvect) | 36 | *(.data..initvect) |
61 | } > romvec | 37 | } |
62 | #endif | 38 | #endif |
63 | 39 | ||
40 | . = KTEXT_ADDR; | ||
41 | |||
42 | _text = .; | ||
43 | _stext = .; | ||
64 | .text : { | 44 | .text : { |
65 | _text = .; | ||
66 | _stext = . ; | ||
67 | HEAD_TEXT | 45 | HEAD_TEXT |
68 | TEXT_TEXT | 46 | TEXT_TEXT |
69 | SCHED_TEXT | 47 | SCHED_TEXT |
70 | LOCK_TEXT | 48 | LOCK_TEXT |
71 | *(.text..lock) | ||
72 | *(.fixup) | 49 | *(.fixup) |
50 | . = ALIGN(16); | ||
51 | } | ||
52 | _etext = .; | ||
53 | |||
54 | #ifdef KDATA_ADDR | ||
55 | . = KDATA_ADDR; | ||
56 | #endif | ||
57 | |||
58 | _sdata = .; | ||
59 | RO_DATA_SECTION(PAGE_SIZE) | ||
60 | RW_DATA_SECTION(16, PAGE_SIZE, THREAD_SIZE) | ||
61 | _edata = .; | ||
73 | 62 | ||
74 | . = ALIGN(16); /* Exception table */ | 63 | EXCEPTION_TABLE(16) |
75 | __start___ex_table = .; | 64 | NOTES |
76 | *(__ex_table) | ||
77 | __stop___ex_table = .; | ||
78 | |||
79 | *(.rodata) *(.rodata.*) | ||
80 | *(__vermagic) /* Kernel version magic */ | ||
81 | *(.rodata1) | ||
82 | *(.rodata.str1.1) | ||
83 | |||
84 | /* Kernel symbol table: Normal symbols */ | ||
85 | . = ALIGN(4); | ||
86 | __start___ksymtab = .; | ||
87 | *(SORT(___ksymtab+*)) | ||
88 | __stop___ksymtab = .; | ||
89 | |||
90 | /* Kernel symbol table: GPL-only symbols */ | ||
91 | __start___ksymtab_gpl = .; | ||
92 | *(SORT(___ksymtab_gpl+*)) | ||
93 | __stop___ksymtab_gpl = .; | ||
94 | |||
95 | /* Kernel symbol table: Normal unused symbols */ | ||
96 | __start___ksymtab_unused = .; | ||
97 | *(SORT(___ksymtab_unused+*)) | ||
98 | __stop___ksymtab_unused = .; | ||
99 | |||
100 | /* Kernel symbol table: GPL-only unused symbols */ | ||
101 | __start___ksymtab_unused_gpl = .; | ||
102 | *(SORT(___ksymtab_unused_gpl+*)) | ||
103 | __stop___ksymtab_unused_gpl = .; | ||
104 | |||
105 | /* Kernel symbol table: GPL-future symbols */ | ||
106 | __start___ksymtab_gpl_future = .; | ||
107 | *(SORT(___ksymtab_gpl_future+*)) | ||
108 | __stop___ksymtab_gpl_future = .; | ||
109 | |||
110 | /* Kernel symbol table: Normal symbols */ | ||
111 | __start___kcrctab = .; | ||
112 | *(SORT(___kcrctab+*)) | ||
113 | __stop___kcrctab = .; | ||
114 | |||
115 | /* Kernel symbol table: GPL-only symbols */ | ||
116 | __start___kcrctab_gpl = .; | ||
117 | *(SORT(___kcrctab_gpl+*)) | ||
118 | __stop___kcrctab_gpl = .; | ||
119 | |||
120 | /* Kernel symbol table: Normal unused symbols */ | ||
121 | __start___kcrctab_unused = .; | ||
122 | *(SORT(___kcrctab_unused+*)) | ||
123 | __stop___kcrctab_unused = .; | ||
124 | |||
125 | /* Kernel symbol table: GPL-only unused symbols */ | ||
126 | __start___kcrctab_unused_gpl = .; | ||
127 | *(SORT(___kcrctab_unused_gpl+*)) | ||
128 | __stop___kcrctab_unused_gpl = .; | ||
129 | |||
130 | /* Kernel symbol table: GPL-future symbols */ | ||
131 | __start___kcrctab_gpl_future = .; | ||
132 | *(SORT(___kcrctab_gpl_future+*)) | ||
133 | __stop___kcrctab_gpl_future = .; | ||
134 | |||
135 | /* Kernel symbol table: strings */ | ||
136 | *(__ksymtab_strings) | ||
137 | |||
138 | /* Built-in module parameters */ | ||
139 | . = ALIGN(4) ; | ||
140 | __start___param = .; | ||
141 | *(__param) | ||
142 | __stop___param = .; | ||
143 | |||
144 | /* Built-in module versions */ | ||
145 | . = ALIGN(4) ; | ||
146 | __start___modver = .; | ||
147 | *(__modver) | ||
148 | __stop___modver = .; | ||
149 | |||
150 | . = ALIGN(4) ; | ||
151 | _etext = . ; | ||
152 | } > TEXT | ||
153 | |||
154 | .data DATA_ADDR : { | ||
155 | . = ALIGN(4); | ||
156 | _sdata = . ; | ||
157 | DATA_DATA | ||
158 | CACHELINE_ALIGNED_DATA(32) | ||
159 | PAGE_ALIGNED_DATA(PAGE_SIZE) | ||
160 | *(.data..shared_aligned) | ||
161 | INIT_TASK_DATA(THREAD_SIZE) | ||
162 | _edata = . ; | ||
163 | } > DATA | ||
164 | 65 | ||
66 | . = ALIGN(PAGE_SIZE); | ||
67 | __init_begin = .; | ||
68 | INIT_TEXT_SECTION(PAGE_SIZE) | ||
69 | INIT_DATA_SECTION(16) | ||
70 | PERCPU_SECTION(16) | ||
165 | .m68k_fixup : { | 71 | .m68k_fixup : { |
166 | __start_fixup = .; | 72 | __start_fixup = .; |
167 | *(.m68k_fixup) | 73 | *(.m68k_fixup) |
168 | __stop_fixup = .; | 74 | __stop_fixup = .; |
169 | } > DATA | 75 | } |
170 | NOTES > DATA | ||
171 | |||
172 | .init.text : { | ||
173 | . = ALIGN(PAGE_SIZE); | ||
174 | __init_begin = .; | ||
175 | } > INIT | ||
176 | INIT_TEXT_SECTION(PAGE_SIZE) > INIT | ||
177 | INIT_DATA_SECTION(16) > INIT | ||
178 | .init.data : { | 76 | .init.data : { |
179 | . = ALIGN(PAGE_SIZE); | 77 | . = ALIGN(PAGE_SIZE); |
180 | __init_end = .; | 78 | __init_end = .; |
181 | } > INIT | 79 | } |
182 | 80 | ||
183 | .bss : { | 81 | _sbss = .; |
184 | . = ALIGN(4); | 82 | BSS_SECTION(0, 0, 0) |
185 | _sbss = . ; | 83 | _ebss = .; |
186 | *(.bss) | 84 | |
187 | *(COMMON) | 85 | _end = .; |
188 | . = ALIGN(4) ; | 86 | |
189 | _ebss = . ; | 87 | STABS_DEBUG |
190 | _end = . ; | 88 | .comment 0 : { *(.comment) } |
191 | } > BSSS | ||
192 | 89 | ||
90 | /* Sections to be discarded */ | ||
193 | DISCARDS | 91 | DISCARDS |
194 | } | 92 | } |
195 | 93 | ||