1 /* 2 * Emulation of Linux signals 3 * 4 * Copyright (c) 2003 Fabrice Bellard 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 #include "qemu/osdep.h" 20 #include "qemu.h" 21 #include "signal-common.h" 22 #include "linux-user/trace.h" 23 24 struct target_sigcontext { 25 struct target_pt_regs regs; 26 abi_ulong oldmask; 27 abi_ulong usp; 28 }; 29 30 struct target_ucontext { 31 abi_ulong tuc_flags; 32 abi_ulong tuc_link; 33 target_stack_t tuc_stack; 34 struct target_sigcontext tuc_mcontext; 35 target_sigset_t tuc_sigmask; /* mask last for extensibility */ 36 }; 37 38 struct target_rt_sigframe { 39 abi_ulong pinfo; 40 uint64_t puc; 41 struct target_siginfo info; 42 struct target_sigcontext sc; 43 struct target_ucontext uc; 44 unsigned char retcode[16]; /* trampoline code */ 45 }; 46 47 /* This is the asm-generic/ucontext.h version */ 48 #if 0 49 static int restore_sigcontext(CPUOpenRISCState *regs, 50 struct target_sigcontext *sc) 51 { 52 unsigned int err = 0; 53 unsigned long old_usp; 54 55 /* Alwys make any pending restarted system call return -EINTR */ 56 current_thread_info()->restart_block.fn = do_no_restart_syscall; 57 58 /* restore the regs from &sc->regs (same as sc, since regs is first) 59 * (sc is already checked for VERIFY_READ since the sigframe was 60 * checked in sys_sigreturn previously) 61 */ 62 63 if (copy_from_user(regs, &sc, sizeof(struct target_pt_regs))) { 64 goto badframe; 65 } 66 67 /* make sure the U-flag is set so user-mode cannot fool us */ 68 69 regs->sr &= ~SR_SM; 70 71 /* restore the old USP as it was before we stacked the sc etc. 72 * (we cannot just pop the sigcontext since we aligned the sp and 73 * stuff after pushing it) 74 */ 75 76 __get_user(old_usp, &sc->usp); 77 phx_signal("old_usp 0x%lx", old_usp); 78 79 __PHX__ REALLY /* ??? */ 80 wrusp(old_usp); 81 regs->gpr[1] = old_usp; 82 83 /* TODO: the other ports use regs->orig_XX to disable syscall checks 84 * after this completes, but we don't use that mechanism. maybe we can 85 * use it now ? 86 */ 87 88 return err; 89 90 badframe: 91 return 1; 92 } 93 #endif 94 95 /* Set up a signal frame. */ 96 97 static void setup_sigcontext(struct target_sigcontext *sc, 98 CPUOpenRISCState *regs, 99 unsigned long mask) 100 { 101 unsigned long usp = cpu_get_gpr(regs, 1); 102 103 /* copy the regs. they are first in sc so we can use sc directly */ 104 105 /*copy_to_user(&sc, regs, sizeof(struct target_pt_regs));*/ 106 107 /* Set the frametype to CRIS_FRAME_NORMAL for the execution of 108 the signal handler. The frametype will be restored to its previous 109 value in restore_sigcontext. */ 110 /*regs->frametype = CRIS_FRAME_NORMAL;*/ 111 112 /* then some other stuff */ 113 __put_user(mask, &sc->oldmask); 114 __put_user(usp, &sc->usp); 115 } 116 117 static inline unsigned long align_sigframe(unsigned long sp) 118 { 119 return sp & ~3UL; 120 } 121 122 static inline abi_ulong get_sigframe(struct target_sigaction *ka, 123 CPUOpenRISCState *regs, 124 size_t frame_size) 125 { 126 unsigned long sp = get_sp_from_cpustate(regs); 127 int onsigstack = on_sig_stack(sp); 128 129 /* redzone */ 130 sp = target_sigsp(sp, ka); 131 132 sp = align_sigframe(sp - frame_size); 133 134 /* 135 * If we are on the alternate signal stack and would overflow it, don't. 136 * Return an always-bogus address instead so we will die with SIGSEGV. 137 */ 138 139 if (onsigstack && !likely(on_sig_stack(sp))) { 140 return -1L; 141 } 142 143 return sp; 144 } 145 146 void setup_rt_frame(int sig, struct target_sigaction *ka, 147 target_siginfo_t *info, 148 target_sigset_t *set, CPUOpenRISCState *env) 149 { 150 int err = 0; 151 abi_ulong frame_addr; 152 unsigned long return_ip; 153 struct target_rt_sigframe *frame; 154 abi_ulong info_addr, uc_addr; 155 156 frame_addr = get_sigframe(ka, env, sizeof(*frame)); 157 trace_user_setup_rt_frame(env, frame_addr); 158 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { 159 goto give_sigsegv; 160 } 161 162 info_addr = frame_addr + offsetof(struct target_rt_sigframe, info); 163 __put_user(info_addr, &frame->pinfo); 164 uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc); 165 __put_user(uc_addr, &frame->puc); 166 167 if (ka->sa_flags & SA_SIGINFO) { 168 tswap_siginfo(&frame->info, info); 169 } 170 171 /*err |= __clear_user(&frame->uc, offsetof(ucontext_t, uc_mcontext));*/ 172 __put_user(0, &frame->uc.tuc_flags); 173 __put_user(0, &frame->uc.tuc_link); 174 target_save_altstack(&frame->uc.tuc_stack, env); 175 setup_sigcontext(&frame->sc, env, set->sig[0]); 176 177 /*err |= copy_to_user(frame->uc.tuc_sigmask, set, sizeof(*set));*/ 178 179 /* trampoline - the desired return ip is the retcode itself */ 180 return_ip = (unsigned long)&frame->retcode; 181 /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */ 182 __put_user(0xa960, (short *)(frame->retcode + 0)); 183 __put_user(TARGET_NR_rt_sigreturn, (short *)(frame->retcode + 2)); 184 __put_user(0x20000001, (unsigned long *)(frame->retcode + 4)); 185 __put_user(0x15000000, (unsigned long *)(frame->retcode + 8)); 186 187 if (err) { 188 goto give_sigsegv; 189 } 190 191 /* TODO what is the current->exec_domain stuff and invmap ? */ 192 193 /* Set up registers for signal handler */ 194 env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */ 195 cpu_set_gpr(env, 9, (unsigned long)return_ip); /* what we enter LATER */ 196 cpu_set_gpr(env, 3, (unsigned long)sig); /* arg 1: signo */ 197 cpu_set_gpr(env, 4, (unsigned long)&frame->info); /* arg 2: (siginfo_t*) */ 198 cpu_set_gpr(env, 5, (unsigned long)&frame->uc); /* arg 3: ucontext */ 199 200 /* actually move the usp to reflect the stacked frame */ 201 cpu_set_gpr(env, 1, (unsigned long)frame); 202 203 return; 204 205 give_sigsegv: 206 unlock_user_struct(frame, frame_addr, 1); 207 force_sigsegv(sig); 208 } 209 210 long do_sigreturn(CPUOpenRISCState *env) 211 { 212 trace_user_do_sigreturn(env, 0); 213 fprintf(stderr, "do_sigreturn: not implemented\n"); 214 return -TARGET_ENOSYS; 215 } 216 217 long do_rt_sigreturn(CPUOpenRISCState *env) 218 { 219 trace_user_do_rt_sigreturn(env, 0); 220 fprintf(stderr, "do_rt_sigreturn: not implemented\n"); 221 return -TARGET_ENOSYS; 222 } 223