From 94bba225839a4444f3555d2a554fa743a15664a9 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sun, 24 Sep 2017 02:04:12 +0100 Subject: [PATCH] 65c816: further updates This is sufficient to get us to the point we enable interrupts, run platform interrupt the first time and then explode on the return path due to what looks like a stack imbalance --- Kernel/bank65c816.c | 10 ++- Kernel/cpu-65c816/README | 30 +++++++++ Kernel/lowlevel-65c816.s | 97 ++++++++++++++++++++++++------ Kernel/platform-v65c816/Makefile | 3 +- Kernel/platform-v65c816/README | 9 ++- Kernel/platform-v65c816/crt0.s | 45 ++++++++++---- Kernel/platform-v65c816/kernel.def | 8 +-- Kernel/platform-v65c816/ld65.cfg | 4 +- Kernel/platform-v65c816/v65.s | 15 +++-- 9 files changed, 166 insertions(+), 55 deletions(-) diff --git a/Kernel/bank65c816.c b/Kernel/bank65c816.c index 6e8e19f9..1ef53fcd 100644 --- a/Kernel/bank65c816.c +++ b/Kernel/bank65c816.c @@ -94,8 +94,8 @@ int swapout(ptptr p) if (map == 0) return ENOMEM; blk = map * SWAP_SIZE; - /* Write the user CPU stack to disk */ - swapwrite(SWAPDEV, blk, 512, (STACK_BANKOFF+(p-ptab)) << 8, 0); + /* Write the user CPU stack and DP to disk */ + swapwrite(SWAPDEV, blk, 512, (STACK_BANKOFF + 2 * (p - ptab)) << 8, 0); /* Write the process including DP and C stack, plus the udata cache */ swapwrite(SWAPDEV, blk + 1, SWAPTOP - SWAPBASE, SWAPBASE, p->p_page); pagemap_free(p); @@ -121,10 +121,8 @@ void swapin(ptptr p, uint16_t map) kprintf("%x: nopage!\n", p); return; } - /* Read the user stack from disk: FIXME - this is half a block - so we need to make sure our disk drivers can cope with this for - read (write is ok) */ - swapread(SWAPDEV, blk, 256, (STACK_BANKOFF+(p-ptab)) << 8, 0); + /* Read the user stack and DP from disk */ + swapread(SWAPDEV, blk, 512, (STACK_BANKOFF + 2 * (p - ptab)) << 8, 0); /* Read the process back in */ swapread(SWAPDEV, blk + 1, SWAPTOP - SWAPBASE, SWAPBASE, p->p_page); #ifdef DEBUG diff --git a/Kernel/cpu-65c816/README b/Kernel/cpu-65c816/README index 58bafa03..8f5c1f28 100644 --- a/Kernel/cpu-65c816/README +++ b/Kernel/cpu-65c816/README @@ -22,3 +22,33 @@ is the legacy memory map of a board with a 65c816 upgrade) it'll break. Verify kernel in banks other than 0 works + +RULES FOR APPLICATION SPACE + ++ Don't assume that DP is 0000 in your current bank. It's not. Likewise your + CPU stack is not 0100. Both are some random place in bank 0 because the CPU + is brain dead. + +- cc65 shouldn't care as it only uses S for temporaries and return addresses, + while the C stack it uses *is* in your bank. This does force us not to use + all the nice stack offset addressing due to this but does mean you can write + 8/16bit code and take the address of stack objects. + +- Don't save and restore S or do maths on it. This may also move during a + fork or swap. cc65 doesn't do this in its runtime so this is ok for cc65 + (it does have a stkchk routine which isn't safe to use). If you push, pop, + jsr and ret all will be fine even across a swap. In other words treat the + stack as a non-addressible object. + +- Don't do long operations, save or restore any bank register or use mvn/mvp. + We might move bank if we are interrupted and swapped. Remember mvn/mvp is + interruptible. A stub for calling it needs adding + +- Syscalls are via jmp $fe for the moment. This needs thought and may change + especially if I implement an o65 loader to sort all the 6502 mess out + +- Binaries load at $0100 + +- If you use > 6502 isntructions then check and print an error at startup. + This will eventually ned up in the o65 handling instead + diff --git a/Kernel/lowlevel-65c816.s b/Kernel/lowlevel-65c816.s index e2abb2cb..f645b249 100644 --- a/Kernel/lowlevel-65c816.s +++ b/Kernel/lowlevel-65c816.s @@ -81,6 +81,29 @@ syscall = $fe + +; +; Helper - given the udata bank in A set the DP value correctly. May +; be worth optimizing one day. +; +setdp: + php + + rep #$30 + .a16 + .i16 + + pha + asl a ; twice page + adc #STACK_BANKOFF ; we now point at the stack + adc #$0100 ; now the DP + pla + + plp + rts + + .a8 + .i8 ; ; This is called from a stub we put into each user process bank that ; does a jsl to the kernel entry point then an rts @@ -155,7 +178,6 @@ noargs: txs ; set our CPU stack ldx #kstackc_top-1 ; set our C stack stx sp ; - cli ; sane state achieved sep #$10 .i8 @@ -189,9 +211,7 @@ noargs: ; pha plb ; User mapping for data bits - xba ; from xx to xx00 for DP - lda #0 - tcd + jsr setdp ; Set DP from A, corrupts A rep #$20 .a16 @@ -268,9 +288,7 @@ signal_out: pea PROGLOAD+20 ; trap handler in user app pha plb ; get the right user data bank - xba ; get into ff00 format - lda #0 - tcd ; set user DP correctly + jsr setdp sty sp ; and finally restore the user C sp sep #$10 ; i8a8 on entry to handler .i8 @@ -292,14 +310,18 @@ _doexec: .a8 lda U_DATA__U_PAGE ; get our bank clc - adc #STACK_BANKOFF + adc U_DATA__U_PAGE ; two * bank + adc #STACK_BANKOFF ; plus offset xba ; swap to xx00 lda #$FF ; stack top is xxff tcs ; Set CPU stack at xxFF + rep #$20 + inc ; gives us the DP at xx+100 + pha + pld ; Split I/D will need to change this logic lda U_DATA__U_PAGE ; our bank - xba ; now in the form xx00 as we need - tcd ; set the user DP + jsr setdp ; We are now on the correct DP and CPU stack ; So fix up the syscall vector ldy #syscall_vector @@ -381,11 +403,14 @@ interrupt_handler: cld ; no funnies with decimal ; Now switch our data and DP to the kernel ones + lda #IRQ_DP ; interrupt has a private direct page + tcd + + sep #$20 + .a8 lda #KERNEL_BANK pha plb - lda #IRQ_DP ; interrupt has a private direct page - tcd ; Switch stacks tsx @@ -395,9 +420,7 @@ interrupt_handler: ldx #istackc_top-1 ; set up C istack (may not need eventually) stx sp - sep #$30 - - .a8 + sep #$10 .i8 lda #1 @@ -418,6 +441,23 @@ join_interrupt_path: .i16 ldx istack_switched_sp txs + + lda _kernel_flag + beq ret_to_user + + lda #KERNEL_BANK + pha + plb + ldx #KERNEL_DP + phx + pld + + ply + plx + pla + rti + +ret_to_user: ; TODO .. pre-emption @@ -441,16 +481,12 @@ join_interrupt_path: pha plb ; Now data is the user bank - xba - lda #0 - tcd ; and DP is right + jsr setdp rep #$30 .a16 .i16 - ldx istack_switched_sp - txs ply plx pla @@ -558,8 +594,29 @@ sync_sig: .a8 .i8 pha + lda _kernel_flag + bne ktrap + lda _inint + bne itrap jmp shoot_myself +itrap: + lda #itrap_msg +outfail: + jsr outstring + jmp _trap_monitor +itrap_msg: + .byte "itrap!", 0 + +ktrap: + lda #ktrap_msg + bra outfail +ktrap_msg: + .byte "ktrap!", 0 + + trap_inst: rep #$30 .a16 diff --git a/Kernel/platform-v65c816/Makefile b/Kernel/platform-v65c816/Makefile index f124f2b4..b1904c4d 100644 --- a/Kernel/platform-v65c816/Makefile +++ b/Kernel/platform-v65c816/Makefile @@ -37,4 +37,5 @@ image: ../syscall_proc.o ../syscall_other.o ../mm.o ../bank65c816.o \ ../tty.o ../devsys.o ../syscall_fs2.o ../syscall_fs3.o \ ../syscall_exec16.o ../usermem.o ../usermem_std-65c816.o devtty.o - dd if=../fuzix.bin of=fuzix.img bs=512 \ No newline at end of file + dd if=../fuzix.bin of=fuzix.img bs=256 skip=255 count=1 + dd if=../fuzix.bin of=fuzix.img bs=256 seek=1 skip=1 conv=notrunc \ No newline at end of file diff --git a/Kernel/platform-v65c816/README b/Kernel/platform-v65c816/README index 9f2d4dd7..0773f475 100644 --- a/Kernel/platform-v65c816/README +++ b/Kernel/platform-v65c816/README @@ -8,13 +8,14 @@ Bank 0: 0x0100 UData + C stack etc 0x0300 Bootcode ... Kernel image - 0xF700 7 x 256 byte CPU stacks for processes + 0xF000 7 x 256 byte CPU stacks for processes paired + with their direct pages 0xFE00 I/O page - 0xFF00 Vectors + 0xFF00 Vectors [packed at 0 in image] And in user space - 0x0000 User DP + 0x0000 Unused 0x0100 Program (CPU stack is in bank 0) 0xFC00 Udata copy (768 bytes) 0xFF00 Stubs [signal return etc] @@ -32,8 +33,6 @@ the emulator. TODO ---- -- Sort out memory map (move udata to 0100 and boot upwards) -- Fix fork() to copy the user C stacks in dofork() - Debug initial sketches - Fix brk() checking [right now its busted entirely] - Make discard sane so we can discard for buffers diff --git a/Kernel/platform-v65c816/crt0.s b/Kernel/platform-v65c816/crt0.s index c63307b0..b0d5a730 100644 --- a/Kernel/platform-v65c816/crt0.s +++ b/Kernel/platform-v65c816/crt0.s @@ -33,7 +33,7 @@ entry: ; -; We are entered at $0202 just after the required magic number +; We are entered at $0102 just after the required magic number ; ; We get run from bank 0, our I/O writes would otherwise need to be ; 24bit @@ -45,13 +45,31 @@ entry: sei ; interrupts off cld ; decimal off + + ; vectors is packed in DP, move it to FF00 + rep #$30 + .a16 + .i16 + lda #255 + ldx #0 + ldy #$FF00 + mvn KERNEL_FAR,KERNEL_FAR + + sep #$30 + .a8 + .i8 + + + lda #'u' + sta $FE20 + rep #$10 .i16 ldx #kstack_top txs ; Stack (6502 not C) - lda #'u' + lda #'z' sta $FE20 ldx #kstackc_top ; C stack @@ -59,7 +77,7 @@ entry: ldx #__BSS_RUN__ - lda #'z' + lda #'i' sta $FE20 txy @@ -78,26 +96,25 @@ entry: .a8 .i8 - lda #'i' - sta $FE20 - lda #'x' sta $FE20 - jsr init_early +; jsr init_early lda #'.' sta $FE20 jsr init_hardware - lda #13 - sta $FE20 - lda #10 - sta $FE20 jmp code -; The above gets blasted into udata space .code + .a8 + .i8 code: + lda #13 + sta $FE20 + lda #10 + sta $FE20 + rep #$30 .a16 .i16 @@ -106,12 +123,14 @@ code: ldy #U_DATA+1 lda #U_DATA__TOTALSIZE-2 stz 0,x - mvn 0,0 + mvn KERNEL_FAR,KERNEL_FAR sep #$30 .a8 .i8 + lda #'G' + sta $FE20 jsr _fuzix_main ; Should never return sei ; Spin stop: bra stop diff --git a/Kernel/platform-v65c816/kernel.def b/Kernel/platform-v65c816/kernel.def index aa631a60..3cba8b90 100644 --- a/Kernel/platform-v65c816/kernel.def +++ b/Kernel/platform-v65c816/kernel.def @@ -2,8 +2,8 @@ ; (this is struct u_data from kernel.h) U_DATA .set $0100 ; stomps over bootstrap -; 256+256+256 bytes. (U, kstack copy, k C stack copy) -U_DATA__TOTALSIZE .set $300 +; 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 PROGLOAD .set $0200 @@ -14,10 +14,10 @@ KERNEL_FAR .set $000000 ; 24 bit ; Add this to the bank number to get the high 8bits of the 16bit CPU stack ; for this process -STACK_BANKOFF .set $F5 ; F600-FCFF +STACK_BANKOFF .set $F0 ; F000-FCFF ; Direct page for IRQ processing (saves us saving/restoring DP registers) ; Can probably use the same page as the IRQ CPU stack... FIXME -IRQ_DP .set $FD ; FD00-FDFF +IRQ_DP .set $FD00 ; FD00-FDFF KERNEL_DP .set $00 ; We use the real ZP for kernel DP MAP_SIZE .set $FC00 \ No newline at end of file diff --git a/Kernel/platform-v65c816/ld65.cfg b/Kernel/platform-v65c816/ld65.cfg index 93d48aae..a8b5471d 100644 --- a/Kernel/platform-v65c816/ld65.cfg +++ b/Kernel/platform-v65c816/ld65.cfg @@ -1,8 +1,8 @@ MEMORY { RAMZ: start = $0000, size = $0100, type = rw, fill = yes; UDATA: start = $0100, size = $0200, type = rw, fill = yes; - MAIN: start = $0300, size = $F400, type = rw, fill = yes; - USTACKS:start = $F700, size = $0700, type = rw, fill = yes; + MAIN: start = $0300, size = $ED00, type = rw, fill = yes; + USEG: start = $F000, size = $0E00, type = rw, fill = yes; IO: start = $FE00, size = $0100, type = rw, fill = yes; STUB: start = $FF00, size = $00E0, type = rw, fill = yes; VECTOR: start = $FFE0, size = $0020, type = rw, fill = yes; diff --git a/Kernel/platform-v65c816/v65.s b/Kernel/platform-v65c816/v65.s index 9b730651..50ba18ce 100644 --- a/Kernel/platform-v65c816/v65.s +++ b/Kernel/platform-v65c816/v65.s @@ -63,10 +63,10 @@ ___hard_ei: ___hard_irqrestore: and #4 ; IRQ flag beq irq_on - cli + sei rts irq_on: - sei + cli rts ; @@ -74,10 +74,11 @@ irq_on: ; init_early: lda #1 -init_loop: sep #$30 .a8 .i8 + +init_loop: sta common_patch+1 ; destination bank phb ; save our bank (mvn will mess it) pha ; and count @@ -85,14 +86,20 @@ init_loop: rep #$30 .a16 .i16 + ldx #$FF00 txy lda #$00FE common_patch: mvn KERNEL_FAR,0 ; copy the block + + sep #$30 + .a8 + .i8 + pla plb ; bank to kernel bank - dec + inc cmp #8 bne init_loop rts -- 2.34.1