Commit 0a440cec authored by David S. Miller's avatar David S. Miller

[SPARC]: Add sys_waitid support.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent dc9267f0
......@@ -74,7 +74,7 @@ sys_call_table:
/*260*/ .long sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
/*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy
/*270*/ .long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
/*275*/ .long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_ni_syscall
/*275*/ .long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
/*280*/ .long sys_ni_syscall, sys_ni_syscall, sys_ni_syscall
#ifdef CONFIG_SUNOS_EMUL
......
......@@ -86,9 +86,62 @@ struct new_signal_frame32 {
__siginfo_fpu_t fpu_state;
};
struct siginfo32 {
int si_signo;
int si_errno;
int si_code;
union {
int _pad[SI_PAD_SIZE32];
/* kill() */
struct {
compat_pid_t _pid; /* sender's pid */
unsigned int _uid; /* sender's uid */
} _kill;
/* 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 */
unsigned int _uid; /* sender's uid */
sigval_t32 _sigval;
} _rt;
/* SIGCHLD */
struct {
compat_pid_t _pid; /* which child */
unsigned int _uid; /* sender's uid */
int _status; /* exit code */
compat_clock_t _utime;
compat_clock_t _stime;
struct compat_rusage _rusage;
} _sigchld;
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
struct {
u32 _addr; /* faulting insn/memory ref. */
int _trapno;
} _sigfault;
/* SIGPOLL */
struct {
int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
int _fd;
} _sigpoll;
} _sifields;
};
struct rt_signal_frame32 {
struct sparc_stackf32 ss;
siginfo_t32 info;
struct siginfo32 info;
struct pt_regs32 regs;
compat_sigset_t mask;
/* __siginfo_fpu32_t * */ u32 fpu_save;
......@@ -105,11 +158,11 @@ struct rt_signal_frame32 {
#define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame32) + 7) & (~7)))
#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame32) + 7) & (~7)))
int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from)
int copy_siginfo_to_user32(struct siginfo32 __user *to, siginfo_t *from)
{
int err;
if (!access_ok(VERIFY_WRITE, to, sizeof(siginfo_t32)))
if (!access_ok(VERIFY_WRITE, to, sizeof(struct siginfo32)))
return -EFAULT;
/* If you change siginfo_t structure, please be sure
......@@ -135,6 +188,8 @@ int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from)
err |= __put_user(from->si_utime, &to->si_utime);
err |= __put_user(from->si_stime, &to->si_stime);
err |= __put_user(from->si_status, &to->si_status);
err |= put_compat_rusage(&from->si_rusage,
&to->si_rusage);
default:
err |= __put_user(from->si_pid, &to->si_pid);
err |= __put_user(from->si_uid, &to->si_uid);
......@@ -155,6 +210,22 @@ int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from)
return err;
}
/* CAUTION: This is just a very minimalist implementation for the
* sake of compat_sys_rt_sigqueueinfo()
*/
int copy_siginfo_to_kernel32(siginfo_t *to, struct siginfo32 __user *from)
{
if (!access_ok(VERIFY_WRITE, from, sizeof(struct siginfo32)))
return -EFAULT;
if (copy_from_user(to, from, 3*sizeof(int)) ||
copy_from_user(to->_sifields._pad, from->_sifields._pad,
SI_PAD_SIZE))
return -EFAULT;
return 0;
}
/*
* atomically swap in the new signal mask, and wait for a signal.
* This is really tricky on the Sparc, watch out...
......
......@@ -1045,7 +1045,7 @@ asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set,
}
asmlinkage long sys32_rt_sigtimedwait(compat_sigset_t __user *uthese,
siginfo_t32 __user *uinfo,
struct siginfo32 __user *uinfo,
struct compat_timespec __user *uts,
compat_size_t sigsetsize)
{
......@@ -1130,15 +1130,15 @@ asmlinkage long sys32_rt_sigtimedwait(compat_sigset_t __user *uthese,
}
asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig,
siginfo_t32 __user *uinfo)
struct siginfo32 __user *uinfo)
{
siginfo_t info;
int ret;
mm_segment_t old_fs = get_fs();
if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
if (copy_siginfo_to_kernel32(&info, uinfo))
return -EFAULT;
set_fs (KERNEL_DS);
ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info);
set_fs (old_fs);
......@@ -1736,3 +1736,23 @@ sys32_timer_create(u32 clock, struct sigevent32 __user *se32,
return err;
}
asmlinkage long compat_sys_waitid(u32 which, u32 pid,
struct siginfo32 __user *uinfo, u32 options)
{
siginfo_t info;
long ret;
mm_segment_t old_fs = get_fs();
memset(&info, 0, sizeof(info));
set_fs (KERNEL_DS);
ret = sys_waitid((int)which, (compat_pid_t) pid,
(siginfo_t __user *) &info, (int) options);
set_fs (old_fs);
if (ret < 0 || info.si_signo == 0)
return ret;
BUG_ON(info.si_code & __SI_MASK);
info.si_code |= __SI_CHLD;
return copy_siginfo_to_user32(uinfo, &info);
}
......@@ -75,7 +75,7 @@ sys_call_table32:
/*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_timer_gettime, sys_timer_getoverrun
.word sys_timer_delete, sys32_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
/*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
.word sys_mq_timedsend, sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, sys_ni_syscall
.word sys_mq_timedsend, sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
/*280*/ .word sys_ni_syscall, sys_ni_syscall, sys_ni_syscall
#endif /* CONFIG_COMPAT */
......@@ -141,7 +141,7 @@ sys_call_table:
/*260*/ .word sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
.word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy
/*270*/ .word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
.word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_ni_syscall
.word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
/*280*/ .word sys_ni_syscall, sys_ni_syscall, sys_ni_syscall
#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
......
......@@ -290,11 +290,12 @@
#define __NR_io_cancel 271
#define __NR_io_getevents 272
#define __NR_mq_open 273
#define __NR_mq_unlink (__NR_mq_open+1)
#define __NR_mq_timedsend (__NR_mq_open+2)
#define __NR_mq_timedreceive (__NR_mq_open+3)
#define __NR_mq_notify (__NR_mq_open+4)
#define __NR_mq_getsetattr (__NR_mq_open+5)
#define __NR_mq_unlink 274
#define __NR_mq_timedsend 275
#define __NR_mq_timedreceive 276
#define __NR_mq_notify 277
#define __NR_mq_getsetattr 278
#define __NR_waitid 279
/* WARNING: You MAY NOT add syscall numbers larger than 282, since
* all of the syscall tables in the Sparc kernel are
......
......@@ -24,57 +24,8 @@ typedef union sigval32 {
u32 sival_ptr;
} sigval_t32;
typedef struct siginfo32 {
int si_signo;
int si_errno;
int si_code;
struct siginfo32;
union {
int _pad[SI_PAD_SIZE32];
/* kill() */
struct {
compat_pid_t _pid; /* sender's pid */
unsigned int _uid; /* sender's uid */
} _kill;
/* 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 */
unsigned int _uid; /* sender's uid */
sigval_t32 _sigval;
} _rt;
/* SIGCHLD */
struct {
compat_pid_t _pid; /* which child */
unsigned int _uid; /* sender's uid */
int _status; /* exit code */
compat_clock_t _utime;
compat_clock_t _stime;
} _sigchld;
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
struct {
u32 _addr; /* faulting insn/memory ref. */
int _trapno;
} _sigfault;
/* SIGPOLL */
struct {
int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
int _fd;
} _sigpoll;
} _sifields;
} siginfo_t32;
#endif /* CONFIG_COMPAT */
#endif /* __KERNEL__ */
......@@ -105,7 +56,8 @@ typedef struct sigevent32 {
} _sigev_un;
} sigevent_t32;
extern int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from);
extern int copy_siginfo_to_user32(struct siginfo32 __user *to, siginfo_t *from);
extern int copy_siginfo_to_kernel32(siginfo_t *to, struct siginfo32 __user *from);
#endif /* CONFIG_COMPAT */
......
......@@ -292,11 +292,13 @@
#define __NR_io_cancel 271
#define __NR_io_getevents 272
#define __NR_mq_open 273
#define __NR_mq_unlink (__NR_mq_open+1)
#define __NR_mq_timedsend (__NR_mq_open+2)
#define __NR_mq_timedreceive (__NR_mq_open+3)
#define __NR_mq_notify (__NR_mq_open+4)
#define __NR_mq_getsetattr (__NR_mq_open+5)
#define __NR_mq_unlink 274
#define __NR_mq_timedsend 275
#define __NR_mq_timedreceive 276
#define __NR_mq_notify 277
#define __NR_mq_getsetattr 278
#define __NR_waitid 279
/* WARNING: You MAY NOT add syscall numbers larger than 282, since
* all of the syscall tables in the Sparc kernel are
* sized to have 283 entries (starting at zero). Therefore
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment