/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright (C) 1994 - 2000 Ralf Baechle
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/syscalls.h>
#include <linux/errno.h>
#include <linux/wait.h>
#include <linux/ptrace.h>
#include <linux/compat.h>
#include <linux/suspend.h>
#include <linux/compiler.h>
#include <asm/asm.h>
#include <linux/bitops.h>
#include <asm/cacheflush.h>
#include <asm/sim.h>
#include <asm/uaccess.h>
#include <asm/ucontext.h>
#include <asm/system.h>
#include <asm/fpu.h>
#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
typedef struct compat_siginfo {
int si_signo;
int si_code;
int si_errno;
union {
int _pad[SI_PAD_SIZE32];
/* kill() */
struct {
compat_pid_t _pid; /* sender's pid */
compat_uid_t _uid; /* sender's uid */
} _kill;
/* SIGCHLD */
struct {
compat_pid_t _pid; /* which child */
compat_uid_t _uid; /* sender's uid */
int _status; /* exit code */
compat_clock_t _utime;
compat_clock_t _stime;
} _sigchld;
/* IRIX SIGCHLD */
struct {
compat_pid_t _pid; /* which child */
compat_clock_t _utime;
int _status; /* exit code */
compat_clock_t _stime;
} _irix_sigchld;
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
struct {
s32 _addr; /* faulting insn/memory ref. */
} _sigfault;
/* SIGPOLL, SIGXFSZ (To do ...) */
struct {
int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
int _fd;
} _sigpoll;
/* POSIX.1b timers */
struct {
timer_t _tid; /* timer id */
int _overrun; /* overrun count */
sigval_t32 _sigval; /* same as below */
int _sys_private; /* not to be passed to user */
} _timer;
/* POSIX.1b signals */
struct {
compat_pid_t _pid; /* sender's pid */
compat_uid_t _uid; /* sender's uid */
compat_sigval_t _sigval;
} _rt;
} _sifields;
} compat_siginfo_t;
/*
* Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
*/
#define __NR_O32_sigreturn 4119
#define __NR_O32_rt_sigreturn 4193
#define __NR_O32_restart_syscall 4253
#define DEBUG_SIG 0
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
/* 32-bit compatibility types */
#define _NSIG_BPW32 32
#define _NSIG_WORDS32 (_NSIG / _NSIG_BPW32)
typedef struct {
unsigned int sig[_NSIG_WORDS32];
} sigset_t32;
typedef unsigned int __sighandler32_t;
typedef void (*vfptr_t)(void);
struct sigaction32 {
unsigned int sa_flags;
__sighandler32_t sa_handler;
compat_sigset_t sa_mask;
};
/* IRIX compatible stack_t */
typedef struct sigaltstack32 {
s32 ss_sp;
compat_size_t ss_size;
int ss_flags;
} stack32_t;
struct ucontext32 {
u32 uc_flags;
s32 uc_link;
stack32_t uc_stack;
struct sigcontext32 uc_mcontext;
sigset_t32 uc_sigmask; /* mask last for extensibility */
};
extern void __put_sigset_unknown_nsig(void);
extern void __get_sigset_unknown_nsig(void);
static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t *ubuf)
{
int err = 0;
if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)))
return -EFAULT;
switch (_NSIG_WORDS) {
default:
__put_sigset_unknown_nsig();
case 2:
err |= __put_user (kbuf->sig[1] >> 32, &ubuf->sig[3]);
err |= __put_user (kbuf->sig[1] & 0xffffffff, &ubuf->sig[2]);
case 1:
err |= __put_user (kbuf->sig[0] >> 32, &ubuf->sig[1]);
err |= __put_user (kbuf->sig[0] & 0xffffffff, &ubuf->sig[0]);
}
return err;
}
static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t *ubuf)
{
int err = 0;
unsigned long sig[4];
if (!access_ok(VERIFY_READ, ubuf, sizeof(*ubuf)))
return -EFAULT;
switch (_NSIG_WORDS) {
default:
__get_sigset_unknown_nsig();
case 2:
err |= __get_user (sig[3], &ubuf->sig[3]);
err |= __get_user (sig[2], &ubuf->sig[2]);
kbuf->sig[1] = sig[2] | (sig[3] << 32);
case 1:
err |= __get_user (sig[1], &ubuf->sig[1]);
err |= __get_user (sig[0], &ubuf->sig[0]);
kbuf->