From: Alan Cox Date: Tue, 11 Sep 2018 22:22:17 +0000 (+0100) Subject: kernel: small updates to single process platforms X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=235f883c0dab8e5798abe7b2824492c042cac333;p=FUZIX.git kernel: small updates to single process platforms In particular remove some shared stuff and put it in lib --- diff --git a/Kernel/lib/z80single.s b/Kernel/lib/z80single.s new file mode 100644 index 00000000..44c71258 --- /dev/null +++ b/Kernel/lib/z80single.s @@ -0,0 +1,230 @@ +; +; Generic handling for single process in memory Z80 systems. +; +; This code could really do with some optimizing. +; + .module tricks + + .globl _ptab_alloc + .globl _newproc + .globl _chksigs + .globl _getproc + .globl _platform_monitor + .globl trap_illegal + .globl _platform_switchout + .globl _switchin + .globl _doexec + .globl _dofork + .globl _runticks + .globl unix_syscall_entry + .globl interrupt_handler + .globl _swapper + .globl _swapout + + ; imported debug symbols + .globl outstring, outde, outhl, outbc, outnewline, outchar, outcharhex + + .include "kernel.def" + .include "../kernel.def" + + .area _COMMONMEM + +; 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(). +; +; This function can have no arguments or auto variables. +_platform_switchout: + di + ; save machine state + + ld hl, #0 ; 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: + push hl ; return code + push ix + push iy + ld (U_DATA__U_SP), sp ; this is where the SP is restored in _switchin + + ; find another process to run (may select this one again) + call _getproc + + push hl + call _switchin + + ; we should never get here + call _platform_monitor + +badswitchmsg: .ascii "_switchin: FAIL" + .db 13, 10, 0 +swapped: .ascii "_switchin: SWAPPED" + .db 13, 10, 0 + +_switchin: + di + pop bc ; return address + pop de ; new process pointer +; +; FIXME: do we actually *need* to restore the stack ! +; + push de ; restore stack + push bc ; restore stack + + push de + ld hl, #P_TAB__P_PAGE_OFFSET + add hl, de ; process ptr + pop de + + ld a, (hl) + + or a + jr nz, not_swapped + ; + ; We are still on the departing processes stack, which is + ; fine for now. + ; + ld sp, #_swapstack + ; + ; The process we are switching from is not resident. In + ; practice that means it exited. We don't need to write + ; it back out as it's dead. + ; + ld ix,(U_DATA__U_PTAB) + ld a,P_TAB__P_PAGE_OFFSET(ix) + + or a + jr z, not_resident + ; + ; DE = process we are switching to + ; + push de ; save process + ; We will always swap out the current process + ld hl, (U_DATA__U_PTAB) + push hl + call _swapout + pop hl + pop de ; process to swap to +not_resident: + push de ; called function may modify on stack arg so make + push de ; two copies + call _swapper + pop de + pop de + +not_swapped: + ; check u_data->u_ptab matches what we wanted + ld hl, (U_DATA__U_PTAB) ; u_data->u_ptab + or a ; clear carry flag + sbc hl, de ; subtract, result will be zero if DE==IX + jr nz, switchinfail + + ; wants optimising up a bit + ld ix, (U_DATA__U_PTAB) + ; next_process->p_status = P_RUNNING + ld P_TAB__P_STATUS_OFFSET(ix), #P_RUNNING + + ; Fix the moved page pointers + ; Just do one byte as that is all we use on this platform + ld a, P_TAB__P_PAGE_OFFSET(ix) + ld (U_DATA__U_PAGE), a + ; runticks = 0 + ld hl, #0 + ld (_runticks), hl + + ; restore machine state -- note we may be returning from either + ; _switchout or _dofork + ld sp, (U_DATA__U_SP) + + pop iy + pop ix + pop hl ; return code + + ; enable interrupts, if the ISR isn't already running + ld a, (U_DATA__U_ININTERRUPT) + or a + ret nz ; in ISR, leave interrupts off + ei + ret ; return with interrupts on + +switchinfail: + call outhl + ld hl, #badswitchmsg + call outstring + ; something went wrong and we didn't switch in what we asked for + jp _platform_monitor + +fork_proc_ptr: .dw 0 ; (C type is struct p_tab *) -- address of child process p_tab entry + +; +; Called from _fork. We are in a syscall, the uarea is live as the +; parent uarea. The kernel is the mapped object. +; +_dofork: + ; always disconnect the vehicle battery before performing maintenance + di ; should already be the case ... belt and braces. + + pop de ; return address + pop hl ; new process p_tab* + push hl + push de + + ld (fork_proc_ptr), hl + + ; prepare return value in parent process -- HL = p->p_pid; + ld de, #P_TAB__P_PID_OFFSET + add hl, de + ld a, (hl) + inc hl + ld h, (hl) + ld l, a + + ; Save the stack pointer and critical registers. + ; When this process (the parent) is switched back in, it will be as if + ; it returns with the value of the child's pid. + push hl ; HL still has p->p_pid from above, the return value in the parent + push ix + push iy + + ; save kernel stack pointer -- when it comes back in the parent we'll be in + ; _switchin which will immediately return (appearing to be _dofork() + ; returning) and with HL (ie return code) containing the child PID. + ; Hurray. + ld (U_DATA__U_SP), sp + + ; now we're in a safe state for _switchin to return in the parent + ; process. + + ld hl, (U_DATA__U_PTAB) + push hl + call _swapout + pop hl + + ; 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. + ; + ; And we exit, with the kernel mapped, the child now being deemed + ; to be the live uarea. The parent is frozen in time and space as + ; if it had done a switchout(). + ret +; +; We can keep a stack in common because we will complete our +; use of it before we switch common block. In this case we have +; a true common so it's even easier. +; + .ds 128 +_swapstack: diff --git a/Kernel/platform-genie-eg64/config.h b/Kernel/platform-genie-eg64/config.h index 5e545eb6..cf9e0d8b 100644 --- a/Kernel/platform-genie-eg64/config.h +++ b/Kernel/platform-genie-eg64/config.h @@ -8,7 +8,7 @@ /* Profil syscall support (not yet complete) */ #undef CONFIG_PROFIL /* Multiple processes in memory at once */ -#define CONFIG_MULTI +#undef CONFIG_MULTI /* Single tasking */ #undef CONFIG_SINGLETASK /* Video terminal, not a serial tty */ diff --git a/Kernel/platform-genie-eg64/tricks.s b/Kernel/platform-genie-eg64/tricks.s index b96992de..0113d75b 100644 --- a/Kernel/platform-genie-eg64/tricks.s +++ b/Kernel/platform-genie-eg64/tricks.s @@ -1,212 +1,5 @@ - .module tricks - - .globl _ptab_alloc - .globl _newproc - .globl _chksigs - .globl _getproc - .globl _platform_monitor - .globl trap_illegal - .globl _platform_switchout - .globl _switchin - .globl _doexec - .globl _dofork - .globl _runticks - .globl unix_syscall_entry - .globl interrupt_handler - .globl _swapper - .globl _swapout - - ; imported debug symbols - .globl outstring, outde, outhl, outbc, outnewline, outchar, outcharhex - .include "kernel.def" .include "../kernel.def" - .area _COMMONMEM - -; 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(). -; -; This function can have no arguments or auto variables. -_platform_switchout: - di - ; save machine state - - ld hl, #0 ; 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: - push hl ; return code - push ix - push iy - ld (U_DATA__U_SP), sp ; this is where the SP is restored in _switchin - - ; find another process to run (may select this one again) - call _getproc - - push hl - call _switchin - - ; we should never get here - call _platform_monitor - -badswitchmsg: .ascii "_switchin: FAIL" - .db 13, 10, 0 -swapped: .ascii "_switchin: SWAPPED" - .db 13, 10, 0 - -_switchin: - di - pop bc ; return address - pop de ; new process pointer -; -; FIXME: do we actually *need* to restore the stack ! -; - push de ; restore stack - push bc ; restore stack - - push de - ld hl, #P_TAB__P_PAGE_OFFSET - add hl, de ; process ptr - pop de - - ld a, (hl) - - or a - jr nz, not_swapped - - ; - ; We are still on the departing processes stack, which is - ; fine for now. - ; - ld sp, #_swapstack - push hl - ; We will always swap out the current process - ld hl, (U_DATA__U_PTAB) - push hl - call _swapout - pop hl - pop hl - push de - call _swapper - pop de - pop hl - ld a, (hl) - -not_swapped: - ; check u_data->u_ptab matches what we wanted - ld hl, (U_DATA__U_PTAB) ; u_data->u_ptab - or a ; clear carry flag - sbc hl, de ; subtract, result will be zero if DE==IX - jr nz, switchinfail - - ; wants optimising up a bit - ld ix, (U_DATA__U_PTAB) - ; next_process->p_status = P_RUNNING - ld P_TAB__P_STATUS_OFFSET(ix), #P_RUNNING - - ; Fix the moved page pointers - ; Just do one byte as that is all we use on this platform - ld a, P_TAB__P_PAGE_OFFSET(ix) - ld (U_DATA__U_PAGE), a - ; runticks = 0 - ld hl, #0 - ld (_runticks), hl - - ; restore machine state -- note we may be returning from either - ; _switchout or _dofork - ld sp, (U_DATA__U_SP) - - pop iy - pop ix - pop hl ; return code - - ; enable interrupts, if the ISR isn't already running - ld a, (U_DATA__U_ININTERRUPT) - or a - ret nz ; in ISR, leave interrupts off - ei - ret ; return with interrupts on - -switchinfail: - call outhl - ld hl, #badswitchmsg - call outstring - ; something went wrong and we didn't switch in what we asked for - jp _platform_monitor - -fork_proc_ptr: .dw 0 ; (C type is struct p_tab *) -- address of child process p_tab entry - -; -; Called from _fork. We are in a syscall, the uarea is live as the -; parent uarea. The kernel is the mapped object. -; -_dofork: - ; always disconnect the vehicle battery before performing maintenance - di ; should already be the case ... belt and braces. - - pop de ; return address - pop hl ; new process p_tab* - push hl - push de - - ld (fork_proc_ptr), hl - - ; prepare return value in parent process -- HL = p->p_pid; - ld de, #P_TAB__P_PID_OFFSET - add hl, de - ld a, (hl) - inc hl - ld h, (hl) - ld l, a - - ; Save the stack pointer and critical registers. - ; When this process (the parent) is switched back in, it will be as if - ; it returns with the value of the child's pid. - push hl ; HL still has p->p_pid from above, the return value in the parent - push ix - push iy - - ; save kernel stack pointer -- when it comes back in the parent we'll be in - ; _switchin which will immediately return (appearing to be _dofork() - ; returning) and with HL (ie return code) containing the child PID. - ; Hurray. - ld (U_DATA__U_SP), sp - - ; now we're in a safe state for _switchin to return in the parent - ; process. - - ld hl, (U_DATA__U_PTAB) - push hl - call _swapout - pop hl - - ; 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 + .include "../lib/z80single.s" - ; runticks = 0; - ld hl, #0 - ld (_runticks), hl - ; in the child process, fork() returns zero. - ; - ; And we exit, with the kernel mapped, the child now being deemed - ; to be the live uarea. The parent is frozen in time and space as - ; if it had done a switchout(). - ret -; -; We can keep a stack in common because we will complete our -; use of it before we switch common block. In this case we have -; a true common so it's even easier. -; - .ds 128 -_swapstack: diff --git a/Kernel/platform-micropack/tricks.s b/Kernel/platform-micropack/tricks.s index a3cfa36c..0113d75b 100644 --- a/Kernel/platform-micropack/tricks.s +++ b/Kernel/platform-micropack/tricks.s @@ -1,231 +1,5 @@ -; 2013-12-21 William R Sowerbutts - - .module tricks - - .globl _ptab_alloc - .globl _newproc - .globl _chksigs - .globl _getproc - .globl _platform_monitor - .globl trap_illegal - .globl _platform_switchout - .globl _switchin - .globl _doexec - .globl _dofork - .globl _runticks - .globl unix_syscall_entry - .globl interrupt_handler - .globl _swapper - .globl _swapout - .globl _curbank - .globl bank_switch_a - - ; imported debug symbols - .globl outstring, outde, outhl, outbc, outnewline, outchar, outcharhex - .include "kernel.def" .include "../kernel.def" - .area _COMMONMEM - -; 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(). -; -; This function can have no arguments or auto variables. -_platform_switchout: - di - ; save machine state - - ld hl, #0 ; 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: - push hl ; return code - push ix - push iy - ld (U_DATA__U_SP), sp ; this is where the SP is restored in _switchin - - ; find another process to run (may select this one again) - call _getproc - - push hl - call _switchin - - ; we should never get here - call _platform_monitor - -badswitchmsg: .ascii "_switchin: FAIL" - .db 13, 10, 0 -swapped: .ascii "_switchin: SWAPPED" - .db 13, 10, 0 - -_switchin: - di - pop bc ; return address - pop de ; new process pointer -; -; FIXME: do we actually *need* to restore the stack ! -; - push de ; restore stack - push bc ; restore stack - - push de - ld hl, #P_TAB__P_PAGE_OFFSET - add hl, de ; process ptr - pop de - - ld a, (hl) - - or a - jr nz, not_swapped - - ; - ; We are still on the departing processes stack, which is - ; fine for now. - ; - ld a, (_curbank) - ld (U_DATA__U_PAGE2), a - ld sp, #_swapstack - push hl - ; We will always swap out the current process - ld hl, (U_DATA__U_PTAB) - push hl - call _swapout - pop hl - pop hl - push de - call _swapper - pop de - pop hl - ld a, (hl) - -not_swapped: - ; check u_data->u_ptab matches what we wanted - ld hl, (U_DATA__U_PTAB) ; u_data->u_ptab - or a ; clear carry flag - sbc hl, de ; subtract, result will be zero if DE==IX - jr nz, switchinfail - - ld a, (U_DATA__U_INSYS) - or a - jr z, not_sys - ld l, a - ; Bank rigt ? - ld a, (U_DATA__U_PAGE2) - ; Any bank - or a - jr z, not_sys - ; Need to switch bank - ld l, a - call bank_switch_a -not_sys: - ; wants optimising up a bit - ld ix, (U_DATA__U_PTAB) - ; next_process->p_status = P_RUNNING - ld P_TAB__P_STATUS_OFFSET(ix), #P_RUNNING - - ; Fix the moved page pointers - ; Just do one byte as that is all we use on this platform - ld a, P_TAB__P_PAGE_OFFSET(ix) - ld (U_DATA__U_PAGE), a - ; runticks = 0 - ld hl, #0 - ld (_runticks), hl - - ; restore machine state -- note we may be returning from either - ; _switchout or _dofork - ld sp, (U_DATA__U_SP) - - pop iy - pop ix - pop hl ; return code - - ; enable interrupts, if the ISR isn't already running - ld a, (U_DATA__U_ININTERRUPT) - or a - ret nz ; in ISR, leave interrupts off - ei - ret ; return with interrupts on - -switchinfail: - call outhl - ld hl, #badswitchmsg - call outstring - ; something went wrong and we didn't switch in what we asked for - jp _platform_monitor - -fork_proc_ptr: .dw 0 ; (C type is struct p_tab *) -- address of child process p_tab entry - -; -; Called from _fork. We are in a syscall, the uarea is live as the -; parent uarea. The kernel is the mapped object. -; -_dofork: - ; always disconnect the vehicle battery before performing maintenance - di ; should already be the case ... belt and braces. - - pop de ; return address - pop hl ; new process p_tab* - push hl - push de - - ld (fork_proc_ptr), hl - - ; prepare return value in parent process -- HL = p->p_pid; - ld de, #P_TAB__P_PID_OFFSET - add hl, de - ld a, (hl) - inc hl - ld h, (hl) - ld l, a - - ; Save the stack pointer and critical registers. - ; When this process (the parent) is switched back in, it will be as if - ; it returns with the value of the child's pid. - push hl ; HL still has p->p_pid from above, the return value in the parent - push ix - push iy - - ; save kernel stack pointer -- when it comes back in the parent we'll be in - ; _switchin which will immediately return (appearing to be _dofork() - ; returning) and with HL (ie return code) containing the child PID. - ; Hurray. - ld (U_DATA__U_SP), sp - - ; now we're in a safe state for _switchin to return in the parent - ; process. - - ld hl, (U_DATA__U_PTAB) - push hl - call _swapout - pop hl - - ; 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 + .include "../lib/z80single.s" - ; runticks = 0; - ld hl, #0 - ld (_runticks), hl - ; in the child process, fork() returns zero. - ; - ; And we exit, with the kernel mapped, the child now being deemed - ; to be the live uarea. The parent is frozen in time and space as - ; if it had done a switchout(). - ret -; -; We can keep a stack in common because we will complete our -; use of it before we switch common block. In this case we have -; a true common so it's even easier. -; - .ds 128 -_swapstack: diff --git a/Kernel/platform-rc2014-tiny/tricks.s b/Kernel/platform-rc2014-tiny/tricks.s index 03a841ba..0113d75b 100644 --- a/Kernel/platform-rc2014-tiny/tricks.s +++ b/Kernel/platform-rc2014-tiny/tricks.s @@ -1,227 +1,5 @@ -; 2013-12-21 William R Sowerbutts - - .module tricks - - .globl _ptab_alloc - .globl _newproc - .globl _chksigs - .globl _getproc - .globl _platform_monitor - .globl trap_illegal - .globl _platform_switchout - .globl _switchin - .globl _doexec - .globl _dofork - .globl _runticks - .globl unix_syscall_entry - .globl interrupt_handler - .globl _swapper - .globl _swapout - - ; imported debug symbols - .globl outstring, outde, outhl, outbc, outnewline, outchar, outcharhex - .include "kernel.def" .include "../kernel.def" - .area _COMMONMEM - -; 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(). -; -; This function can have no arguments or auto variables. -_platform_switchout: - di - ; save machine state - - ld hl, #0 ; 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: - push hl ; return code - push ix - push iy - ld (U_DATA__U_SP), sp ; this is where the SP is restored in _switchin - - ; find another process to run (may select this one again) - call _getproc - - push hl - call _switchin - - ; we should never get here - call _platform_monitor - -badswitchmsg: .ascii "_switchin: FAIL" - .db 13, 10, 0 -swapped: .ascii "_switchin: SWAPPED" - .db 13, 10, 0 - -_switchin: - di - pop bc ; return address - pop de ; new process pointer -; -; FIXME: do we actually *need* to restore the stack ! -; - push de ; restore stack - push bc ; restore stack - - push de - ld hl, #P_TAB__P_PAGE_OFFSET - add hl, de ; process ptr - pop de - - ld a, (hl) - - or a - jr nz, not_swapped - ; - ; We are still on the departing processes stack, which is - ; fine for now. - ; - ld sp, #_swapstack - ; - ; The process we are switching from is not resident. In - ; practice that means it exited. We don't need to write - ; it back out as it's dead. - ; - ld ix,(U_DATA__U_PTAB) - ld a,P_TAB__P_PAGE_OFFSET(ix) - - or a - jr z, not_resident - ; - ; DE = process we are switching to - ; - push de ; save process - ; We will always swap out the current process - ld hl, (U_DATA__U_PTAB) - push hl - call _swapout - pop hl - pop de ; process to swap to -not_resident: - push de ; called function may modify on stack arg so make - push de ; two copies - call _swapper - pop de - pop de - -not_swapped: - ; check u_data->u_ptab matches what we wanted - ld hl, (U_DATA__U_PTAB) ; u_data->u_ptab - or a ; clear carry flag - sbc hl, de ; subtract, result will be zero if DE==IX - jr nz, switchinfail - - ; wants optimising up a bit - ld ix, (U_DATA__U_PTAB) - ; next_process->p_status = P_RUNNING - ld P_TAB__P_STATUS_OFFSET(ix), #P_RUNNING - - ; Fix the moved page pointers - ; Just do one byte as that is all we use on this platform - ld a, P_TAB__P_PAGE_OFFSET(ix) - ld (U_DATA__U_PAGE), a - ; runticks = 0 - ld hl, #0 - ld (_runticks), hl - - ; restore machine state -- note we may be returning from either - ; _switchout or _dofork - ld sp, (U_DATA__U_SP) - - pop iy - pop ix - pop hl ; return code - - ; enable interrupts, if the ISR isn't already running - ld a, (U_DATA__U_ININTERRUPT) - or a - ret nz ; in ISR, leave interrupts off - ei - ret ; return with interrupts on - -switchinfail: - call outhl - ld hl, #badswitchmsg - call outstring - ; something went wrong and we didn't switch in what we asked for - jp _platform_monitor - -fork_proc_ptr: .dw 0 ; (C type is struct p_tab *) -- address of child process p_tab entry - -; -; Called from _fork. We are in a syscall, the uarea is live as the -; parent uarea. The kernel is the mapped object. -; -_dofork: - ; always disconnect the vehicle battery before performing maintenance - di ; should already be the case ... belt and braces. - - pop de ; return address - pop hl ; new process p_tab* - push hl - push de - - ld (fork_proc_ptr), hl - - ; prepare return value in parent process -- HL = p->p_pid; - ld de, #P_TAB__P_PID_OFFSET - add hl, de - ld a, (hl) - inc hl - ld h, (hl) - ld l, a - - ; Save the stack pointer and critical registers. - ; When this process (the parent) is switched back in, it will be as if - ; it returns with the value of the child's pid. - push hl ; HL still has p->p_pid from above, the return value in the parent - push ix - push iy - - ; save kernel stack pointer -- when it comes back in the parent we'll be in - ; _switchin which will immediately return (appearing to be _dofork() - ; returning) and with HL (ie return code) containing the child PID. - ; Hurray. - ld (U_DATA__U_SP), sp - - ; now we're in a safe state for _switchin to return in the parent - ; process. - - ld hl, (U_DATA__U_PTAB) - push hl - call _swapout - pop hl - - ; 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 + .include "../lib/z80single.s" - ; runticks = 0; - ld hl, #0 - ld (_runticks), hl - ; in the child process, fork() returns zero. - ; - ; And we exit, with the kernel mapped, the child now being deemed - ; to be the live uarea. The parent is frozen in time and space as - ; if it had done a switchout(). - ret -; -; We can keep a stack in common because we will complete our -; use of it before we switch common block. In this case we have -; a true common so it's even easier. -; - .ds 128 -_swapstack: diff --git a/Kernel/platform-v68/config.h b/Kernel/platform-v68/config.h index cf9a2a54..471b8cd8 100644 --- a/Kernel/platform-v68/config.h +++ b/Kernel/platform-v68/config.h @@ -7,7 +7,7 @@ #define CONFIG_32BIT -#define CONFIG_MULTI +#undef CONFIG_MULTI #define CONFIG_SWAP_ONLY #define CONFIG_USERMEM_DIRECT #define CONFIG_BANKS 1