From 1c65a54caeedceb325b67fb9cd478d5b8dcdbba2 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sat, 31 Jan 2015 19:44:19 +0000 Subject: [PATCH] socz80: fork code Doesn't work yet but committing as a debugging basepoint --- Kernel/platform-socz80/tricks.s | 207 +++++++++++++++++++++----------- 1 file changed, 137 insertions(+), 70 deletions(-) diff --git a/Kernel/platform-socz80/tricks.s b/Kernel/platform-socz80/tricks.s index 2fc8121b..7fc5e4b0 100644 --- a/Kernel/platform-socz80/tricks.s +++ b/Kernel/platform-socz80/tricks.s @@ -58,8 +58,6 @@ _switchout: ; we should never get here call _trap_monitor -badswitchmsg: .ascii "_switchin: FAIL" - .db 13, 10, 0 _switchin: di pop bc ; return address @@ -132,9 +130,8 @@ switchinfail: ld hl, #badswitchmsg call outstring ; something went wrong and we didn't switch in what we asked for - call nz, _trap_monitor + jp _trap_monitor -fork_proc_ptr: .dw 0 ; (C type is struct p_tab *) -- address of child process p_tab entry _dofork: ; always disconnect the vehicle battery before performing maintenance @@ -168,50 +165,154 @@ _dofork: ; Hurray. ld (U_DATA__U_SP), sp - ; now we're in a safe state for _switchin to return in the parent - ; process. + ; + ; We will return on the parent stack with everything copied. We can + ; thus return safely down the stack as we switch stacks below + ; + + call fork_copy + + ; + ; switch into the child process context + ; get address of top page + ; + ld hl, (fork_proc_ptr) + ld de, #P_TAB__P_PAGE_OFFSET + 3 + add hl, de + ; load p_page[3] + ld l, (hl) + ld h, #0 + add hl, hl + add hl, hl + inc hl ; last one of the group + inc hl + inc hl + push hl + call outhl + pop hl + ; load into MMU + ld a, #0x0F + out (MMU_SELECT), a + ld a, d + out (MMU_FRAMEHI), a + ld a, e + out (MMU_FRAMELO), a - ; --------- copy process --------- + ; now the copy operation is complete we can get rid of the stuff + ; _switchin will be expecting from our copy of the stack. + pop bc + pop bc + pop bc + + ; Make a new process table entry, etc. + ld hl, (fork_proc_ptr) + push hl + call _newproc + pop bc + + ; runticks = 0; + ld hl, #0 + ld (_runticks), hl + + ; in the child process, fork() returns zero. + ret + + +fork_copy: + ; child mapping + ld hl, (fork_proc_ptr) + ld de, #P_TAB__P_PAGE_OFFSET + add hl, de + ; parent mapping to be copied + ld de, #U_DATA__U_PAGE + +; +; Walk the 16K banks using a generic code pattern +; bank_copy is invoked with registers saved and the +; parent and child in a nd c +; + + ld a, #4 + ld b, #0 ; not a valid page +nextbank: + push af + ld c, (hl) + inc hl + ld a, (de) + inc de + cp b + jr z, done ; repeated map, means all we need is copied + ld b, a + push bc + push de + push hl + call bank_copy ; copies the 16K + pop hl + pop de + pop bc + pop af + dec a + jr nz, nextbank + ret +done: + pop af + ret + + +; +; Copy 16K from bank b to bank a (as seen by the software 16K paging). +; In fact we need to move blocks of four pages. +; +bank_copy: + + ; save the parent mapping + ld b, a + call outcharhex + ld a, c + call outcharhex ; store the old MMU mapping ld a, #0x0E out (MMU_SELECT), a in a, (MMU_FRAMEHI) - ld b, a + ld d, a in a, (MMU_FRAMELO) - ld c, a - push bc + ld e, a + push de ld a, #0x0D out (MMU_SELECT), a in a, (MMU_FRAMEHI) - ld b, a + ld d, a in a, (MMU_FRAMELO) - ld c, a - push bc - - ; Copy entire 64k process into Child's address space - ; note source base page is in DE - ; dest base page is in (_ub+OPAGE) which is in 0xF000, which will not - ; be available after we start remapping - ; we can do the copy in frame 0xE000 and 0xF000 + ld e, a + push de - ld hl, (fork_proc_ptr) - ld de, #P_TAB__P_PAGE_OFFSET - add hl, de - ; load child base page - ld e, (hl) - inc hl - ld d, (hl) - ld hl, #0x1000 ; +16MB, this puts the destination pointer into uncached DRAM. + ; Copy a 16K bank + + ; child base page is in c parent in b + ld d,#0 + ld l,d + ld c,a + sla a + rl d + sla a + rl d + ld e, a + ld h,#0x10 ; +16MB, this puts the destination pointer into uncached DRAM. add hl, de ; this is so we don't obliterate the read cache (the cache is ; direct mapped and so the parent and child processes are cache ; aliases of each other) - ld de, (U_DATA__U_PAGE) ; load parent page base page + ld a, b ; parent + ld d, #0 + sla a + rl d + sla a + rl d ; de now holds the src pointer - ld b, #16 ; we're going to copy 0x0000 ... 0xFFFF + ld b, #4 ; we're going to copy 16K copynextpage: ; map source page at E000 - LD A, #0x0E + LD a, #0x0E out (MMU_SELECT), a ld a, d out (MMU_FRAMEHI), a @@ -260,45 +361,11 @@ copynextpage: out (MMU_FRAMEHI), a ld a, c out (MMU_FRAMELO), a - ; --------- copy completed --------- - - ; switch into the child process context - ; get address of top page: fork_proc_ptr->p_page + 0x0f - ld hl, (fork_proc_ptr) - ld de, #P_TAB__P_PAGE_OFFSET - add hl, de - ; load p_page - ld e, (hl) - inc hl - ld d, (hl) - ; add 0x000F - ld hl, #0x000F - add hl, de - ; load into MMU - ld a, #0x0F - out (MMU_SELECT), a - ld a, h - out (MMU_FRAMEHI), a - ld a, l - out (MMU_FRAMELO), a - - ; now the copy operation is complete we can get rid of the stuff - ; _switchin will be expecting from our copy of the stack. - pop bc - pop bc - pop bc - ; Make a new process table entry, etc. - ld hl, (fork_proc_ptr) - push hl - call _newproc - pop bc - - ; runticks = 0; - ld hl, #0 - ld (_runticks), hl - - ; in the child process, fork() returns zero. - ld hl, #0 - ret + ret + .area _DATA +fork_proc_ptr: .dw 0 ; (C type is struct p_tab *) -- address of child process p_tab entry + .area _CONST +badswitchmsg: .ascii "_switchin: FAIL" + .db 13, 10, 0 -- 2.34.1