aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m68k/kernel')
-rw-r--r--arch/m68k/kernel/ints.c1
-rw-r--r--arch/m68k/kernel/irq.c1
-rw-r--r--arch/m68k/kernel/process.c376
-rw-r--r--arch/m68k/kernel/process_mm.c369
-rw-r--r--arch/m68k/kernel/process_no.c406
-rw-r--r--arch/m68k/kernel/ptrace.c305
-rw-r--r--arch/m68k/kernel/ptrace_mm.c295
-rw-r--r--arch/m68k/kernel/ptrace_no.c255
-rw-r--r--arch/m68k/kernel/setup_no.c3
-rw-r--r--arch/m68k/kernel/time.c116
-rw-r--r--arch/m68k/kernel/time_mm.c114
-rw-r--r--arch/m68k/kernel/time_no.c90
-rw-r--r--arch/m68k/kernel/traps.c1
-rw-r--r--arch/m68k/kernel/vectors.c1
-rw-r--r--arch/m68k/kernel/vmlinux-nommu.lds200
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
21asmlinkage void do_IRQ(int irq, struct pt_regs *regs) 20asmlinkage 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
36asmlinkage void ret_from_fork(void);
37
38
39/*
40 * Return saved PC from a blocked thread
41 */
42unsigned 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 */
55static 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
66void (*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 */
74void 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
84void machine_restart(char * __unused)
85{
86 if (mach_reset)
87 mach_reset();
88 for (;;);
89}
90
91void machine_halt(void)
92{
93 if (mach_halt)
94 mach_halt();
95 for (;;);
96}
97
98void machine_power_off(void)
99{
100 if (mach_power_off)
101 mach_power_off();
102 for (;;);
103}
104
105void (*pm_power_off)(void) = machine_power_off;
106EXPORT_SYMBOL(pm_power_off);
107
108void 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 */
126int 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}
166EXPORT_SYMBOL(kernel_thread);
167
168void 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
186asmlinkage 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
195asmlinkage 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
201asmlinkage 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
218int 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
287int 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}
334EXPORT_SYMBOL(dump_fpu);
335#endif /* CONFIG_FPU */
336
337/*
338 * sys_execve() executes a new program.
339 */
340asmlinkage 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
357unsigned 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
37asmlinkage void ret_from_fork(void);
38
39
40/*
41 * Return saved PC from a blocked thread
42 */
43unsigned 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 */
56static 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
67void (*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 */
75void 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
87void machine_restart(char * __unused)
88{
89 if (mach_reset)
90 mach_reset();
91 for (;;);
92}
93
94void machine_halt(void)
95{
96 if (mach_halt)
97 mach_halt();
98 for (;;);
99}
100
101void machine_power_off(void)
102{
103 if (mach_power_off)
104 mach_power_off();
105 for (;;);
106}
107
108void (*pm_power_off)(void) = machine_power_off;
109EXPORT_SYMBOL(pm_power_off);
110
111void 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 */
129int 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}
167EXPORT_SYMBOL(kernel_thread);
168
169void 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
185asmlinkage int m68k_fork(struct pt_regs *regs)
186{
187 return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL);
188}
189
190asmlinkage 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
196asmlinkage 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
213int 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
280int 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}
327EXPORT_SYMBOL(dump_fpu);
328
329/*
330 * sys_execve() executes a new program.
331 */
332asmlinkage 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
349unsigned 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
38asmlinkage void ret_from_fork(void);
39
40/*
41 * The following aren't currently used.
42 */
43void (*pm_idle)(void);
44EXPORT_SYMBOL(pm_idle);
45
46void (*pm_power_off)(void);
47EXPORT_SYMBOL(pm_power_off);
48
49/*
50 * The idle loop on an m68knommu..
51 */
52static 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
63void (*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 */
71void 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
82void machine_restart(char * __unused)
83{
84 if (mach_reset)
85 mach_reset();
86 for (;;);
87}
88
89void machine_halt(void)
90{
91 if (mach_halt)
92 mach_halt();
93 for (;;);
94}
95
96void machine_power_off(void)
97{
98 if (mach_power_off)
99 mach_power_off();
100 for (;;);
101}
102
103void 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 */
121int 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}
154EXPORT_SYMBOL(kernel_thread);
155
156void 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
178asmlinkage int m68k_fork(struct pt_regs *regs)
179{
180 /* fork almost works, enough to trick you into looking elsewhere :-( */
181 return(-EINVAL);
182}
183
184asmlinkage int m68k_vfork(struct pt_regs *regs)
185{
186 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL);
187}
188
189asmlinkage 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
202int 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
254int 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}
287EXPORT_SYMBOL(dump_fpu);
288
289/*
290 * Generic dumping code. Used for panic and debug.
291 */
292void 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 */
354asmlinkage 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
371unsigned 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 */
396unsigned 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). */
49static 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 */
74static 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 */
98static 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 */
126static 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 */
136void ptrace_disable(struct task_struct *child)
137{
138 singlestep_disable(child);
139}
140
141void 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" 149void 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
156void user_disable_single_step(struct task_struct *child)
157{
158 singlestep_disable(child);
159}
160
161long 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;
270out_eio:
271 return -EIO;
272}
273
274asmlinkage 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
290asmlinkage 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
299asmlinkage 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). */
50static 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 */
75static 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 */
99static 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 */
127static 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 */
137void ptrace_disable(struct task_struct *child)
138{
139 singlestep_disable(child);
140}
141
142void 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
149void 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
155void user_disable_single_step(struct task_struct *child)
156{
157 singlestep_disable(child);
158}
159
160long 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;
261out_eio:
262 return -EIO;
263}
264
265asmlinkage 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
281asmlinkage 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
290asmlinkage 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). */
48static 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 */
59static 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 */
75static 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
90void 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
97void 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 */
109void 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
115long 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
242asmlinkage 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
251asmlinkage 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);
47char __initdata command_line[COMMAND_LINE_SIZE]; 48char __initdata command_line[COMMAND_LINE_SIZE];
48 49
49/* machine dependent timer functions */ 50/* machine dependent timer functions */
51void (*mach_sched_init)(irq_handler_t handler) __initdata = NULL;
50int (*mach_set_clock_mmss)(unsigned long); 52int (*mach_set_clock_mmss)(unsigned long);
53int (*mach_hwclk) (int, struct rtc_time*);
51 54
52/* machine dependent reboot functions */ 55/* machine dependent reboot functions */
53void (*mach_reset)(void); 56void (*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 */
35static 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
67void 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
83void __init time_init(void)
84{
85 mach_sched_init(timer_interrupt);
86}
87
88#ifdef CONFIG_M68KCLASSIC
89
90u32 arch_gettimeoffset(void)
91{
92 return mach_gettimeoffset() * 1000;
93}
94
95static 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
109module_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
31static 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 */
42static 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
74void 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
90void __init time_init(void)
91{
92 mach_sched_init(timer_interrupt);
93}
94
95u32 arch_gettimeoffset(void)
96{
97 return mach_gettimeoffset() * 1000;
98}
99
100static 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
114module_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 */
30void (*mach_gettod)(int*, int*, int*, int*, int*, int*);
31
32static 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 */
44irqreturn_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
58static 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
76void read_persistent_clock(struct timespec *ts)
77{
78 ts->tv_sec = read_rtc_mmss();
79 ts->tv_nsec = 0;
80}
81
82int update_persistent_clock(struct timespec now)
83{
84 return set_rtc_mmss(now.tv_sec);
85}
86
87void 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
40OUTPUT_ARCH(m68k) 23OUTPUT_ARCH(m68k)
41ENTRY(_start) 24ENTRY(_start)
42 25
43MEMORY {
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
51jiffies = jiffies_64 + 4; 26jiffies = jiffies_64 + 4;
52 27
53SECTIONS { 28SECTIONS {
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