.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
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)
; 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
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