68000: first cut at signal handling
authorAlan Cox <alan@linux.intel.com>
Wed, 19 Oct 2016 19:47:00 +0000 (20:47 +0100)
committerAlan Cox <alan@linux.intel.com>
Wed, 19 Oct 2016 19:47:00 +0000 (20:47 +0100)
This needs a fixed position user space helper which will follow in the lib
patches

Kernel/lowlevel-68000.S

index 98471ca..f702a18 100644 (file)
@@ -384,6 +384,7 @@ SYM (__umodsi3):
                .globl trace,unimpa,unimpf,misctrap,trap15,trap14,sysc_err
                .globl spurious,unexpected,uninit
                .globl udata_shadow
+               .globl signal_helper
 
 .mri 1
 get_usp:       move.l  usp,a0
@@ -473,12 +474,19 @@ misctrap: move.w #SIGILL,-(sp)
 trap15:                move.w #SIGTRAP,-(sp)                   ; by convention
                bra sig_or_die
 
-               ; This path set wants optimising badly
-trap14:                movem.l a0-a6/d2-d7,-(sp)
+;
+;              Save as little as we can
+;              a0/a1 we are allowed to trash
+;              d0/d1 are our returns
+;              a5 we save, but otherwise we leave it to C to do needed
+;              saves only
+;
+trap14:                move.l a5,-(sp)
                move.l udata_shadow,a5
                move.b d0,U_DATA__U_CALLNO(a5)
                move.l usp,a0
                move.l a0,U_DATA__U_SYSCALL_SP(a5)
+               move.b #1,U_DATA__U_INSYS(a5)
                move.l 4(a0),U_DATA__U_ARGN(a5)
                move.l 8(a0),U_DATA__U_ARGN1(a5)
                move.l 12(a0),U_DATA__U_ARGN2(a5)
@@ -488,16 +496,79 @@ trap14:           movem.l a0-a6/d2-d7,-(sp)
                ; FIXME: EI per platform really
                and.w #$F8FF,sr
                bsr unix_syscall
-               ; FIXME: signal handling in the C code or not ?
                or.w #$0700,sr
+               clr.b U_DATA__U_INSYS(a5)
+               ; Now we need to be careful. We can make a syscall in a
+               ; signal handler and we must not screw up the return from
+               ; this call
                move.w U_DATA__U_ERROR(a5),d1
                bne sysc_err
                move.l U_DATA__U_RETVAL(a5),d0
-               movem.l (sp)+,a0-a6/d2-d7
+               ; return data is now safe
+sysc_sig:
+               tst.b U_DATA__U_CURSIG(a5)
+               bne return_via_signal
+               ; no signal - normal path
+               move.l d0,a0            ; need to set a0, so set to d0
+                                       ; avoids syscalls having to do it
+                                       ; for pointer returns
+               move.l d0,a1            ; no leakage please
+               move.l (sp)+,a5
                rte
 sysc_err:      moveq #-1,d0
-               movem.l (sp)+,a0-a6/d2-d7
-               rte
+               bra sysc_sig
+;
+;              Signal handler return path
+;
+return_via_signal:
+               move.l usp,a0
+               subq #6,a0                      ; make a space for the
+                                               ; return and ccr
+;
+;      This looks weird but think about it. We've executed trap #foo
+;      so our A0/A1 are some caller destroyed value we don't care about (
+;      and will be D0 on a normal trap return). Thus if we make the signal
+;      handler also restore D0 all is fine. The IRQ path uses signal_helper
+;      below because it does have to stack the true a1/a0/d1/d0
+;
+               move.l d0,-(a0)                 ; old A1
+               move.l d0,-(a0)                 ; old A0 (= D0)
+               movem.l d0/d1,-(a0)             ; stack ret/errno
+
+signal_helper:
+
+               ;
+               ;       Now arrange to return via the signal handler
+               ;
+               lea U_DATA__U_SIGVEC(a5),a0
+               move.b U_DATA__U_CURSIG(a5),d0
+               clr.b U_DATA__U_CURSIG(a5)
+               ; Good for 64 signals..
+               add.b d0,d0
+               add.b d0,d0
+               ext.w d0
+               add.w d0,a0
+               move.l U_DATA__U_CODEBASE(a5),a1
+               add #64,a1                      ; _sigunwind
+               move.l (sp)+,a5
+               move.w (sp)+,d0                 ; status word
+               ; We don't actually need to copy the CCR except for IRQ
+               move.w d0,16(a0)                ; CCR to recover
+               move.l (sp)+,d0                 ; return address
+               move.l d0,18(a0)                ; into user stack
+
+               move.l a0,usp                   ; set user stack pointer
+               ;
+               ;       New exception frame. FIXME set program base
+               ;       correctly !!!
+               ;
+               move.l a1,-(sp)                 ; _sigunwind
+               clr.w -(sp)                     ; status
+               moveq #0,d0
+               moveq #0,d1
+               move.l d0,a0
+               move.l d0,a1
+               rte                             ; exit trap handler
 
 spurious:      movem.l a0-a6/d0-d7,-(sp)
                move.l #strspurious,a0
@@ -567,24 +638,32 @@ intvector7:       movem.l a0-a6/d0-d7,-(sp)
 sig_or_die:    
                tst.b kernel_flag
                beq sig_user
-               move.b (sp),d0
+               move.w (sp)+,d0
                bsr outcharhex
                lea panic_sig,a0
                bsr outstring
-               lea panic_sig2,a0
+               move.w #15,d2
+stackout:
+               move.l (sp)+,a0
+               bsr outa0hex
+               lea crnl,a0
+               bsr outstring
+               dbra d2,stackout
+               move.l #panic_sig2,-(sp)
                bsr panic                       ; won't return
 panic_sig:     ascii ": signal in kernel mode."
-               byte 13,10
-panic_sig2:    asciz ": ksig"
+crnl:
+               byte 13,10,0
+panic_sig2:    asciz "ksig"
                .align 2
 
-sig_user:      movem.l a0-a6/d0-d7,-(sp)
+sig_user:      movem.l a0-a1/a5/d0-d1,-(sp)
                move.l udata_shadow,a5
                move.l U_DATA__U_PTAB(a5),-(sp)
                bsr ssig
                adda #4,sp
                ; Do signal processing bit here if we return
-               movem.l (sp)+,a0-a6/d0-d7
+               movem.l (sp)+,a0-a1/a5/d0-d1
                adda #4,sp
                rte