aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2014-03-03 10:06:12 +0100
committerHeiko Carstens <heiko.carstens@de.ibm.com>2014-03-04 09:12:25 +0100
commitc2e7c3d0ef0d1a3765792a35ae9e6f91a3025214 (patch)
tree8351238e290456d0a9f02368f512b3a9fad037ba
parentab4f8bba19323eb78b7473df42b225eb14090fcc (diff)
downloadlinux-stericsson-c2e7c3d0ef0d1a3765792a35ae9e6f91a3025214.tar.gz
s390/compat: partial parameter conversion within syscall wrappers
Parameter conversion within the system call wrappers is only needed for parameters which differ in size and have a size of eight bytes on 64 bit. For system call parameters with a size of less than eight byte the called system call itself will perform parameter conversion anyway. So we can save the double conversion of e.g. int parameters. The only types which need to be converted are therefore pointer and (unsigned) long parameters. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
-rw-r--r--arch/s390/kernel/compat_wrap.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/arch/s390/kernel/compat_wrap.c b/arch/s390/kernel/compat_wrap.c
index d6a2cac1af12..d123f5d87b82 100644
--- a/arch/s390/kernel/compat_wrap.c
+++ b/arch/s390/kernel/compat_wrap.c
@@ -15,6 +15,9 @@
#define COMPAT_SYSCALL_WRAP6(name, ...) \
COMPAT_SYSCALL_WRAPx(6, _##name, __VA_ARGS__)
+#define __SC_COMPAT_TYPE(t, a) \
+ __typeof(__builtin_choose_expr(sizeof(t) > 4, 0L, (t)0)) a
+
#define __SC_COMPAT_CAST(t, a) \
({ \
long __ReS = a; \
@@ -30,10 +33,22 @@
(t)__ReS; \
})
+/*
+ * The COMPAT_SYSCALL_WRAP macro generates system call wrappers to be used by
+ * compat tasks. These wrappers will only be used for system calls where only
+ * the system call arguments need sign or zero extension or zeroing of the upper
+ * 33 bits of pointers.
+ * Note: since the wrapper function will afterwards call a system call which
+ * again performs zero and sign extension for all system call arguments with
+ * a size of less than eight bytes, these compat wrappers only touch those
+ * system call arguments with a size of eight bytes ((unsigned) long and
+ * pointers). Zero and sign extension for e.g. int parameters will be done by
+ * the regular system call wrappers.
+ */
#define COMPAT_SYSCALL_WRAPx(x, name, ...) \
asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \
- asmlinkage long compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \
- asmlinkage long compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \
+ asmlinkage long compat_sys##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__));\
+ asmlinkage long compat_sys##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__)) \
{ \
return sys##name(__MAP(x,__SC_COMPAT_CAST,__VA_ARGS__)); \
}