From eaf1536f95784c3dfe0f9ffe7e11594d147f268d Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 19 Oct 2016 20:49:06 +0100 Subject: [PATCH] v68: task switching All the bits needed for pure swap --- Kernel/platform-v68/tricks.S | 116 +++++++++++++++++++++++++++++++---- 1 file changed, 104 insertions(+), 12 deletions(-) diff --git a/Kernel/platform-v68/tricks.S b/Kernel/platform-v68/tricks.S index 95819f2e..be197244 100644 --- a/Kernel/platform-v68/tricks.S +++ b/Kernel/platform-v68/tricks.S @@ -16,11 +16,13 @@ switchout: bsr chksigs ; 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 + 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: - movem.l a2-a4/a6/d2-d7,-(sp) - move.l sp,U_DATA__U_SP(a5) ; this is where the SP is restored in _switchin + move.l usp,a0 + movem.l a0/a2-a4/a6/d2-d7,-(sp) + bsr outa0hex + 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 @@ -34,18 +36,51 @@ switchout: switchin: or #$0700,sr move.l 4(sp),a0 ; task to switch to - move.l P_TAB__P_UDATA_OFFSET(a0),a5 - move.l a5,udata_shadow ; update the saved copy used for IRQ - ; handling etc + tst.w P_TAB__P_PAGE_OFFSET(a0) ; swapped or existing process ? + bne not_swapped + +; +; If you have one udata and swap them then you need to stack switch +; for the swap in as you'll overwrite the kernel stack. You can use +; the IRQ stack but only if you leave IRQs off for a swap in (ugghh) +; + +; +; FIXME: sort IRQ enables +; + +; +; In simple mode the existing process always gets the boot here +; before we can swap the new one in +; + move.l U_DATA__U_PTAB(a5),a1 ; old process + tst.w P_TAB__P_PAGE_OFFSET(a1) ; swapped out/dead ? + beq its_dead_jim ; corpses don't need swapping out + + move.l a0,-(sp) + move.l a1,-(sp) + jsr swapout + addq #4,sp + move.l (sp)+,a0 + +its_dead_jim: + move.l sp,a1 + move.l #irqstack+256,sp + move.l a1,-(sp) + move.l a0,-(sp) + jsr swapper + move.l (sp)+,a0 + move.w #1,P_TAB__P_PAGE_OFFSET(a0) ; swapped in + move.l (sp)+,a1 ; straight into a7 fails + move.l a1,a7 ; emulator bug or CPU funny ?? - move.l U_DATA__U_PTAB(a5),a0 + or #$0700,sr +not_swapped: ; check u_data->u_ptab matches what we wanted - move.l 4(sp),d0 - cmp.l U_DATA__U_PTAB(a5),d0 + cmp.l U_DATA__U_PTAB(a5),a0 bne switchinfail - ; wants optimising up a bit move.b #P_RUNNING,P_TAB__P_STATUS_OFFSET(a0) ; runticks = 0 @@ -53,7 +88,9 @@ switchin: ; restore machine state move.l U_DATA__U_SP(a5),sp - movem.l (sp)+,a2-a4/a6/d2-d7 + movem.l (sp)+,a0/a2-a4/a6/d2-d7 + move.l a0,usp + bsr outa0hex move.w (sp)+,d0 ; FIXME: can we merge ? tst.b U_DATA__U_ININTERRUPT(a5) @@ -69,8 +106,63 @@ switchinfail: ; something went wrong and we didn't switch in what we asked for bra trap_monitor + ; + ; this gets exciting on the 68000 because our udata is not in a + ; fixed location except for swap only platforms. That means any + ; udata relative pointers on the stack when we duplicate the kernel + ; stack point to the parent. For the simple case we have a single + ; swapped udata and stack so all is fairly easy. For the other + ; cases we have to return as the parent but set up a fake stack + ; frame for the child to exit the syscall. Simply being careful + ; about pointers doesn't work - the compiler will internally + ; use link/unlk and other stuff. + ; + ; 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: + ; + ; simple edition for swap only + ; + move.l 4(sp),a0 ; child p_tab + ; + ; in the simple case we only have one udata. In the complex cases + ; we would have to compute the new one and load it into a5 and + ; offset + ; + move.l a5,P_TAB__P_UDATA_OFFSET(a0) + move.w P_TAB__P_PID_OFFSET(a0),-(sp) ; child pid (parent return) + move.l usp,a0 + movem.l a0/a2-a4/a6/d2-d7,-(sp) ; save state + move.l sp,U_DATA__U_SP(a5) ; save pointer + move.l U_DATA__U_PTAB(a5),-(sp) ; parent p_tab + jsr swapout + add.w #50,sp ; throw the call frame and + ; the frame we built for + ; switchin + tst.w d0 + bne forked_up + + move.l 4(sp),a0 + move.l a0,-(sp) + jsr newproc + addq #4,sp + + moveq #0,d0 ; child, ok + clr.w runticks + rts +forked_up: + moveq #-1,d0 ; parent, failed + rts + badswitchmsg: ascii "_switchin: FAIL" byte 13,10,0 swapped: ascii "_switchin: SWAPPED" byte 13,10,0 + .even -- 2.34.1