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