From cc031e0bd4d364f886185badb0f591ed47fe1e35 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 23 Jan 2019 14:29:08 +0000 Subject: [PATCH] 68000: move common code for fork/switching on 68000 flat model to lib --- Kernel/lib/68000flat.S | 191 +++++++++++++++++++++++++++++++ Kernel/platform-tiny68k/Makefile | 2 + Kernel/platform-tiny68k/tricks.S | 190 +----------------------------- 3 files changed, 194 insertions(+), 189 deletions(-) create mode 100644 Kernel/lib/68000flat.S diff --git a/Kernel/lib/68000flat.S b/Kernel/lib/68000flat.S new file mode 100644 index 00000000..3740eca0 --- /dev/null +++ b/Kernel/lib/68000flat.S @@ -0,0 +1,191 @@ +#include "../kernel-68000.def" + + +.globl platform_switchout,switchin,dofork,udata_shadow + +.mri 1 + +; Switchout switches out the current process, finds another that is READY, +; possibly the same process, and switches it in. When a process is +; restarted after calling switchout, it thinks it has just returned +; from switchout(). +platform_switchout: + or #$0700,sr + ; save machine state + + clr.w -(sp) ; return code set here is ignored, but switchin can + ; return from either switchout OR dofork, so they must both write + ; U_DATA__U_SP with the following on the stack: + move.l usp,a0 + movem.l a0/a2-a4/a6/d2-d7,-(sp) + move.l sp,U_DATA__U_SP(a5) ; this is where the SP is restored in switchin + + ; find another process to run (may select this one again) + bsr getproc + + move.l d0,-(sp) + bsr switchin + + ; we should never get here + bra platform_monitor + +switchin: + or #$0700,sr + move.l 4(sp),a0 ; task to switch to + move.l P_TAB__P_UDATA_OFFSET(a0),a5 + ; check u_data->u_ptab matches what we wanted + cmp.l U_DATA__U_PTAB(a5),a0 + bne switchinfail + + ; Switch the stacks back + move.l a5,udata_shadow ; For IRQs etc to recover A5 state + move.l U_DATA__U_SP(a5),a7 + + move.b #P_RUNNING,P_TAB__P_STATUS_OFFSET(a0) + + ; + ; Get the user pages back. We can safely + ; do this above the parent kernel stack I think + ; + clr.l -(sp) + move.l a0,-(sp) + jsr pagemap_switch + addq #8,sp + + ; runticks = 0 + clr.w runticks + + ; recover the task switch state + movem.l (sp)+,a0/a2-a4/a6/d2-d7 + move.l a0,USP + ; and return code - FIXME: we have a different fork path so the d0 + ; stacking can go + move.w (sp)+,d0 + + tst.b U_DATA__U_ININTERRUPT(a5) + bne keepoff ; in ISR, leave interrupts off + and #$F8FF,sr +keepoff: + rts ; return with interrupts on + +switchinfail: + bsr outa0hex + lea badswitchmsg,a0 + bsr outstring + ; something went wrong and we didn't switch in what we asked for + bra platform_monitor + + ; + ; this gets exciting on the 68000 because our udata is not in a + ; fixed location except for swap only platforms. To deal with this + ; we return parent first and create a new return frame for the child + ; + ; Entry: + ; A5 = u_data pointer for parent + ; 4(sp) = child process table entry + ; + ; Exit: + ; We are running as the child, A5 = u_data pointer of child, on + ; child stack + ; +dofork: + move.l 4(sp),a0 ; child p_tab + move.l a2,-(sp) + + move.l P_TAB__P_UDATA_OFFSET(a0),a1 ; child udata + + ; Copy the udata + ; FIXME: we don't need to copy the stack too! + + move.l a5,a2 + move.w #255,d0 +loop: + move.l (a2)+,(a1)+ + dbra d0,loop + + + ; + ; Save the child PID for later and the udata offset + ; + move.w P_TAB__P_PID_OFFSET(a0),-(sp) + move.l P_TAB__P_UDATA_OFFSET(a0),-(sp) + ; + ; Configure the child udata now we copied it + ; BUG: child udata is NULL ???? + + move.l P_TAB__P_UDATA_OFFSET(a0),-(sp) + move.l a0,-(sp) + jsr makeproc + addq #8,sp + ; + ; The memory map is clone by ptab_alloc (we might want to + ; adjust that bit) + ; + ;tst.l d0 + ;bne forked_up + + move.l (sp)+,a2 ; Get the udata pointer back + ; + ; Now build a custom return frame for the child + ; + lea.l 1024(a2),a1 ; End of stack + ; + ; 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 + ; needed for PIC processes + ; + ; Stack a return address + ; + move.l #forkreturn,-(a1) + ; + ; USP has to be in a0 + ; + move.l usp,a0 + ; + ; And a frame as if we did a switchout + ; + move.w #0,-(a1) + movem.l a0/a2-a4/a6/d2-d7,-(a1) + move.l a1,U_DATA__U_SP(a2) ; Set the stack pointer + + ; And carry on as the parent + move.w (sp)+,d0 ; child pid + move.l (sp)+,a2 + clr.w runticks + rts +forked_up: + moveq #-1,d0 ; parent, failed + rts +; +; This code gets called when we resume the child +; +forkreturn: + ; Wipe any stray kernel data + moveq #0,d1 + move.l d1,a0 + move.l d1,a1 + move.l d1,a2 + move.l d1,a3 + move.l d1,a4 + move.l d1,a6 + move.l d1,d2 + move.l d1,d3 + move.l d1,d4 + move.l d1,d5 + move.l d1,d6 + move.l d1,d7 + ; recover A5 to match the parent + move.l (sp)+,a5 + ; and RTE to the same address (which is fine as the user memory + ; has already been juggled if needed). + rte + +badswitchmsg: ascii "_switchin: FAIL" + byte 13,10,0 +.even diff --git a/Kernel/platform-tiny68k/Makefile b/Kernel/platform-tiny68k/Makefile index 7c940975..14a20276 100644 --- a/Kernel/platform-tiny68k/Makefile +++ b/Kernel/platform-tiny68k/Makefile @@ -25,6 +25,8 @@ $(AOBJS): %.o: %.S $(DOBJS): %.o: ../dev/%.c $(CROSS_CC) $(CROSS_CCOPTS) -c $< +tricks.S: ../lib/68000flat.S + clean: rm -f *.o fuzix.elf loader.elf loader.map loader.bin core *~ diff --git a/Kernel/platform-tiny68k/tricks.S b/Kernel/platform-tiny68k/tricks.S index 3740eca0..b98eaa3d 100644 --- a/Kernel/platform-tiny68k/tricks.S +++ b/Kernel/platform-tiny68k/tricks.S @@ -1,191 +1,3 @@ #include "../kernel-68000.def" - -.globl platform_switchout,switchin,dofork,udata_shadow - -.mri 1 - -; Switchout switches out the current process, finds another that is READY, -; possibly the same process, and switches it in. When a process is -; restarted after calling switchout, it thinks it has just returned -; from switchout(). -platform_switchout: - or #$0700,sr - ; save machine state - - clr.w -(sp) ; return code set here is ignored, but switchin can - ; return from either switchout OR dofork, so they must both write - ; U_DATA__U_SP with the following on the stack: - move.l usp,a0 - movem.l a0/a2-a4/a6/d2-d7,-(sp) - move.l sp,U_DATA__U_SP(a5) ; this is where the SP is restored in switchin - - ; find another process to run (may select this one again) - bsr getproc - - move.l d0,-(sp) - bsr switchin - - ; we should never get here - bra platform_monitor - -switchin: - or #$0700,sr - move.l 4(sp),a0 ; task to switch to - move.l P_TAB__P_UDATA_OFFSET(a0),a5 - ; check u_data->u_ptab matches what we wanted - cmp.l U_DATA__U_PTAB(a5),a0 - bne switchinfail - - ; Switch the stacks back - move.l a5,udata_shadow ; For IRQs etc to recover A5 state - move.l U_DATA__U_SP(a5),a7 - - move.b #P_RUNNING,P_TAB__P_STATUS_OFFSET(a0) - - ; - ; Get the user pages back. We can safely - ; do this above the parent kernel stack I think - ; - clr.l -(sp) - move.l a0,-(sp) - jsr pagemap_switch - addq #8,sp - - ; runticks = 0 - clr.w runticks - - ; recover the task switch state - movem.l (sp)+,a0/a2-a4/a6/d2-d7 - move.l a0,USP - ; and return code - FIXME: we have a different fork path so the d0 - ; stacking can go - move.w (sp)+,d0 - - tst.b U_DATA__U_ININTERRUPT(a5) - bne keepoff ; in ISR, leave interrupts off - and #$F8FF,sr -keepoff: - rts ; return with interrupts on - -switchinfail: - bsr outa0hex - lea badswitchmsg,a0 - bsr outstring - ; something went wrong and we didn't switch in what we asked for - bra platform_monitor - - ; - ; this gets exciting on the 68000 because our udata is not in a - ; fixed location except for swap only platforms. To deal with this - ; we return parent first and create a new return frame for the child - ; - ; Entry: - ; A5 = u_data pointer for parent - ; 4(sp) = child process table entry - ; - ; Exit: - ; We are running as the child, A5 = u_data pointer of child, on - ; child stack - ; -dofork: - move.l 4(sp),a0 ; child p_tab - move.l a2,-(sp) - - move.l P_TAB__P_UDATA_OFFSET(a0),a1 ; child udata - - ; Copy the udata - ; FIXME: we don't need to copy the stack too! - - move.l a5,a2 - move.w #255,d0 -loop: - move.l (a2)+,(a1)+ - dbra d0,loop - - - ; - ; Save the child PID for later and the udata offset - ; - move.w P_TAB__P_PID_OFFSET(a0),-(sp) - move.l P_TAB__P_UDATA_OFFSET(a0),-(sp) - ; - ; Configure the child udata now we copied it - ; BUG: child udata is NULL ???? - - move.l P_TAB__P_UDATA_OFFSET(a0),-(sp) - move.l a0,-(sp) - jsr makeproc - addq #8,sp - ; - ; The memory map is clone by ptab_alloc (we might want to - ; adjust that bit) - ; - ;tst.l d0 - ;bne forked_up - - move.l (sp)+,a2 ; Get the udata pointer back - ; - ; Now build a custom return frame for the child - ; - lea.l 1024(a2),a1 ; End of stack - ; - ; 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 - ; needed for PIC processes - ; - ; Stack a return address - ; - move.l #forkreturn,-(a1) - ; - ; USP has to be in a0 - ; - move.l usp,a0 - ; - ; And a frame as if we did a switchout - ; - move.w #0,-(a1) - movem.l a0/a2-a4/a6/d2-d7,-(a1) - move.l a1,U_DATA__U_SP(a2) ; Set the stack pointer - - ; And carry on as the parent - move.w (sp)+,d0 ; child pid - move.l (sp)+,a2 - clr.w runticks - rts -forked_up: - moveq #-1,d0 ; parent, failed - rts -; -; This code gets called when we resume the child -; -forkreturn: - ; Wipe any stray kernel data - moveq #0,d1 - move.l d1,a0 - move.l d1,a1 - move.l d1,a2 - move.l d1,a3 - move.l d1,a4 - move.l d1,a6 - move.l d1,d2 - move.l d1,d3 - move.l d1,d4 - move.l d1,d5 - move.l d1,d6 - move.l d1,d7 - ; recover A5 to match the parent - move.l (sp)+,a5 - ; and RTE to the same address (which is fine as the user memory - ; has already been juggled if needed). - rte - -badswitchmsg: ascii "_switchin: FAIL" - byte 13,10,0 -.even +#include "../lib/68000flat.S" -- 2.34.1