From: Anton Blanchard Here are a number of updates for the 32bit compat layer from Paul, Olaf and myself. - Switch to using the new compat aio syscalls - add compat timer/clock syscalls - use compat_statfs64 - add compat fadvise64_64 arch/ppc64/kernel/misc.S | 30 ++++----- arch/ppc64/kernel/signal32.c | 14 ++-- arch/ppc64/kernel/sys_ppc32.c | 135 +++++++++++++----------------------------- include/asm-ppc64/ppc32.h | 25 +++++-- include/linux/compat.h | 5 + 5 files changed, 88 insertions(+), 121 deletions(-) diff -puN arch/ppc64/kernel/misc.S~ppc64-32bit-compat-update arch/ppc64/kernel/misc.S --- 25/arch/ppc64/kernel/misc.S~ppc64-32bit-compat-update 2003-12-31 01:42:27.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/misc.S 2003-12-31 01:42:27.000000000 -0800 @@ -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 */ diff -puN arch/ppc64/kernel/signal32.c~ppc64-32bit-compat-update arch/ppc64/kernel/signal32.c --- 25/arch/ppc64/kernel/signal32.c~ppc64-32bit-compat-update 2003-12-31 01:42:27.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/signal32.c 2003-12-31 01:42:27.000000000 -0800 @@ -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 } -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(siginf 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 -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 * (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); diff -puN arch/ppc64/kernel/sys_ppc32.c~ppc64-32bit-compat-update arch/ppc64/kernel/sys_ppc32.c --- 25/arch/ppc64/kernel/sys_ppc32.c~ppc64-32bit-compat-update 2003-12-31 01:42:27.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/sys_ppc32.c 2003-12-31 01:42:27.000000000 -0800 @@ -2683,98 +2683,6 @@ unsigned long sys32_mmap2(unsigned long 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; isigev_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; +} diff -puN include/asm-ppc64/ppc32.h~ppc64-32bit-compat-update include/asm-ppc64/ppc32.h --- 25/include/asm-ppc64/ppc32.h~ppc64-32bit-compat-update 2003-12-31 01:42:27.000000000 -0800 +++ 25-akpm/include/asm-ppc64/ppc32.h 2003-12-31 01:42:27.000000000 -0800 @@ -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; diff -puN include/linux/compat.h~ppc64-32bit-compat-update include/linux/compat.h --- 25/include/linux/compat.h~ppc64-32bit-compat-update 2003-12-31 01:42:27.000000000 -0800 +++ 25-akpm/include/linux/compat.h 2003-12-31 01:42:27.000000000 -0800 @@ -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 */ _