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_ds()        (KERNEL_DS)
  35#define get_fs()        (current->thread.mm_segment)
  36#define segment_eq(a,b) (((a) & 2) == ((b) & 2))
  37
  38void set_fs(mm_segment_t fs);
  39
  40static inline int __range_ok(unsigned long addr, unsigned long size)
  41{
  42        return 1;
  43}
  44
  45#define __access_ok(addr, size)                         \
  46({                                                      \
  47        __chk_user_ptr(addr);                           \
  48        __range_ok((unsigned long)(addr), (size));      \
  49})
  50
  51#define access_ok(type, addr, size) __access_ok(addr, size)
  52
  53unsigned long __must_check
  54raw_copy_from_user(void *to, const void __user *from, unsigned long n);
  55
  56unsigned long __must_check
  57raw_copy_to_user(void __user *to, const void *from, unsigned long n);
  58
  59#define INLINE_COPY_FROM_USER
  60#define INLINE_COPY_TO_USER
  61
  62#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
  63
  64#define __put_get_user_asm(to, from, size, spec)                \
  65({                                                              \
  66        register unsigned long __reg0 asm("0") = spec;          \
  67        int __rc;                                               \
  68                                                                \
  69        asm volatile(                                           \
  70                "0:     mvcos   %1,%3,%2\n"                     \
  71                "1:     xr      %0,%0\n"                        \
  72                "2:\n"                                          \
  73                ".pushsection .fixup, \"ax\"\n"                 \
  74                "3:     lhi     %0,%5\n"                        \
  75                "       jg      2b\n"                           \
  76                ".popsection\n"                                 \
  77                EX_TABLE(0b,3b) EX_TABLE(1b,3b)                 \
  78                : "=d" (__rc), "+Q" (*(to))                     \
  79                : "d" (size), "Q" (*(from)),                    \
  80                  "d" (__reg0), "K" (-EFAULT)                   \
  81                : "cc");                                        \
  82        __rc;                                                   \
  83})
  84
  85static inline int __put_user_fn(void *x, void __user *ptr, unsigned long size)
  86{
  87        unsigned long spec = 0x010000UL;
  88        int rc;
  89
  90        switch (size) {
  91        case 1:
  92                rc = __put_get_user_asm((unsigned char __user *)ptr,
  93                                        (unsigned char *)x,
  94                                        size, spec);
  95                break;
  96        case 2:
  97                rc = __put_get_user_asm((unsigned short __user *)ptr,
  98                                        (unsigned short *)x,
  99                                        size, spec);
 100                break;
 101        case 4:
 102                rc = __put_get_user_asm((unsigned int __user *)ptr,
 103                                        (unsigned int *)x,
 104                                        size, spec);
 105                break;
 106        case 8:
 107                rc = __put_get_user_asm((unsigned long __user *)ptr,
 108                                        (unsigned long *)x,
 109                                        size, spec);
 110                break;
 111        }
 112        return rc;
 113}
 114
 115static inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size)
 116{
 117        unsigned long spec = 0x01UL;
 118        int rc;
 119
 120        switch (size) {
 121        case 1:
 122                rc = __put_get_user_asm((unsigned char *)x,
 123                                        (unsigned char __user *)ptr,
 124                                        size, spec);
 125                break;
 126        case 2:
 127                rc = __put_get_user_asm((unsigned short *)x,
 128                                        (unsigned short __user *)ptr,
 129                                        size, spec);
 130                break;
 131        case 4:
 132                rc = __put_get_user_asm((unsigned int *)x,
 133                                        (unsigned int __user *)ptr,
 134                                        size, spec);
 135                break;
 136        case 8:
 137                rc = __put_get_user_asm((unsigned long *)x,
 138                                        (unsigned long __user *)ptr,
 139                                        size, spec);
 140                break;
 141        }
 142        return rc;
 143}
 144
 145#else /* CONFIG_HAVE_MARCH_Z10_FEATURES */
 146
 147static inline int __put_user_fn(void *x, void __user *ptr, unsigned long size)
 148{
 149        size = raw_copy_to_user(ptr, x, size);
 150        return size ? -EFAULT : 0;
 151}
 152
 153static inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size)
 154{
 155        size = raw_copy_from_user(x, ptr, size);
 156        return size ? -EFAULT : 0;
 157}
 158
 159#endif /* CONFIG_HAVE_MARCH_Z10_FEATURES */
 160
 161/*
 162 * These are the main single-value transfer routines.  They automatically
 163 * use the right size if we just have the right pointer type.
 164 */
 165#define __put_user(x, ptr) \
 166({                                                              \
 167        __typeof__(*(ptr)) __x = (x);                           \
 168        int __pu_err = -EFAULT;                                 \
 169        __chk_user_ptr(ptr);                                    \
 170        switch (sizeof (*(ptr))) {                              \
 171        case 1:                                                 \
 172        case 2:                                                 \
 173        case 4:                                                 \
 174        case 8:                                                 \
 175                __pu_err = __put_user_fn(&__x, ptr,             \
 176                                         sizeof(*(ptr)));       \
 177                break;                                          \
 178        default:                                                \
 179                __put_user_bad();                               \
 180                break;                                          \
 181         }                                                      \
 182        __builtin_expect(__pu_err, 0);                          \
 183})
 184
 185#define put_user(x, ptr)                                        \
 186({                                                              \
 187        might_fault();                                          \
 188        __put_user(x, ptr);                                     \
 189})
 190
 191
 192int __put_user_bad(void) __attribute__((noreturn));
 193
 194#define __get_user(x, ptr)                                      \
 195({                                                              \
 196        int __gu_err = -EFAULT;                                 \
 197        __chk_user_ptr(ptr);                                    \
 198        switch (sizeof(*(ptr))) {                               \
 199        case 1: {                                               \
 200                unsigned char __x = 0;                          \
 201                __gu_err = __get_user_fn(&__x, ptr,             \
 202                                         sizeof(*(ptr)));       \
 203                (x) = *(__force __typeof__(*(ptr)) *) &__x;     \
 204                break;                                          \
 205        };                                                      \
 206        case 2: {                                               \
 207                unsigned short __x = 0;                         \
 208                __gu_err = __get_user_fn(&__x, ptr,             \
 209                                         sizeof(*(ptr)));       \
 210                (x) = *(__force __typeof__(*(ptr)) *) &__x;     \
 211                break;                                          \
 212        };                                                      \
 213        case 4: {                                               \
 214                unsigned int __x = 0;                           \
 215                __gu_err = __get_user_fn(&__x, ptr,             \
 216                                         sizeof(*(ptr)));       \
 217                (x) = *(__force __typeof__(*(ptr)) *) &__x;     \
 218                break;                                          \
 219        };                                                      \
 220        case 8: {                                               \
 221                unsigned long long __x = 0;                     \
 222                __gu_err = __get_user_fn(&__x, ptr,             \
 223                                         sizeof(*(ptr)));       \
 224                (x) = *(__force __typeof__(*(ptr)) *) &__x;     \
 225                break;                                          \
 226        };                                                      \
 227        default:                                                \
 228                __get_user_bad();                               \
 229                break;                                          \
 230        }                                                       \
 231        __builtin_expect(__gu_err, 0);                          \
 232})
 233
 234#define get_user(x, ptr)                                        \
 235({                                                              \
 236        might_fault();                                          \
 237        __get_user(x, ptr);                                     \
 238})
 239
 240int __get_user_bad(void) __attribute__((noreturn));
 241
 242unsigned long __must_check
 243raw_copy_in_user(void __user *to, const void __user *from, unsigned long n);
 244
 245/*
 246 * Copy a null terminated string from userspace.
 247 */
 248
 249long __strncpy_from_user(char *dst, const char __user *src, long count);
 250
 251static inline long __must_check
 252strncpy_from_user(char *dst, const char __user *src, long count)
 253{
 254        might_fault();
 255        return __strncpy_from_user(dst, src, count);
 256}
 257
 258unsigned long __must_check __strnlen_user(const char __user *src, unsigned long count);
 259
 260static inline unsigned long strnlen_user(const char __user *src, unsigned long n)
 261{
 262        might_fault();
 263        return __strnlen_user(src, n);
 264}
 265
 266/*
 267 * Zero Userspace
 268 */
 269unsigned long __must_check __clear_user(void __user *to, unsigned long size);
 270
 271static inline unsigned long __must_check clear_user(void __user *to, unsigned long n)
 272{
 273        might_fault();
 274        return __clear_user(to, n);
 275}
 276
 277int copy_to_user_real(void __user *dest, void *src, unsigned long count);
 278void s390_kernel_write(void *dst, const void *src, size_t size);
 279
 280#endif /* __S390_UACCESS_H */
 281