Commit f408553c authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ppc64: compat layer update, from Paul Mackerras, Olaf Hering and myself

From: Anton Blanchard <anton@samba.org>

- Switch to using the new compat aio syscalls
- add compat timer/clock syscalls
- use compat_statfs64
- add compat fadvise64_64
parent 45738bdd
......@@ -825,10 +825,10 @@ _GLOBAL(sys_call_table32)
.llong .sys_ni_syscall
.llong .sys_ni_syscall /* 225 - reserved for tux */
.llong .sys32_sendfile64
.llong .sys32_io_setup
.llong .compat_sys_io_setup
.llong .sys_io_destroy
.llong .sys32_io_getevents
.llong .sys32_io_submit
.llong .compat_sys_io_getevents
.llong .compat_sys_io_submit
.llong .sys_io_cancel
.llong .sys_set_tid_address
.llong .ppc32_fadvise64
......@@ -838,20 +838,21 @@ _GLOBAL(sys_call_table32)
.llong .sys_epoll_ctl
.llong .sys_epoll_wait
.llong .sys_remap_file_pages
.llong .sys_ni_syscall /* 240 */
.llong .sys_ni_syscall
.llong .sys_ni_syscall
.llong .sys_ni_syscall
.llong .sys_ni_syscall
.llong .sys_ni_syscall /* 245 */
.llong .sys_ni_syscall
.llong .sys_ni_syscall
.llong .sys_ni_syscall
.llong .ppc32_timer_create /* 240 */
.llong .compat_timer_settime
.llong .compat_timer_gettime
.llong .sys_timer_getoverrun
.llong .sys_timer_delete
.llong .compat_clock_settime /* 245 */
.llong .compat_clock_gettime
.llong .compat_clock_getres
.llong .compat_clock_nanosleep
.llong .sys_ni_syscall
.llong .sys32_tgkill /* 250 */
.llong .sys32_utimes
.llong .sys_statfs64
.llong .sys_fstatfs64
.llong .compat_statfs64
.llong .compat_fstatfs64
.llong .ppc32_fadvise64_64 /* 32bit only fadvise64_64 */
.balign 8
_GLOBAL(sys_call_table)
......@@ -1109,3 +1110,4 @@ _GLOBAL(sys_call_table)
.llong .sys_utimes
.llong .sys_statfs64
.llong .sys_fstatfs64
.llong .sys_ni_syscall /* 32bit only fadvise64_64 */
......@@ -93,7 +93,7 @@ struct rt_sigframe_32 {
* it is a pointer to the user context in the rt stack frame
*/
u32 puc;
struct siginfo32 info;
struct compat_siginfo info;
struct ucontext32 uc;
};
......@@ -639,7 +639,7 @@ long sys32_rt_sigpending(compat_sigset_t *set, compat_size_t sigsetsize)
}
static int copy_siginfo_to_user32(siginfo_t32 *d, siginfo_t *s)
static int copy_siginfo_to_user32(compat_siginfo_t *d, siginfo_t *s)
{
int err;
......@@ -681,7 +681,7 @@ static int copy_siginfo_to_user32(siginfo_t32 *d, siginfo_t *s)
return err;
}
long sys32_rt_sigtimedwait(compat_sigset_t *uthese, siginfo_t32 *uinfo,
long sys32_rt_sigtimedwait(compat_sigset_t *uthese, compat_siginfo_t *uinfo,
struct compat_timespec *uts, compat_size_t sigsetsize)
{
sigset_t s;
......@@ -714,7 +714,7 @@ long sys32_rt_sigtimedwait(compat_sigset_t *uthese, siginfo_t32 *uinfo,
static siginfo_t * siginfo32to64(siginfo_t *d, siginfo_t32 *s)
static siginfo_t * siginfo32to64(siginfo_t *d, compat_siginfo_t *s)
{
d->si_signo = s->si_signo;
d->si_errno = s->si_errno;
......@@ -758,14 +758,14 @@ static siginfo_t * siginfo32to64(siginfo_t *d, siginfo_t32 *s)
* (msr in 32-bit mode) and the register representation of a signed int
* (msr in 64-bit mode) is performed.
*/
long sys32_rt_sigqueueinfo(u32 pid, u32 sig, siginfo_t32 *uinfo)
long sys32_rt_sigqueueinfo(u32 pid, u32 sig, compat_siginfo_t *uinfo)
{
siginfo_t info;
siginfo_t32 info32;
compat_siginfo_t info32;
int ret;
mm_segment_t old_fs = get_fs();
if (copy_from_user (&info32, uinfo, sizeof(siginfo_t32)))
if (copy_from_user (&info32, uinfo, sizeof(compat_siginfo_t)))
return -EFAULT;
/* XXX: Is this correct? */
siginfo32to64(&info, &info32);
......
......@@ -2683,98 +2683,6 @@ unsigned long sys32_mmap2(unsigned long addr, size_t len,
return sys_mmap(addr, len, prot, flags, fd, pgoff << 12);
}
extern long sys_io_setup(unsigned nr_reqs, aio_context_t *ctx);
long sys32_io_setup(unsigned nr_reqs, u32 *ctx32p)
{
long ret;
aio_context_t ctx64;
mm_segment_t oldfs = get_fs();
if (get_user((u32)ctx64, ctx32p))
return -EFAULT;
set_fs(KERNEL_DS);
ret = sys_io_setup(nr_reqs, &ctx64);
set_fs(oldfs);
/* truncating is ok because it's a user address */
if (!ret)
ret = put_user((u32)ctx64, ctx32p);
return ret;
}
long sys_io_getevents(aio_context_t ctx_id, long min_nr, long nr,
struct io_event *events, struct timespec *timeout);
long sys32_io_getevents(aio_context_t ctx_id, u32 min_nr, u32 nr,
struct io_event *events, struct compat_timespec *t32)
{
struct timespec t;
long ret;
mm_segment_t oldfs = get_fs();
if (t32) {
if (get_user(t.tv_sec, &t32->tv_sec) ||
__get_user(t.tv_nsec, &t32->tv_nsec))
return -EFAULT;
}
if (verify_area(VERIFY_WRITE, events, nr * sizeof(*events)))
return -EFAULT;
set_fs(KERNEL_DS);
/* sign extend min_nr and nr */
ret = sys_io_getevents(ctx_id, (int)min_nr, (int)nr, events,
t32 ? &t : NULL);
set_fs(oldfs);
return ret;
}
long sys32_io_submit(aio_context_t ctx_id, u32 number, u32 *iocbpp)
{
struct kioctx *ctx;
long ret = 0;
int i;
int nr = (int)number; /* sign extend */
if (unlikely(nr < 0))
return -EINVAL;
if (unlikely(!access_ok(VERIFY_READ, iocbpp, (nr*sizeof(u32)))))
return -EFAULT;
ctx = lookup_ioctx(ctx_id);
if (unlikely(!ctx)) {
pr_debug("EINVAL: io_submit: invalid context id\n");
return -EINVAL;
}
for (i=0; i<nr; i++) {
struct iocb tmp;
u32 *user_iocb;
if (unlikely(__get_user((u32)(long)user_iocb, iocbpp + i))) {
ret = -EFAULT;
break;
}
if (unlikely(copy_from_user(&tmp, user_iocb, sizeof(tmp)))) {
ret = -EFAULT;
break;
}
ret = io_submit_one(ctx, (struct iocb *)user_iocb, &tmp);
if (ret)
break;
}
put_ioctx(ctx);
return i ? i : ret;
}
int get_compat_timeval(struct timeval *tv, struct compat_timeval *ctv)
{
return (verify_area(VERIFY_READ, ctv, sizeof(*ctv)) ||
......@@ -2878,3 +2786,46 @@ long ppc32_fadvise64(int fd, u32 unused, u32 offset_high, u32 offset_low,
advice);
}
long ppc32_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low,
u32 len_high, u32 len_low)
{
return sys_fadvise64(fd, (u64)offset_high << 32 | offset_low,
(u64)len_high << 32 | len_low, advice);
}
extern long sys_timer_create(clockid_t, sigevent_t *, timer_t *);
long ppc32_timer_create(clockid_t clock,
struct compat_sigevent __user *ev32,
timer_t __user *timer_id)
{
sigevent_t event;
timer_t t;
long err;
mm_segment_t savefs;
if (ev32 == NULL)
return sys_timer_create(clock, NULL, timer_id);
memset(&event, 0, sizeof(event));
if (!access_ok(VERIFY_READ, ev32, sizeof(struct compat_sigevent))
|| __get_user(event.sigev_value.sival_int,
&ev32->sigev_value.sival_int)
|| __get_user(event.sigev_signo, &ev32->sigev_signo)
|| __get_user(event.sigev_notify, &ev32->sigev_notify)
|| __get_user(event.sigev_notify_thread_id,
&ev32->sigev_notify_thread_id))
return -EFAULT;
if (!access_ok(VERIFY_WRITE, timer_id, sizeof(timer_t)))
return -EFAULT;
savefs = get_fs();
err = sys_timer_create(clock, &event, &t);
set_fs(savefs);
if (err == 0)
err = __put_user(t, timer_id);
return err;
}
......@@ -40,12 +40,7 @@
/* These are here to support 32-bit syscalls on a 64-bit kernel. */
typedef union sigval32 {
int sival_int;
unsigned int sival_ptr;
} sigval_t32;
typedef struct siginfo32 {
typedef struct compat_siginfo {
int si_signo;
int si_errno;
int si_code;
......@@ -69,7 +64,7 @@ typedef struct siginfo32 {
struct {
compat_pid_t _pid; /* sender's pid */
compat_uid_t _uid; /* sender's uid */
sigval_t32 _sigval;
compat_sigval_t _sigval;
} _rt;
/* SIGCHLD */
......@@ -92,7 +87,7 @@ typedef struct siginfo32 {
int _fd;
} _sigpoll;
} _sifields;
} siginfo_t32;
} compat_siginfo_t;
#define __old_sigaction32 old_sigaction32
......@@ -134,6 +129,20 @@ struct ucontext32 {
sigset_t uc_sigmask; /* mask last for extensibility */
};
typedef struct compat_sigevent {
compat_sigval_t sigev_value;
int sigev_signo;
int sigev_notify;
union {
int _pad[SIGEV_PAD_SIZE];
int _tid;
struct {
compat_uptr_t _function;
compat_uptr_t _attribute;
} _sigev_thread;
} _sigev_un;
} compat_sigevent_t;
struct ipc_kludge_32 {
unsigned int msgp;
int msgtyp;
......
......@@ -83,5 +83,10 @@ struct compat_dirent {
char d_name[256];
};
typedef union compat_sigval {
compat_int_t sival_int;
compat_uptr_t sival_ptr;
} compat_sigval_t;
#endif /* CONFIG_COMPAT */
#endif /* _LINUX_COMPAT_H */
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