]> git.hungrycats.org Git - linux/commitdiff
[PATCH] ia64: epoll support for ia32 applications
authorArun Sharma <arun.sharma@intel.com>
Thu, 7 Aug 2003 16:31:18 +0000 (09:31 -0700)
committerDavid Mosberger <davidm@tiger.hpl.hp.com>
Thu, 7 Aug 2003 16:31:18 +0000 (09:31 -0700)
The patch was created by Matt Helsley <matthltc at us.ibm.com> for 2.4 and
has been changed slightly to match 2.6.

The implementation compromises performance for correctness.

arch/ia64/ia32/ia32_entry.S
arch/ia64/ia32/sys_ia32.c

index 17ec2150ffbeffdf1b71b570a7716d6d5a5a7b14..f0aa315d87986c06b6e13a833aef6744f69d272b 100644 (file)
@@ -440,9 +440,9 @@ ia32_syscall_table:
        data8 sys_ni_syscall
        data8 sys_ni_syscall
        data8 sys_ni_syscall
-       data8 sys_ni_syscall
-       data8 sys_ni_syscall    /*255*/
-       data8 sys_ni_syscall
+       data8 sys_epoll_create
+       data8 sys32_epoll_ctl   /* 255 */
+       data8 sys32_epoll_wait
        data8 sys_ni_syscall
        data8 sys_ni_syscall
        data8 sys_ni_syscall
index 8d7fd9458f34139f2fc1866e220b4aa2b4926f56..1ca997cf8aa94f362a9245cc4d1987c40b76eac7 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/nfsd/xdr.h>
 #include <linux/nfsd/syscall.h>
 #include <linux/poll.h>
+#include <linux/eventpoll.h>
 #include <linux/personality.h>
 #include <linux/ptrace.h>
 #include <linux/stat.h>
@@ -2704,6 +2705,95 @@ out_error:
        goto out;
 }
 
+/* Structure for ia32 emulation on ia64 */
+struct epoll_event32
+{
+       u32 events;
+       u64 data;
+} __attribute__((packed));
+
+asmlinkage long
+sys32_epoll_ctl(int epfd, int op, int fd, struct epoll_event32 *event)
+{
+       mm_segment_t old_fs = get_fs();
+       struct epoll_event event64;
+       int error = -EFAULT;
+       u32 data_halfword;
+
+       if ((error = verify_area(VERIFY_READ, event,
+                                sizeof(struct epoll_event32))))
+               return error;
+
+       __get_user(event64.events, &event->events);
+       __get_user(data_halfword, (u32*)(&event->data));
+       event64.data = data_halfword;
+       __get_user(data_halfword, ((u32*)(&event->data) + 1));
+       event64.data |= ((u64)data_halfword) << 32;
+
+       set_fs(KERNEL_DS);
+       error = sys_epoll_ctl(epfd, op, fd, &event64);
+       set_fs(old_fs);
+
+       return error;
+}
+
+asmlinkage long
+sys32_epoll_wait(int epfd, struct epoll_event32 *events, int maxevents,
+                int timeout)
+{
+       struct epoll_event *events64 = NULL;
+       mm_segment_t old_fs = get_fs();
+       int error;
+       int evt_idx;
+
+       if (maxevents <= 0) {
+               return -EINVAL;
+       }
+
+       /* Verify that the area passed by the user is writeable */
+       if ((error = verify_area(VERIFY_WRITE, events,
+                                maxevents * sizeof(struct epoll_event32))))
+               return error;
+
+       /* Allocate the space needed for the intermediate copy */
+       events64 = kmalloc(maxevents * sizeof(struct epoll_event), GFP_KERNEL);
+       if (events64 == NULL) {
+               return -ENOMEM;
+       }
+
+       /* Expand the 32-bit structures into the 64-bit structures */
+       for (evt_idx = 0; evt_idx < maxevents; evt_idx++) {
+               u32 data_halfword;
+               __get_user(events64[evt_idx].events, &events[evt_idx].events);
+               __get_user(data_halfword, (u32*)(&events[evt_idx].data));
+               events64[evt_idx].data = data_halfword;
+               __get_user(data_halfword, ((u32*)(&events[evt_idx].data) + 1));
+               events64[evt_idx].data |= ((u64)data_halfword) << 32;
+       }
+
+       /* Do the system call */
+       set_fs(KERNEL_DS); /* copy_to/from_user should work on kernel mem*/
+       error = sys_epoll_wait(epfd, events64, maxevents, timeout);
+       set_fs(old_fs);
+
+       /* Don't modify userspace memory if we're returning an error */
+       if (!error) {
+               /* Translate the 64-bit structures back into the 32-bit
+                  structures */
+               for (evt_idx = 0; evt_idx < maxevents; evt_idx++) {
+                       __put_user(events64[evt_idx].events,
+                                  &events[evt_idx].events);
+                       __put_user((u32)(events64[evt_idx].data),
+                                  (u32*)(&events[evt_idx].data));
+                       __put_user((u32)(events64[evt_idx].data >> 32),
+                                  ((u32*)(&events[evt_idx].data) + 1));
+               }
+       }
+
+       kfree(events64);
+       return error;
+}
+
 #ifdef NOTYET  /* UNTESTED FOR IA64 FROM HERE DOWN */
 
 struct ncp_mount_data32 {