diff options
Diffstat (limited to 'arch/m68k/kernel')
-rw-r--r-- | arch/m68k/kernel/Makefile | 21 | ||||
-rw-r--r-- | arch/m68k/kernel/asm-offsets.c | 3 | ||||
-rw-r--r-- | arch/m68k/kernel/entry.S | 2 | ||||
-rw-r--r-- | arch/m68k/kernel/entry_mm.S | 31 | ||||
-rw-r--r-- | arch/m68k/kernel/entry_no.S | 9 | ||||
-rw-r--r-- | arch/m68k/kernel/init_task.c | 3 | ||||
-rw-r--r-- | arch/m68k/kernel/m68k_ksyms.c | 2 | ||||
-rw-r--r-- | arch/m68k/kernel/process_mm.c | 75 | ||||
-rw-r--r-- | arch/m68k/kernel/ptrace_mm.c | 18 | ||||
-rw-r--r-- | arch/m68k/kernel/setup_mm.c | 22 | ||||
-rw-r--r-- | arch/m68k/kernel/setup_no.c | 1 | ||||
-rw-r--r-- | arch/m68k/kernel/signal_mm.c | 204 | ||||
-rw-r--r-- | arch/m68k/kernel/time.c | 2 | ||||
-rw-r--r-- | arch/m68k/kernel/time_no.c | 3 | ||||
-rw-r--r-- | arch/m68k/kernel/traps.c | 104 | ||||
-rw-r--r-- | arch/m68k/kernel/vmlinux-nommu.lds (renamed from arch/m68k/kernel/vmlinux.lds_no.S) | 8 | ||||
-rw-r--r-- | arch/m68k/kernel/vmlinux-std.lds | 2 | ||||
-rw-r--r-- | arch/m68k/kernel/vmlinux-sun3.lds | 2 | ||||
-rw-r--r-- | arch/m68k/kernel/vmlinux.lds.S | 15 | ||||
-rw-r--r-- | arch/m68k/kernel/vmlinux.lds_mm.S | 10 |
20 files changed, 407 insertions, 130 deletions
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile index c5696193281a..40d29a788b05 100644 --- a/arch/m68k/kernel/Makefile +++ b/arch/m68k/kernel/Makefile @@ -2,19 +2,24 @@ # Makefile for the linux kernel. # -extra-$(CONFIG_MMU) := head.o +extra-$(CONFIG_AMIGA) := head.o +extra-$(CONFIG_ATARI) := head.o +extra-$(CONFIG_MAC) := head.o +extra-$(CONFIG_APOLLO) := head.o +extra-$(CONFIG_VME) := head.o +extra-$(CONFIG_HP300) := head.o +extra-$(CONFIG_Q40) := head.o +extra-$(CONFIG_SUN3X) := head.o extra-$(CONFIG_SUN3) := sun3-head.o extra-y += vmlinux.lds -obj-y := entry.o irq.o m68k_ksyms.o module.o process.o ptrace.o setup.o \ - signal.o sys_m68k.o syscalltable.o time.o traps.o +obj-y := entry.o init_task.o irq.o m68k_ksyms.o module.o process.o ptrace.o +obj-y += setup.o signal.o sys_m68k.o syscalltable.o time.o traps.o -obj-$(CONFIG_MMU) += ints.o vectors.o +obj-$(CONFIG_MMU_MOTOROLA) += ints.o vectors.o +obj-$(CONFIG_MMU_SUN3) += ints.o vectors.o ifndef CONFIG_MMU_SUN3 -obj-y += dma.o -endif -ifndef CONFIG_MMU -obj-y += init_task.o +obj-y += dma.o endif diff --git a/arch/m68k/kernel/asm-offsets.c b/arch/m68k/kernel/asm-offsets.c index 983fed9d469b..a972b00cd77d 100644 --- a/arch/m68k/kernel/asm-offsets.c +++ b/arch/m68k/kernel/asm-offsets.c @@ -24,8 +24,7 @@ int main(void) /* offsets into the task struct */ DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); DEFINE(TASK_MM, offsetof(struct task_struct, mm)); - DEFINE(TASK_INFO, offsetof(struct task_struct, thread.info)); - DEFINE(TASK_TINFO, offsetof(struct task_struct, thread.info)); + DEFINE(TASK_STACK, offsetof(struct task_struct, stack)); /* offsets into the thread struct */ DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index 081cf96f243b..b8daf64e347d 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S @@ -1,4 +1,4 @@ -#ifdef CONFIG_MMU +#if defined(CONFIG_MMU) && !defined(CONFIG_COLDFIRE) #include "entry_mm.S" #else #include "entry_no.S" diff --git a/arch/m68k/kernel/entry_mm.S b/arch/m68k/kernel/entry_mm.S index c713f514843d..675a854966a6 100644 --- a/arch/m68k/kernel/entry_mm.S +++ b/arch/m68k/kernel/entry_mm.S @@ -99,7 +99,8 @@ do_trace_exit: jra .Lret_from_exception ENTRY(ret_from_signal) - tstb %curptr@(TASK_INFO+TINFO_FLAGS+2) + movel %curptr@(TASK_STACK),%a1 + tstb %a1@(TINFO_FLAGS+2) jge 1f jbsr syscall_trace 1: RESTORE_SWITCH_STACK @@ -120,11 +121,13 @@ ENTRY(system_call) SAVE_ALL_SYS GET_CURRENT(%d1) + movel %d1,%a1 + | save top of frame movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) | syscall trace? - tstb %curptr@(TASK_INFO+TINFO_FLAGS+2) + tstb %a1@(TINFO_FLAGS+2) jmi do_trace_entry cmpl #NR_syscalls,%d0 jcc badsys @@ -133,7 +136,8 @@ syscall: movel %d0,%sp@(PT_OFF_D0) | save the return value ret_from_syscall: |oriw #0x0700,%sr - movew %curptr@(TASK_INFO+TINFO_FLAGS+2),%d0 + movel %curptr@(TASK_STACK),%a1 + movew %a1@(TINFO_FLAGS+2),%d0 jne syscall_exit_work 1: RESTORE_ALL @@ -159,7 +163,8 @@ ENTRY(ret_from_exception) andw #ALLOWINT,%sr resume_userspace: - moveb %curptr@(TASK_INFO+TINFO_FLAGS+3),%d0 + movel %curptr@(TASK_STACK),%a1 + moveb %a1@(TINFO_FLAGS+3),%d0 jne exit_work 1: RESTORE_ALL @@ -199,7 +204,8 @@ do_delayed_trace: ENTRY(auto_inthandler) SAVE_ALL_INT GET_CURRENT(%d0) - addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) + movel %d0,%a1 + addqb #1,%a1@(TINFO_PREEMPT+1) | put exception # in d0 bfextu %sp@(PT_OFF_FORMATVEC){#4,#10},%d0 subw #VEC_SPUR,%d0 @@ -211,7 +217,8 @@ auto_irqhandler_fixup = . + 2 addql #8,%sp | pop parameters off stack ret_from_interrupt: - subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) + movel %curptr@(TASK_STACK),%a1 + subqb #1,%a1@(TINFO_PREEMPT+1) jeq ret_from_last_interrupt 2: RESTORE_ALL @@ -232,7 +239,8 @@ ret_from_last_interrupt: ENTRY(user_inthandler) SAVE_ALL_INT GET_CURRENT(%d0) - addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) + movel %d0,%a1 + addqb #1,%a1@(TINFO_PREEMPT+1) | put exception # in d0 bfextu %sp@(PT_OFF_FORMATVEC){#4,#10},%d0 user_irqvec_fixup = . + 2 @@ -243,7 +251,8 @@ user_irqvec_fixup = . + 2 jsr do_IRQ | process the IRQ addql #8,%sp | pop parameters off stack - subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) + movel %curptr@(TASK_STACK),%a1 + subqb #1,%a1@(TINFO_PREEMPT+1) jeq ret_from_last_interrupt RESTORE_ALL @@ -252,13 +261,15 @@ user_irqvec_fixup = . + 2 ENTRY(bad_inthandler) SAVE_ALL_INT GET_CURRENT(%d0) - addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) + movel %d0,%a1 + addqb #1,%a1@(TINFO_PREEMPT+1) movel %sp,%sp@- jsr handle_badint addql #4,%sp - subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) + movel %curptr@(TASK_STACK),%a1 + subqb #1,%a1@(TINFO_PREEMPT+1) jeq ret_from_last_interrupt RESTORE_ALL diff --git a/arch/m68k/kernel/entry_no.S b/arch/m68k/kernel/entry_no.S index 1b4289061a64..d80cba45589f 100644 --- a/arch/m68k/kernel/entry_no.S +++ b/arch/m68k/kernel/entry_no.S @@ -44,8 +44,7 @@ ENTRY(buserr) SAVE_ALL_INT - moveq #-1,%d0 - movel %d0,%sp@(PT_OFF_ORIG_D0) + GET_CURRENT(%d0) movel %sp,%sp@- /* stack frame pointer argument */ jsr buserr_c addql #4,%sp @@ -53,8 +52,7 @@ ENTRY(buserr) ENTRY(trap) SAVE_ALL_INT - moveq #-1,%d0 - movel %d0,%sp@(PT_OFF_ORIG_D0) + GET_CURRENT(%d0) movel %sp,%sp@- /* stack frame pointer argument */ jsr trap_c addql #4,%sp @@ -65,8 +63,7 @@ ENTRY(trap) .globl dbginterrupt ENTRY(dbginterrupt) SAVE_ALL_INT - moveq #-1,%d0 - movel %d0,%sp@(PT_OFF_ORIG_D0) + GET_CURRENT(%d0) movel %sp,%sp@- /* stack frame pointer argument */ jsr dbginterrupt_c addql #4,%sp diff --git a/arch/m68k/kernel/init_task.c b/arch/m68k/kernel/init_task.c index cbf9dc3cc51d..c744cfc6bfa1 100644 --- a/arch/m68k/kernel/init_task.c +++ b/arch/m68k/kernel/init_task.c @@ -19,7 +19,6 @@ static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); * * All other task structs will be allocated on slabs in fork.c */ -__asm__(".align 4"); struct task_struct init_task = INIT_TASK(init_task); EXPORT_SYMBOL(init_task); @@ -27,7 +26,7 @@ EXPORT_SYMBOL(init_task); /* * Initial thread structure. * - * We need to make sure that this is 8192-byte aligned due to the + * We need to make sure that this is THREAD size aligned due to the * way process stacks are handled. This is done by having a special * "init_task" linker map entry.. */ diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c index 1b7a14d1a000..774c1bd59c36 100644 --- a/arch/m68k/kernel/m68k_ksyms.c +++ b/arch/m68k/kernel/m68k_ksyms.c @@ -14,7 +14,7 @@ EXPORT_SYMBOL(__ashrdi3); EXPORT_SYMBOL(__lshrdi3); EXPORT_SYMBOL(__muldi3); -#if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE) +#if defined(CONFIG_CPU_HAS_NO_MULDIV64) /* * Simpler 68k and ColdFire parts also need a few other gcc functions. */ diff --git a/arch/m68k/kernel/process_mm.c b/arch/m68k/kernel/process_mm.c index 1bc223aa07ec..125f34e00bf0 100644 --- a/arch/m68k/kernel/process_mm.c +++ b/arch/m68k/kernel/process_mm.c @@ -33,22 +33,6 @@ #include <asm/setup.h> #include <asm/pgtable.h> -/* - * Initial task/thread structure. Make this a per-architecture thing, - * because different architectures tend to have different - * alignment requirements and potentially different initial - * setup. - */ -static struct signal_struct init_signals = INIT_SIGNALS(init_signals); -static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -union thread_union init_thread_union __init_task_data - __attribute__((aligned(THREAD_SIZE))) = - { INIT_THREAD_INFO(init_task) }; - -/* initial task structure */ -struct task_struct init_task = INIT_TASK(init_task); - -EXPORT_SYMBOL(init_task); asmlinkage void ret_from_fork(void); @@ -188,9 +172,7 @@ void flush_thread(void) current->thread.fs = __USER_DS; if (!FPU_IS_EMU) - asm volatile (".chip 68k/68881\n\t" - "frestore %0@\n\t" - ".chip 68k" : : "a" (&zero)); + asm volatile ("frestore %0@" : : "a" (&zero) : "memory"); } /* @@ -264,11 +246,28 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, /* Copy the current fpu state */ asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory"); - if (!CPU_IS_060 ? p->thread.fpstate[0] : p->thread.fpstate[2]) - asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t" - "fmoveml %/fpiar/%/fpcr/%/fpsr,%1" - : : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0]) - : "memory"); + if (!CPU_IS_060 ? p->thread.fpstate[0] : p->thread.fpstate[2]) { + if (CPU_IS_COLDFIRE) { + asm volatile ("fmovemd %/fp0-%/fp7,%0\n\t" + "fmovel %/fpiar,%1\n\t" + "fmovel %/fpcr,%2\n\t" + "fmovel %/fpsr,%3" + : + : "m" (p->thread.fp[0]), + "m" (p->thread.fpcntl[0]), + "m" (p->thread.fpcntl[1]), + "m" (p->thread.fpcntl[2]) + : "memory"); + } else { + asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t" + "fmoveml %/fpiar/%/fpcr/%/fpsr,%1" + : + : "m" (p->thread.fp[0]), + "m" (p->thread.fpcntl[0]) + : "memory"); + } + } + /* Restore the state in case the fpu was busy */ asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0])); } @@ -301,12 +300,28 @@ int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu) if (!CPU_IS_060 ? !fpustate[0] : !fpustate[2]) return 0; - asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0" - :: "m" (fpu->fpcntl[0]) - : "memory"); - asm volatile ("fmovemx %/fp0-%/fp7,%0" - :: "m" (fpu->fpregs[0]) - : "memory"); + if (CPU_IS_COLDFIRE) { + asm volatile ("fmovel %/fpiar,%0\n\t" + "fmovel %/fpcr,%1\n\t" + "fmovel %/fpsr,%2\n\t" + "fmovemd %/fp0-%/fp7,%3" + : + : "m" (fpu->fpcntl[0]), + "m" (fpu->fpcntl[1]), + "m" (fpu->fpcntl[2]), + "m" (fpu->fpregs[0]) + : "memory"); + } else { + asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0" + : + : "m" (fpu->fpcntl[0]) + : "memory"); + asm volatile ("fmovemx %/fp0-%/fp7,%0" + : + : "m" (fpu->fpregs[0]) + : "memory"); + } + return 1; } EXPORT_SYMBOL(dump_fpu); diff --git a/arch/m68k/kernel/ptrace_mm.c b/arch/m68k/kernel/ptrace_mm.c index 0b252683cefb..7bc999b73529 100644 --- a/arch/m68k/kernel/ptrace_mm.c +++ b/arch/m68k/kernel/ptrace_mm.c @@ -18,6 +18,7 @@ #include <linux/ptrace.h> #include <linux/user.h> #include <linux/signal.h> +#include <linux/tracehook.h> #include <asm/uaccess.h> #include <asm/page.h> @@ -275,3 +276,20 @@ asmlinkage void syscall_trace(void) current->exit_code = 0; } } + +#ifdef CONFIG_COLDFIRE +asmlinkage int syscall_trace_enter(void) +{ + int ret = 0; + + if (test_thread_flag(TIF_SYSCALL_TRACE)) + ret = tracehook_report_syscall_entry(task_pt_regs(current)); + return ret; +} + +asmlinkage void syscall_trace_leave(void) +{ + if (test_thread_flag(TIF_SYSCALL_TRACE)) + tracehook_report_syscall_exit(task_pt_regs(current), 0); +} +#endif /* CONFIG_COLDFIRE */ diff --git a/arch/m68k/kernel/setup_mm.c b/arch/m68k/kernel/setup_mm.c index c3b45061dd08..d872ce4807c9 100644 --- a/arch/m68k/kernel/setup_mm.c +++ b/arch/m68k/kernel/setup_mm.c @@ -221,7 +221,8 @@ void __init setup_arch(char **cmdline_p) #endif /* The bootinfo is located right after the kernel bss */ - m68k_parse_bootinfo((const struct bi_record *)_end); + if (!CPU_IS_COLDFIRE) + m68k_parse_bootinfo((const struct bi_record *)_end); if (CPU_IS_040) m68k_is040or060 = 4; @@ -235,7 +236,7 @@ void __init setup_arch(char **cmdline_p) * with them, we should add a test to check_bugs() below] */ #ifndef CONFIG_M68KFPU_EMU_ONLY /* clear the fpu if we have one */ - if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) { + if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060|FPU_COLDFIRE)) { volatile int zero = 0; asm volatile ("frestore %0" : : "m" (zero)); } @@ -258,6 +259,10 @@ void __init setup_arch(char **cmdline_p) init_mm.end_data = (unsigned long)_edata; init_mm.brk = (unsigned long)_end; +#if defined(CONFIG_BOOTPARAM) + strncpy(m68k_command_line, CONFIG_BOOTPARAM_STRING, CL_SIZE); + m68k_command_line[CL_SIZE - 1] = 0; +#endif /* CONFIG_BOOTPARAM */ *cmdline_p = m68k_command_line; memcpy(boot_command_line, *cmdline_p, CL_SIZE); @@ -323,6 +328,11 @@ void __init setup_arch(char **cmdline_p) config_sun3x(); break; #endif +#ifdef CONFIG_COLDFIRE + case MACH_M54XX: + config_BSP(NULL, 0); + break; +#endif default: panic("No configuration setup"); } @@ -384,6 +394,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) #define LOOP_CYCLES_68030 (8) #define LOOP_CYCLES_68040 (3) #define LOOP_CYCLES_68060 (1) +#define LOOP_CYCLES_COLDFIRE (2) if (CPU_IS_020) { cpu = "68020"; @@ -397,6 +408,9 @@ static int show_cpuinfo(struct seq_file *m, void *v) } else if (CPU_IS_060) { cpu = "68060"; clockfactor = LOOP_CYCLES_68060; + } else if (CPU_IS_COLDFIRE) { + cpu = "ColdFire"; + clockfactor = LOOP_CYCLES_COLDFIRE; } else { cpu = "680x0"; clockfactor = 0; @@ -415,6 +429,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) fpu = "68060"; else if (m68k_fputype & FPU_SUNFPA) fpu = "Sun FPA"; + else if (m68k_fputype & FPU_COLDFIRE) + fpu = "ColdFire"; else fpu = "none"; #endif @@ -431,6 +447,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) mmu = "Sun-3"; else if (m68k_mmutype & MMU_APOLLO) mmu = "Apollo"; + else if (m68k_mmutype & MMU_COLDFIRE) + mmu = "ColdFire"; else mmu = "unknown"; diff --git a/arch/m68k/kernel/setup_no.c b/arch/m68k/kernel/setup_no.c index 2ed8c0fb1517..ca3df0dc7e88 100644 --- a/arch/m68k/kernel/setup_no.c +++ b/arch/m68k/kernel/setup_no.c @@ -47,7 +47,6 @@ EXPORT_SYMBOL(memory_end); char __initdata command_line[COMMAND_LINE_SIZE]; /* machine dependent timer functions */ -void (*mach_gettod)(int*, int*, int*, int*, int*, int*); int (*mach_set_clock_mmss)(unsigned long); /* machine dependent reboot functions */ diff --git a/arch/m68k/kernel/signal_mm.c b/arch/m68k/kernel/signal_mm.c index a0afc239304e..cb856f9da655 100644 --- a/arch/m68k/kernel/signal_mm.c +++ b/arch/m68k/kernel/signal_mm.c @@ -56,7 +56,11 @@ static const int frame_extra_sizes[16] = { [1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */ [2] = sizeof(((struct frame *)0)->un.fmt2), [3] = sizeof(((struct frame *)0)->un.fmt3), +#ifdef CONFIG_COLDFIRE + [4] = 0, +#else [4] = sizeof(((struct frame *)0)->un.fmt4), +#endif [5] = -1, /* sizeof(((struct frame *)0)->un.fmt5), */ [6] = -1, /* sizeof(((struct frame *)0)->un.fmt6), */ [7] = sizeof(((struct frame *)0)->un.fmt7), @@ -84,7 +88,11 @@ int handle_kernel_fault(struct pt_regs *regs) regs->stkadj = frame_extra_sizes[regs->format]; tregs = (struct pt_regs *)((long)regs + regs->stkadj); tregs->vector = regs->vector; +#ifdef CONFIG_COLDFIRE + tregs->format = 4; +#else tregs->format = 0; +#endif tregs->pc = fixup->fixup; tregs->sr = regs->sr; @@ -195,7 +203,8 @@ static inline int restore_fpu_state(struct sigcontext *sc) if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) { /* Verify the frame format. */ - if (!CPU_IS_060 && (sc->sc_fpstate[0] != fpu_version)) + if (!(CPU_IS_060 || CPU_IS_COLDFIRE) && + (sc->sc_fpstate[0] != fpu_version)) goto out; if (CPU_IS_020_OR_030) { if (m68k_fputype & FPU_68881 && @@ -214,19 +223,43 @@ static inline int restore_fpu_state(struct sigcontext *sc) sc->sc_fpstate[3] == 0x60 || sc->sc_fpstate[3] == 0xe0)) goto out; + } else if (CPU_IS_COLDFIRE) { + if (!(sc->sc_fpstate[0] == 0x00 || + sc->sc_fpstate[0] == 0x05 || + sc->sc_fpstate[0] == 0xe5)) + goto out; } else goto out; - __asm__ volatile (".chip 68k/68881\n\t" - "fmovemx %0,%%fp0-%%fp1\n\t" - "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t" - ".chip 68k" - : /* no outputs */ - : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl)); + if (CPU_IS_COLDFIRE) { + __asm__ volatile ("fmovemd %0,%%fp0-%%fp1\n\t" + "fmovel %1,%%fpcr\n\t" + "fmovel %2,%%fpsr\n\t" + "fmovel %3,%%fpiar" + : /* no outputs */ + : "m" (sc->sc_fpregs[0]), + "m" (sc->sc_fpcntl[0]), + "m" (sc->sc_fpcntl[1]), + "m" (sc->sc_fpcntl[2])); + } else { + __asm__ volatile (".chip 68k/68881\n\t" + "fmovemx %0,%%fp0-%%fp1\n\t" + "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t" + ".chip 68k" + : /* no outputs */ + : "m" (*sc->sc_fpregs), + "m" (*sc->sc_fpcntl)); + } + } + + if (CPU_IS_COLDFIRE) { + __asm__ volatile ("frestore %0" : : "m" (*sc->sc_fpstate)); + } else { + __asm__ volatile (".chip 68k/68881\n\t" + "frestore %0\n\t" + ".chip 68k" + : : "m" (*sc->sc_fpstate)); } - __asm__ volatile (".chip 68k/68881\n\t" - "frestore %0\n\t" - ".chip 68k" : : "m" (*sc->sc_fpstate)); err = 0; out: @@ -241,7 +274,7 @@ out: static inline int rt_restore_fpu_state(struct ucontext __user *uc) { unsigned char fpstate[FPCONTEXT_SIZE]; - int context_size = CPU_IS_060 ? 8 : 0; + int context_size = CPU_IS_060 ? 8 : (CPU_IS_COLDFIRE ? 12 : 0); fpregset_t fpregs; int err = 1; @@ -260,10 +293,11 @@ static inline int rt_restore_fpu_state(struct ucontext __user *uc) if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate)) goto out; if (CPU_IS_060 ? fpstate[2] : fpstate[0]) { - if (!CPU_IS_060) + if (!(CPU_IS_060 || CPU_IS_COLDFIRE)) context_size = fpstate[1]; /* Verify the frame format. */ - if (!CPU_IS_060 && (fpstate[0] != fpu_version)) + if (!(CPU_IS_060 || CPU_IS_COLDFIRE) && + (fpstate[0] != fpu_version)) goto out; if (CPU_IS_020_OR_030) { if (m68k_fputype & FPU_68881 && @@ -282,26 +316,50 @@ static inline int rt_restore_fpu_state(struct ucontext __user *uc) fpstate[3] == 0x60 || fpstate[3] == 0xe0)) goto out; + } else if (CPU_IS_COLDFIRE) { + if (!(fpstate[3] == 0x00 || + fpstate[3] == 0x05 || + fpstate[3] == 0xe5)) + goto out; } else goto out; if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs, sizeof(fpregs))) goto out; - __asm__ volatile (".chip 68k/68881\n\t" - "fmovemx %0,%%fp0-%%fp7\n\t" - "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t" - ".chip 68k" - : /* no outputs */ - : "m" (*fpregs.f_fpregs), - "m" (*fpregs.f_fpcntl)); + + if (CPU_IS_COLDFIRE) { + __asm__ volatile ("fmovemd %0,%%fp0-%%fp7\n\t" + "fmovel %1,%%fpcr\n\t" + "fmovel %2,%%fpsr\n\t" + "fmovel %3,%%fpiar" + : /* no outputs */ + : "m" (fpregs.f_fpregs[0]), + "m" (fpregs.f_fpcntl[0]), + "m" (fpregs.f_fpcntl[1]), + "m" (fpregs.f_fpcntl[2])); + } else { + __asm__ volatile (".chip 68k/68881\n\t" + "fmovemx %0,%%fp0-%%fp7\n\t" + "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t" + ".chip 68k" + : /* no outputs */ + : "m" (*fpregs.f_fpregs), + "m" (*fpregs.f_fpcntl)); + } } if (context_size && __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1, context_size)) goto out; - __asm__ volatile (".chip 68k/68881\n\t" - "frestore %0\n\t" - ".chip 68k" : : "m" (*fpstate)); + + if (CPU_IS_COLDFIRE) { + __asm__ volatile ("frestore %0" : : "m" (*fpstate)); + } else { + __asm__ volatile (".chip 68k/68881\n\t" + "frestore %0\n\t" + ".chip 68k" + : : "m" (*fpstate)); + } err = 0; out: @@ -336,8 +394,12 @@ static int mangle_kernel_stack(struct pt_regs *regs, int formatvec, regs->format = formatvec >> 12; regs->vector = formatvec & 0xfff; #define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack)) - __asm__ __volatile__ - (" movel %0,%/a0\n\t" + __asm__ __volatile__ ( +#ifdef CONFIG_COLDFIRE + " movel %0,%/sp\n\t" + " bra ret_from_signal\n" +#else + " movel %0,%/a0\n\t" " subl %1,%/a0\n\t" /* make room on stack */ " movel %/a0,%/sp\n\t" /* set stack pointer */ /* move switch_stack and pt_regs */ @@ -350,6 +412,7 @@ static int mangle_kernel_stack(struct pt_regs *regs, int formatvec, "2: movel %4@+,%/a0@+\n\t" " dbra %1,2b\n\t" " bral ret_from_signal\n" +#endif : /* no outputs, it doesn't ever return */ : "a" (sw), "d" (fsize), "d" (frame_offset/4-1), "n" (frame_offset), "a" (buf + fsize/4) @@ -516,10 +579,15 @@ static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs) return; } - __asm__ volatile (".chip 68k/68881\n\t" - "fsave %0\n\t" - ".chip 68k" - : : "m" (*sc->sc_fpstate) : "memory"); + if (CPU_IS_COLDFIRE) { + __asm__ volatile ("fsave %0" + : : "m" (*sc->sc_fpstate) : "memory"); + } else { + __asm__ volatile (".chip 68k/68881\n\t" + "fsave %0\n\t" + ".chip 68k" + : : "m" (*sc->sc_fpstate) : "memory"); + } if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) { fpu_version = sc->sc_fpstate[0]; @@ -530,21 +598,35 @@ static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs) if (*(unsigned short *) sc->sc_fpstate == 0x1f38) sc->sc_fpstate[0x38] |= 1 << 3; } - __asm__ volatile (".chip 68k/68881\n\t" - "fmovemx %%fp0-%%fp1,%0\n\t" - "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t" - ".chip 68k" - : "=m" (*sc->sc_fpregs), - "=m" (*sc->sc_fpcntl) - : /* no inputs */ - : "memory"); + + if (CPU_IS_COLDFIRE) { + __asm__ volatile ("fmovemd %%fp0-%%fp1,%0\n\t" + "fmovel %%fpcr,%1\n\t" + "fmovel %%fpsr,%2\n\t" + "fmovel %%fpiar,%3" + : "=m" (sc->sc_fpregs[0]), + "=m" (sc->sc_fpcntl[0]), + "=m" (sc->sc_fpcntl[1]), + "=m" (sc->sc_fpcntl[2]) + : /* no inputs */ + : "memory"); + } else { + __asm__ volatile (".chip 68k/68881\n\t" + "fmovemx %%fp0-%%fp1,%0\n\t" + "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t" + ".chip 68k" + : "=m" (*sc->sc_fpregs), + "=m" (*sc->sc_fpcntl) + : /* no inputs */ + : "memory"); + } } } static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs) { unsigned char fpstate[FPCONTEXT_SIZE]; - int context_size = CPU_IS_060 ? 8 : 0; + int context_size = CPU_IS_060 ? 8 : (CPU_IS_COLDFIRE ? 12 : 0); int err = 0; if (FPU_IS_EMU) { @@ -557,15 +639,19 @@ static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs * return err; } - __asm__ volatile (".chip 68k/68881\n\t" - "fsave %0\n\t" - ".chip 68k" - : : "m" (*fpstate) : "memory"); + if (CPU_IS_COLDFIRE) { + __asm__ volatile ("fsave %0" : : "m" (*fpstate) : "memory"); + } else { + __asm__ volatile (".chip 68k/68881\n\t" + "fsave %0\n\t" + ".chip 68k" + : : "m" (*fpstate) : "memory"); + } err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate); if (CPU_IS_060 ? fpstate[2] : fpstate[0]) { fpregset_t fpregs; - if (!CPU_IS_060) + if (!(CPU_IS_060 || CPU_IS_COLDFIRE)) context_size = fpstate[1]; fpu_version = fpstate[0]; if (CPU_IS_020_OR_030 && @@ -575,14 +661,27 @@ static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs * if (*(unsigned short *) fpstate == 0x1f38) fpstate[0x38] |= 1 << 3; } - __asm__ volatile (".chip 68k/68881\n\t" - "fmovemx %%fp0-%%fp7,%0\n\t" - "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t" - ".chip 68k" - : "=m" (*fpregs.f_fpregs), - "=m" (*fpregs.f_fpcntl) - : /* no inputs */ - : "memory"); + if (CPU_IS_COLDFIRE) { + __asm__ volatile ("fmovemd %%fp0-%%fp7,%0\n\t" + "fmovel %%fpcr,%1\n\t" + "fmovel %%fpsr,%2\n\t" + "fmovel %%fpiar,%3" + : "=m" (fpregs.f_fpregs[0]), + "=m" (fpregs.f_fpcntl[0]), + "=m" (fpregs.f_fpcntl[1]), + "=m" (fpregs.f_fpcntl[2]) + : /* no inputs */ + : "memory"); + } else { + __asm__ volatile (".chip 68k/68881\n\t" + "fmovemx %%fp0-%%fp7,%0\n\t" + "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t" + ".chip 68k" + : "=m" (*fpregs.f_fpregs), + "=m" (*fpregs.f_fpcntl) + : /* no inputs */ + : "memory"); + } err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs, sizeof(fpregs)); } @@ -679,8 +778,7 @@ static inline void push_cache (unsigned long vaddr) "cpushl %%bc,(%0)\n\t" ".chip 68k" : : "a" (temp)); - } - else { + } else if (!CPU_IS_COLDFIRE) { /* * 68030/68020 have no writeback cache; * still need to clear icache. diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c index a5cf40c26de5..75ab79b3bdeb 100644 --- a/arch/m68k/kernel/time.c +++ b/arch/m68k/kernel/time.c @@ -1,4 +1,4 @@ -#ifdef CONFIG_MMU +#if defined(CONFIG_MMU) && !defined(CONFIG_COLDFIRE) #include "time_mm.c" #else #include "time_no.c" diff --git a/arch/m68k/kernel/time_no.c b/arch/m68k/kernel/time_no.c index 6623909f70e6..3ef0f7768dcd 100644 --- a/arch/m68k/kernel/time_no.c +++ b/arch/m68k/kernel/time_no.c @@ -26,6 +26,9 @@ #define TICK_SIZE (tick_nsec / 1000) +/* machine dependent timer functions */ +void (*mach_gettod)(int*, int*, int*, int*, int*, int*); + static inline int set_rtc_mmss(unsigned long nowtime) { if (mach_set_clock_mmss) diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c index 89362f2bb56a..a76452ca964e 100644 --- a/arch/m68k/kernel/traps.c +++ b/arch/m68k/kernel/traps.c @@ -706,6 +706,88 @@ create_atc_entry: #endif /* CPU_M68020_OR_M68030 */ #endif /* !CONFIG_SUN3 */ +#if defined(CONFIG_COLDFIRE) && defined(CONFIG_MMU) +#include <asm/mcfmmu.h> + +/* + * The following table converts the FS encoding of a ColdFire + * exception stack frame into the error_code value needed by + * do_fault. +*/ +static const unsigned char fs_err_code[] = { + 0, /* 0000 */ + 0, /* 0001 */ + 0, /* 0010 */ + 0, /* 0011 */ + 1, /* 0100 */ + 0, /* 0101 */ + 0, /* 0110 */ + 0, /* 0111 */ + 2, /* 1000 */ + 3, /* 1001 */ + 2, /* 1010 */ + 0, /* 1011 */ + 1, /* 1100 */ + 1, /* 1101 */ + 0, /* 1110 */ + 0 /* 1111 */ +}; + +static inline void access_errorcf(unsigned int fs, struct frame *fp) +{ + unsigned long mmusr, addr; + unsigned int err_code; + int need_page_fault; + + mmusr = mmu_read(MMUSR); + addr = mmu_read(MMUAR); + + /* + * error_code: + * bit 0 == 0 means no page found, 1 means protection fault + * bit 1 == 0 means read, 1 means write + */ + switch (fs) { + case 5: /* 0101 TLB opword X miss */ + need_page_fault = cf_tlb_miss(&fp->ptregs, 0, 0, 0); + addr = fp->ptregs.pc; + break; + case 6: /* 0110 TLB extension word X miss */ + need_page_fault = cf_tlb_miss(&fp->ptregs, 0, 0, 1); + addr = fp->ptregs.pc + sizeof(long); + break; + case 10: /* 1010 TLB W miss */ + need_page_fault = cf_tlb_miss(&fp->ptregs, 1, 1, 0); + break; + case 14: /* 1110 TLB R miss */ + need_page_fault = cf_tlb_miss(&fp->ptregs, 0, 1, 0); + break; + default: + /* 0000 Normal */ + /* 0001 Reserved */ + /* 0010 Interrupt during debug service routine */ + /* 0011 Reserved */ + /* 0100 X Protection */ + /* 0111 IFP in emulator mode */ + /* 1000 W Protection*/ + /* 1001 Write error*/ + /* 1011 Reserved*/ + /* 1100 R Protection*/ + /* 1101 R Protection*/ + /* 1111 OEP in emulator mode*/ + need_page_fault = 1; + break; + } + + if (need_page_fault) { + err_code = fs_err_code[fs]; + if ((fs == 13) && (mmusr & MMUSR_WF)) /* rd-mod-wr access */ + err_code |= 2; /* bit1 - write, bit0 - protection */ + do_page_fault(&fp->ptregs, addr, err_code); + } +} +#endif /* CONFIG_COLDFIRE CONFIG_MMU */ + asmlinkage void buserr_c(struct frame *fp) { /* Only set esp0 if coming from user mode */ @@ -716,6 +798,28 @@ asmlinkage void buserr_c(struct frame *fp) printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format); #endif +#if defined(CONFIG_COLDFIRE) && defined(CONFIG_MMU) + if (CPU_IS_COLDFIRE) { + unsigned int fs; + fs = (fp->ptregs.vector & 0x3) | + ((fp->ptregs.vector & 0xc00) >> 8); + switch (fs) { + case 0x5: + case 0x6: + case 0x7: + case 0x9: + case 0xa: + case 0xd: + case 0xe: + case 0xf: + access_errorcf(fs, fp); + return; + default: + break; + } + } +#endif /* CONFIG_COLDFIRE && CONFIG_MMU */ + switch (fp->ptregs.format) { #if defined (CONFIG_M68060) case 4: /* 68060 access error */ diff --git a/arch/m68k/kernel/vmlinux.lds_no.S b/arch/m68k/kernel/vmlinux-nommu.lds index 4e2389340837..8e66ccb0935e 100644 --- a/arch/m68k/kernel/vmlinux.lds_no.S +++ b/arch/m68k/kernel/vmlinux-nommu.lds @@ -69,6 +69,7 @@ SECTIONS { SCHED_TEXT LOCK_TEXT *(.text..lock) + *(.fixup) . = ALIGN(16); /* Exception table */ __start___ex_table = .; @@ -161,6 +162,13 @@ SECTIONS { _edata = . ; } > DATA + .m68k_fixup : { + __start_fixup = .; + *(.m68k_fixup) + __stop_fixup = .; + } > DATA + NOTES > DATA + .init.text : { . = ALIGN(PAGE_SIZE); __init_begin = .; diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds index d0993594f558..63407c836826 100644 --- a/arch/m68k/kernel/vmlinux-std.lds +++ b/arch/m68k/kernel/vmlinux-std.lds @@ -31,7 +31,9 @@ SECTIONS RW_DATA_SECTION(16, PAGE_SIZE, THREAD_SIZE) + _sbss = .; BSS_SECTION(0, 0, 0) + _ebss = .; _edata = .; /* End of data section */ diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds index 8080469ee6c1..ad0f46d64c0b 100644 --- a/arch/m68k/kernel/vmlinux-sun3.lds +++ b/arch/m68k/kernel/vmlinux-sun3.lds @@ -44,7 +44,9 @@ __init_begin = .; . = ALIGN(PAGE_SIZE); __init_end = .; + _sbss = .; BSS_SECTION(0, 0, 0) + _ebss = .; _end = . ; diff --git a/arch/m68k/kernel/vmlinux.lds.S b/arch/m68k/kernel/vmlinux.lds.S index 030dabf0bc53..69ec79638870 100644 --- a/arch/m68k/kernel/vmlinux.lds.S +++ b/arch/m68k/kernel/vmlinux.lds.S @@ -1,5 +1,14 @@ -#ifdef CONFIG_MMU -#include "vmlinux.lds_mm.S" +#if defined(CONFIG_MMU) && !defined(CONFIG_COLDFIRE) +PHDRS +{ + text PT_LOAD FILEHDR PHDRS FLAGS (7); + data PT_LOAD FLAGS (7); +} +#ifdef CONFIG_SUN3 +#include "vmlinux-sun3.lds" #else -#include "vmlinux.lds_no.S" +#include "vmlinux-std.lds" +#endif +#else +#include "vmlinux-nommu.lds" #endif diff --git a/arch/m68k/kernel/vmlinux.lds_mm.S b/arch/m68k/kernel/vmlinux.lds_mm.S deleted file mode 100644 index 99ba315bd0a8..000000000000 --- a/arch/m68k/kernel/vmlinux.lds_mm.S +++ /dev/null @@ -1,10 +0,0 @@ -PHDRS -{ - text PT_LOAD FILEHDR PHDRS FLAGS (7); - data PT_LOAD FLAGS (7); -} -#ifdef CONFIG_SUN3 -#include "vmlinux-sun3.lds" -#else -#include "vmlinux-std.lds" -#endif |