Module: xenomai-3
Branch: next
Commit: 367867fafbd9174fec9cfcae06979911e3a78c50
URL:    
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=367867fafbd9174fec9cfcae06979911e3a78c50

Author: Philippe Gerum <r...@xenomai.org>
Date:   Thu Oct 16 14:20:49 2014 +0200

cobalt: fixup generic 32bit syscall support

---

 include/cobalt/kernel/rtdm/fd.h                    |   25 +++++-
 include/cobalt/uapi/syscall.h                      |    2 +-
 kernel/cobalt/Kconfig                              |    3 -
 kernel/cobalt/debug.c                              |   26 +-----
 kernel/cobalt/debug.h                              |    4 +-
 .../cobalt/include/asm-generic/xenomai/syscall.h   |    5 ++
 .../cobalt/include/asm-generic/xenomai/syscall32.h |    6 +-
 kernel/cobalt/posix/syscall.c                      |   88 +++++++++++++++-----
 kernel/cobalt/rtdm/fd.c                            |   45 +++++++++-
 9 files changed, 146 insertions(+), 58 deletions(-)

diff --git a/include/cobalt/kernel/rtdm/fd.h b/include/cobalt/kernel/rtdm/fd.h
index cf47fcb..51609b3 100644
--- a/include/cobalt/kernel/rtdm/fd.h
+++ b/include/cobalt/kernel/rtdm/fd.h
@@ -24,6 +24,7 @@
 #include <linux/socket.h>
 #include <linux/file.h>
 #include <cobalt/kernel/tree.h>
+#include <asm-generic/xenomai/syscall.h>
 
 struct vm_area_struct;
 struct rtdm_fd;
@@ -299,30 +300,48 @@ struct rtdm_fd {
        unsigned int refs;
        int minor;
        int oflags;
+#ifdef CONFIG_COMPAT
+       int compat;
+#endif
        struct list_head cleanup;
 };
 
 #define RTDM_FD_MAGIC 0x52544446
 
+#define RTDM_FD_COMPAT __COBALT_COMPAT_BIT
+#define RTDM_FD_COMPATX        __COBALT_COMPATX_BIT
+
 int __rtdm_anon_getfd(const char *name, int flags);
 
 void __rtdm_anon_putfd(int ufd);
 
-static inline struct cobalt_ppd *rtdm_fd_owner(struct rtdm_fd *fd)
+static inline struct cobalt_ppd *rtdm_fd_owner(const struct rtdm_fd *fd)
 {
        return fd->owner;
 }
 
-static inline int rtdm_fd_minor(struct rtdm_fd *fd)
+static inline int rtdm_fd_minor(const struct rtdm_fd *fd)
 {
        return fd->minor;
 }
 
-static inline int rtdm_fd_flags(struct rtdm_fd *fd)
+static inline int rtdm_fd_flags(const struct rtdm_fd *fd)
 {
        return fd->oflags;
 }
 
+#ifdef CONFIG_COMPAT
+static inline int rtdm_fd_compat(const struct rtdm_fd *fd)
+{
+       return fd->compat;
+}
+#else
+static inline int rtdm_fd_compat(const struct rtdm_fd *fd)
+{
+       return 0;
+}
+#endif
+
 int rtdm_fd_enter(struct rtdm_fd *rtdm_fd, int ufd,
                  unsigned int magic, struct rtdm_fd_ops *ops);
 
diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h
index 59d90e5..aa364a1 100644
--- a/include/cobalt/uapi/syscall.h
+++ b/include/cobalt/uapi/syscall.h
@@ -120,6 +120,6 @@
 #define sc_cobalt_extend                       97
 #define sc_cobalt_sysconf                      98
 
-#define __NR_COBALT_SYSCALLS                   100
+#define __NR_COBALT_SYSCALLS                   128 /* Power of 2 */
 
 #endif /* !_COBALT_UAPI_SYSCALL_H */
diff --git a/kernel/cobalt/Kconfig b/kernel/cobalt/Kconfig
index c4185b2..2e49d37 100644
--- a/kernel/cobalt/Kconfig
+++ b/kernel/cobalt/Kconfig
@@ -257,9 +257,6 @@ config XENO_OPT_VFILE
        depends on PROC_FS
        default y
 
-config XENO_OPT_SYS3264
-       bool
-
 endmenu
 
 menu "Sizes and static limits"
diff --git a/kernel/cobalt/debug.c b/kernel/cobalt/debug.c
index a809dc9..ad72a3e 100644
--- a/kernel/cobalt/debug.c
+++ b/kernel/cobalt/debug.c
@@ -111,7 +111,6 @@ out:
  */
 #define RELAX_SPOTNR   128
 #define RELAX_HSLOTS   (1 << 8)
