patch-2.4.2 linux/include/asm-s390x/uaccess.h

Next file: linux/include/asm-s390x/ucontext.h
Previous file: linux/include/asm-s390x/types.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/uaccess.h linux/include/asm-s390x/uaccess.h
@@ -0,0 +1,559 @@
+/*
+ *  include/asm-s390/uaccess.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Hartmut Penner (hpenner@de.ibm.com),
+ *               Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *
+ *  Derived from "include/asm-i386/uaccess.h"
+ */
+#ifndef __S390_UACCESS_H
+#define __S390_UACCESS_H
+
+/*
+ * User space memory access functions
+ */
+#include <linux/sched.h>
+
+#define VERIFY_READ     0
+#define VERIFY_WRITE    1
+
+
+/*
+ * The fs value determines whether argument validity checking should be
+ * performed or not.  If get_fs() == USER_DS, checking is performed, with
+ * get_fs() == KERNEL_DS, checking is bypassed.
+ *
+ * For historical reasons, these macros are grossly misnamed.
+ */
+
+#define MAKE_MM_SEG(s)	((mm_segment_t) { (s) })
+
+
+#define KERNEL_DS	MAKE_MM_SEG(0)
+#define USER_DS		MAKE_MM_SEG(1)
+
+#define get_ds()	(KERNEL_DS)
+#define get_fs()	(current->addr_limit)
+#define set_fs(x)       ({asm volatile("sar   4,%0"::"a" ((x).ar4));\
+                          current->addr_limit = (x);})
+
+#define segment_eq(a,b)	((a).ar4 == (b).ar4)
+
+
+#define __access_ok(addr,size) (1)
+
+#define access_ok(type,addr,size) __access_ok(addr,size)
+
+extern inline int verify_area(int type, const void * addr, unsigned long size)
+{
+        return access_ok(type,addr,size)?0:-EFAULT;
+}
+
+/*
+ * The exception table consists of pairs of addresses: the first is the
+ * address of an instruction that is allowed to fault, and the second is
+ * the address at which the program should continue.  No registers are
+ * modified, so it is entirely up to the continuation code to figure out
+ * what to do.
+ *
+ * All the routines below use bits of fixup code that are out of line
+ * with the main instruction path.  This means when everything is well,
+ * we don't even have to jump over them.  Further, they do not intrude
+ * on our cache or tlb entries.
+ */
+
+struct exception_table_entry
+{
+        unsigned long insn, fixup;
+};
+
+/* Returns 0 if exception not found and fixup otherwise.  */
+extern unsigned long search_exception_table(unsigned long);
+
+
+/*
+ * These are the main single-value transfer routines.  They automatically
+ * use the right size if we just have the right pointer type.
+ */
+
+extern inline int __put_user_asm_8(__u64 x, void *ptr)
+{
+        int err;
+
+        __asm__ __volatile__ (  "   sr    %1,%1\n"
+				"   la    4,%0\n"
+                                "   sacf  512\n"
+                                "0: stg   %2,0(4)\n"
+                                "1: sacf  0\n"
+				".section .fixup,\"ax\"\n"
+				"2: lhi   %1,%h3\n"
+				"   jg    1b\n"
+				".previous\n"
+				".section __ex_table,\"a\"\n"
+				"   .align 8\n"
+				"   .quad  0b,2b\n"
+				".previous"
+                                : "=m" (*((__u64*) ptr)) , "=&d" (err)
+                                : "d" (x), "K" (-EFAULT)
+                                : "4" );
+        return err;
+}
+extern inline int __put_user_asm_4(__u32 x, void *ptr)
+{
+        int err;
+
+        __asm__ __volatile__ (  "   sr    %1,%1\n"
+				"   la    4,%0\n"
+                                "   sacf  512\n"
+                                "0: st    %2,0(4)\n"
+                                "1: sacf  0\n"
+				".section .fixup,\"ax\"\n"
+				"2: lhi   %1,%h3\n"
+				"   jg    1b\n"
+				".previous\n"
+				".section __ex_table,\"a\"\n"
+				"   .align 8\n"
+				"   .quad  0b,2b\n"
+				".previous"
+                                : "=m" (*((__u32*) ptr)) , "=&d" (err)
+                                : "d" (x), "K" (-EFAULT)
+                                : "4" );
+        return err;
+}
+
+extern inline int __put_user_asm_2(__u16 x, void *ptr)
+{
+        int err;
+
+        __asm__ __volatile__ (  "   sr    %1,%1\n"
+				"   la    4,%0\n"
+                                "   sacf  512\n"
+                                "0: sth   %2,0(4)\n"
+                                "1: sacf  0\n"
+				".section .fixup,\"ax\"\n"
+				"2: lhi   %1,%h3\n"
+				"   jg    1b\n"
+				".previous\n"
+				".section __ex_table,\"a\"\n"
+				"   .align 8\n"
+				"   .quad  0b,2b\n"
+				".previous"
+                                : "=m" (*((__u16*) ptr)) , "=&d" (err)
+                                : "d" (x), "K" (-EFAULT)
+                                : "4" );
+        return err;
+}
+
+extern inline int __put_user_asm_1(__u8 x, void *ptr)
+{
+        int err;
+
+        __asm__ __volatile__ (  "   sr    %1,%1\n"
+				"   la    4,%0\n"
+                                "   sacf  512\n"
+                                "0: stc   %2,0(4)\n"
+                                "1: sacf  0\n"
+				".section .fixup,\"ax\"\n"
+				"2: lhi   %1,%h3\n"
+				"   jg    1b\n"
+				".previous\n"
+				".section __ex_table,\"a\"\n"
+				"   .align 8\n"
+				"   .quad  0b,2b\n"
+				".previous"
+                                : "=m" (*((__u8*) ptr)) , "=&d" (err)
+                                : "d" (x), "K" (-EFAULT)
+                                : "1", "4" );
+        return err;
+}
+
+/*
+ * (u?)(u64) ... autsch, but that the only way we can suppress the
+ * warnings when compiling binfmt_elf.c
+ */
+#define __put_user(x, ptr)                                      \
+({                                                              \
+        int __pu_err;                                           \
+        switch (sizeof (*(ptr))) {                              \
+                case 1:                                         \
+                        __pu_err = __put_user_asm_1((__u8)(__u64)(x),(ptr));\
+                        break;                                  \
+                case 2:                                         \
+                        __pu_err = __put_user_asm_2((__u16)(__u64)(x),(ptr));\
+                        break;                                  \
+                case 4:                                         \
+                        __pu_err = __put_user_asm_4((__u32)(__u64)(x),(ptr));\
+                        break;                                  \
+                case 8:                                         \
+                        __pu_err = __put_user_asm_8((__u64)(x),(ptr));\
+                        break;                                  \
+                default:                                        \
+                __pu_err = __put_user_bad();                    \
+                break;                                          \
+         }                                                      \
+        __pu_err;                                               \
+})
+
+#define put_user(x, ptr)                                        \
+({                                                              \
+        long __pu_err = -EFAULT;                                \
+        __typeof__(*(ptr)) *__pu_addr = (ptr);                  \
+        __typeof__(*(ptr)) __x = (x);                           \
+        if (__access_ok((long)__pu_addr,sizeof(*(ptr)))) {      \
+                __pu_err = 0;                                   \
+                __put_user((__x), (__pu_addr));                 \
+        }                                                       \
+        __pu_err;                                               \
+})
+
+extern int __put_user_bad(void);
+
+
+#define __get_user_asm_8(x, ptr, err)                                      \
+({                                                                         \
+        __asm__ __volatile__ (  "   sr    %1,%1\n"                         \
+                                "   la    4,%2\n"                          \
+                                "   sacf  512\n"                           \
+                                "0: lg    %0,0(4)\n"                       \
+                                "1: sacf  0\n"                             \
+                                ".section .fixup,\"ax\"\n"                 \
+                                "2: lhi   %1,%h3\n"                        \
+                                "   jg    1b\n"                            \
+                                ".previous\n"                              \
+                                ".section __ex_table,\"a\"\n"              \
+                                "   .align 8\n"                            \
+                                "   .quad 0b,2b\n"                         \
+                                ".previous"                                \
+                                : "=d" (x) , "=&d" (err)                   \
+                                : "m" (*(const __u64*)(ptr)),"K" (-EFAULT) \
+                                : "4" );                                   \
+})
+#define __get_user_asm_4(x, ptr, err)                                      \
+({                                                                         \
+        __asm__ __volatile__ (  "   sr    %1,%1\n"                         \
+                                "   la    4,%2\n"                          \
+                                "   sacf  512\n"                           \
+                                "0: l     %0,0(4)\n"                       \
+                                "1: sacf  0\n"                             \
+                                ".section .fixup,\"ax\"\n"                 \
+                                "2: lhi   %1,%h3\n"                        \
+                                "   jg    1b\n"                            \
+                                ".previous\n"                              \
+                                ".section __ex_table,\"a\"\n"              \
+                                "   .align 8\n"                            \
+                                "   .quad 0b,2b\n"                         \
+                                ".previous"                                \
+                                : "=d" (x) , "=&d" (err)                   \
+                                : "m" (*(const __u32*)(ptr)),"K" (-EFAULT) \
+                                : "4" );                                   \
+})
+
+#define __get_user_asm_2(x, ptr, err)                                      \
+({                                                                         \
+        __asm__ __volatile__ (  "   sr    %1,%1\n"                         \
+                                "   la    4,%2\n"                          \
+                                "   sacf  512\n"                           \
+                                "0: lh    %0,0(4)\n"                       \
+                                "1: sacf  0\n"                             \
+                                ".section .fixup,\"ax\"\n"                 \
+                                "2: lhi   %1,%h3\n"                        \
+                                "   jg    1b\n"                            \
+                                ".previous\n"                              \
+                                ".section __ex_table,\"a\"\n"              \
+                                "   .align 8\n"                            \
+                                "   .quad 0b,2b\n"                         \
+                                ".previous"                                \
+                                : "=d" (x) , "=&d" (err)                   \
+                                : "m" (*(const __u16*)(ptr)),"K" (-EFAULT) \
+                                : "4" );                                   \
+})
+
+#define __get_user_asm_1(x, ptr, err)                                     \
+({                                                                        \
+        __asm__ __volatile__ (  "   sr    %1,%1\n"                        \
+                                "   la    4,%2\n"                         \
+                                "   sr    %0,%0\n"                        \
+                                "   sacf  512\n"                          \
+                                "0: ic    %0,0(4)\n"                      \
+                                "1: sacf  0\n"                            \
+                                ".section .fixup,\"ax\"\n"                \
+                                "2: lhi   %1,%h3\n"                       \
+                                "   jg    1b\n"                           \
+                                ".previous\n"                             \
+                                ".section __ex_table,\"a\"\n"             \
+                                "   .align 8\n"                           \
+                                "   .quad 0b,2b\n"                        \
+                                ".previous"                               \
+                                : "=d" (x) , "=&d" (err)                  \
+                                : "m" (*(const __u8*)(ptr)),"K" (-EFAULT) \
+                                : "4" );                                  \
+})
+
+#define __get_user(x, ptr)                                      \
+({                                                              \
+        int __gu_err;                                           \
+        switch (sizeof(*(ptr))) {                               \
+                case 1:                                         \
+                        __get_user_asm_1(x,ptr,__gu_err);       \
+                        break;                                  \
+                case 2:                                         \
+                        __get_user_asm_2(x,ptr,__gu_err);       \
+                        break;                                  \
+                case 4:                                         \
+                        __get_user_asm_4(x,ptr,__gu_err);       \
+                        break;                                  \
+                case 8:                                         \
+                        __get_user_asm_8(x,ptr,__gu_err);       \
+                        break;                                  \
+                default:                                        \
+                        (x) = 0;                                \
+                        __gu_err = __get_user_bad();            \
+                break;                                          \
+        }                                                       \
+        __gu_err;                                               \
+})
+
+#define get_user(x, ptr)                                        \
+({                                                              \
+        long __gu_err = -EFAULT;                                \
+        __typeof__(ptr) __gu_addr = (ptr);                      \
+        __typeof__(*(ptr)) __x;                                 \
+        if (__access_ok((long)__gu_addr,sizeof(*(ptr)))) {      \
+                __gu_err = 0;                                   \
+                __get_user((__x), (__gu_addr));                 \
+                (x) = __x;                                      \
+        }                                                       \
+        else                                                    \
+                (x) = 0;                                        \
+        __gu_err;                                               \
+})
+
+extern int __get_user_bad(void);
+
+/*
+ * access register are set up, that 4 points to secondary (user) , 2 to primary (kernel)
+ */
+
+asmlinkage void __copy_from_user_fixup(void /* special calling convention */);
+asmlinkage void __copy_to_user_fixup(void /* special calling convention */);
+
+extern inline unsigned long
+__copy_to_user_asm(void* to, const void* from,  long n)
+{
+
+        __asm__ __volatile__ (  "   lgr   2,%2\n"
+                                "   lgr   4,%1\n"
+                                "   lgr   3,%0\n"
+                                "   lgr   5,3\n"
+                                "   sacf  512\n"
+                                "0: mvcle 4,2,0\n"
+                                "   jo    0b\n"
+                                "   sacf  0\n"
+                                "   lgr   %0,3\n"
+				".section __ex_table,\"a\"\n"
+				"   .align 8\n"
+				"   .quad  0b,__copy_to_user_fixup\n"
+				".previous"
+                                : "+&d" (n) : "d" (to), "d" (from)
+                                : "1", "2", "3", "4", "5" );
+        return n;
+}
+
+#define __copy_to_user(to, from, n)                             \
+({                                                              \
+        __copy_to_user_asm(to,from,n);                          \
+})
+
+#define copy_to_user(to, from, n)                               \
+({                                                              \
+        long err = 0;                                           \
+        __typeof__(n) __n = (n);                                \
+        if (__access_ok(to,__n)) {                              \
+                err = __copy_to_user_asm(to,from,__n);          \
+        }                                                       \
+        else                                                    \
+                err = __n;                                      \
+        err;                                                    \
+})
+
+extern inline unsigned long
+__copy_from_user_asm(void* to, const void* from,  long n)
+{
+        __asm__ __volatile__ (  "   lgr   2,%1\n"
+                                "   lgr   4,%2\n"
+                                "   lgr   3,%0\n"
+                                "   lgr   5,3\n"
+                                "   sacf  512\n"
+                                "0: mvcle 2,4,0\n"
+                                "   jo    0b\n"
+                                "   sacf  0\n"
+                                "   lgr   %0,5\n"
+				".section __ex_table,\"a\"\n"
+				"   .align 8\n"
+				"   .quad  0b,__copy_from_user_fixup\n"
+				".previous"
+                                : "+&d" (n) : "d" (to), "d" (from)
+                                : "1", "2", "3", "4", "5" );
+        return n;
+}
+
+
+#define __copy_from_user(to, from, n)                           \
+({                                                              \
+        __copy_from_user_asm(to,from,n);                        \
+})
+
+#define copy_from_user(to, from, n)                             \
+({                                                              \
+        long err = 0;                                           \
+        __typeof__(n) __n = (n);                                \
+        if (__access_ok(from,__n)) {                            \
+                err = __copy_from_user_asm(to,from,__n);        \
+        }                                                       \
+        else                                                    \
+                err = __n;                                      \
+        err;                                                    \
+})
+
+/*
+ * Copy a null terminated string from userspace.
+ */
+
+static inline long
+__strncpy_from_user(char *dst, const char *src, long count)
+{
+        long len;
+        __asm__ __volatile__ (  "   slgr  %0,%0\n"
+				"   lgr   2,%1\n"
+                                "   lgr   4,%2\n"
+                                "   slr   3,3\n"
+                                "   sacf  512\n"
+                                "0: ic    3,0(%0,4)\n"
+                                "1: stc   3,0(%0,2)\n"
+                                "   aghi  %0,1\n"
+                                "   cgr   %0,%3\n"
+                                "   je    2f\n"
+                                "   ltr   3,3\n"
+                                "   jne   0b\n"
+                                "2: sacf  0\n"
+				"3:\n"
+				".section .fixup,\"ax\"\n"
+				"4: lghi  %0,%h4\n"
+				"   jg    3b\n"  
+				".previous\n"
+				".section __ex_table,\"a\"\n"
+				"   .align 8\n"
+				"   .quad  0b,4b\n"
+				"   .quad  1b,4b\n"
+				".previous"
+                                : "=&a" (len)
+                                : "a"  (dst), "d" (src), "d" (count),
+                                  "K" (-EFAULT)
+                                : "2" ,"3", "4" );
+        return len;
+}
+
+static inline long
+strncpy_from_user(char *dst, const char *src, long count)
+{
+        long res = -EFAULT;
+        if (access_ok(VERIFY_READ, src, 1))
+                res = __strncpy_from_user(dst, src, count);
+        return res;
+}
+
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return 0 for error
+ */
+static inline unsigned long
+strnlen_user(const char * src, unsigned long n)
+{
+#if 0
+        __asm__ __volatile__ ("   algr  %0,%1\n"
+                              "   slgr  0,0\n"
+                              "   lgr   4,%1\n"
+                              "   sacf  512\n"
+                              "0: srst  %0,4\n"
+                              "   jo    0b\n"
+                              "   slgr  %0,%1\n"
+                              "   aghi  %0,1\n"
+                              "1: sacf  0\n"
+                              ".section .fixup,\"ax\"\n"
+                              "2: slgr  %0,%0\n"
+                              "   jg    1b\n"
+                              ".previous\n"
+                              ".section __ex_table,\"a\"\n"
+                              "   .align 8\n"
+                              "   .quad  0b,2b\n"
+                              ".previous"
+                              : "+&a" (n) : "d" (src)
+                              : "cc", "0", "4" );
+#else
+	__asm__ __volatile__ ("   lgr   4,%1\n"
+			      "   sacf  512\n"
+			      "0: cli   0(4),0x00\n"
+                              "   la    4,1(4)\n"
+			      "   je    1f\n"
+                              "   brctg %0,0b\n"
+			      "1: lgr   %0,4\n"
+			      "   slgr  %0,%1\n"
+			      "2: sacf  0\n"
+                              ".section .fixup,\"ax\"\n"
+                              "3: slgr  %0,%0\n"
+                              "   jg    2b\n"  
+                              ".previous\n"
+			      ".section __ex_table,\"a\"\n"
+			      "   .align 8\n"
+			      "   .quad  0b,3b\n"
+			      ".previous"
+			      : "+&a" (n) : "d" (src)
+			      : "cc", "4" );
+#endif
+        return n;
+}
+#define strlen_user(str) strnlen_user(str, ~0UL)
+
+/*
+ * Zero Userspace
+ */
+
+static inline unsigned long
+__clear_user(void *to, unsigned long n)
+{
+        __asm__ __volatile__ (  "   sacf  512\n"
+                                "   lgr   4,%1\n"
+                                "   lgr   5,%0\n"
+                                "   sgr   2,2\n"
+                                "   sgr   3,3\n"
+                                "0: mvcle 4,2,0\n"
+                                "   jo    0b\n"
+                                "1: sacf  0\n"
+                                "   lgr   %0,5\n"
+				".section __ex_table,\"a\"\n"
+				"   .align 8\n"
+				"   .quad  0b,__copy_to_user_fixup\n"
+				".previous"
+                                : "+&a" (n)
+                                : "a"   (to)
+                                : "cc", "1", "2", "3", "4", "5" );
+        return n;
+}
+
+static inline unsigned long
+clear_user(void *to, unsigned long n)
+{
+        if (access_ok(VERIFY_WRITE, to, n))
+                n = __clear_user(to, n);
+        return n;
+}
+
+#endif                                 /* _S390_UACCESS_H                  */
+
+
+
+
+

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)