signal32.c (e82a82c19f4272ea5437cc76e5711b98e2ee6223) | signal32.c (d1e63c947a6fa4f61253343d9bbd834394a6c364) |
---|---|
1/* 2 * This file is subject to the terms and conditions of the GNU General Public 3 * License. See the file "COPYING" in the main directory of this archive 4 * for more details. 5 * 6 * Copyright (C) 1991, 1992 Linus Torvalds 7 * Copyright (C) 1994 - 2000, 2006 Ralf Baechle 8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc. | 1/* 2 * This file is subject to the terms and conditions of the GNU General Public 3 * License. See the file "COPYING" in the main directory of this archive 4 * for more details. 5 * 6 * Copyright (C) 1991, 1992 Linus Torvalds 7 * Copyright (C) 1994 - 2000, 2006 Ralf Baechle 8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc. |
9 * Copyright (C) 2016, Imagination Technologies Ltd. |
|
9 */ | 10 */ |
10#include <linux/cache.h> 11#include <linux/compat.h> 12#include <linux/sched.h> 13#include <linux/mm.h> 14#include <linux/smp.h> | 11#include <linux/compiler.h> 12#include <linux/errno.h> |
15#include <linux/kernel.h> 16#include <linux/signal.h> 17#include <linux/syscalls.h> | 13#include <linux/kernel.h> 14#include <linux/signal.h> 15#include <linux/syscalls.h> |
18#include <linux/errno.h> 19#include <linux/wait.h> 20#include <linux/ptrace.h> 21#include <linux/suspend.h> 22#include <linux/compiler.h> 23#include <linux/uaccess.h> | |
24 | 16 |
25#include <asm/abi.h> 26#include <asm/asm.h> | 17#include <asm/compat.h> |
27#include <asm/compat-signal.h> | 18#include <asm/compat-signal.h> |
28#include <linux/bitops.h> 29#include <asm/cacheflush.h> 30#include <asm/sim.h> 31#include <asm/ucontext.h> 32#include <asm/fpu.h> 33#include <asm/war.h> 34#include <asm/dsp.h> | 19#include <asm/uaccess.h> 20#include <asm/unistd.h> |
35 36#include "signal-common.h" 37 | 21 22#include "signal-common.h" 23 |
38/* 39 * Including <asm/unistd.h> would give use the 64-bit syscall numbers ... 40 */ 41#define __NR_O32_restart_syscall 4253 42 | |
43/* 32-bit compatibility types */ 44 45typedef unsigned int __sighandler32_t; 46typedef void (*vfptr_t)(void); 47 | 24/* 32-bit compatibility types */ 25 26typedef unsigned int __sighandler32_t; 27typedef void (*vfptr_t)(void); 28 |
48struct ucontext32 { 49 u32 uc_flags; 50 s32 uc_link; 51 compat_stack_t uc_stack; 52 struct sigcontext32 uc_mcontext; 53 compat_sigset_t uc_sigmask; /* mask last for extensibility */ 54}; 55 56struct sigframe32 { 57 u32 sf_ass[4]; /* argument save space for o32 */ 58 u32 sf_pad[2]; /* Was: signal trampoline */ 59 struct sigcontext32 sf_sc; 60 compat_sigset_t sf_mask; 61}; 62 63struct rt_sigframe32 { 64 u32 rs_ass[4]; /* argument save space for o32 */ 65 u32 rs_pad[2]; /* Was: signal trampoline */ 66 compat_siginfo_t rs_info; 67 struct ucontext32 rs_uc; 68}; 69 70static int setup_sigcontext32(struct pt_regs *regs, 71 struct sigcontext32 __user *sc) 72{ 73 int err = 0; 74 int i; 75 76 err |= __put_user(regs->cp0_epc, &sc->sc_pc); 77 78 err |= __put_user(0, &sc->sc_regs[0]); 79 for (i = 1; i < 32; i++) 80 err |= __put_user(regs->regs[i], &sc->sc_regs[i]); 81 82 err |= __put_user(regs->hi, &sc->sc_mdhi); 83 err |= __put_user(regs->lo, &sc->sc_mdlo); 84 if (cpu_has_dsp) { 85 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp); 86 err |= __put_user(mfhi1(), &sc->sc_hi1); 87 err |= __put_user(mflo1(), &sc->sc_lo1); 88 err |= __put_user(mfhi2(), &sc->sc_hi2); 89 err |= __put_user(mflo2(), &sc->sc_lo2); 90 err |= __put_user(mfhi3(), &sc->sc_hi3); 91 err |= __put_user(mflo3(), &sc->sc_lo3); 92 } 93 94 /* 95 * Save FPU state to signal context. Signal handler 96 * will "inherit" current FPU state. 97 */ 98 err |= protected_save_fp_context(sc); 99 100 return err; 101} 102 103static int restore_sigcontext32(struct pt_regs *regs, 104 struct sigcontext32 __user *sc) 105{ 106 int err = 0; 107 s32 treg; 108 int i; 109 110 /* Always make any pending restarted system calls return -EINTR */ 111 current->restart_block.fn = do_no_restart_syscall; 112 113 err |= __get_user(regs->cp0_epc, &sc->sc_pc); 114 err |= __get_user(regs->hi, &sc->sc_mdhi); 115 err |= __get_user(regs->lo, &sc->sc_mdlo); 116 if (cpu_has_dsp) { 117 err |= __get_user(treg, &sc->sc_hi1); mthi1(treg); 118 err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg); 119 err |= __get_user(treg, &sc->sc_hi2); mthi2(treg); 120 err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg); 121 err |= __get_user(treg, &sc->sc_hi3); mthi3(treg); 122 err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg); 123 err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK); 124 } 125 126 for (i = 1; i < 32; i++) 127 err |= __get_user(regs->regs[i], &sc->sc_regs[i]); 128 129 return err ?: protected_restore_fp_context(sc); 130} 131 | |
132/* 133 * Atomically swap in the new signal mask, and wait for a signal. 134 */ 135 136asmlinkage int sys32_sigsuspend(compat_sigset_t __user *uset) 137{ 138 return compat_sys_rt_sigsuspend(uset, sizeof(compat_sigset_t)); 139} --- 102 unchanged lines hidden (view full) --- 242{ 243 if (copy_from_user(to, from, 3*sizeof(int)) || 244 copy_from_user(to->_sifields._pad, 245 from->_sifields._pad, SI_PAD_SIZE32)) 246 return -EFAULT; 247 248 return 0; 249} | 29/* 30 * Atomically swap in the new signal mask, and wait for a signal. 31 */ 32 33asmlinkage int sys32_sigsuspend(compat_sigset_t __user *uset) 34{ 35 return compat_sys_rt_sigsuspend(uset, sizeof(compat_sigset_t)); 36} --- 102 unchanged lines hidden (view full) --- 139{ 140 if (copy_from_user(to, from, 3*sizeof(int)) || 141 copy_from_user(to->_sifields._pad, 142 from->_sifields._pad, SI_PAD_SIZE32)) 143 return -EFAULT; 144 145 return 0; 146} |
250 251asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs) 252{ 253 struct sigframe32 __user *frame; 254 sigset_t blocked; 255 int sig; 256 257 frame = (struct sigframe32 __user *) regs.regs[29]; 258 if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 259 goto badframe; 260 if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask)) 261 goto badframe; 262 263 set_current_blocked(&blocked); 264 265 sig = restore_sigcontext32(®s, &frame->sf_sc); 266 if (sig < 0) 267 goto badframe; 268 else if (sig) 269 force_sig(sig, current); 270 271 /* 272 * Don't let your children do this ... 273 */ 274 __asm__ __volatile__( 275 "move\t$29, %0\n\t" 276 "j\tsyscall_exit" 277 :/* no outputs */ 278 :"r" (®s)); 279 /* Unreached */ 280 281badframe: 282 force_sig(SIGSEGV, current); 283} 284 285asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) 286{ 287 struct rt_sigframe32 __user *frame; 288 sigset_t set; 289 int sig; 290 291 frame = (struct rt_sigframe32 __user *) regs.regs[29]; 292 if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 293 goto badframe; 294 if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask)) 295 goto badframe; 296 297 set_current_blocked(&set); 298 299 sig = restore_sigcontext32(®s, &frame->rs_uc.uc_mcontext); 300 if (sig < 0) 301 goto badframe; 302 else if (sig) 303 force_sig(sig, current); 304 305 if (compat_restore_altstack(&frame->rs_uc.uc_stack)) 306 goto badframe; 307 308 /* 309 * Don't let your children do this ... 310 */ 311 __asm__ __volatile__( 312 "move\t$29, %0\n\t" 313 "j\tsyscall_exit" 314 :/* no outputs */ 315 :"r" (®s)); 316 /* Unreached */ 317 318badframe: 319 force_sig(SIGSEGV, current); 320} 321 322static int setup_frame_32(void *sig_return, struct ksignal *ksig, 323 struct pt_regs *regs, sigset_t *set) 324{ 325 struct sigframe32 __user *frame; 326 int err = 0; 327 328 frame = get_sigframe(ksig, regs, sizeof(*frame)); 329 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) 330 return -EFAULT; 331 332 err |= setup_sigcontext32(regs, &frame->sf_sc); 333 err |= __copy_conv_sigset_to_user(&frame->sf_mask, set); 334 335 if (err) 336 return -EFAULT; 337 338 /* 339 * Arguments to signal handler: 340 * 341 * a0 = signal number 342 * a1 = 0 (should be cause) 343 * a2 = pointer to struct sigcontext 344 * 345 * $25 and c0_epc point to the signal handler, $29 points to the 346 * struct sigframe. 347 */ 348 regs->regs[ 4] = ksig->sig; 349 regs->regs[ 5] = 0; 350 regs->regs[ 6] = (unsigned long) &frame->sf_sc; 351 regs->regs[29] = (unsigned long) frame; 352 regs->regs[31] = (unsigned long) sig_return; 353 regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler; 354 355 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", 356 current->comm, current->pid, 357 frame, regs->cp0_epc, regs->regs[31]); 358 359 return 0; 360} 361 362static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig, 363 struct pt_regs *regs, sigset_t *set) 364{ 365 struct rt_sigframe32 __user *frame; 366 int err = 0; 367 368 frame = get_sigframe(ksig, regs, sizeof(*frame)); 369 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) 370 return -EFAULT; 371 372 /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */ 373 err |= copy_siginfo_to_user32(&frame->rs_info, &ksig->info); 374 375 /* Create the ucontext. */ 376 err |= __put_user(0, &frame->rs_uc.uc_flags); 377 err |= __put_user(0, &frame->rs_uc.uc_link); 378 err |= __compat_save_altstack(&frame->rs_uc.uc_stack, regs->regs[29]); 379 err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext); 380 err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set); 381 382 if (err) 383 return -EFAULT; 384 385 /* 386 * Arguments to signal handler: 387 * 388 * a0 = signal number 389 * a1 = 0 (should be cause) 390 * a2 = pointer to ucontext 391 * 392 * $25 and c0_epc point to the signal handler, $29 points to 393 * the struct rt_sigframe32. 394 */ 395 regs->regs[ 4] = ksig->sig; 396 regs->regs[ 5] = (unsigned long) &frame->rs_info; 397 regs->regs[ 6] = (unsigned long) &frame->rs_uc; 398 regs->regs[29] = (unsigned long) frame; 399 regs->regs[31] = (unsigned long) sig_return; 400 regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler; 401 402 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", 403 current->comm, current->pid, 404 frame, regs->cp0_epc, regs->regs[31]); 405 406 return 0; 407} 408 409/* 410 * o32 compatibility on 64-bit kernels, without DSP ASE 411 */ 412struct mips_abi mips_abi_32 = { 413 .setup_frame = setup_frame_32, 414 .setup_rt_frame = setup_rt_frame_32, 415 .restart = __NR_O32_restart_syscall, 416 417 .off_sc_fpregs = offsetof(struct sigcontext32, sc_fpregs), 418 .off_sc_fpc_csr = offsetof(struct sigcontext32, sc_fpc_csr), 419 .off_sc_used_math = offsetof(struct sigcontext32, sc_used_math), 420 421 .vdso = &vdso_image_o32, 422}; | |