Commit 2b748116 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ppc64: 32/64bit emulation for aio

From: Anton Blanchard <anton@samba.org>

PPC64 32/64-bit emulation for AIO.
parent 276df1b2
...@@ -735,11 +735,11 @@ _GLOBAL(sys_call_table32) ...@@ -735,11 +735,11 @@ _GLOBAL(sys_call_table32)
.llong .sys_ni_syscall .llong .sys_ni_syscall
.llong .sys_ni_syscall /* 225 - reserved for tux */ .llong .sys_ni_syscall /* 225 - reserved for tux */
.llong .sys32_sendfile64 .llong .sys32_sendfile64
.llong .sys_ni_syscall /* reserved for sys_io_setup */ .llong .sys32_io_setup
.llong .sys_ni_syscall /* reserved for sys_io_destroy */ .llong .sys_io_destroy
.llong .sys_ni_syscall /* reserved for sys_io_getevents */ .llong .sys32_io_getevents
.llong .sys_ni_syscall /* 230 - reserved for sys_io_submit */ .llong .sys32_io_submit
.llong .sys_ni_syscall /* reserved for sys_io_cancel */ .llong .sys_io_cancel
.llong .sys_set_tid_address .llong .sys_set_tid_address
.llong .ppc32_fadvise64 .llong .ppc32_fadvise64
.llong .sys_exit_group .llong .sys_exit_group
......
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
#include <linux/security.h> #include <linux/security.h>
#include <linux/compat.h> #include <linux/compat.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/aio_abi.h>
#include <asm/types.h> #include <asm/types.h>
#include <asm/ipc.h> #include <asm/ipc.h>
...@@ -2643,6 +2644,98 @@ unsigned long sys32_mmap2(unsigned long addr, size_t len, ...@@ -2643,6 +2644,98 @@ unsigned long sys32_mmap2(unsigned long addr, size_t len,
return sys_mmap(addr, len, prot, flags, fd, pgoff << 12); 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(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, user_iocb, &tmp);
if (ret)
break;
}
put_ioctx(ctx);
return i ? i : ret;
}
/* /*
* long long munging: * long long munging:
* The 32 bit ABI passes long longs in an odd even register pair. * The 32 bit ABI passes long longs in an odd even register pair.
......
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