compat_signal.c revision f8544ec4f49ffb9cb93419e41f0d8c0fb39eb78f
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;
39ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens	__u32 gprs_high[NUM_GPRS];
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u8 retcode[S390_SYSCALL_SIZE];
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} sigframe32;
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef struct
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u8 retcode[S390_SYSCALL_SIZE];
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	compat_siginfo_t info;
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ucontext32 uc;
49ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens	__u32 gprs_high[NUM_GPRS];
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} rt_sigframe32;
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* If you change siginfo_t structure, please be sure
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   this code is fixed accordingly.
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   It should never copy any pad contained in the structure
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   to avoid security leaks, but must copy the generic
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   3 ints plus the relevant union member.
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   This routine must convert siginfo from 64bit to 32bit as well
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   at the same time.  */
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = __put_user(from->si_signo, &to->si_signo);
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err |= __put_user(from->si_errno, &to->si_errno);
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err |= __put_user((short)from->si_code, &to->si_code);
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (from->si_code < 0)
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (from->si_code >> 16) {
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case __SI_RT >> 16: /* This is not generated by the kernel as of now.  */
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case __SI_MESGQ >> 16:
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __put_user(from->si_int, &to->si_int);
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* fallthrough */
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case __SI_KILL >> 16:
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __put_user(from->si_pid, &to->si_pid);
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __put_user(from->si_uid, &to->si_uid);
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case __SI_CHLD >> 16:
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __put_user(from->si_pid, &to->si_pid);
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __put_user(from->si_uid, &to->si_uid);
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __put_user(from->si_utime, &to->si_utime);
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __put_user(from->si_stime, &to->si_stime);
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __put_user(from->si_status, &to->si_status);
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case __SI_FAULT >> 16:
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __put_user((unsigned long) from->si_addr,
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					  &to->si_addr);
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case __SI_POLL >> 16:
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __put_user(from->si_band, &to->si_band);
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __put_user(from->si_fd, &to->si_fd);
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case __SI_TIMER >> 16:
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __put_user(from->si_tid, &to->si_tid);
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __put_user(from->si_overrun, &to->si_overrun);
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __put_user(from->si_int, &to->si_int);
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1020ebfd313fd4baf3fa1bd02d5f106e377595d4987Heiko Carstens	return err ? -EFAULT : 0;
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 tmp;
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = __get_user(to->si_signo, &from->si_signo);
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err |= __get_user(to->si_errno, &from->si_errno);
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err |= __get_user(to->si_code, &from->si_code);
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (to->si_code < 0)
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (to->si_code >> 16) {
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case __SI_RT >> 16: /* This is not generated by the kernel as of now.  */
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case __SI_MESGQ >> 16:
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __get_user(to->si_int, &from->si_int);
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* fallthrough */
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case __SI_KILL >> 16:
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __get_user(to->si_pid, &from->si_pid);
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __get_user(to->si_uid, &from->si_uid);
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case __SI_CHLD >> 16:
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __get_user(to->si_pid, &from->si_pid);
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __get_user(to->si_uid, &from->si_uid);
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __get_user(to->si_utime, &from->si_utime);
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __get_user(to->si_stime, &from->si_stime);
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __get_user(to->si_status, &from->si_status);
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case __SI_FAULT >> 16:
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __get_user(tmp, &from->si_addr);
1353c52e49d7c81434e3d2ccb520b3a654c2cc7d03dMartin Schwidefsky			to->si_addr = (void __force __user *)
1363c52e49d7c81434e3d2ccb520b3a654c2cc7d03dMartin Schwidefsky				(u64) (tmp & PSW32_ADDR_INSN);
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case __SI_POLL >> 16:
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __get_user(to->si_band, &from->si_band);
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __get_user(to->si_fd, &from->si_fd);
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case __SI_TIMER >> 16:
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __get_user(to->si_tid, &from->si_tid);
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __get_user(to->si_overrun, &from->si_overrun);
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err |= __get_user(to->si_int, &from->si_int);
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1510ebfd313fd4baf3fa1bd02d5f106e377595d4987Heiko Carstens	return err ? -EFAULT : 0;
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	_s390_regs_common32 regs32;
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err, i;
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
159b50511e41aa51a89b4176784a670582424bc7db6Martin Schwidefsky	regs32.psw.mask = psw32_user_bits |
160b50511e41aa51a89b4176784a670582424bc7db6Martin Schwidefsky		((__u32)(regs->psw.mask >> 32) & PSW32_MASK_USER);
161d4e81b35b882d96f059afdb0f98e5b6025973b09Martin Schwidefsky	regs32.psw.addr = (__u32) regs->psw.addr |
162d4e81b35b882d96f059afdb0f98e5b6025973b09Martin Schwidefsky		(__u32)(regs->psw.mask & PSW_MASK_BA);
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < NUM_GPRS; i++)
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs32.gprs[i] = (__u32) regs->gprs[i];
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	save_access_regs(current->thread.acrs);
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(regs32.acrs, current->thread.acrs, sizeof(regs32.acrs));
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = __copy_to_user(&sregs->regs, &regs32, sizeof(regs32));
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
169f8544ec4f49ffb9cb93419e41f0d8c0fb39eb78fHeiko Carstens		return -EFAULT;
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	save_fp_regs(&current->thread.fp_regs);
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* s390_fp_regs and _s390_fp_regs32 are the same ! */
172f8544ec4f49ffb9cb93419e41f0d8c0fb39eb78fHeiko Carstens	err = __copy_to_user(&sregs->fpregs, &current->thread.fp_regs,
173f8544ec4f49ffb9cb93419e41f0d8c0fb39eb78fHeiko Carstens			     sizeof(_s390_fp_regs32));
174f8544ec4f49ffb9cb93419e41f0d8c0fb39eb78fHeiko Carstens	if (err)
175f8544ec4f49ffb9cb93419e41f0d8c0fb39eb78fHeiko Carstens		return -EFAULT;
176f8544ec4f49ffb9cb93419e41f0d8c0fb39eb78fHeiko Carstens	return 0;
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	_s390_regs_common32 regs32;
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err, i;
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Alwys make any pending restarted system call return -EINTR */
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	current_thread_info()->restart_block.fn = do_no_restart_syscall;
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = __copy_from_user(&regs32, &sregs->regs, sizeof(regs32));
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
189f8544ec4f49ffb9cb93419e41f0d8c0fb39eb78fHeiko Carstens		return -EFAULT;
190b50511e41aa51a89b4176784a670582424bc7db6Martin Schwidefsky	regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
191d4e81b35b882d96f059afdb0f98e5b6025973b09Martin Schwidefsky		(__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 |
192d4e81b35b882d96f059afdb0f98e5b6025973b09Martin Schwidefsky		(__u64)(regs32.psw.addr & PSW32_ADDR_AMODE);
193fa968ee215c0ca91e4a9c3a69ac2405aae6e5d2fMartin Schwidefsky	/* Check for invalid user address space control. */
194e258d719ff28ecc7a048eb8f78380e68c4b3a3f0Martin Schwidefsky	if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_HOME)
195e258d719ff28ecc7a048eb8f78380e68c4b3a3f0Martin Schwidefsky		regs->psw.mask = PSW_ASC_PRIMARY |
196fa968ee215c0ca91e4a9c3a69ac2405aae6e5d2fMartin Schwidefsky			(regs->psw.mask & ~PSW_MASK_ASC);
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN);
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < NUM_GPRS; i++)
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->gprs[i] = (__u64) regs32.gprs[i];
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(current->thread.acrs, regs32.acrs, sizeof(current->thread.acrs));
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	restore_access_regs(current->thread.acrs);
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = __copy_from_user(&current->thread.fp_regs, &sregs->fpregs,
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       sizeof(_s390_fp_regs32));
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	current->thread.fp_regs.fpc &= FPC_VALID_MASK;
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
207f8544ec4f49ffb9cb93419e41f0d8c0fb39eb78fHeiko Carstens		return -EFAULT;
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	restore_fp_regs(&current->thread.fp_regs);
210b6ef5bb3d93efb95ba855a628740375c2280a59eMartin Schwidefsky	clear_thread_flag(TIF_SYSCALL);	/* No longer in a system call */
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
214ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstensstatic int save_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)
215ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens{
216ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens	__u32 gprs_high[NUM_GPRS];
217ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens	int i;
218ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens
219ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens	for (i = 0; i < NUM_GPRS; i++)
220ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens		gprs_high[i] = regs->gprs[i] >> 32;
221f8544ec4f49ffb9cb93419e41f0d8c0fb39eb78fHeiko Carstens	if (__copy_to_user(uregs, &gprs_high, sizeof(gprs_high)))
222f8544ec4f49ffb9cb93419e41f0d8c0fb39eb78fHeiko Carstens		return -EFAULT;
223f8544ec4f49ffb9cb93419e41f0d8c0fb39eb78fHeiko Carstens	return 0;
224ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens}
225ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens
226ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstensstatic int restore_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)
227ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens{
228ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens	__u32 gprs_high[NUM_GPRS];
229f8544ec4f49ffb9cb93419e41f0d8c0fb39eb78fHeiko Carstens	int i;
230ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens
231f8544ec4f49ffb9cb93419e41f0d8c0fb39eb78fHeiko Carstens	if (__copy_from_user(&gprs_high, uregs, sizeof(gprs_high)))
232f8544ec4f49ffb9cb93419e41f0d8c0fb39eb78fHeiko Carstens		return -EFAULT;
233ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens	for (i = 0; i < NUM_GPRS; i++)
234ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens		*(__u32 *)&regs->gprs[i] = gprs_high[i];
235ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens	return 0;
236ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens}
237ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens
23803ff9a235a0602724fc54916469b6e0939c62c9bMartin Schwidefskyasmlinkage long sys32_sigreturn(void)
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
24003ff9a235a0602724fc54916469b6e0939c62c9bMartin Schwidefsky	struct pt_regs *regs = task_pt_regs(current);
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15];
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sigset_t set;
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32))
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto badframe;
246391c62feb1798b6d31bd88076eae649b091ad8bfHeiko Carstens	set_current_blocked(&set);
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (restore_sigregs32(regs, &frame->sregs))
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto badframe;
249ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens	if (restore_sigregs_gprs_high(regs, frame->gprs_high))
250ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens		goto badframe;
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return regs->gprs[2];
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsbadframe:
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	force_sig(SIGSEGV, current);
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25703ff9a235a0602724fc54916469b6e0939c62c9bMartin Schwidefskyasmlinkage long sys32_rt_sigreturn(void)
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
25903ff9a235a0602724fc54916469b6e0939c62c9bMartin Schwidefsky	struct pt_regs *regs = task_pt_regs(current);
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rt_sigframe32 __user *frame = (rt_sigframe32 __user *)regs->gprs[15];
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sigset_t set;
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto badframe;
265391c62feb1798b6d31bd88076eae649b091ad8bfHeiko Carstens	set_current_blocked(&set);
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (restore_sigregs32(regs, &frame->uc.uc_mcontext))
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto badframe;
268ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens	if (restore_sigregs_gprs_high(regs, frame->gprs_high))
269ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens		goto badframe;
270e214125aa8c0546b24dabf6f47b28c5e20133d1dAl Viro	if (compat_restore_altstack(&frame->uc.uc_stack))
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto badframe;
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return regs->gprs[2];
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsbadframe:
27403ff9a235a0602724fc54916469b6e0939c62c9bMartin Schwidefsky	force_sig(SIGSEGV, current);
27503ff9a235a0602724fc54916469b6e0939c62c9bMartin Schwidefsky	return 0;
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set up a signal frame.
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Determine which stack to use..
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void __user *
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsget_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long sp;
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Default to using normal stack */
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sp = (unsigned long) A(regs->gprs[15]);
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
294de553438eb6c487f72d46019eb3821f6687ce011Heiko Carstens	/* Overflow on alternate signal stack gives SIGSEGV. */
295de553438eb6c487f72d46019eb3821f6687ce011Heiko Carstens	if (on_sig_stack(sp) && !on_sig_stack((sp - frame_size) & -8UL))
296de553438eb6c487f72d46019eb3821f6687ce011Heiko Carstens		return (void __user *) -1UL;
297de553438eb6c487f72d46019eb3821f6687ce011Heiko Carstens
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* This is the X/Open sanctioned signal stack switching.  */
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ka->sa.sa_flags & SA_ONSTACK) {
30028f223782bca914ae65d08234c57c2175ecd7f5dLaurent Meyer		if (! sas_ss_flags(sp))
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			sp = current->sas_ss_sp + current->sas_ss_size;
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (void __user *)((sp - frame_size) & -8ul);
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int map_signal(int sig)
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (current_thread_info()->exec_domain
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    && current_thread_info()->exec_domain->signal_invmap
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    && sig < 32)
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return current_thread_info()->exec_domain->signal_invmap[sig];
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return sig;
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31754dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstensstatic int setup_frame32(int sig, struct k_sigaction *ka,
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			sigset_t *set, struct pt_regs * regs)
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(sigframe32));
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
322de553438eb6c487f72d46019eb3821f6687ce011Heiko Carstens	if (frame == (void __user *) -1UL)
323de553438eb6c487f72d46019eb3821f6687ce011Heiko Carstens		goto give_sigsegv;
324de553438eb6c487f72d46019eb3821f6687ce011Heiko Carstens
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32))
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto give_sigsegv;
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (save_sigregs32(regs, &frame->sregs))
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto give_sigsegv;
330ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens	if (save_sigregs_gprs_high(regs, frame->gprs_high))
331ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens		goto give_sigsegv;
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs))
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto give_sigsegv;
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set up to return from userspace.  If provided, use a stub
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   already in userspace.  */
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ka->sa.sa_flags & SA_RESTORER) {
3385b512beb0f18024e32e228976e3690d349b05b6aHeiko Carstens		regs->gprs[14] = (__u64 __force) ka->sa.sa_restorer | PSW32_ADDR_AMODE;
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3405b512beb0f18024e32e228976e3690d349b05b6aHeiko Carstens		regs->gprs[14] = (__u64 __force) frame->retcode | PSW32_ADDR_AMODE;
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
3423c52e49d7c81434e3d2ccb520b3a654c2cc7d03dMartin Schwidefsky			       (u16 __force __user *)(frame->retcode)))
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto give_sigsegv;
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set up backchain. */
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto give_sigsegv;
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set up registers for signal handler */
3513c52e49d7c81434e3d2ccb520b3a654c2cc7d03dMartin Schwidefsky	regs->gprs[15] = (__force __u64) frame;
352fa968ee215c0ca91e4a9c3a69ac2405aae6e5d2fMartin Schwidefsky	/* Force 31 bit amode and default user address space control. */
353fa968ee215c0ca91e4a9c3a69ac2405aae6e5d2fMartin Schwidefsky	regs->psw.mask = PSW_MASK_BA |
354e258d719ff28ecc7a048eb8f78380e68c4b3a3f0Martin Schwidefsky		(PSW_USER_BITS & PSW_MASK_ASC) |
355fa968ee215c0ca91e4a9c3a69ac2405aae6e5d2fMartin Schwidefsky		(regs->psw.mask & ~PSW_MASK_ASC);
3563c52e49d7c81434e3d2ccb520b3a654c2cc7d03dMartin Schwidefsky	regs->psw.addr = (__force __u64) ka->sa.sa_handler;
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->gprs[2] = map_signal(sig);
3593c52e49d7c81434e3d2ccb520b3a654c2cc7d03dMartin Schwidefsky	regs->gprs[3] = (__force __u64) &frame->sc;
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* We forgot to include these in the sigcontext.
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   To avoid breaking binary compatibility, they are passed as args. */
363aa33c8cbbae2eb98489a3a363099b362146a8f4cMartin Schwidefsky	if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
364aa33c8cbbae2eb98489a3a363099b362146a8f4cMartin Schwidefsky	    sig == SIGTRAP || sig == SIGFPE) {
365aa33c8cbbae2eb98489a3a363099b362146a8f4cMartin Schwidefsky		/* set extra registers only for synchronous signals */
366aa33c8cbbae2eb98489a3a363099b362146a8f4cMartin Schwidefsky		regs->gprs[4] = regs->int_code & 127;
367aa33c8cbbae2eb98489a3a363099b362146a8f4cMartin Schwidefsky		regs->gprs[5] = regs->int_parm_long;
368bd9e034ef340e3a00301f67b00a247617891f1f0Michael Holzheu		regs->gprs[6] = task_thread_info(current)->last_break;
369aa33c8cbbae2eb98489a3a363099b362146a8f4cMartin Schwidefsky	}
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Place signal number on stack to allow backtrace from handler.  */
3723c52e49d7c81434e3d2ccb520b3a654c2cc7d03dMartin Schwidefsky	if (__put_user(regs->gprs[2], (int __force __user *) &frame->signo))
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto give_sigsegv;
37454dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens	return 0;
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsgive_sigsegv:
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	force_sigsegv(sig, current);
37854dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens	return -EFAULT;
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38154dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstensstatic int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   sigset_t *set, struct pt_regs * regs)
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err = 0;
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rt_sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(rt_sigframe32));
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
387de553438eb6c487f72d46019eb3821f6687ce011Heiko Carstens	if (frame == (void __user *) -1UL)
388de553438eb6c487f72d46019eb3821f6687ce011Heiko Carstens		goto give_sigsegv;
389de553438eb6c487f72d46019eb3821f6687ce011Heiko Carstens
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (copy_siginfo_to_user32(&frame->info, info))
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto give_sigsegv;
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Create the ucontext.  */
394ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens	err |= __put_user(UC_EXTENDED, &frame->uc.uc_flags);
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err |= __put_user(0, &frame->uc.uc_link);
396e214125aa8c0546b24dabf6f47b28c5e20133d1dAl Viro	err |= __compat_save_altstack(&frame->uc.uc_stack, regs->gprs[15]);
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err |= save_sigregs32(regs, &frame->uc.uc_mcontext);
398ea2a4d3a3a929ef494952bba57a0ef1a8a877881Heiko Carstens	err |= save_sigregs_gprs_high(regs, frame->gprs_high);
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto give_sigsegv;
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set up to return from userspace.  If provided, use a stub
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   already in userspace.  */
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ka->sa.sa_flags & SA_RESTORER) {
4065b512beb0f18024e32e228976e3690d349b05b6aHeiko Carstens		regs->gprs[14] = (__u64 __force) ka->sa.sa_restorer | PSW32_ADDR_AMODE;
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
4085b512beb0f18024e32e228976e3690d349b05b6aHeiko Carstens		regs->gprs[14] = (__u64 __force) frame->retcode | PSW32_ADDR_AMODE;
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
4103c52e49d7c81434e3d2ccb520b3a654c2cc7d03dMartin Schwidefsky				  (u16 __force __user *)(frame->retcode));
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set up backchain. */
4143c52e49d7c81434e3d2ccb520b3a654c2cc7d03dMartin Schwidefsky	if (__put_user(regs->gprs[15], (unsigned int __force __user *) frame))
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto give_sigsegv;
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set up registers for signal handler */
4183c52e49d7c81434e3d2ccb520b3a654c2cc7d03dMartin Schwidefsky	regs->gprs[15] = (__force __u64) frame;
419fa968ee215c0ca91e4a9c3a69ac2405aae6e5d2fMartin Schwidefsky	/* Force 31 bit amode and default user address space control. */
420fa968ee215c0ca91e4a9c3a69ac2405aae6e5d2fMartin Schwidefsky	regs->psw.mask = PSW_MASK_BA |
421e258d719ff28ecc7a048eb8f78380e68c4b3a3f0Martin Schwidefsky		(PSW_USER_BITS & PSW_MASK_ASC) |
422fa968ee215c0ca91e4a9c3a69ac2405aae6e5d2fMartin Schwidefsky		(regs->psw.mask & ~PSW_MASK_ASC);
4235b512beb0f18024e32e228976e3690d349b05b6aHeiko Carstens	regs->psw.addr = (__u64 __force) ka->sa.sa_handler;
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->gprs[2] = map_signal(sig);
4263c52e49d7c81434e3d2ccb520b3a654c2cc7d03dMartin Schwidefsky	regs->gprs[3] = (__force __u64) &frame->info;
4273c52e49d7c81434e3d2ccb520b3a654c2cc7d03dMartin Schwidefsky	regs->gprs[4] = (__force __u64) &frame->uc;
428bd9e034ef340e3a00301f67b00a247617891f1f0Michael Holzheu	regs->gprs[5] = task_thread_info(current)->last_break;
42954dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens	return 0;
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsgive_sigsegv:
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	force_sigsegv(sig, current);
43354dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens	return -EFAULT;
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * OK, we're invoking a handler
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
440a610d6e672d6d3723e8da257ad4a8a288a8f2f89Al Virovoid handle_signal32(unsigned long sig, struct k_sigaction *ka,
441391c62feb1798b6d31bd88076eae649b091ad8bfHeiko Carstens		    siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
44354dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens	int ret;
44454dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set up the stack frame */
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ka->sa.sa_flags & SA_SIGINFO)
44754dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens		ret = setup_rt_frame32(sig, ka, info, oldset, regs);
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
44954dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens		ret = setup_frame32(sig, ka, oldset, regs);
450391c62feb1798b6d31bd88076eae649b091ad8bfHeiko Carstens	if (ret)
451a610d6e672d6d3723e8da257ad4a8a288a8f2f89Al Viro		return;
452efee984c27b67e3ebef40410f35671997441b57cAl Viro	signal_delivered(sig, info, ka, regs,
453a610d6e672d6d3723e8da257ad4a8a288a8f2f89Al Viro				 test_thread_flag(TIF_SINGLE_STEP));
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
456