From: Anton Blanchard <anton@samba.org>

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; 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,
 			     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;
+}
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 */

_