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 "target_signal.h" 22 #include "signal-common.h" 23 #include "linux-user/trace.h" 24 25 #define __NUM_GPRS 16 26 #define __NUM_FPRS 16 27 #define __NUM_ACRS 16 28 29 #define S390_SYSCALL_SIZE 2 30 #define __SIGNAL_FRAMESIZE 160 /* FIXME: 31-bit mode -> 96 */ 31 32 #define _SIGCONTEXT_NSIG 64 33 #define _SIGCONTEXT_NSIG_BPW 64 /* FIXME: 31-bit mode -> 32 */ 34 #define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW) 35 #define _SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS) 36 #define PSW_ADDR_AMODE 0x0000000000000000UL /* 0x80000000UL for 31-bit */ 37 #define S390_SYSCALL_OPCODE ((uint16_t)0x0a00) 38 39 typedef struct { 40 target_psw_t psw; 41 target_ulong gprs[__NUM_GPRS]; 42 unsigned int acrs[__NUM_ACRS]; 43 } target_s390_regs_common; 44 45 typedef struct { 46 unsigned int fpc; 47 double fprs[__NUM_FPRS]; 48 } target_s390_fp_regs; 49 50 typedef struct { 51 target_s390_regs_common regs; 52 target_s390_fp_regs fpregs; 53 } target_sigregs; 54 55 struct target_sigcontext { 56 target_ulong oldmask[_SIGCONTEXT_NSIG_WORDS]; 57 target_sigregs *sregs; 58 }; 59 60 typedef struct { 61 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE]; 62 struct target_sigcontext sc; 63 target_sigregs sregs; 64 int signo; 65 uint8_t retcode[S390_SYSCALL_SIZE]; 66 } sigframe; 67 68 struct target_ucontext { 69 target_ulong tuc_flags; 70 struct target_ucontext *tuc_link; 71 target_stack_t tuc_stack; 72 target_sigregs tuc_mcontext; 73 target_sigset_t tuc_sigmask; /* mask last for extensibility */ 74 }; 75 76 typedef struct { 77 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE]; 78 uint8_t retcode[S390_SYSCALL_SIZE]; 79 struct target_siginfo info; 80 struct target_ucontext uc; 81 } rt_sigframe; 82 83 static inline abi_ulong 84 get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size) 85 { 86 abi_ulong sp; 87 88 /* Default to using normal stack */ 89 sp = env->regs[15]; 90 91 /* This is the X/Open sanctioned signal stack switching. */ 92 if (ka->sa_flags & TARGET_SA_ONSTACK) { 93 if (!sas_ss_flags(sp)) { 94 sp = target_sigaltstack_used.ss_sp + 95 target_sigaltstack_used.ss_size; 96 } 97 } 98 99 /* This is the legacy signal stack switching. */ 100 else if (/* FIXME !user_mode(regs) */ 0 && 101 !(ka->sa_flags & TARGET_SA_RESTORER) && 102 ka->sa_restorer) { 103 sp = (abi_ulong) ka->sa_restorer; 104 } 105 106 return (sp - frame_size) & -8ul; 107 } 108 109 static void save_sigregs(CPUS390XState *env, target_sigregs *sregs) 110 { 111 int i; 112 //save_access_regs(current->thread.acrs); FIXME 113 114 /* Copy a 'clean' PSW mask to the user to avoid leaking 115 information about whether PER is currently on. */ 116 __put_user(env->psw.mask, &sregs->regs.psw.mask); 117 __put_user(env->psw.addr, &sregs->regs.psw.addr); 118 for (i = 0; i < 16; i++) { 119 __put_user(env->regs[i], &sregs->regs.gprs[i]); 120 } 121 for (i = 0; i < 16; i++) { 122 __put_user(env->aregs[i], &sregs->regs.acrs[i]); 123 } 124 /* 125 * We have to store the fp registers to current->thread.fp_regs 126 * to merge them with the emulated registers. 127 */ 128 //save_fp_regs(¤t->thread.fp_regs); FIXME 129 for (i = 0; i < 16; i++) { 130 __put_user(get_freg(env, i)->ll, &sregs->fpregs.fprs[i]); 131 } 132 } 133 134 void setup_frame(int sig, struct target_sigaction *ka, 135 target_sigset_t *set, CPUS390XState *env) 136 { 137 sigframe *frame; 138 abi_ulong frame_addr; 139 140 frame_addr = get_sigframe(ka, env, sizeof(*frame)); 141 trace_user_setup_frame(env, frame_addr); 142 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { 143 goto give_sigsegv; 144 } 145 146 __put_user(set->sig[0], &frame->sc.oldmask[0]); 147 148 save_sigregs(env, &frame->sregs); 149 150 __put_user((abi_ulong)(unsigned long)&frame->sregs, 151 (abi_ulong *)&frame->sc.sregs); 152 153 /* Set up to return from userspace. If provided, use a stub 154 already in userspace. */ 155 if (ka->sa_flags & TARGET_SA_RESTORER) { 156 env->regs[14] = (unsigned long) 157 ka->sa_restorer | PSW_ADDR_AMODE; 158 } else { 159 env->regs[14] = (frame_addr + offsetof(sigframe, retcode)) 160 | PSW_ADDR_AMODE; 161 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn, 162 (uint16_t *)(frame->retcode)); 163 } 164 165 /* Set up backchain. */ 166 __put_user(env->regs[15], (abi_ulong *) frame); 167 168 /* Set up registers for signal handler */ 169 env->regs[15] = frame_addr; 170 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE; 171 172 env->regs[2] = sig; //map_signal(sig); 173 env->regs[3] = frame_addr += offsetof(typeof(*frame), sc); 174 175 /* We forgot to include these in the sigcontext. 176 To avoid breaking binary compatibility, they are passed as args. */ 177 env->regs[4] = 0; // FIXME: no clue... current->thread.trap_no; 178 env->regs[5] = 0; // FIXME: no clue... current->thread.prot_addr; 179 180 /* Place signal number on stack to allow backtrace from handler. */ 181 __put_user(env->regs[2], &frame->signo); 182 unlock_user_struct(frame, frame_addr, 1); 183 return; 184 185 give_sigsegv: 186 force_sigsegv(sig); 187 } 188 189 void setup_rt_frame(int sig, struct target_sigaction *ka, 190 target_siginfo_t *info, 191 target_sigset_t *set, CPUS390XState *env) 192 { 193 int i; 194 rt_sigframe *frame; 195 abi_ulong frame_addr; 196 197 frame_addr = get_sigframe(ka, env, sizeof *frame); 198 trace_user_setup_rt_frame(env, frame_addr); 199 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { 200 goto give_sigsegv; 201 } 202 203 tswap_siginfo(&frame->info, info); 204 205 /* Create the ucontext. */ 206 __put_user(0, &frame->uc.tuc_flags); 207 __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link); 208 __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp); 209 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), 210 &frame->uc.tuc_stack.ss_flags); 211 __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size); 212 save_sigregs(env, &frame->uc.tuc_mcontext); 213 for (i = 0; i < TARGET_NSIG_WORDS; i++) { 214 __put_user((abi_ulong)set->sig[i], 215 (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]); 216 } 217 218 /* Set up to return from userspace. If provided, use a stub 219 already in userspace. */ 220 if (ka->sa_flags & TARGET_SA_RESTORER) { 221 env->regs[14] = (unsigned long) ka->sa_restorer | PSW_ADDR_AMODE; 222 } else { 223 env->regs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE; 224 __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn, 225 (uint16_t *)(frame->retcode)); 226 } 227 228 /* Set up backchain. */ 229 __put_user(env->regs[15], (abi_ulong *) frame); 230 231 /* Set up registers for signal handler */ 232 env->regs[15] = frame_addr; 233 env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE; 234 235 env->regs[2] = sig; //map_signal(sig); 236 env->regs[3] = frame_addr + offsetof(typeof(*frame), info); 237 env->regs[4] = frame_addr + offsetof(typeof(*frame), uc); 238 return; 239 240 give_sigsegv: 241 force_sigsegv(sig); 242 } 243 244 static int 245 restore_sigregs(CPUS390XState *env, target_sigregs *sc) 246 { 247 int err = 0; 248 int i; 249 250 for (i = 0; i < 16; i++) { 251 __get_user(env->regs[i], &sc->regs.gprs[i]); 252 } 253 254 __get_user(env->psw.mask, &sc->regs.psw.mask); 255 trace_user_s390x_restore_sigregs(env, (unsigned long long)sc->regs.psw.addr, 256 (unsigned long long)env->psw.addr); 257 __get_user(env->psw.addr, &sc->regs.psw.addr); 258 /* FIXME: 31-bit -> | PSW_ADDR_AMODE */ 259 260 for (i = 0; i < 16; i++) { 261 __get_user(env->aregs[i], &sc->regs.acrs[i]); 262 } 263 for (i = 0; i < 16; i++) { 264 __get_user(get_freg(env, i)->ll, &sc->fpregs.fprs[i]); 265 } 266 267 return err; 268 } 269 270 long do_sigreturn(CPUS390XState *env) 271 { 272 sigframe *frame; 273 abi_ulong frame_addr = env->regs[15]; 274 target_sigset_t target_set; 275 sigset_t set; 276 277 trace_user_do_sigreturn(env, frame_addr); 278 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { 279 goto badframe; 280 } 281 __get_user(target_set.sig[0], &frame->sc.oldmask[0]); 282 283 target_to_host_sigset_internal(&set, &target_set); 284 set_sigmask(&set); /* ~_BLOCKABLE? */ 285 286 if (restore_sigregs(env, &frame->sregs)) { 287 goto badframe; 288 } 289 290 unlock_user_struct(frame, frame_addr, 0); 291 return -TARGET_QEMU_ESIGRETURN; 292 293 badframe: 294 force_sig(TARGET_SIGSEGV); 295 return -TARGET_QEMU_ESIGRETURN; 296 } 297 298 long do_rt_sigreturn(CPUS390XState *env) 299 { 300 rt_sigframe *frame; 301 abi_ulong frame_addr = env->regs[15]; 302 sigset_t set; 303 304 trace_user_do_rt_sigreturn(env, frame_addr); 305 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { 306 goto badframe; 307 } 308 target_to_host_sigset(&set, &frame->uc.tuc_sigmask); 309 310 set_sigmask(&set); /* ~_BLOCKABLE? */ 311 312 if (restore_sigregs(env, &frame->uc.tuc_mcontext)) { 313 goto badframe; 314 } 315 316 if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0, 317 get_sp_from_cpustate(env)) == -EFAULT) { 318 goto badframe; 319 } 320 unlock_user_struct(frame, frame_addr, 0); 321 return -TARGET_QEMU_ESIGRETURN; 322 323 badframe: 324 unlock_user_struct(frame, frame_addr, 0); 325 force_sig(TARGET_SIGSEGV); 326 return -TARGET_QEMU_ESIGRETURN; 327 } 328