68000 trap quirks: - The 68000 doesn't have a VBR (Vector Base Register), so the exception table is always at address zero, - The 68000 doesn't store the format and vector number in the stack frame automatically, so we have to use a different routine for each vector we want to be able to identify uniquely, - The 68000 uses a different exception stack frame for bus and address errors. --- arch/m68k/amiga/chipram.c | 10 ++ arch/m68k/kernel/entry.S | 159 +++++++++++++++++++++++++++++++++++++--------- arch/m68k/kernel/traps.c | 140 +++++++++++++++++++++++++--------------- include/asm-m68k/traps.h | 39 ++++++++++- 4 files changed, 262 insertions(+), 86 deletions(-) --- linux-m68k-2.6.8.1+uc0/arch/m68k/amiga/chipram.c 2004-05-24 11:13:22.000000000 +0200 +++ uClinux-amiga-2.6.8.1/arch/m68k/amiga/chipram.c 2004-06-26 17:17:35.000000000 +0200 @@ -36,10 +36,14 @@ void __init amiga_chip_init(void) */ amiga_chip_size -= 0x4000; #endif +#ifdef CONFIG_M68000 + /* On 68000, the exception table is at address zero */ + chipram_res.start += 0x400; +#endif - chipram_res.end = amiga_chip_size-1; + chipram_res.end = CHIP_PHYSADDR+amiga_chip_size-1; request_resource(&iomem_resource, &chipram_res); - chipavail = amiga_chip_size; + chipavail = chipram_res.end-chipram_res.start+1; } @@ -85,7 +89,7 @@ void * __init amiga_chip_alloc_res(unsig /* round up */ size = PAGE_ALIGN(size); /* dmesg into chipmem prefers memory at the safe end */ - start = CHIP_PHYSADDR + chipavail - size; + start = chipram_res.end+1-size; #ifdef DEBUG printk("amiga_chip_alloc_res: allocate %ld bytes\n", size); --- linux-m68k-2.6.8.1+uc0/arch/m68k/kernel/entry.S 2004-05-24 11:13:22.000000000 +0200 +++ uClinux-amiga-2.6.8.1/arch/m68k/kernel/entry.S 2004-06-26 17:19:20.000000000 +0200 @@ -61,20 +61,47 @@ .globl sys_fork, sys_clone, sys_vfork .globl ret_from_interrupt, bad_interrupt +#ifdef CONFIG_M68000 +.globl addrerr +.globl trap_10, trap_14, trap_18, trap_1c, trap_20, trap_24, trap_28, trap_2c +.globl trap_30, trap_34, trap_38, trap_3c +.globl inthandler_64, inthandler_68, inthandler_6c, inthandler_70 +.globl inthandler_74, inthandler_78, inthandler_7c +#else /* 68010 or higher */ +.globl trap +#endif /* 68010 or higher */ + .text ENTRY(buserr) +#ifdef CONFIG_M68000 +addrerr: +#endif SAVE_ALL_INT GET_CURRENT(%d0) movel %sp,%sp@- | stack frame pointer argument - bsrl buserr_c + jbsr buserr_c addql #4,%sp jra ret_from_exception ENTRY(trap) +#ifdef CONFIG_M68000 +trap_10: +trap_14: +trap_18: +trap_1c: +trap_20: +trap_24: +trap_28: +trap_2c: +trap_30: +trap_34: +trap_38: +trap_3c: +#endif SAVE_ALL_INT GET_CURRENT(%d0) movel %sp,%sp@- | stack frame pointer argument - bsrl trap_c + jbsr trap_c addql #4,%sp jra ret_from_exception @@ -92,7 +129,14 @@ do_trace: movel #-ENOSYS,%d0 cmpl #NR_syscalls,%d1 jcc 1f +#if defined(CONFIG_M68000) || defined(CONFIG_M68010) + lsll #2,%d1 + leal sys_call_table,%a0 + movel (%a0,%d1:l),%a0 + jbsr (%a0) +#else /* 68020 or higher */ jbsr @(sys_call_table,%d1:l:4)@(0) +#endif /* 68020 or higher */ 1: movel %d0,%sp@(PT_D0) | save the return value subql #4,%sp | dummy return address SAVE_SWITCH_STACK @@ -124,7 +168,14 @@ ENTRY(system_call) jne do_trace cmpl #NR_syscalls,%d0 jcc badsys +#if defined(CONFIG_M68000) || defined(CONFIG_M68010) + lsll #2,%d0 + leal sys_call_table,%a0 + movel (%a0,%d0:l),%a0 + jbsr (%a0) +#else /* 68020 or higher */ jbsr @(sys_call_table,%d0:l:4)@(0) +#endif /* 68020 or higher */ movel %d0,%sp@(PT_D0) | save the return value |oriw #0x0700,%sr @@ -172,7 +223,7 @@ do_signal_return: SAVE_SWITCH_STACK pea %sp@(SWITCH_STACK_SIZE) clrl %sp@- - bsrl do_signal + jbsr do_signal addql #8,%sp RESTORE_SWITCH_STACK addql #4,%sp @@ -189,44 +240,100 @@ do_delayed_trace: jbra resume_userspace -#if 0 -#ifdef CONFIG_AMIGA -ami_inthandler: - addql #1,irq_stat+CPUSTAT_LOCAL_IRQ_COUNT +/* +** This is the main interrupt handler, responsible for calling process_int() +*/ +#ifdef CONFIG_M68000 +inthandler_64: SAVE_ALL_INT GET_CURRENT(%d0) + addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+2) + | put exception # in d0 + movel %sp,%sp@- + movel #25,%sp@- | put vector # on stack + jbsr process_int | process the IRQ +3: addql #8,%sp | pop parameters off stack + bra ret_from_interrupt - bfextu %sp@(PT_VECTOR){#4,#12},%d0 - movel %d0,%a0 - addql #1,%a0@(kstat+STAT_IRQ-VECOFF(VEC_SPUR)) - movel %a0@(autoirq_list-VECOFF(VEC_SPUR)),%a0 - -| amiga vector int handler get the req mask instead of irq vector - lea CUSTOMBASE,%a1 - movew %a1@(C_INTREQR),%d0 - andw %a1@(C_INTENAR),%d0 - -| prepare stack (push frame pointer, dev_id & req mask) - pea %sp@ - movel %a0@(IRQ_DEVID),%sp@- - movel %d0,%sp@- - pea %pc@(ret_from_interrupt:w) - jbra @(IRQ_HANDLER,%a0)@(0) +inthandler_68: + SAVE_ALL_INT + GET_CURRENT(%d0) + addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+2) + | put exception # in d0 + movel %sp,%sp@- + movel #26,%sp@- | put vector # on stack + jbsr process_int | process the IRQ +3: addql #8,%sp | pop parameters off stack + bra ret_from_interrupt -ENTRY(nmi_handler) - rte -#endif -#endif +inthandler_6c: + SAVE_ALL_INT + GET_CURRENT(%d0) + addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+2) + | put exception # in d0 + movel %sp,%sp@- + movel #27,%sp@- | put vector # on stack + jbsr process_int | process the IRQ +3: addql #8,%sp | pop parameters off stack + bra ret_from_interrupt + +inthandler_70: + SAVE_ALL_INT + GET_CURRENT(%d0) + addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+2) + | put exception # in d0 + movel %sp,%sp@- + movel #28,%sp@- | put vector # on stack + jbsr process_int | process the IRQ +3: addql #8,%sp | pop parameters off stack + bra ret_from_interrupt + +inthandler_74: + SAVE_ALL_INT + GET_CURRENT(%d0) + addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+2) + | put exception # in d0 + movel %sp,%sp@- + movel #29,%sp@- | put vector # on stack + jbsr process_int | process the IRQ +3: addql #8,%sp | pop parameters off stack + bra ret_from_interrupt + +inthandler_78: + SAVE_ALL_INT + GET_CURRENT(%d0) + addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+2) + | put exception # in d0 + movel %sp,%sp@- + movel #30,%sp@- | put vector # on stack + jbsr process_int | process the IRQ +3: addql #8,%sp | pop parameters off stack + bra ret_from_interrupt + +inthandler_7c: + SAVE_ALL_INT + GET_CURRENT(%d0) + addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+2) + | put exception # in d0 + movel %sp,%sp@- + movel #31,%sp@- | put vector # on stack + jbsr process_int | process the IRQ +3: addql #8,%sp | pop parameters off stack + bra ret_from_interrupt +#endif /* CONFIG_M68000 */ -/* -** This is the main interrupt handler, responsible for calling process_int() -*/ inthandler: SAVE_ALL_INT GET_CURRENT(%d0) addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+2) | put exception # in d0 - bfextu %sp@(PT_VECTOR){#4,#10},%d0 +#if defined(CONFIG_M68000) || defined(CONFIG_M68010) + movel %sp@(PT_VECTOR),%d0 + lsr #4,%d0 + and #0x3ff,%d0 +#else /* 68020 or higher */ + bfextu %sp@(PT_VECTOR){#4,#10},%d0 +#endif /* 68020 or higher */ movel %sp,%sp@- movel %d0,%sp@- | put vector # on stack --- linux-m68k-2.6.8.1+uc0/arch/m68k/kernel/traps.c 2004-08-14 15:35:13.000000000 +0200 +++ uClinux-amiga-2.6.8.1/arch/m68k/kernel/traps.c 2004-10-08 21:01:07.000000000 +0200 @@ -46,58 +46,93 @@ asmlinkage void system_call(void); asmlinkage void buserr(void); asmlinkage void trap(void); asmlinkage void inthandler(void); + +#ifdef CONFIG_M68000 + + /* + * The 68000 doesn't store the format and vector number in the stack + * frame automatically, so we have to use a different routine for each + * vector + */ +#define E_VEC_NUM 64 +asmlinkage void addrerr(void); +asmlinkage void trap_10(void); +asmlinkage void trap_14(void); +asmlinkage void trap_18(void); +asmlinkage void trap_1c(void); +asmlinkage void trap_20(void); +asmlinkage void trap_24(void); +asmlinkage void trap_28(void); +asmlinkage void trap_2c(void); +asmlinkage void trap_30(void); +asmlinkage void trap_34(void); +asmlinkage void trap_38(void); +asmlinkage void trap_3c(void); +asmlinkage void inthandler_64(void); +asmlinkage void inthandler_68(void); +asmlinkage void inthandler_6c(void); +asmlinkage void inthandler_70(void); +asmlinkage void inthandler_74(void); +asmlinkage void inthandler_78(void); +asmlinkage void inthandler_7c(void); + +#else /* 68010 or higher */ + +#define e_vectors vectors +#define E_VEC_NUM 256 +#define addrerr trap +#define trap_10 trap +#define trap_14 trap +#define trap_18 trap +#define trap_1c trap +#define trap_20 trap +#define trap_24 trap +#define trap_28 trap +#define trap_2c trap +#define trap_30 trap +#define trap_34 trap +#define trap_38 trap +#define trap_3c trap +#define inthandler_64 inthandler +#define inthandler_68 inthandler +#define inthandler_6c inthandler +#define inthandler_70 inthandler +#define inthandler_74 inthandler +#define inthandler_78 inthandler +#define inthandler_7c inthandler + +#endif /* 68010 or higher */ asmlinkage void nmihandler(void); #ifdef CONFIG_M68KFPU_EMU asmlinkage void fpu_emu(void); #endif -e_vector vectors[256] = { +e_vector e_vectors[E_VEC_NUM] = { [VEC_BUSERR] = buserr, - [VEC_ADDRERR] = trap, - [VEC_ILLEGAL] = trap, - [VEC_ZERODIV] = trap, - [VEC_CHK] = trap, - [VEC_TRAP] = trap, - [VEC_PRIV] = trap, - [VEC_TRACE] = trap, - [VEC_LINE10] = trap, - [VEC_LINE11] = trap, - [VEC_RESV12] = trap, - [VEC_COPROC] = trap, - [VEC_FORMAT] = trap, - [VEC_UNINT] = trap, - [VEC_RESV16] = trap, - [VEC_RESV17] = trap, - [VEC_RESV18] = trap, - [VEC_RESV19] = trap, - [VEC_RESV20] = trap, - [VEC_RESV21] = trap, - [VEC_RESV22] = trap, - [VEC_RESV23] = trap, + [VEC_ADDRERR] = addrerr, + [VEC_ILLEGAL] = trap_10, + [VEC_ZERODIV] = trap_14, + [VEC_CHK] = trap_18, + [VEC_TRAP] = trap_1c, + [VEC_PRIV] = trap_20, + [VEC_TRACE] = trap_24, + [VEC_LINE10] = trap_28, + [VEC_LINE11] = trap_2c, + [VEC_RESV12] = trap_30, + [VEC_COPROC] = trap_34, + [VEC_FORMAT] = trap_38, + [VEC_UNINT] = trap_3c, + [VEC_SPUR] = inthandler, - [VEC_INT1] = inthandler, - [VEC_INT2] = inthandler, - [VEC_INT3] = inthandler, - [VEC_INT4] = inthandler, - [VEC_INT5] = inthandler, - [VEC_INT6] = inthandler, - [VEC_INT7] = inthandler, - [VEC_SYS] = system_call, - [VEC_TRAP1] = trap, - [VEC_TRAP2] = trap, - [VEC_TRAP3] = trap, - [VEC_TRAP4] = trap, - [VEC_TRAP5] = trap, - [VEC_TRAP6] = trap, - [VEC_TRAP7] = trap, - [VEC_TRAP8] = trap, - [VEC_TRAP9] = trap, - [VEC_TRAP10] = trap, - [VEC_TRAP11] = trap, - [VEC_TRAP12] = trap, - [VEC_TRAP13] = trap, - [VEC_TRAP14] = trap, - [VEC_TRAP15] = trap, + [VEC_INT1] = inthandler_64, + [VEC_INT2] = inthandler_68, + [VEC_INT3] = inthandler_6c, + [VEC_INT4] = inthandler_70, + [VEC_INT5] = inthandler_74, + [VEC_INT6] = inthandler_78, + [VEC_INT7] = inthandler_7c, + + [VEC_SYS] = system_call }; /* nmi handler for the Amiga */ @@ -117,8 +147,12 @@ void __init base_trap_init(void) __asm__ volatile ("movec %%vbr, %0" : "=r" ((void*)sun3x_prom_vbr)); } - /* setup the exception vector table */ - __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors)); +#ifndef CPU_M68000_ONLY + if (!CPU_IS_000) { + /* setup the exception vector table */ + __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors)); + } +#endif /* !CPU_M68000_ONLY */ if (CPU_IS_060) { /* set up ISP entry points */ @@ -132,10 +164,9 @@ void __init trap_init (void) { int i; - for (i = 48; i < 64; i++) - if (!vectors[i]) - vectors[i] = trap; - + /* setup the exception vector table */ + for (i = 2; i < 64; i++) + vectors[i] = e_vectors[i] ? e_vectors[i] : trap; for (i = 64; i < 256; i++) vectors[i] = inthandler; --- linux-m68k-2.6.8.1+uc0/include/asm-m68k/traps.h 2004-04-28 16:08:30.000000000 +0200 +++ uClinux-amiga-2.6.8.1/include/asm-m68k/traps.h 2004-10-08 21:01:07.000000000 +0200 @@ -11,13 +11,19 @@ #ifndef _M68K_TRAPS_H #define _M68K_TRAPS_H +#include + #ifndef __ASSEMBLY__ typedef void (*e_vector)(void); +#ifdef CONFIG_M68000 +#define vectors ((e_vector *)0) +#else /* 68010 or higher */ extern e_vector vectors[]; +#endif /* 68010 or higher */ -#endif +#endif /* !__ASSEMBLY__ */ #define VEC_RESETSP (0) #define VEC_RESETPC (1) @@ -291,6 +297,37 @@ struct frame { } un; }; +#ifdef CONFIG_M68000 + +struct frame68000 { + struct { + long d1; + long d2; + long d3; + long d4; + long d5; + long a0; + long a1; + long a2; + long d0; + long orig_d0; + long stkadj; + } ptregs; + /* MC68000 Bus or Address Error Exception Stack Frame */ + struct { + unsigned unused : 11; + unsigned rw : 1; /* read(1)/write(0) */ + unsigned in : 1; /* instruction(0)/not(1) */ + unsigned fc : 3; /* function code */ + unsigned long faddr; /* fault address */ + unsigned short ir; /* instruction register */ + unsigned short sr; /* status register */ + unsigned long pc; /* program counter */ + } fmt; +}; + +#endif /* M68000 */ + #endif /* __ASSEMBLY__ */ #endif /* _M68K_TRAPS_H */