From 800e4583bd1cca121a5b2e3f339570d80555280a Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 4 Feb 2019 00:37:59 +0000 Subject: [PATCH] 68000: Basic 68010 support --- Kernel/cpu-68000/cpu.h | 3 ++ Kernel/cpu-68000/rules.mk | 2 +- Kernel/lib/68000exception.c | 45 ++++++++++++++++++-------- Kernel/lib/68000flat.S | 31 ++++++++++++++---- Kernel/lowlevel-68000.S | 64 +++++++++++++++++++++++++++++++++++-- 5 files changed, 122 insertions(+), 23 deletions(-) diff --git a/Kernel/cpu-68000/cpu.h b/Kernel/cpu-68000/cpu.h index 5069f11e..f7f8be77 100644 --- a/Kernel/cpu-68000/cpu.h +++ b/Kernel/cpu-68000/cpu.h @@ -86,3 +86,6 @@ register struct u_data *udata_ptr asm ("a5"); extern void copy_blocks(void *, void *, unsigned int); extern void *memcpy32(void *to, const void *from, size_t bytes); + +extern int probe_memory(void *p); +extern int cpu_type(void); diff --git a/Kernel/cpu-68000/rules.mk b/Kernel/cpu-68000/rules.mk index 3f9c8616..0e268623 100644 --- a/Kernel/cpu-68000/rules.mk +++ b/Kernel/cpu-68000/rules.mk @@ -2,7 +2,7 @@ export CROSS_LD=m68k-uclinux-ld export CROSS_CC = m68k-uclinux-gcc # Do not use the Fedora gcc 5.3.1. It miscompiles stuff badly. export CROSS_CCOPTS=-c -Os -fno-strict-aliasing -fomit-frame-pointer -fno-builtin -Wall -m68000 -I$(ROOT_DIR)/cpu-68000 -I$(ROOT_DIR)/platform-$(TARGET) -I$(ROOT_DIR)/include -export CROSS_AS=$(CROSS_CC) $(CROSS_CCOPTS) #-Wa,-M +export CROSS_AS=$(CROSS_CC) $(CROSS_CCOPTS) -m68060 #-Wa,-M export CROSS_CC_SEG1= export CROSS_CC_SEG2= export CROSS_CC_SEG3= diff --git a/Kernel/lib/68000exception.c b/Kernel/lib/68000exception.c index 93a13d39..8448e2d7 100644 --- a/Kernel/lib/68000exception.c +++ b/Kernel/lib/68000exception.c @@ -25,6 +25,8 @@ struct trapdata { #define FRAME_A 1 #define FRAME_B 2 +#define FRAME_C 3 +#define FRAME_D 4 static void explode(struct trapdata *framedata, int type) { @@ -68,7 +70,14 @@ static void explode(struct trapdata *framedata, int type) for (j = 0;j < 16; j++) kprintf("%d: %x\n", j, excp[j]); - /* For now we only do 68000 */ + /* 68010 long frame */ + if (type == FRAME_C) { + kputs((excp[4] & 0x100)?"R":"W"); + kprintf(" FC %x", excp[4] & 7); + fv = (uint32_t *)(excp +5); + kprintf(" Addr %p SSW %x ", *fv, excp[4]); + } + /* 68000 long frame */ if (type == FRAME_A) { kputs((excp[0] & 0x10)?"R":"W"); kprintf(" FC %x", excp[0] & 7); @@ -76,10 +85,9 @@ static void explode(struct trapdata *framedata, int type) kprintf(" Addr %p IR %x ", *fv, excp[3]); excp += 4; } - if (type == FRAME_A || type == FRAME_B) { - fv = (uint32_t *)(excp + 1); - kprintf("PC %p SR %x\n", *fv, *excp); - } + /* All frames */ + fv = (uint32_t *)(excp + 1); + kprintf("PC %p SR %x\n", *fv, *excp); } /* Our caller did a movem of the registers to kstack then pushed an @@ -127,22 +135,31 @@ int exception(struct trapdata *framedata) proc = udata.u_ptab; - /* Most synchronous exceptions are type B */ - /* FIXME: sizes need to become chip aware */ - frame = FRAME_B; - fsize = 3; /* Three words on 68000 */ - /* TODO: On the 68010 there are at least 4 words as word 4 always holds - the vector and format */ + if (sysinfo.cpu[0] == 10) { + /* Long or short frame: the CPU tells us the frame format */ + if (framedata->exception[3] & 0x8000) { + fsize = 29; + frame = FRAME_C; + } else { + fsize = 4; + frame = FRAME_D; + } + } else { + frame = FRAME_B; + fsize = 3; + } if (trap == 0) { sig = udata.u_cursig; udata.u_cursig = 0; } else if (trap < 12) { if (trap < 4) { - /* TODO: On a 68010 this frame is 29 words and the event is + /* On a 68010 this frame is 29 words and the event is restartable (although not always usefully). We need to decide whether to set the restart flag case by case */ - frame = FRAME_A; - fsize = 7; + if (sysinfo.cpu[0] == 0) { + frame = FRAME_A; + fsize = 7; + } } sig = trap_to_sig[trap]; } else if (trap >= 32 && trap < 48) diff --git a/Kernel/lib/68000flat.S b/Kernel/lib/68000flat.S index 9f1f0b3a..38648f54 100644 --- a/Kernel/lib/68000flat.S +++ b/Kernel/lib/68000flat.S @@ -127,17 +127,36 @@ loop: ; ; Copy over the parent top of stack return info ; - ; FIXME: This assumes 68000 trap format. For the 68010 - ; there will be 4 words not 3 - ; - move.l 1020(a5),-(a1) ; Copy the PC - move.w 1018(a5),-(a1) ; Copy the status word - move.l 1014(a5),-(a1) ; Copy the A5 save of the parent + ; 68000 68010 + ; 1022 PC.L VECTOR + ; 1020 PC.H PC.L + ; 1018 STATUS PC.H + ; 1016 A5 STATUS + ; 1014 A5 A5 + ; 1012 A5 + ; + tst.b cpu_has_trapvec + beq cpu_3word + + move.w 1022(a5),-(a1) ; Copy the vector + move.l 1018(a5),-(a1) ; Copy the PC + move.w 1016(a5),-(a1) ; Copy the Status + move.l 1012(a5),-(a1) ; Copy the A5 save of the parent ; needed for PIC processes + bra pushret +cpu_3word: + move.l 1020(a5),-(a1) ; Copy the PC + move.w 1018(a5),-(a1) ; Copy the Status + move.l 1014(a5),-(a1) ; Copy A5 +pushret: ; ; Stack a return address ; move.l #forkreturn,-(a1) + + move.l a1,-(sp) + jsr dumpshit + addq #4,sp ; ; USP has to be in a0 ; diff --git a/Kernel/lowlevel-68000.S b/Kernel/lowlevel-68000.S index af3bb750..50aa903f 100644 --- a/Kernel/lowlevel-68000.S +++ b/Kernel/lowlevel-68000.S @@ -385,6 +385,7 @@ SYM (__umodsi3): .globl trap0,trap1,trap2,trap3,trap4,trap5,trap6,trap7 .globl trap8,trap9,trap10,trap11,trap12,trap13,trap14,trap15 .globl spurious,unexpected,uninit + .globl cpu_type,probe_memory,cpu_has_trapvec .globl udata_shadow .globl trap_via_signal .globl dump_registers @@ -448,13 +449,16 @@ vdso: trap #12 ; syscall entry ; switch modes as we switch address so that we don't fault if there ; is memory protection. ; -; TODO: 68010 support needs adjusting here -; doexec: move.l 4(sp),a1 ; go address lea.l 1024(a5),a7 ; reset the supervisor stack and.w #$F8FF,sr ; IRQ on + + tst.b cpu_has_trapvec + beq threeword + clr.w -(sp) ; push vector +threeword: move.l a1,-(sp) ; return address clr.w -(sp) ; set up the status register move.l U_DATA__U_ISP(a5),a0 @@ -519,6 +523,57 @@ init_trap_loop: move.l #spurious,$60(a0) rts +; +; Interrupts assumed to be off for these trap tricks +; + +; +; Override the bus error trap and check if a memory address faults +; (Returns 1 if it errors) +; +probe_memory: + move.l 4(sp),a0 + move.l #probe_error,8 + move.l a7,a1 + moveq #0,d0 + move.w (a0),d1 +probe_out: move.l #bus_error,8 + rts +probe_error: + moveq #1,d0 + move.l a1,a7 + bra probe_out +; +; Check the cpu type and return 0,10,etc. +; +; FIXME: doesn't tell 68020 from 68030 +; One way we could do that would be to issue a CALLM with a bogus +; module descriptor and see if we get illegal (68030) or a format +; exception. We can fix that when we actually need to support anything +; bigger than a 68010 ! +; +cpu_type: + move.l #cpu_ill_error,16 + move.l a7,a1 + moveq #0,d0 + movec vbr,d1 ; faults on a 68000 + moveq #10,d0 + movec cacr,d1 ; faults on a 68000 and 010 + moveq #20,d0 + movec itt0,d1 ; faults on 68020/30 + moveq #40,d0 + movec pcr,d1 ; faults on all but 68060 + moveq #60,d0 +cpu_type_exit: + move.l #illegal,16 + move.b d0,cpu_has_trapvec + rts +; +; We found the faulting instruction for this CPU type so bail +; +cpu_ill_error: + move.l a1,a7 + bra cpu_type_exit bus_error: move.w sr,-(sp) move.w #2,-(sp) @@ -691,6 +746,9 @@ spurious: movem.l a0-a6/d0-d7,-(sp) unexpected: movem.l a0-a6/d0-d7,-(sp) move.l #strunexpected,a0 bsr outstring + move.w 6(sp),d0 + move.w d0,a0 + bsr outa0hex unexpectedl: bra unexpectedl uninit: movem.l a0-a6/d0-d7,-(sp) @@ -910,3 +968,5 @@ dump_registers: kernel_flag: byte 0 udata_shadow: long 0 trap_id: word 0 +cpu_has_trapvec: + byte 0 \ No newline at end of file -- 2.34.1