1 /* The kernel call that is implemented in this file:
4 * The parameters for this kernel call are:
5 * m_sigcalls.endpt # process to call signal handler
6 * m_sigcalls.sigctx # pointer to sigcontext structure
10 #include "kernel/system.h"
16 /*===========================================================================*
18 *===========================================================================*/
19 int do_sigsend(struct proc
* caller
, message
* m_ptr
)
21 /* Handle sys_sigsend, POSIX-style signal handling. */
24 register struct proc
*rp
;
25 struct sigframe_sigcontext fr
, *frp
;
31 if (!isokendpt(m_ptr
->m_sigcalls
.endpt
, &proc_nr
)) return EINVAL
;
32 if (iskerneln(proc_nr
)) return EPERM
;
33 rp
= proc_addr(proc_nr
);
35 /* Get the sigmsg structure into our address space. */
36 if ((r
= data_copy_vmcheck(caller
, caller
->p_endpoint
,
37 (vir_bytes
)m_ptr
->m_sigcalls
.sigctx
, KERNEL
,
38 (vir_bytes
)&smsg
, (phys_bytes
) sizeof(struct sigmsg
))) != OK
)
41 /* WARNING: the following code may be run more than once even for a single
42 * signal delivery. Do not change registers here. See the comment below.
45 /* Compute the user stack pointer where sigframe will start. */
46 smsg
.sm_stkptr
= arch_get_sp(rp
);
47 frp
= (struct sigframe_sigcontext
*) smsg
.sm_stkptr
- 1;
49 /* Copy the registers to the sigcontext structure. */
50 memset(&fr
, 0, sizeof(fr
));
51 fr
.sf_scp
= &frp
->sf_sc
;
54 fr
.sf_sc
.sc_gs
= rp
->p_reg
.gs
;
55 fr
.sf_sc
.sc_fs
= rp
->p_reg
.fs
;
56 fr
.sf_sc
.sc_es
= rp
->p_reg
.es
;
57 fr
.sf_sc
.sc_ds
= rp
->p_reg
.ds
;
58 fr
.sf_sc
.sc_edi
= rp
->p_reg
.di
;
59 fr
.sf_sc
.sc_esi
= rp
->p_reg
.si
;
60 fr
.sf_sc
.sc_ebp
= rp
->p_reg
.fp
;
61 fr
.sf_sc
.sc_ebx
= rp
->p_reg
.bx
;
62 fr
.sf_sc
.sc_edx
= rp
->p_reg
.dx
;
63 fr
.sf_sc
.sc_ecx
= rp
->p_reg
.cx
;
64 fr
.sf_sc
.sc_eax
= rp
->p_reg
.retreg
;
65 fr
.sf_sc
.sc_eip
= rp
->p_reg
.pc
;
66 fr
.sf_sc
.sc_cs
= rp
->p_reg
.cs
;
67 fr
.sf_sc
.sc_eflags
= rp
->p_reg
.psw
;
68 fr
.sf_sc
.sc_esp
= rp
->p_reg
.sp
;
69 fr
.sf_sc
.sc_ss
= rp
->p_reg
.ss
;
70 fr
.sf_fp
= rp
->p_reg
.fp
;
71 fr
.sf_signum
= smsg
.sm_signo
;
72 new_fp
= (reg_t
) &frp
->sf_fp
;
73 fr
.sf_scpcopy
= fr
.sf_scp
;
74 fr
.sf_ra_sigreturn
= smsg
.sm_sigreturn
;
75 fr
.sf_ra
= rp
->p_reg
.pc
;
77 fr
.sf_sc
.trap_style
= rp
->p_seg
.p_kern_trap_style
;
79 if (fr
.sf_sc
.trap_style
== KTS_NONE
) {
80 printf("do_sigsend: sigsend an unsaved process\n");
84 if (proc_used_fpu(rp
)) {
85 /* save the FPU context before saving it to the sig context */
87 memcpy(&fr
.sf_sc
.sc_fpu_state
, rp
->p_seg
.fpu_state
, FPU_XFP_SIZE
);
92 fr
.sf_sc
.sc_spsr
= rp
->p_reg
.psr
;
93 fr
.sf_sc
.sc_r0
= rp
->p_reg
.retreg
;
94 fr
.sf_sc
.sc_r1
= rp
->p_reg
.r1
;
95 fr
.sf_sc
.sc_r2
= rp
->p_reg
.r2
;
96 fr
.sf_sc
.sc_r3
= rp
->p_reg
.r3
;
97 fr
.sf_sc
.sc_r4
= rp
->p_reg
.r4
;
98 fr
.sf_sc
.sc_r5
= rp
->p_reg
.r5
;
99 fr
.sf_sc
.sc_r6
= rp
->p_reg
.r6
;
100 fr
.sf_sc
.sc_r7
= rp
->p_reg
.r7
;
101 fr
.sf_sc
.sc_r8
= rp
->p_reg
.r8
;
102 fr
.sf_sc
.sc_r9
= rp
->p_reg
.r9
;
103 fr
.sf_sc
.sc_r10
= rp
->p_reg
.r10
;
104 fr
.sf_sc
.sc_r11
= rp
->p_reg
.fp
;
105 fr
.sf_sc
.sc_r12
= rp
->p_reg
.r12
;
106 fr
.sf_sc
.sc_usr_sp
= rp
->p_reg
.sp
;
107 fr
.sf_sc
.sc_usr_lr
= rp
->p_reg
.lr
;
108 fr
.sf_sc
.sc_svc_lr
= 0; /* ? */
109 fr
.sf_sc
.sc_pc
= rp
->p_reg
.pc
; /* R15 */
112 /* Finish the sigcontext initialization. */
113 fr
.sf_sc
.sc_mask
= smsg
.sm_mask
;
114 fr
.sf_sc
.sc_flags
= rp
->p_misc_flags
& MF_FPU_INITIALIZED
;
115 fr
.sf_sc
.sc_magic
= SC_MAGIC
;
117 /* Initialize the sigframe structure. */
118 fpu_sigcontext(rp
, &fr
, &fr
.sf_sc
);
120 /* Copy the sigframe structure to the user's stack. */
121 if ((r
= data_copy_vmcheck(caller
, KERNEL
, (vir_bytes
)&fr
,
122 m_ptr
->m_sigcalls
.endpt
, (vir_bytes
)frp
,
123 (vir_bytes
)sizeof(struct sigframe_sigcontext
))) != OK
)
126 /* WARNING: up to the statement above, the code may run multiple times, since
127 * copying out the frame/context may fail with VMSUSPEND the first time. For
128 * that reason, changes to process registers *MUST* be deferred until after
129 * this last copy -- otherwise, these changes will be made several times,
130 * possibly leading to corrupted process state.
133 /* Reset user registers to execute the signal handler. */
134 rp
->p_reg
.sp
= (reg_t
) frp
;
135 rp
->p_reg
.pc
= (reg_t
) smsg
.sm_sighandler
;
137 #if defined(__i386__)
138 rp
->p_reg
.fp
= new_fp
;
139 #elif defined(__arm__)
140 /* use the ARM link register to set the return address from the signal
143 rp
->p_reg
.lr
= (reg_t
) smsg
.sm_sigreturn
;
144 if(rp
->p_reg
.lr
& 1) { printf("sigsend: LSB LR makes no sense.\n"); }
146 /* pass signal handler parameters in registers */
147 rp
->p_reg
.retreg
= (reg_t
) smsg
.sm_signo
;
148 rp
->p_reg
.r1
= 0; /* sf_code */
149 rp
->p_reg
.r2
= (reg_t
) fr
.sf_scp
;
150 rp
->p_misc_flags
|= MF_CONTEXT_SET
;
153 /* Signal handler should get clean FPU. */
154 rp
->p_misc_flags
&= ~MF_FPU_INITIALIZED
;
156 if(!RTS_ISSET(rp
, RTS_PROC_STOP
)) {
157 printf("system: warning: sigsend a running process\n");
158 printf("caller stack: ");
159 proc_stacktrace(caller
);
165 #endif /* USE_SIGSEND */