.import _runticks
.import outcharhex
.import outstring
+ .import kstack_base
.code
.a8
lda U_DATA__U_PAGE
sta f:KERNEL_CODE_FAR+switch_patch_1+1 ; target bank of save
+.if ( KERNEL_BANK )
+ sta f:KERNEL_CODE_FAR+switch_patch_2+1 ; target bank of save
+.endif
rep #$30
.i16
.a16
phb
switch_patch_1:
mvn 0,KERNEL_BANK ; save stack and udata
+
+.if ( KERNEL_BANK )
+ ;
+ ; Big (non bank 0) kernels by necessity split off the
+ ; kstack into bank 0.
+ ;
+ ; FIXME: some day split the user ZP to be half ZP half Kstack
+ ;
+ lda #$FF
+ ldx #kstack_base
+switch_patch_2:
+ mvn 0,0
+
+.endif
plb
sep #$30
stz _inint
; If this is zero we need swapping so the swapper checks go here
; FIXME
- sta f:KERNEL_CODE_FAR+switch_patch_2+2 ; source bank of retrieve
+ sta f:KERNEL_CODE_FAR+switch_patch_3+2 ; source bank of retrieve
+.if ( KERNEL_BANK )
+ sta f:KERNEL_CODE_FAR+switch_patch_4+2 ; source bank of retrieve
+.endif
rep #$30
.i16
.a16
ldx #U_DATA_STASH
ldy #U_DATA
lda #U_DATA__TOTALSIZE-1
-switch_patch_2:
+switch_patch_3:
mvn KERNEL_BANK,0
- ; after the MVN our data bank is KERNEL_DATA
+
+.if ( KERNEL_BANK )
+ ;
+ ; Big kernel - recover kstack into bank 0
+ ;
+ ldy #kstack_base
+ lda #$FF
+switch_patch_4:
+ mvn 0,0
+
+.endif
+
+ ; Bank may be invalid but we don't have a stack we can use
+ ; so force a far access
+ ; after this our data bank is KERNEL_DATA
; Our stack is now valid and we may use it again, our UDATA
; is for the new process
- ldx U_DATA__U_SP ; correct stack pointer
+ lda f:KERNEL_FAR+U_DATA__U_SP ; correct stack pointer
+ tax
txs
+ ; Now our stack is valid fix the bank register
+
+ sep #$20
+ .a8
+ lda #KERNEL_BANK
+ pha
+ plb
+
ldx U_DATA__U_PTAB
cpx ptr1
bne switchinfail ; wrong process !!
stz _runticks
- sep #$20
- .a8
+
lda #P_RUNNING
sta a:P_TAB__P_STATUS_OFFSET,x
; This will only be needed once we swap, and we will need to
lda U_DATA__U_PAGE
sta f:KERNEL_CODE_FAR+fork_patch+2 ; source bank (parent)
sta f:KERNEL_CODE_FAR+fork_patch_2+1 ; destination udata stash
+.if ( KERNEL_BANK )
+ sta f:KERNEL_CODE_FAR+fork_patch_3+1 ; destination udata stash
+.endif
asl a
adc #STACK_BANKOFF
sta ptr2+1 ; source for S and DP
; Our context is now a valid stack frame so we can save stuff
ldx #0
txy
- lda #MAP_SIZE ; 64K - udata shadow
+ lda #MAP_SIZE-1 ; 64K - udata shadow
phb
fork_patch:
mvn 0,0 ; copy the entire bank below the save
lda #U_DATA__TOTALSIZE-1
fork_patch_2:
mvn 0,KERNEL_BANK
- plb ; back to kernel bank
-
- ldx ptr2
- ldy ptr3
+.if ( KERNEL_BANK )
+ ;
+ ; For big kernels copy the kstack separately as it's in
+ ; bank 0 but the C stack and udata are in kernel data.
+ ;
+ ldx #kstack_base
+ lda #$FF
+fork_patch_3:
+ mvn 0,0
+.endif
+ ;
+ ; Clone DP and stack between parent and child
+ ;
+ ldx ptr2 ; in DP
+ ldy ptr3 ; in DP
lda #$01FF ; DP and stack
+
mvn 0,0
+ plb ; back to corect bank register
;
; Final hairy detail - the child S value needs to be shifted
TODO
----
-- Fix task switching: on big model our udata is in bank 2 and our kstack
- ring 0 so we can't save them as single 512 byte xfer but as we know we
- won't be using nearly all the 512 bytes of C stack we can save udata and
- most of C stack just fine.
- See 65c816 port for general notes
- Save jmpvec+1/2 in seg 2 on IRQ entry and restore on exit
-Optimisations We Need To Do
---------------------------------------------------------------
-- Only copy the needed memory when forking, not 64K ?
.export _ub
.export _udata
.export kstack_top
+ .export kstack_base
.export kstackc_top
.export istack_top
.export istackc_top
; stack and a small CPU stack in the banking
;
; Our current layout is
-; [udata][C stack] 256 bytes
-; [C stack] 256
+; [udata] ~256 bytes (279 with L2)
+; [C stack] 256 (or thereabouts)
;
; There is a separate IRQ DP, stack and C stack.
;
kstackc_base:
.res 512,0
kstackc_top:
+ ; and our saved area follows this by a copy of kstack
;
; We have a single istack so we can stuff that anywhere we like
*/
#define CONFIG_BANK_65C816
#define KERNEL_BANK 2
-#define MAX_MAPS 125
-#define MAP_SIZE 0xFC00 /* 0-FBFF */
+#define MAX_MAPS 125
+#define MAP_SIZE 0xFB00 /* 0-FAFF */
/* 0xEE because our first bank is 1 and 0xEE + 2 * 1 = 0xF0 */
#define STACK_BANKOFF 0x00 /* 0400-FDFF */
#define MAPBASE 0x0000 /* We map from 0 */
#define PROGBASE 0x0100 /* also data base */
#define PROGLOAD 0x0100
-#define PROGTOP 0xFC00 /* Top of program. If we fixed a few things we
+#define PROGTOP 0xFB00 /* Top of program. If we fixed a few things we
could go to FE00 */
#define BOOT_TTY 513 /* Set this to default device for stdio, stderr */
U_DATA .set $0100 ; avoid ZP
; 256+256 (U, kstack copy, k C stack copy)
U_DATA__TOTALSIZE .set $0200
-U_DATA_STASH .set $FC00 ; leaves FFxx for vectors and stubs
+U_DATA_STASH .set $FB00 ; leaves FFxx for vectors and stubs
PROGLOAD .set $0100
ZPBASE .set $0
IRQ_DP .set $FF80 ; FF80-FFBF
KERNEL_DP .set $00 ; We use the real ZP for kernel DP
-MAP_SIZE .set $FC00
+MAP_SIZE .set $FB00
PROGBASE .set $0100
TODO
----
-- Test revized brk() checking
- Add swap logic
- Relocatable binaries
- cc65 stubs optimized for 65c816
Optimisations We Need To Do
--------------------------------------------------------------
- Only copy the needed memory when forking, not 64K ?
+- Can we keep udata in kernel ZP (at least for level 1). Would need to
+ audit that we don't take pointers to ZP but might be faster and we
+ need to do the same audit for some cases with 68K etc anyway
+- Can we put the kernel per process CPU stack (kstack) into the upper half
+ of ZP for each process. We don't need 256 bytes of ZP per process
+- Can we trim down to say 64 bytes ZP + 256 stack per process so we can go
+ above 8MB - do we care ??