linux/arch/s390/include/asm/uaccess.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/*
   3 *  S390 version
   4 *    Copyright IBM Corp. 1999, 2000
   5 *    Author(s): Hartmut Penner (hp@de.ibm.com),
   6 *               Martin Schwidefsky (schwidefsky@de.ibm.com)
   7 *
   8 *  Derived from "include/asm-i386/uaccess.h"
   9 */
  10#ifndef __S390_UACCESS_H
  11#define __S390_UACCESS_H
  12
  13/*
  14 * User space memory access functions
  15 */
  16#include <asm/processor.h>
  17#include <asm/ctl_reg.h>
  18#include <asm/extable.h>
  19#include <asm/facility.h>
  20
  21/*
  22 * The fs value determines whether argument validity checking should be
  23 * performed or not.  If get_fs() == USER_DS, checking is performed, with
  24 * get_fs() == KERNEL_DS, checking is bypassed.
  25 *
  26 * For historical reasons, these macros are grossly misnamed.
  27 */
  28
  29#define KERNEL_DS       (0)
  30#define KERNEL_DS_SACF  (1)
  31#define USER_DS         (2)
  32#define USER_DS_SACF    (3)
  33
  34#define get_fs()        (current->thread.mm_segment)
  35#define uaccess_kernel() ((get_fs() & 2) == KERNEL_DS)
  36
  37void set_fs(mm_segment_t fs);
  38
  39static inline int __range_ok(unsigned long addr, unsigned long size)
  40{
  41        return 1;
  42}
  43
  44#define __access_ok(addr, size)                         \
  45({                                                      \
  46        __chk_user_ptr(addr);                           \
  47        __range_ok((unsigned long)(addr), (size));      \
  48})
  49
  50#define access_ok(addr, size) __access_ok(addr, size)
  51
  52unsigned long __must_check
  53raw_copy_from_user(void *to, const void __user *from, unsigned long n);
  54
  55unsigned long __must_check
  56raw_copy_to_user(void __user *to, const void *from, unsigned long n);
  57
  58#ifndef CONFIG_KASAN
  59#define INLINE_COPY_FROM_USER
  60#define INLINE_COPY_TO_USER
  61#endif
  62
  63#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
  64
  65#define __put_get_user_asm(to, from, size, spec)                \
  66({                                                              \
  67        register unsigned long __reg0 asm("0") = spec;          \
  68        int __rc;                                               \
  69                                                                \
  70        asm volatile(                                           \
  71                "0:     mvcos   %1,%3,%2\n"                     \
  72                "1:     xr      %0,%0\n"                        \
  73                "2:\n"                                          \
  74                ".pushsection .fixup, \"ax\"\n"                 \
  75                "3:     lhi     %0,%5\n"                        \
  76                "       jg      2b\n"                           \
  77                ".popsection\n"                                 \
  78                EX_TABLE(0b,3b) EX_TABLE(1b,3b)                 \
  79                : "=d" (__rc), "+Q" (*(to))                     \
  80                : "d" (size), "Q" (*(from)),                    \
  81                  "d" (__reg0), "K" (-EFAULT)                   \
  82                : "cc");                                        \
  83        __rc;                                                   \
  84})
  85
  86static __always_inline int __put_user_fn(void *x, void __user *ptr, unsigned long size)
  87{
  88        unsigned long spec = 0x010000UL;
  89        int rc;
  90
  91        switch (size) {
  92        case 1:
  93                rc = __put_get_user_asm((unsigned char __user *)ptr,
  94                                        (unsigned char *)x,
  95                                        size, spec);
  96                break;
  97        case 2:
  98                rc = __put_get_user_asm((unsigned short __user *)ptr,
  99                                        (unsigned short *)x,
 100                                        size, spec);
 101                break;
 102        case 4:
 103                rc = __put_get_user_asm((unsigned int __user *)ptr,
 104                                        (unsigned int *)x,
 105                                        size, spec);
 106                break;
 107        case 8:
 108                rc = __put_get_user_asm((unsigned long __user *)ptr,
 109                                        (unsigned long *)x,
 110                                        size, spec);
 111                break;
 112        }
 113        return rc;
 114}
 115
 116static __always_inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size)
 117{
 118        unsigned long spec = 0x01UL;
 119        int rc;
 120
 121        switch (size) {
 122        case 1:
 123                rc = __put_get_user_asm((unsigned char *)x,
 124                                        (unsigned char __user *)ptr,
 125                                        size, spec);
 126                break;
 127        case 2:
 128                rc = __put_get_user_asm((unsigned short *)x,
 129                                        (unsigned short __user *)ptr,
 130                                        size, spec);
 131                break;
 132        case 4:
 133                rc = __put_get_user_asm((unsigned int *)x,
 134                                        (unsigned int __user *)ptr,
 135                                        size, spec);
 136                break;
 137        case 8:
 138                rc = __put_get_user_asm((unsigned long *)x,
 139                                        (unsigned long __user *)ptr,
 140                                        size, spec);
 141                break;
 142        }
 143        return rc;
 144}
 145
 146#else /* CONFIG_HAVE_MARCH_Z10_FEATURES */
 147
 148static inline int __put_user_fn(void *x, void __user *ptr, unsigned long size)
 149{
 150        size = raw_copy_to_user(ptr, x, size);
 151        return size ? -EFAULT : 0;
 152}
 153
 154static inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size)
 155{
 156        size = raw_copy_from_user(x, ptr, size);
 157        return size ? -EFAULT : 0;
 158}
 159
 160#endif /* CONFIG_HAVE_MARCH_Z10_FEATURES */
 161
 162/*
 163 * These are the main single-value transfer routines.  They automatically
 164 * use the right size if we just have the right pointer type.
 165 */
 166#define __put_user(x, ptr) \
 167({                                                              \
 168        __typeof__(*(ptr)) __x = (x);                           \
 169        int __pu_err = -EFAULT;                                 \
 170        __chk_user_ptr(ptr);                                    \
 171        switch (sizeof (*(ptr))) {                              \
 172        case 1:                                                 \
 173        case 2:                                                 \
 174        case 4:                                                 \
 175        case 8:                                                 \
 176                __pu_err = __put_user_fn(&__x, ptr,             \
 177                                         sizeof(*(ptr)));       \
 178                break;                                          \
 179        default:                                                \
 180                __put_user_bad();                               \
 181                break;                                          \
 182         }                                                      \
 183        __builtin_expect(__pu_err, 0);                          \
 184})
 185
 186#define put_user(x, ptr)                                        \
 187({                                                              \
 188        might_fault();                                          \
 189        __put_user(x, ptr);                                     \
 190})
 191
 192
 193int __put_user_bad(void) __attribute__((noreturn));
 194
 195#define __get_user(x, ptr)                                      \
 196({                                                              \
 197        int __gu_err = -EFAULT;                                 \
 198        __chk_user_ptr(ptr);                                    \
 199        switch (sizeof(*(ptr))) {                               \
 200        case 1: {                                               \
 201                unsigned char __x = 0;                          \
 202                __gu_err = __get_user_fn(&__x, ptr,             \
 203                                         sizeof(*(ptr)));       \
 204                (x) = *(__force __typeof__(*(ptr)) *) &__x;     \
 205                break;                                          \
 206        };                                                      \
 207        case 2: {                                               \
 208                unsigned short __x = 0;                         \
 209                __gu_err = __get_user_fn(&__x, ptr,             \
 210                                         sizeof(*(ptr)));       \
 211                (x) = *(__force __typeof__(*(ptr)) *) &__x;     \
 212                break;                                          \
 213        };                                                      \
 214        case 4: {                                               \
 215                unsigned int __x = 0;                           \
 216                __gu_err = __get_user_fn(&__x, ptr,             \
 217                                         sizeof(*(ptr)));       \
 218                (x) = *(__force __typeof__(*(ptr)) *) &__x;     \
 219                break;                                          \
 220        };                                                      \
 221        case 8: {                                               \
 222                unsigned long long __x = 0;                     \
 223                __gu_err = __get_user_fn(&__x, ptr,             \
 224                                         sizeof(*(ptr)));       \
 225                (x) = *(__force __typeof__(*(ptr)) *) &__x;     \
 226                break;                                          \
 227        };                                                      \
 228        default:                                                \
 229                __get_user_bad();                               \
 230                break;                                          \
 231        }                                                       \
 232        __builtin_expect(__gu_err, 0);                          \
 233})
 234
 235#define get_user(x, ptr)                                        \
 236({                                                              \
 237        might_fault();                                          \
 238        __get_user(x, ptr);                                     \
 239})
 240
 241int __get_user_bad(void) __attribute__((noreturn));
 242
 243unsigned long __must_check
 244raw_copy_in_user(void __user *to, const void __user *from, unsigned long n);
 245
 246/*
 247 * Copy a null terminated string from userspace.
 248 */
 249
 250long __strncpy_from_user(char *dst, const char __user *src, long count);
 251
 252static inline long __must_check
 253strncpy_from_user(char *dst, const char __user *src, long count)
 254{
 255        might_fault();
 256        return __strncpy_from_user(dst, src, count);
 257}
 258
 259unsigned long __must_check __strnlen_user(const char __user *src, unsigned long count);
 260
 261static inline unsigned long strnlen_user(const char __user *src, unsigned long n)
 262{
 263        might_fault();
 264        return __strnlen_user(src, n);
 265}
 266
 267/*
 268 * Zero Userspace
 269 */
 270unsigned long __must_check __clear_user(void __user *to, unsigned long size);
 271
 272static inline unsigned long __must_check clear_user(void __user *to, unsigned long n)
 273{
 274        might_fault();
 275        return __clear_user(to, n);
 276}
 277
 278int copy_to_user_real(void __user *dest, void *src, unsigned long count);
 279void *s390_kernel_write(void *dst, const void *src, size_t size);
 280
 281#endif /* __S390_UACCESS_H */
 282