11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2a53c8fab3f87c995c30ac226a03af95361243144Heiko Carstens * Copyright IBM Corp. 2000, 2006 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Gerhard Tonn (ton@de.ibm.com) 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/compat.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/smp.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/signal.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/wait.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ptrace.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/unistd.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/stddef.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/personality.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/binfmts.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/ucontext.h> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/lowcore.h> 28a0616cdebcfd575dcd4c46102d1b52fbb827fc29David Howells#include <asm/switch_to.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "compat_linux.h" 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "compat_ptrace.h" 31a806170e29c5468b1d641a22518243bdf1b8d58bHeiko Carstens#include "entry.h" 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef struct 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __u8 callee_used_stack[__SIGNAL_FRAMESIZE32]; 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sigcontext32 sc; 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds _sigregs32 sregs; 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int signo; 398070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky _sigregs_ext32 sregs_ext; 408070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky __u16 svc_insn; /* Offset of svc_insn is NOT fixed! */ 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} sigframe32; 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef struct 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __u8 callee_used_stack[__SIGNAL_FRAMESIZE32]; 468070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky __u16 svc_insn; 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds compat_siginfo_t info; 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ucontext32 uc; 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} rt_sigframe32; 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51ce3959604878c1c693979ec552069dc8bdb5ccdeAl Viroint copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* If you change siginfo_t structure, please be sure 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds this code is fixed accordingly. 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds It should never copy any pad contained in the structure 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to avoid security leaks, but must copy the generic 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3 ints plus the relevant union member. 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This routine must convert siginfo from 64bit to 32bit as well 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds at the same time. */ 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = __put_user(from->si_signo, &to->si_signo); 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_errno, &to->si_errno); 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user((short)from->si_code, &to->si_code); 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (from->si_code < 0) 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (from->si_code >> 16) { 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_RT >> 16: /* This is not generated by the kernel as of now. */ 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_MESGQ >> 16: 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_int, &to->si_int); 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* fallthrough */ 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_KILL >> 16: 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_pid, &to->si_pid); 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_uid, &to->si_uid); 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_CHLD >> 16: 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_pid, &to->si_pid); 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_uid, &to->si_uid); 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_utime, &to->si_utime); 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_stime, &to->si_stime); 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_status, &to->si_status); 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_FAULT >> 16: 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user((unsigned long) from->si_addr, 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &to->si_addr); 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_POLL >> 16: 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_band, &to->si_band); 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_fd, &to->si_fd); 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_TIMER >> 16: 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_tid, &to->si_tid); 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_overrun, &to->si_overrun); 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_int, &to->si_int); 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1010ebfd313fd4baf3fa1bd02d5f106e377595d4987Heiko Carstens return err ? -EFAULT : 0; 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 tmp; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = __get_user(to->si_signo, &from->si_signo); 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_errno, &from->si_errno); 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_code, &from->si_code); 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (to->si_code < 0) 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (to->si_code >> 16) { 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_RT >> 16: /* This is not generated by the kernel as of now. */ 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_MESGQ >> 16: 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_int, &from->si_int); 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* fallthrough */ 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_KILL >> 16: 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_pid, &from->si_pid); 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_uid, &from->si_uid); 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_CHLD >> 16: 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_pid, &from->si_pid); 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_uid, &from->si_uid); 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_utime, &from->si_utime); 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_stime, &from->si_stime); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_status, &from->si_status); 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_FAULT >> 16: 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(tmp, &from->si_addr); 1343c52e49d7c81434e3d2ccb520b3a654c2cc7d03dMartin Schwidefsky to->si_addr = (void __force __user *) 1353c52e49d7c81434e3d2ccb520b3a654c2cc7d03dMartin Schwidefsky (u64) (tmp & PSW32_ADDR_INSN); 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_POLL >> 16: 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_band, &from->si_band); 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_fd, &from->si_fd); 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_TIMER >> 16: 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_tid, &from->si_tid); 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_overrun, &from->si_overrun); 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_int, &from->si_int); 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1500ebfd313fd4baf3fa1bd02d5f106e377595d4987Heiko Carstens return err ? -EFAULT : 0; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1538070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky/* Store registers needed to create the signal frame */ 1548070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefskystatic void store_sigregs(void) 1558070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky{ 1568070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky int i; 1578070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky 1588070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky save_access_regs(current->thread.acrs); 1598070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky save_fp_ctl(¤t->thread.fp_regs.fpc); 1608070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky if (current->thread.vxrs) { 1618070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky save_vx_regs(current->thread.vxrs); 1628070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky for (i = 0; i < __NUM_FPRS; i++) 1638070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky current->thread.fp_regs.fprs[i] = 1648070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky *(freg_t *)(current->thread.vxrs + i); 1658070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky } else 1668070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky save_fp_regs(current->thread.fp_regs.fprs); 1678070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky} 1688070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky 1698070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky/* Load registers after signal return */ 1708070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefskystatic void load_sigregs(void) 1718070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky{ 1728070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky int i; 1738070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky 1748070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky restore_access_regs(current->thread.acrs); 1758070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky /* restore_fp_ctl is done in restore_sigregs */ 1768070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky if (current->thread.vxrs) { 1778070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky for (i = 0; i < __NUM_FPRS; i++) 1788070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky *(freg_t *)(current->thread.vxrs + i) = 1798070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky current->thread.fp_regs.fprs[i]; 1808070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky restore_vx_regs(current->thread.vxrs); 1818070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky } else 1828070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky restore_fp_regs(current->thread.fp_regs.fprs); 1838070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky} 1848070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs) 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1874725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky _sigregs32 user_sregs; 1884725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky int i; 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1905ebf250dabbae83ad875f0dda5a108503cf78f3bHeiko Carstens user_sregs.regs.psw.mask = (__u32)(regs->psw.mask >> 32); 1915ebf250dabbae83ad875f0dda5a108503cf78f3bHeiko Carstens user_sregs.regs.psw.mask &= PSW32_MASK_USER | PSW32_MASK_RI; 192f26946d7ecad0afdd85e6ae56663d0fe26676b34Heiko Carstens user_sregs.regs.psw.mask |= PSW32_USER_BITS; 1934725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky user_sregs.regs.psw.addr = (__u32) regs->psw.addr | 194d4e81b35b882d96f059afdb0f98e5b6025973b09Martin Schwidefsky (__u32)(regs->psw.mask & PSW_MASK_BA); 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < NUM_GPRS; i++) 1964725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky user_sregs.regs.gprs[i] = (__u32) regs->gprs[i]; 1974725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky memcpy(&user_sregs.regs.acrs, current->thread.acrs, 1984725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky sizeof(user_sregs.regs.acrs)); 1994725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky memcpy(&user_sregs.fpregs, ¤t->thread.fp_regs, 2004725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky sizeof(user_sregs.fpregs)); 2014725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky if (__copy_to_user(sregs, &user_sregs, sizeof(_sigregs32))) 202f8544ec4f49ffb9cb93419e41f0d8c0fb39eb78fHeiko Carstens return -EFAULT; 203f8544ec4f49ffb9cb93419e41f0d8c0fb39eb78fHeiko Carstens return 0; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs) 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2084725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky _sigregs32 user_sregs; 2094725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky int i; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Alwys make any pending restarted system call return -EINTR */ 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_thread_info()->restart_block.fn = do_no_restart_syscall; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2144725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky if (__copy_from_user(&user_sregs, &sregs->regs, sizeof(user_sregs))) 215f8544ec4f49ffb9cb93419e41f0d8c0fb39eb78fHeiko Carstens return -EFAULT; 2164725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky 2175ebf250dabbae83ad875f0dda5a108503cf78f3bHeiko Carstens if (!is_ri_task(current) && (user_sregs.regs.psw.mask & PSW32_MASK_RI)) 2185ebf250dabbae83ad875f0dda5a108503cf78f3bHeiko Carstens return -EINVAL; 2195ebf250dabbae83ad875f0dda5a108503cf78f3bHeiko Carstens 2204725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky /* Loading the floating-point-control word can fail. Do that first. */ 2214725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky if (restore_fp_ctl(&user_sregs.fpregs.fpc)) 2224725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky return -EINVAL; 2234725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky 2244725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky /* Use regs->psw.mask instead of PSW_USER_BITS to preserve PER bit. */ 225aa7e04b3808614980d474735cdb0bf35ac5cdf26Hendrik Brueckner regs->psw.mask = (regs->psw.mask & ~(PSW_MASK_USER | PSW_MASK_RI)) | 2264725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky (__u64)(user_sregs.regs.psw.mask & PSW32_MASK_USER) << 32 | 2275ebf250dabbae83ad875f0dda5a108503cf78f3bHeiko Carstens (__u64)(user_sregs.regs.psw.mask & PSW32_MASK_RI) << 32 | 2284725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky (__u64)(user_sregs.regs.psw.addr & PSW32_ADDR_AMODE); 229fa968ee215c0ca91e4a9c3a69ac2405aae6e5d2fMartin Schwidefsky /* Check for invalid user address space control. */ 230e258d719ff28ecc7a048eb8f78380e68c4b3a3f0Martin Schwidefsky if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_HOME) 231e258d719ff28ecc7a048eb8f78380e68c4b3a3f0Martin Schwidefsky regs->psw.mask = PSW_ASC_PRIMARY | 232fa968ee215c0ca91e4a9c3a69ac2405aae6e5d2fMartin Schwidefsky (regs->psw.mask & ~PSW_MASK_ASC); 2334725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky regs->psw.addr = (__u64)(user_sregs.regs.psw.addr & PSW32_ADDR_INSN); 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < NUM_GPRS; i++) 2354725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky regs->gprs[i] = (__u64) user_sregs.regs.gprs[i]; 2364725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky memcpy(¤t->thread.acrs, &user_sregs.regs.acrs, 2374725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky sizeof(current->thread.acrs)); 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2394725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky memcpy(¤t->thread.fp_regs, &user_sregs.fpregs, 2404725c86055f5bbdcdfe47199c0715881893a2c79Martin Schwidefsky sizeof(current->thread.fp_regs)); 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 242d3a73acbc26a4a81a01a35fd162973e53d0386f5Martin Schwidefsky clear_pt_regs_flag(regs, PIF_SYSCALL); /* No longer in a system call */ 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2468070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefskystatic int save_sigregs_ext32(struct pt_regs *regs, 2478070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky _sigregs_ext32 __user *sregs_ext) 248ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens{ 249ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens __u32 gprs_high[NUM_GPRS]; 2508070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky __u64 vxrs[__NUM_VXRS_LOW]; 251ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens int i; 252ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens 2538070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky /* Save high gprs to signal stack */ 254ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens for (i = 0; i < NUM_GPRS; i++) 255ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens gprs_high[i] = regs->gprs[i] >> 32; 2568070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky if (__copy_to_user(&sregs_ext->gprs_high, &gprs_high, 2578070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky sizeof(sregs_ext->gprs_high))) 258f8544ec4f49ffb9cb93419e41f0d8c0fb39eb78fHeiko Carstens return -EFAULT; 2598070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky 2608070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky /* Save vector registers to signal stack */ 2618070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky if (current->thread.vxrs) { 2628070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky for (i = 0; i < __NUM_VXRS_LOW; i++) 2638070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky vxrs[i] = *((__u64 *)(current->thread.vxrs + i) + 1); 2648070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky if (__copy_to_user(&sregs_ext->vxrs_low, vxrs, 2658070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky sizeof(sregs_ext->vxrs_low)) || 2668070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky __copy_to_user(&sregs_ext->vxrs_high, 2678070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky current->thread.vxrs + __NUM_VXRS_LOW, 2688070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky sizeof(sregs_ext->vxrs_high))) 2698070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky return -EFAULT; 2708070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky } 271f8544ec4f49ffb9cb93419e41f0d8c0fb39eb78fHeiko Carstens return 0; 272ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens} 273ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens 2748070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefskystatic int restore_sigregs_ext32(struct pt_regs *regs, 2758070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky _sigregs_ext32 __user *sregs_ext) 276ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens{ 277ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens __u32 gprs_high[NUM_GPRS]; 2788070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky __u64 vxrs[__NUM_VXRS_LOW]; 279f8544ec4f49ffb9cb93419e41f0d8c0fb39eb78fHeiko Carstens int i; 280ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens 2818070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky /* Restore high gprs from signal stack */ 2828070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky if (__copy_from_user(&gprs_high, &sregs_ext->gprs_high, 2838070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky sizeof(&sregs_ext->gprs_high))) 284f8544ec4f49ffb9cb93419e41f0d8c0fb39eb78fHeiko Carstens return -EFAULT; 285ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens for (i = 0; i < NUM_GPRS; i++) 286ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens *(__u32 *)®s->gprs[i] = gprs_high[i]; 2878070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky 2888070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky /* Restore vector registers from signal stack */ 2898070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky if (current->thread.vxrs) { 2908070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky if (__copy_from_user(vxrs, &sregs_ext->vxrs_low, 2918070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky sizeof(sregs_ext->vxrs_low)) || 2928070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky __copy_from_user(current->thread.vxrs + __NUM_VXRS_LOW, 2938070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky &sregs_ext->vxrs_high, 2948070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky sizeof(sregs_ext->vxrs_high))) 2958070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky return -EFAULT; 2968070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky for (i = 0; i < __NUM_VXRS_LOW; i++) 2978070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky *((__u64 *)(current->thread.vxrs + i) + 1) = vxrs[i]; 2988070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky } 299ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens return 0; 300ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens} 301ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens 3025b098c204827ed21961988b4206b411f90cc89c8Heiko CarstensCOMPAT_SYSCALL_DEFINE0(sigreturn) 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 30403ff9a235a0602724fc54916469b6e0939c62c9bMartin Schwidefsky struct pt_regs *regs = task_pt_regs(current); 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15]; 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sigset_t set; 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32)) 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto badframe; 310391c62feb1798b6d31bd88076eae649b091ad8bfHeiko Carstens set_current_blocked(&set); 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (restore_sigregs32(regs, &frame->sregs)) 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto badframe; 3138070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky if (restore_sigregs_ext32(regs, &frame->sregs_ext)) 314ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens goto badframe; 3158070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky load_sigregs(); 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return regs->gprs[2]; 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsbadframe: 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sig(SIGSEGV, current); 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3225b098c204827ed21961988b4206b411f90cc89c8Heiko CarstensCOMPAT_SYSCALL_DEFINE0(rt_sigreturn) 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 32403ff9a235a0602724fc54916469b6e0939c62c9bMartin Schwidefsky struct pt_regs *regs = task_pt_regs(current); 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rt_sigframe32 __user *frame = (rt_sigframe32 __user *)regs->gprs[15]; 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sigset_t set; 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto badframe; 330391c62feb1798b6d31bd88076eae649b091ad8bfHeiko Carstens set_current_blocked(&set); 3318070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky if (compat_restore_altstack(&frame->uc.uc_stack)) 3328070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky goto badframe; 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (restore_sigregs32(regs, &frame->uc.uc_mcontext)) 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto badframe; 3358070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky if (restore_sigregs_ext32(regs, &frame->uc.uc_mcontext_ext)) 336ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens goto badframe; 3378070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky load_sigregs(); 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return regs->gprs[2]; 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsbadframe: 34003ff9a235a0602724fc54916469b6e0939c62c9bMartin Schwidefsky force_sig(SIGSEGV, current); 34103ff9a235a0602724fc54916469b6e0939c62c9bMartin Schwidefsky return 0; 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set up a signal frame. 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Determine which stack to use.. 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void __user * 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsget_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long sp; 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Default to using normal stack */ 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sp = (unsigned long) A(regs->gprs[15]); 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 360de553438eb6c487f72d46019eb3821f6687ce011Heiko Carstens /* Overflow on alternate signal stack gives SIGSEGV. */ 361de553438eb6c487f72d46019eb3821f6687ce011Heiko Carstens if (on_sig_stack(sp) && !on_sig_stack((sp - frame_size) & -8UL)) 362de553438eb6c487f72d46019eb3821f6687ce011Heiko Carstens return (void __user *) -1UL; 363de553438eb6c487f72d46019eb3821f6687ce011Heiko Carstens 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This is the X/Open sanctioned signal stack switching. */ 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ka->sa.sa_flags & SA_ONSTACK) { 36628f223782bca914ae65d08234c57c2175ecd7f5dLaurent Meyer if (! sas_ss_flags(sp)) 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sp = current->sas_ss_sp + current->sas_ss_size; 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (void __user *)((sp - frame_size) & -8ul); 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int map_signal(int sig) 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (current_thread_info()->exec_domain 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds && current_thread_info()->exec_domain->signal_invmap 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds && sig < 32) 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return current_thread_info()->exec_domain->signal_invmap[sig]; 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sig; 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 383067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinbergerstatic int setup_frame32(struct ksignal *ksig, sigset_t *set, 384067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinberger struct pt_regs *regs) 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 386067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinberger int sig = ksig->sig; 3878070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky sigframe32 __user *frame; 3888070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky struct sigcontext32 sc; 3898070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky unsigned long restorer; 3908070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky size_t frame_size; 3918070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky 3928070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky /* 3938070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky * gprs_high are always present for 31-bit compat tasks. 3948070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky * The space for vector registers is only allocated if 3958070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky * the machine supports it 3968070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky */ 3978070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky frame_size = sizeof(*frame) - sizeof(frame->sregs_ext.__reserved); 3988070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky if (!MACHINE_HAS_VX) 3998070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky frame_size -= sizeof(frame->sregs_ext.vxrs_low) + 4008070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky sizeof(frame->sregs_ext.vxrs_high); 4018070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky frame = get_sigframe(&ksig->ka, regs, frame_size); 402de553438eb6c487f72d46019eb3821f6687ce011Heiko Carstens if (frame == (void __user *) -1UL) 403067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinberger return -EFAULT; 404de553438eb6c487f72d46019eb3821f6687ce011Heiko Carstens 4058070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky /* Set up backchain. */ 4068070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky if (__put_user(regs->gprs[15], (unsigned int __user *) frame)) 4078070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky return -EFAULT; 4088070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky 4098070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky /* Create struct sigcontext32 on the signal stack */ 4108070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky memcpy(&sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32); 4118070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky sc.sregs = (__u32)(unsigned long __force) &frame->sregs; 4128070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky if (__copy_to_user(&frame->sc, &sc, sizeof(frame->sc))) 413067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinberger return -EFAULT; 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4158070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky /* Store registers needed to create the signal frame */ 4168070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky store_sigregs(); 4178070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky 4188070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky /* Create _sigregs32 on the signal stack */ 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (save_sigregs32(regs, &frame->sregs)) 420067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinberger return -EFAULT; 4218070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky 4228070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky /* Place signal number on stack to allow backtrace from handler. */ 4238070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky if (__put_user(regs->gprs[2], (int __force __user *) &frame->signo)) 424067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinberger return -EFAULT; 4258070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky 4268070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky /* Create _sigregs_ext32 on the signal stack */ 4278070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky if (save_sigregs_ext32(regs, &frame->sregs_ext)) 428067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinberger return -EFAULT; 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set up to return from userspace. If provided, use a stub 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds already in userspace. */ 432067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinberger if (ksig->ka.sa.sa_flags & SA_RESTORER) { 4338070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky restorer = (unsigned long __force) 4348070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE; 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4368070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky /* Signal frames without vectors registers are short ! */ 4378070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky __u16 __user *svc = (void *) frame + frame_size - 2; 4388070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn, svc)) 439067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinberger return -EFAULT; 4408070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky restorer = (unsigned long __force) svc | PSW32_ADDR_AMODE; 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set up registers for signal handler */ 4448070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky regs->gprs[14] = restorer; 4453c52e49d7c81434e3d2ccb520b3a654c2cc7d03dMartin Schwidefsky regs->gprs[15] = (__force __u64) frame; 446fa968ee215c0ca91e4a9c3a69ac2405aae6e5d2fMartin Schwidefsky /* Force 31 bit amode and default user address space control. */ 447fa968ee215c0ca91e4a9c3a69ac2405aae6e5d2fMartin Schwidefsky regs->psw.mask = PSW_MASK_BA | 448e258d719ff28ecc7a048eb8f78380e68c4b3a3f0Martin Schwidefsky (PSW_USER_BITS & PSW_MASK_ASC) | 449fa968ee215c0ca91e4a9c3a69ac2405aae6e5d2fMartin Schwidefsky (regs->psw.mask & ~PSW_MASK_ASC); 450067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinberger regs->psw.addr = (__force __u64) ksig->ka.sa.sa_handler; 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->gprs[2] = map_signal(sig); 4533c52e49d7c81434e3d2ccb520b3a654c2cc7d03dMartin Schwidefsky regs->gprs[3] = (__force __u64) &frame->sc; 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We forgot to include these in the sigcontext. 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds To avoid breaking binary compatibility, they are passed as args. */ 457aa33c8cbbae2eb98489a3a363099b362146a8f4cMartin Schwidefsky if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL || 458aa33c8cbbae2eb98489a3a363099b362146a8f4cMartin Schwidefsky sig == SIGTRAP || sig == SIGFPE) { 459aa33c8cbbae2eb98489a3a363099b362146a8f4cMartin Schwidefsky /* set extra registers only for synchronous signals */ 460aa33c8cbbae2eb98489a3a363099b362146a8f4cMartin Schwidefsky regs->gprs[4] = regs->int_code & 127; 461aa33c8cbbae2eb98489a3a363099b362146a8f4cMartin Schwidefsky regs->gprs[5] = regs->int_parm_long; 462bd9e034ef340e3a00301f67b00a247617891f1f0Michael Holzheu regs->gprs[6] = task_thread_info(current)->last_break; 463aa33c8cbbae2eb98489a3a363099b362146a8f4cMartin Schwidefsky } 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 46554dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens return 0; 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 468067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinbergerstatic int setup_rt_frame32(struct ksignal *ksig, sigset_t *set, 469067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinberger struct pt_regs *regs) 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4718070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky rt_sigframe32 __user *frame; 4728070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky unsigned long restorer; 4738070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky size_t frame_size; 4748070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky u32 uc_flags; 4758070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky 4768070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky frame_size = sizeof(*frame) - 4778070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky sizeof(frame->uc.uc_mcontext_ext.__reserved); 4788070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky /* 4798070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky * gprs_high are always present for 31-bit compat tasks. 4808070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky * The space for vector registers is only allocated if 4818070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky * the machine supports it 4828070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky */ 4838070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky uc_flags = UC_GPRS_HIGH; 4848070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky if (MACHINE_HAS_VX) { 4858070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky if (current->thread.vxrs) 4868070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky uc_flags |= UC_VXRS; 4878070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky } else 4888070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky frame_size -= sizeof(frame->uc.uc_mcontext_ext.vxrs_low) + 4898070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky sizeof(frame->uc.uc_mcontext_ext.vxrs_high); 4908070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky frame = get_sigframe(&ksig->ka, regs, frame_size); 491de553438eb6c487f72d46019eb3821f6687ce011Heiko Carstens if (frame == (void __user *) -1UL) 492067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinberger return -EFAULT; 493de553438eb6c487f72d46019eb3821f6687ce011Heiko Carstens 4948070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky /* Set up backchain. */ 4958070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky if (__put_user(regs->gprs[15], (unsigned int __force __user *) frame)) 496067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinberger return -EFAULT; 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set up to return from userspace. If provided, use a stub 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds already in userspace. */ 500067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinberger if (ksig->ka.sa.sa_flags & SA_RESTORER) { 5018070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky restorer = (unsigned long __force) 5028070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE; 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5048070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky __u16 __user *svc = &frame->svc_insn; 5058070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, svc)) 506067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinberger return -EFAULT; 5078070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky restorer = (unsigned long __force) svc | PSW32_ADDR_AMODE; 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5108070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky /* Create siginfo on the signal stack */ 5118070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky if (copy_siginfo_to_user32(&frame->info, &ksig->info)) 5128070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky return -EFAULT; 5138070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky 5148070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky /* Store registers needed to create the signal frame */ 5158070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky store_sigregs(); 5168070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky 5178070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky /* Create ucontext on the signal stack. */ 5188070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky if (__put_user(uc_flags, &frame->uc.uc_flags) || 5198070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky __put_user(0, &frame->uc.uc_link) || 5208070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky __compat_save_altstack(&frame->uc.uc_stack, regs->gprs[15]) || 5218070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky save_sigregs32(regs, &frame->uc.uc_mcontext) || 5228070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)) || 5238070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky save_sigregs_ext32(regs, &frame->uc.uc_mcontext_ext)) 524067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinberger return -EFAULT; 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set up registers for signal handler */ 5278070361799ae1e3f4ef347bd10f0a508ac10acfbMartin Schwidefsky regs->gprs[14] = restorer; 5283c52e49d7c81434e3d2ccb520b3a654c2cc7d03dMartin Schwidefsky regs->gprs[15] = (__force __u64) frame; 529fa968ee215c0ca91e4a9c3a69ac2405aae6e5d2fMartin Schwidefsky /* Force 31 bit amode and default user address space control. */ 530fa968ee215c0ca91e4a9c3a69ac2405aae6e5d2fMartin Schwidefsky regs->psw.mask = PSW_MASK_BA | 531e258d719ff28ecc7a048eb8f78380e68c4b3a3f0Martin Schwidefsky (PSW_USER_BITS & PSW_MASK_ASC) | 532fa968ee215c0ca91e4a9c3a69ac2405aae6e5d2fMartin Schwidefsky (regs->psw.mask & ~PSW_MASK_ASC); 533067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinberger regs->psw.addr = (__u64 __force) ksig->ka.sa.sa_handler; 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 535067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinberger regs->gprs[2] = map_signal(ksig->sig); 5363c52e49d7c81434e3d2ccb520b3a654c2cc7d03dMartin Schwidefsky regs->gprs[3] = (__force __u64) &frame->info; 5373c52e49d7c81434e3d2ccb520b3a654c2cc7d03dMartin Schwidefsky regs->gprs[4] = (__force __u64) &frame->uc; 538bd9e034ef340e3a00301f67b00a247617891f1f0Michael Holzheu regs->gprs[5] = task_thread_info(current)->last_break; 53954dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens return 0; 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * OK, we're invoking a handler 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 546067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinbergervoid handle_signal32(struct ksignal *ksig, sigset_t *oldset, 547067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinberger struct pt_regs *regs) 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 54954dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens int ret; 55054dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set up the stack frame */ 552067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinberger if (ksig->ka.sa.sa_flags & SA_SIGINFO) 553067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinberger ret = setup_rt_frame32(ksig, oldset, regs); 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 555067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinberger ret = setup_frame32(ksig, oldset, regs); 556067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinberger 557067bf2d4d3a7aedc5982f6a58716054e5004b801Richard Weinberger signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLE_STEP)); 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 560