-#define RELAX_CALLDEPTH        SIGSHADOW_BACKTRACE_DEPTH
 
 struct relax_record {
        /* Number of hits for this location */
@@ -124,7 +123,7 @@ struct relax_record {
                struct backtrace {
                        unsigned long pc;
                        const char *mapname;
-               } backtrace[RELAX_CALLDEPTH];
+               } backtrace[SIGSHADOW_BACKTRACE_DEPTH];
                /* Program hash value of the caller. */
                u32 proghash;
                /* Pid of the caller. */
@@ -201,10 +200,9 @@ void xndebug_notify_relax(struct xnthread *thread, int 
reason)
                          sigshadow_int(SIGSHADOW_ACTION_BACKTRACE, reason));
 }
 
-void xndebug_trace_relax(int nr, unsigned long __user *u_backtrace,
+void xndebug_trace_relax(int nr, unsigned long *backtrace,
                         int reason)
 {
-       unsigned long backtrace[RELAX_CALLDEPTH];
        struct relax_record *p, **h;
        struct vm_area_struct *vma;
        struct xnthread *thread;
@@ -220,25 +218,7 @@ void xndebug_trace_relax(int nr, unsigned long __user 
*u_backtrace,
        thread = xnthread_current();
        if (thread == NULL)
                return;         /* Can't be, right? What a mess. */
-       /*
-        * In case backtrace() in userland is broken or fails. We may
-        * want to know about this in kernel space however, for future
-        * use.
-        */
-       if (nr <= 0)
-               return;
-       /*
-        * We may omit the older frames if we can't store the full
-        * backtrace.
-        */
-       if (nr > RELAX_CALLDEPTH)
-               nr = RELAX_CALLDEPTH;
-       /*
-        * Fetch the backtrace array, filled with PC values as seen
-        * from the relaxing thread in user-space. This can't fail
-        */
-       if (__xn_safe_copy_from_user(backtrace, u_backtrace, nr * sizeof(pc)))
-               return;
+
        /*
         * We compute PC values relative to the base of the shared
         * executable mappings we find in the backtrace, which makes
diff --git a/kernel/cobalt/debug.h b/kernel/cobalt/debug.h
index 6cb6ad5..2af4fcb 100644
--- a/kernel/cobalt/debug.h
+++ b/kernel/cobalt/debug.h
@@ -54,7 +54,7 @@ static inline void xndebug_shadow_init(struct xnthread 
*thread)
 #ifdef CONFIG_XENO_OPT_DEBUG_TRACE_RELAX
 void xndebug_notify_relax(struct xnthread *thread,
                          int reason);
-void xndebug_trace_relax(int nr, unsigned long __user *u_backtrace,
+void xndebug_trace_relax(int nr, unsigned long *backtrace,
                         int reason);
 #else
 static inline
@@ -62,7 +62,7 @@ void xndebug_notify_relax(struct xnthread *thread, int reason)
 {
 }
 static inline
-void xndebug_trace_relax(int nr, unsigned long __user *u_backtrace,
+void xndebug_trace_relax(int nr, unsigned long *backtrace,
                         int reason)
 {
        /* Simply ignore. */
diff --git a/kernel/cobalt/include/asm-generic/xenomai/syscall.h 
b/kernel/cobalt/include/asm-generic/xenomai/syscall.h
index eae4a68..8a00008 100644
--- a/kernel/cobalt/include/asm-generic/xenomai/syscall.h
+++ b/kernel/cobalt/include/asm-generic/xenomai/syscall.h
@@ -65,4 +65,9 @@ static inline int __xn_safe_strncpy_from_user(char *dst,
        return __xn_strncpy_from_user(dst, src, count);
 }
 
+/* 32bit syscall emulation */
+#define __COBALT_COMPAT_BIT    0x1
+/* 32bit syscall emulation - extended form */
+#define __COBALT_COMPATX_BIT   0x2
+
 #endif /* !_COBALT_ASM_GENERIC_SYSCALL_H */
diff --git a/kernel/cobalt/include/asm-generic/xenomai/syscall32.h 
b/kernel/cobalt/include/asm-generic/xenomai/syscall32.h
index 1ffc546..b0c6f4a 100644
--- a/kernel/cobalt/include/asm-generic/xenomai/syscall32.h
+++ b/kernel/cobalt/include/asm-generic/xenomai/syscall32.h
@@ -19,8 +19,12 @@
 #ifndef _COBALT_ASM_GENERIC_SYSCALL32_H
 #define _COBALT_ASM_GENERIC_SYSCALL32_H
 
+#define __COBALT_CALL32_INITHAND(__handler)
+
+#define __COBALT_CALL32_INITMODE(__mode)
+
 #define __COBALT_CALL32_ENTRY(__name, __handler)
 
-#define COBALT_SYSCALL32x_DECL(__name, __type, __args)
+#define __COBALT_CALL_COMPAT(__reg)    0
 
 #endif /* !_COBALT_ASM_GENERIC_SYSCALL32_H */
diff --git a/kernel/cobalt/posix/syscall.c b/kernel/cobalt/posix/syscall.c
index 550f57a..ae879fc 100644
--- a/kernel/cobalt/posix/syscall.c
+++ b/kernel/cobalt/posix/syscall.c
@@ -132,7 +132,7 @@ static int handle_head_syscall(struct ipipe_domain *ipd, 
struct pt_regs *regs)
        }
 
        handler = cobalt_syscalls[nr];
-       sysflags = cobalt_sysmodes[nr];
+       sysflags = cobalt_sysmodes[nr & (__NR_COBALT_SYSCALLS - 1)];
 
        /*
         * Executing Cobalt services requires CAP_SYS_NICE, except for
@@ -313,7 +313,7 @@ static int handle_root_syscall(struct ipipe_domain *ipd, 
struct pt_regs *regs)
        /* Processing a Xenomai syscall. */
 
        handler = cobalt_syscalls[nr];
-       sysflags = cobalt_sysmodes[nr];
+       sysflags = cobalt_sysmodes[nr & (__NR_COBALT_SYSCALLS - 1)];
 
        if ((sysflags & __xn_exec_conforming) != 0)
                sysflags |= (thread ? __xn_exec_histage : __xn_exec_lostage);
@@ -512,7 +512,32 @@ static COBALT_SYSCALL(backtrace, current,
                      int, (int nr, unsigned long __user *u_backtrace,
                            int reason))
 {
-       xndebug_trace_relax(nr, u_backtrace, reason);
+       unsigned long backtrace[SIGSHADOW_BACKTRACE_DEPTH];
+       int ret;
+
+       /*
+        * In case backtrace() in userland is broken or fails. We may
+        * want to know about this in kernel space however, for future
+        * use.
+        */
+       if (nr <= 0)
+               return 0;
+       /*
+        * We may omit the older frames if we can't store the full
+        * backtrace.
+        */
+       if (nr > SIGSHADOW_BACKTRACE_DEPTH)
+               nr = SIGSHADOW_BACKTRACE_DEPTH;
+       /*
+        * Fetch the backtrace array, filled with PC values as seen
+        * from the relaxing thread in user-space. This can't fail
+        */
+       ret = __xn_safe_copy_from_user(backtrace, u_backtrace, nr * 
sizeof(long));
+       if (ret)
+               return ret;
+
+       xndebug_trace_relax(nr, backtrace, reason);
+
        return 0;
 }
 
@@ -722,17 +747,17 @@ static int cobalt_ni(void)
  * returning -ENOSYS, as the table may be sparse.
  *
  * - then __COBALT_CALL_ENTRY() produces a native call entry
- * (e.g. pure 64bit call handler for a 64bit architecture), and
- * optionally a set of 32bit syscall entries offset by an
+ * (e.g. pure 64bit call handler for a 64bit architecture), optionally
+ * followed by a set of 32bit syscall entries offset by an
  * arch-specific base index, which default to the native calls. These
- * nitty-gritty details are defined by <asm/xenomai/syscall32.h>. 32bit
- * architectures - or 64bit ones for which we don't support any 32bit
- * ABI model - will simply define __COBALT_CALL32_ENTRY() as an empty
- * macro.
+ * nitty-gritty details are defined by
+ * <asm/xenomai/syscall32.h>. 32bit architectures - or 64bit ones for
+ * which we don't support any 32bit ABI model - will simply define
+ * __COBALT_CALL32_ENTRY() as an empty macro.
  *
- * - finally, pure 32bit call entries are generated per-architecture,
- * by including <asm/xenomai/syscall32-table.h>, overriding the
- * default handlers installed during the previous step.
+ * - finally, 32bit thunk entries are generated per-architecture, by
+ * including <asm/xenomai/syscall32-table.h>, overriding the default
+ * handlers installed during the previous step.
  *
  * For instance, with CONFIG_X86_X32 support enabled in an x86_64
  * kernel, sc_cobalt_mq_timedreceive would appear twice in the table,
@@ -744,7 +769,7 @@ static int cobalt_ni(void)
  *
  * cobalt32x_mq_timedreceive() would do the required thunking for
  * dealing with the 32<->64bit conversion of arguments. On the other
- * hand, sc_cobalt_sched_yield - which do not require any thunking -
+ * hand, sc_cobalt_sched_yield - which do not require any thunk -
  * would also appear twice, but both entries would point at the native
  * syscall implementation:
  *
@@ -762,21 +787,38 @@ static int cobalt_ni(void)
  * routines it may need for handing 32bit calls over their respective
  * 64bit implementation.
  *
- * By convention, there is NO 32bit-specific syscall, which means that
+ * By convention, there is NO pure 32bit syscall, which means that
  * each 32bit syscall defined by a compat ABI interface MUST match a
  * native (64bit) syscall. This is important as we share the call
  * modes (i.e. __xn_exec_ bits) between all ABI models.
  *
  * --rpm
  */
-#define __syshand__(__name)            ((cobalt_syshand)(cobalt_ ## __name))
-#define __COBALT_CALL_ENTRY(__name)    [sc_cobalt_ ## __name] = 
__syshand__(__name)    \
-                                       __COBALT_CALL32_ENTRY(__name, 
__syshand__(__name))
-#define __COBALT_MODE(__name, __mode)  [sc_cobalt_ ## __name] = 
__xn_exec_##__mode
-#define __COBALT_NI                    __syshand__(ni)
+#define __syshand__(__name)    ((cobalt_syshand)(cobalt_ ## __name))
+
+#define __COBALT_NI    __syshand__(ni)
+
+#define __COBALT_CALL_NI                               \
+       [0 ... __NR_COBALT_SYSCALLS-1] = __COBALT_NI    \
+       __COBALT_CALL32_INITHAND(__COBALT_NI)
+
+#define __COBALT_CALL_NFLAGS                           \
+       [0 ... __NR_COBALT_SYSCALLS-1] = 0              \
+       __COBALT_CALL32_INITMODE(0)
+
+#define __COBALT_CALL_ENTRY(__name)                            \
+       [sc_cobalt_ ## __name] = __syshand__(__name)            \
+       __COBALT_CALL32_ENTRY(__name, __syshand__(__name))
+
+#define __COBALT_MODE(__name, __mode)  \
+       [sc_cobalt_ ## __name] = __xn_exec_##__mode
+
+#ifdef CONFIG_XENO_ARCH_SYS3264
+#include "syscall32.h"
+#endif 
 
 static const cobalt_syshand cobalt_syscalls[] = {
-       [0 ... __NR_COBALT_SYSCALLS-1] = __COBALT_NI,
+       __COBALT_CALL_NI,
        __COBALT_CALL_ENTRY(thread_create),
        __COBALT_CALL_ENTRY(thread_getpid),
        __COBALT_CALL_ENTRY(thread_setschedparam_ex),
@@ -873,14 +915,14 @@ static const cobalt_syshand cobalt_syscalls[] = {
        __COBALT_CALL_ENTRY(backtrace),
        __COBALT_CALL_ENTRY(serialdbg),
        __COBALT_CALL_ENTRY(sysconf),
-       __COBALT_CALL_ENTRY(sysctl),
-#ifdef CONFIG_XENO_OPT_SYS3264
+       __COBALT_CALL_ENTRY(sysctl)
+#ifdef CONFIG_XENO_ARCH_SYS3264
 #include <asm/xenomai/syscall32-table.h>
 #endif 
 };
 
 static const int cobalt_sysmodes[] = {
-       [0 ... __NR_COBALT_SYSCALLS-1] = 0,
+       __COBALT_CALL_NFLAGS,
        __COBALT_MODE(thread_create, init),
        __COBALT_MODE(thread_getpid, current),
        __COBALT_MODE(thread_setschedparam_ex, conforming),
diff --git a/kernel/cobalt/rtdm/fd.c b/kernel/cobalt/rtdm/fd.c
index f75c7e5..61ace15 100644
--- a/kernel/cobalt/rtdm/fd.c
+++ b/kernel/cobalt/rtdm/fd.c
@@ -31,6 +31,7 @@
 #include <rtdm/fd.h>
 #include "internal.h"
 #include "posix/process.h"
+#include "posix/syscall.h"
 
 DEFINE_PRIVATE_XNLOCK(fdtree_lock);
 static LIST_HEAD(rtdm_fd_cleanup_queue);
@@ -115,6 +116,29 @@ static struct rtdm_fd *fetch_fd(struct cobalt_ppd *p, int 
ufd)
                }                                                       \
        while (0)
 
+#ifdef CONFIG_COMPAT
+
+static inline void set_compat_bit(struct rtdm_fd *fd)
+{
+       struct pt_regs *regs;
+
+       if (cobalt_ppd_get(0) == &__xnsys_global_ppd)
+               fd->compat = 0;
+       else {
+               regs = task_pt_regs(current);
+               XENO_BUGON(COBALT, !__xn_syscall_p(regs));
+               fd->compat = __COBALT_CALL_COMPAT(__xn_reg_sys(regs));
+       }
+}
+
+#else  /* !CONFIG_COMPAT */
+
+static inline void set_compat_bit(struct rtdm_fd *fd)
+{
+}
+
+#endif /* !CONFIG_COMPAT */
+
 int rtdm_fd_enter(struct rtdm_fd *fd, int ufd, unsigned int magic,
                  struct rtdm_fd_ops *ops)
 {
@@ -146,6 +170,7 @@ int rtdm_fd_enter(struct rtdm_fd *fd, int ufd, unsigned int 
magic,
        fd->ops = ops;
        fd->owner = ppd;
        fd->refs = 1;
+       set_compat_bit(fd);
 
        idx->fd = fd;
 
@@ -332,8 +357,8 @@ EXPORT_SYMBOL_GPL(rtdm_fd_unlock);
 
 int rtdm_fd_ioctl(int ufd, unsigned int request, ...)
 {
-       void __user *arg;
        struct rtdm_fd *fd;
+       void __user *arg;
        va_list args;
        int err, ret;
 
@@ -347,6 +372,8 @@ int rtdm_fd_ioctl(int ufd, unsigned int request, ...)
                goto out;
        }
 
+       set_compat_bit(fd);
+
        trace_cobalt_fd_ioctl(current, fd, ufd, request);
 
        if (ipipe_root_p)
@@ -384,6 +411,8 @@ rtdm_fd_read(int ufd, void __user *buf, size_t size)
                goto out;
        }
 
+       set_compat_bit(fd);
+
        trace_cobalt_fd_read(current, fd, ufd, size);
 
        if (ipipe_root_p)
@@ -415,6 +444,8 @@ ssize_t rtdm_fd_write(int ufd, const void __user *buf, 
size_t size)
                goto out;
        }
 
+       set_compat_bit(fd);
+
        trace_cobalt_fd_write(current, fd, ufd, size);
 
        if (ipipe_root_p)
@@ -446,6 +477,8 @@ ssize_t rtdm_fd_recvmsg(int ufd, struct msghdr *msg, int 
flags)
                goto out;
        }
 
+       set_compat_bit(fd);
+
        trace_cobalt_fd_recvmsg(current, fd, ufd, flags);
 
        if (ipipe_root_p)
@@ -454,7 +487,7 @@ ssize_t rtdm_fd_recvmsg(int ufd, struct msghdr *msg, int 
flags)
                err = fd->ops->recvmsg_rt(fd, msg, flags);
 
        if (!XENO_ASSERT(COBALT, !spltest()))
-                   splnone();
+               splnone();
 
        rtdm_fd_put(fd);
 out:
@@ -476,6 +509,8 @@ ssize_t rtdm_fd_sendmsg(int ufd, const struct msghdr *msg, 
int flags)
                goto out;
        }
 
+       set_compat_bit(fd);
+
        trace_cobalt_fd_sendmsg(current, fd, ufd, flags);
 
        if (ipipe_root_p)
@@ -527,6 +562,8 @@ ebadf:
                return -EBADF;
        }
 
+       set_compat_bit(fd);
+
        trace_cobalt_fd_close(current, fd, ufd, fd->refs);
 
        /*
@@ -557,6 +594,8 @@ int rtdm_fd_mmap(int ufd, struct _rtdm_mmap_request *rma,
                goto out;
        }
 
+       set_compat_bit(fd);
+
        trace_cobalt_fd_mmap(current, fd, ufd, rma);
 
        if (rma->flags & (MAP_FIXED|MAP_ANONYMOUS)) {
@@ -616,6 +655,8 @@ int rtdm_fd_select(int ufd, struct xnselector *selector,
        if (IS_ERR(fd))
                return PTR_ERR(fd);
 
+       set_compat_bit(fd);
+
        rc = fd->ops->select(fd, selector, type, ufd);
 
        if (!XENO_ASSERT(COBALT, !spltest()))


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to