1 /* The kernel call that is implemented in this file: 2 * m_type: SYS_SIGSEND 3 * 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 7 * 8 */ 9 10 #include "kernel/system.h" 11 #include <signal.h> 12 #include <string.h> 13 14 #if USE_SIGSEND 15 16 /*===========================================================================* 17 * do_sigsend * 18 *===========================================================================*/ 19 int do_sigsend(struct proc * caller, message * m_ptr) 20 { 21 /* Handle sys_sigsend, POSIX-style signal handling. */ 22 23 struct sigmsg smsg; 24 register struct proc *rp; 25 struct sigframe_sigcontext fr, *frp; 26 int proc_nr, r; 27 #if defined(__i386__) 28 reg_t new_fp; 29 #endif 30 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); 34 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) 39 return r; 40 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. 43 */ 44 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; 48 49 /* Copy the registers to the sigcontext structure. */ 50 memset(&fr, 0, sizeof(fr)); 51 fr.sf_scp = &frp->sf_sc; 52 53 #if defined(__i386__) 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; 76 77 fr.sf_sc.trap_style = rp->p_seg.p_kern_trap_style; 78 79 if (fr.sf_sc.trap_style == KTS_NONE) { 80 printf("do_sigsend: sigsend an unsaved process\n"); 81 return EINVAL; 82 } 83 84 if (proc_used_fpu(rp)) { 85 /* save the FPU context before saving it to the sig context */ 86 save_fpu(rp); 87 memcpy(&fr.sf_sc.sc_fpu_state, rp->p_seg.fpu_state, FPU_XFP_SIZE); 88 } 89 #endif 90 91 #if defined(__arm__) 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 */ 110 #endif 111 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; 116 117 /* Initialize the sigframe structure. */ 118 fpu_sigcontext(rp, &fr, &fr.sf_sc); 119 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) 124 return r; 125 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. 131 */ 132 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; 136 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 141 * handler 142 */ 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"); } 145 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; 151 #endif 152 153 /* Signal handler should get clean FPU. */ 154 rp->p_misc_flags &= ~MF_FPU_INITIALIZED; 155 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); 160 } 161 162 return OK; 163 } 164 165 #endif /* USE_SIGSEND */ 166 167