From: Alan Cox Date: Fri, 16 Nov 2018 20:56:49 +0000 (+0000) Subject: lowlevel-z80-thunked: Fix pre-emption crashes X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=ea2b1eec242acd0fee7d392f2ec326148c721e90;p=FUZIX.git lowlevel-z80-thunked: Fix pre-emption crashes This changes the way things work between the stubs and core code as they were broken. The stubs are now responsible for saving all the register state on the user stack. The istack cannot be used for this as it was before because it may be blown away by another interrupt. Instead the stubs carefully shuffle the two bytes of return address onto the kstack of the process and return on that stack in the pre-emption case. It's not pretty but it's hard to do anything more elegant, and speedwise it's a fast way to handle it. A 'You are not expected to understand this code' moment, but it's buried in support assembly code that nobody else has to understand. --- diff --git a/Kernel/lowlevel-z80-thunked.s b/Kernel/lowlevel-z80-thunked.s index f06b7b81..e4ca5b0d 100644 --- a/Kernel/lowlevel-z80-thunked.s +++ b/Kernel/lowlevel-z80-thunked.s @@ -202,15 +202,6 @@ traphl: ; interrupt_handler: call map_save_low ; save old and map kernel - ex af,af' - push af - push bc - exx - push bc - push de - push hl - push ix - push iy ld a,#1 ld (_inint),a ld (U_DATA__U_ININTERRUPT),a @@ -233,8 +224,8 @@ intreti:di ld a, (U_DATA__U_INSYS) or a jr nz, interrupt_kernel - call map_user_low intsig: + call map_user_low ld a,(U_DATA__U_CURSIG) or a jr nz, interrupt_sig @@ -245,17 +236,6 @@ no_sig: ld e,a ld a,(U_DATA__U_PAGE+1) intret: - ex af,af' - exx - pop iy - pop ix - pop hl - pop de - pop bc - exx - pop bc - pop af - ex af,af' ret interrupt_kernel: @@ -290,13 +270,27 @@ interrupt_sig: ; ; The horrible case - task switching time ; +; Everything important is on the user stack, except that there is +; a vital stubs return address top of our current stack +; +; We move the return address onto the kstack, switch to the kstack +; and then park ourselves in platform_switchout. On our return the +; istack has been lost but our kstack (private to us) still has the +; needed return address to the stubs and we can unwind everything +; via that stack. +; +.globl preemption + preemption: + pop de ; return address to stubs xor a ld (_need_resched),a ; we are doing it thank you ld hl,(istack_switched_sp) ld (U_DATA__U_SYSCALL_SP), hl ; save the stack save ld sp, #kstack_top ; free because we are not pre-empted ; during a system call + push de ; return address onto our kstack + ; istack will be lost ld hl,#intret2 push hl reti ; reti M1 cycle for IM2 @@ -311,14 +305,15 @@ intret2: ; Give up the CPU ; FIXME: can we get here on timers when only one thing is running ; and we don't need to pre-empt ????? Is this more generally busted - ; ? + ; ? It is .... review timer interrupt logic... FIXME call _platform_switchout ; Undo the fakery xor a ld (U_DATA__U_ININTERRUPT),a ld (U_DATA__U_INSYS),a - ld hl,(U_DATA__U_SYSCALL_SP) - ld (istack_switched_sp),hl + ; The istack was lost but that is ok as we saved the return onto the + ; kernel stack, so when we finally ret we end up in the right place + ld sp,#kstack_top - 2 ; saved return address ; Now continue on the interrupt return path ; looking for signals jr intsig diff --git a/Kernel/platform-sam/README b/Kernel/platform-sam/README index cb01022e..f1a9d2a2 100644 --- a/Kernel/platform-sam/README +++ b/Kernel/platform-sam/README @@ -39,6 +39,7 @@ and all the bank juggling tricks Stub code is in the low parts of the low banks and the top of the high banks so we have two copier routines one for each half. +DONE - Crashes on interrupt preempt (Fixed I hope) - Fix signal handling crashes - Sometimes we seem to pre-empt in the middle of a pre-empt and crash ?? we see a kprintf from an interrupt interrupted @@ -51,7 +52,7 @@ DONE - Move fonts to video bank after frame buffer - Floppy driver (at least for read) DONE - Get to init (but not much further) IP - Debug all the new banking code and stubs - - Atom IDE driver + - Atom IDE driver (prob need minimal copiers in high stubs) DONE - Atom-lite IDE driver DONE - Look at how to preserve high colour bits diff --git a/Kernel/platform-sam/sam.s b/Kernel/platform-sam/sam.s index de2cdd3f..f94cd243 100644 --- a/Kernel/platform-sam/sam.s +++ b/Kernel/platform-sam/sam.s @@ -370,6 +370,17 @@ interrupt_high: push af push de push hl + + ex af,af' + push af + push bc + exx + push bc + push de + push hl + push ix + push iy + in a,(251) and #0x60 or #KERNEL_HIGH @@ -398,6 +409,18 @@ interrupt_high: cp e call nz, sigpath kernout: + ex af,af' + exx + pop iy + pop ix + pop hl + pop de + pop bc + exx + pop bc + pop af + ex af,af' + pop hl pop de pop af