Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  *  S390 version
0004  *    Copyright IBM Corp. 1999, 2000
0005  *    Author(s): Hartmut Penner (hp@de.ibm.com),
0006  *       Martin Schwidefsky (schwidefsky@de.ibm.com)
0007  *
0008  *  Derived from "include/asm-i386/uaccess.h"
0009  */
0010 #ifndef __S390_UACCESS_H
0011 #define __S390_UACCESS_H
0012 
0013 /*
0014  * User space memory access functions
0015  */
0016 #include <asm/asm-extable.h>
0017 #include <asm/processor.h>
0018 #include <asm/ctl_reg.h>
0019 #include <asm/extable.h>
0020 #include <asm/facility.h>
0021 #include <asm-generic/access_ok.h>
0022 
0023 void debug_user_asce(int exit);
0024 
0025 unsigned long __must_check
0026 raw_copy_from_user(void *to, const void __user *from, unsigned long n);
0027 
0028 unsigned long __must_check
0029 raw_copy_to_user(void __user *to, const void *from, unsigned long n);
0030 
0031 #ifndef CONFIG_KASAN
0032 #define INLINE_COPY_FROM_USER
0033 #define INLINE_COPY_TO_USER
0034 #endif
0035 
0036 unsigned long __must_check
0037 _copy_from_user_key(void *to, const void __user *from, unsigned long n, unsigned long key);
0038 
0039 static __always_inline unsigned long __must_check
0040 copy_from_user_key(void *to, const void __user *from, unsigned long n, unsigned long key)
0041 {
0042     if (check_copy_size(to, n, false))
0043         n = _copy_from_user_key(to, from, n, key);
0044     return n;
0045 }
0046 
0047 unsigned long __must_check
0048 _copy_to_user_key(void __user *to, const void *from, unsigned long n, unsigned long key);
0049 
0050 static __always_inline unsigned long __must_check
0051 copy_to_user_key(void __user *to, const void *from, unsigned long n, unsigned long key)
0052 {
0053     if (check_copy_size(from, n, true))
0054         n = _copy_to_user_key(to, from, n, key);
0055     return n;
0056 }
0057 
0058 union oac {
0059     unsigned int val;
0060     struct {
0061         struct {
0062             unsigned short key : 4;
0063             unsigned short     : 4;
0064             unsigned short as  : 2;
0065             unsigned short     : 4;
0066             unsigned short k   : 1;
0067             unsigned short a   : 1;
0068         } oac1;
0069         struct {
0070             unsigned short key : 4;
0071             unsigned short     : 4;
0072             unsigned short as  : 2;
0073             unsigned short     : 4;
0074             unsigned short k   : 1;
0075             unsigned short a   : 1;
0076         } oac2;
0077     };
0078 };
0079 
0080 int __noreturn __put_user_bad(void);
0081 
0082 #define __put_user_asm(to, from, size)                  \
0083 ({                                  \
0084     union oac __oac_spec = {                    \
0085         .oac1.as = PSW_BITS_AS_SECONDARY,           \
0086         .oac1.a = 1,                        \
0087     };                              \
0088     int __rc;                           \
0089                                     \
0090     asm volatile(                           \
0091         "   lr  0,%[spec]\n"                \
0092         "0: mvcos   %[_to],%[_from],%[_size]\n"     \
0093         "1: xr  %[rc],%[rc]\n"              \
0094         "2:\n"                          \
0095         EX_TABLE_UA_STORE(0b, 2b, %[rc])            \
0096         EX_TABLE_UA_STORE(1b, 2b, %[rc])            \
0097         : [rc] "=&d" (__rc), [_to] "+Q" (*(to))         \
0098         : [_size] "d" (size), [_from] "Q" (*(from)),        \
0099           [spec] "d" (__oac_spec.val)               \
0100         : "cc", "0");                       \
0101     __rc;                               \
0102 })
0103 
0104 static __always_inline int __put_user_fn(void *x, void __user *ptr, unsigned long size)
0105 {
0106     int rc;
0107 
0108     switch (size) {
0109     case 1:
0110         rc = __put_user_asm((unsigned char __user *)ptr,
0111                     (unsigned char *)x,
0112                     size);
0113         break;
0114     case 2:
0115         rc = __put_user_asm((unsigned short __user *)ptr,
0116                     (unsigned short *)x,
0117                     size);
0118         break;
0119     case 4:
0120         rc = __put_user_asm((unsigned int __user *)ptr,
0121                     (unsigned int *)x,
0122                     size);
0123         break;
0124     case 8:
0125         rc = __put_user_asm((unsigned long __user *)ptr,
0126                     (unsigned long *)x,
0127                     size);
0128         break;
0129     default:
0130         __put_user_bad();
0131         break;
0132     }
0133     return rc;
0134 }
0135 
0136 int __noreturn __get_user_bad(void);
0137 
0138 #define __get_user_asm(to, from, size)                  \
0139 ({                                  \
0140     union oac __oac_spec = {                    \
0141         .oac2.as = PSW_BITS_AS_SECONDARY,           \
0142         .oac2.a = 1,                        \
0143     };                              \
0144     int __rc;                           \
0145                                     \
0146     asm volatile(                           \
0147         "   lr  0,%[spec]\n"                \
0148         "0: mvcos   0(%[_to]),%[_from],%[_size]\n"      \
0149         "1: xr  %[rc],%[rc]\n"              \
0150         "2:\n"                          \
0151         EX_TABLE_UA_LOAD_MEM(0b, 2b, %[rc], %[_to], %[_ksize])  \
0152         EX_TABLE_UA_LOAD_MEM(1b, 2b, %[rc], %[_to], %[_ksize])  \
0153         : [rc] "=&d" (__rc), "=Q" (*(to))           \
0154         : [_size] "d" (size), [_from] "Q" (*(from)),        \
0155           [spec] "d" (__oac_spec.val), [_to] "a" (to),      \
0156           [_ksize] "K" (size)                   \
0157         : "cc", "0");                       \
0158     __rc;                               \
0159 })
0160 
0161 static __always_inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size)
0162 {
0163     int rc;
0164 
0165     switch (size) {
0166     case 1:
0167         rc = __get_user_asm((unsigned char *)x,
0168                     (unsigned char __user *)ptr,
0169                     size);
0170         break;
0171     case 2:
0172         rc = __get_user_asm((unsigned short *)x,
0173                     (unsigned short __user *)ptr,
0174                     size);
0175         break;
0176     case 4:
0177         rc = __get_user_asm((unsigned int *)x,
0178                     (unsigned int __user *)ptr,
0179                     size);
0180         break;
0181     case 8:
0182         rc = __get_user_asm((unsigned long *)x,
0183                     (unsigned long __user *)ptr,
0184                     size);
0185         break;
0186     default:
0187         __get_user_bad();
0188         break;
0189     }
0190     return rc;
0191 }
0192 
0193 /*
0194  * These are the main single-value transfer routines.  They automatically
0195  * use the right size if we just have the right pointer type.
0196  */
0197 #define __put_user(x, ptr)                      \
0198 ({                                  \
0199     __typeof__(*(ptr)) __x = (x);                   \
0200     int __pu_err = -EFAULT;                     \
0201                                     \
0202     __chk_user_ptr(ptr);                        \
0203     switch (sizeof(*(ptr))) {                   \
0204     case 1:                             \
0205     case 2:                             \
0206     case 4:                             \
0207     case 8:                             \
0208         __pu_err = __put_user_fn(&__x, ptr, sizeof(*(ptr)));    \
0209         break;                          \
0210     default:                            \
0211         __put_user_bad();                   \
0212         break;                          \
0213     }                               \
0214     __builtin_expect(__pu_err, 0);                  \
0215 })
0216 
0217 #define put_user(x, ptr)                        \
0218 ({                                  \
0219     might_fault();                          \
0220     __put_user(x, ptr);                     \
0221 })
0222 
0223 #define __get_user(x, ptr)                      \
0224 ({                                  \
0225     int __gu_err = -EFAULT;                     \
0226                                     \
0227     __chk_user_ptr(ptr);                        \
0228     switch (sizeof(*(ptr))) {                   \
0229     case 1: {                           \
0230         unsigned char __x;                  \
0231                                     \
0232         __gu_err = __get_user_fn(&__x, ptr, sizeof(*(ptr)));    \
0233         (x) = *(__force __typeof__(*(ptr)) *)&__x;      \
0234         break;                          \
0235     };                              \
0236     case 2: {                           \
0237         unsigned short __x;                 \
0238                                     \
0239         __gu_err = __get_user_fn(&__x, ptr, sizeof(*(ptr)));    \
0240         (x) = *(__force __typeof__(*(ptr)) *)&__x;      \
0241         break;                          \
0242     };                              \
0243     case 4: {                           \
0244         unsigned int __x;                   \
0245                                     \
0246         __gu_err = __get_user_fn(&__x, ptr, sizeof(*(ptr)));    \
0247         (x) = *(__force __typeof__(*(ptr)) *)&__x;      \
0248         break;                          \
0249     };                              \
0250     case 8: {                           \
0251         unsigned long __x;                  \
0252                                     \
0253         __gu_err = __get_user_fn(&__x, ptr, sizeof(*(ptr)));    \
0254         (x) = *(__force __typeof__(*(ptr)) *)&__x;      \
0255         break;                          \
0256     };                              \
0257     default:                            \
0258         __get_user_bad();                   \
0259         break;                          \
0260     }                               \
0261     __builtin_expect(__gu_err, 0);                  \
0262 })
0263 
0264 #define get_user(x, ptr)                        \
0265 ({                                  \
0266     might_fault();                          \
0267     __get_user(x, ptr);                     \
0268 })
0269 
0270 /*
0271  * Copy a null terminated string from userspace.
0272  */
0273 long __must_check strncpy_from_user(char *dst, const char __user *src, long count);
0274 
0275 long __must_check strnlen_user(const char __user *src, long count);
0276 
0277 /*
0278  * Zero Userspace
0279  */
0280 unsigned long __must_check __clear_user(void __user *to, unsigned long size);
0281 
0282 static inline unsigned long __must_check clear_user(void __user *to, unsigned long n)
0283 {
0284     might_fault();
0285     return __clear_user(to, n);
0286 }
0287 
0288 void *s390_kernel_write(void *dst, const void *src, size_t size);
0289 
0290 int __noreturn __put_kernel_bad(void);
0291 
0292 #define __put_kernel_asm(val, to, insn)                 \
0293 ({                                  \
0294     int __rc;                           \
0295                                     \
0296     asm volatile(                           \
0297         "0:   " insn "  %[_val],%[_to]\n"           \
0298         "1: xr  %[rc],%[rc]\n"              \
0299         "2:\n"                          \
0300         EX_TABLE_UA_STORE(0b, 2b, %[rc])            \
0301         EX_TABLE_UA_STORE(1b, 2b, %[rc])            \
0302         : [rc] "=d" (__rc), [_to] "+Q" (*(to))          \
0303         : [_val] "d" (val)                  \
0304         : "cc");                        \
0305     __rc;                               \
0306 })
0307 
0308 #define __put_kernel_nofault(dst, src, type, err_label)         \
0309 do {                                    \
0310     unsigned long __x = (unsigned long)(*((type *)(src)));      \
0311     int __pk_err;                           \
0312                                     \
0313     switch (sizeof(type)) {                     \
0314     case 1:                             \
0315         __pk_err = __put_kernel_asm(__x, (type *)(dst), "stc"); \
0316         break;                          \
0317     case 2:                             \
0318         __pk_err = __put_kernel_asm(__x, (type *)(dst), "sth"); \
0319         break;                          \
0320     case 4:                             \
0321         __pk_err = __put_kernel_asm(__x, (type *)(dst), "st");  \
0322         break;                          \
0323     case 8:                             \
0324         __pk_err = __put_kernel_asm(__x, (type *)(dst), "stg"); \
0325         break;                          \
0326     default:                            \
0327         __pk_err = __put_kernel_bad();              \
0328         break;                          \
0329     }                               \
0330     if (unlikely(__pk_err))                     \
0331         goto err_label;                     \
0332 } while (0)
0333 
0334 int __noreturn __get_kernel_bad(void);
0335 
0336 #define __get_kernel_asm(val, from, insn)               \
0337 ({                                  \
0338     int __rc;                           \
0339                                     \
0340     asm volatile(                           \
0341         "0:   " insn "  %[_val],%[_from]\n"         \
0342         "1: xr  %[rc],%[rc]\n"              \
0343         "2:\n"                          \
0344         EX_TABLE_UA_LOAD_REG(0b, 2b, %[rc], %[_val])        \
0345         EX_TABLE_UA_LOAD_REG(1b, 2b, %[rc], %[_val])        \
0346         : [rc] "=d" (__rc), [_val] "=d" (val)           \
0347         : [_from] "Q" (*(from))                 \
0348         : "cc");                        \
0349     __rc;                               \
0350 })
0351 
0352 #define __get_kernel_nofault(dst, src, type, err_label)         \
0353 do {                                    \
0354     int __gk_err;                           \
0355                                     \
0356     switch (sizeof(type)) {                     \
0357     case 1: {                           \
0358         unsigned char __x;                  \
0359                                     \
0360         __gk_err = __get_kernel_asm(__x, (type *)(src), "ic");  \
0361         *((type *)(dst)) = (type)__x;               \
0362         break;                          \
0363     };                              \
0364     case 2: {                           \
0365         unsigned short __x;                 \
0366                                     \
0367         __gk_err = __get_kernel_asm(__x, (type *)(src), "lh");  \
0368         *((type *)(dst)) = (type)__x;               \
0369         break;                          \
0370     };                              \
0371     case 4: {                           \
0372         unsigned int __x;                   \
0373                                     \
0374         __gk_err = __get_kernel_asm(__x, (type *)(src), "l");   \
0375         *((type *)(dst)) = (type)__x;               \
0376         break;                          \
0377     };                              \
0378     case 8: {                           \
0379         unsigned long __x;                  \
0380                                     \
0381         __gk_err = __get_kernel_asm(__x, (type *)(src), "lg");  \
0382         *((type *)(dst)) = (type)__x;               \
0383         break;                          \
0384     };                              \
0385     default:                            \
0386         __gk_err = __get_kernel_bad();              \
0387         break;                          \
0388     }                               \
0389     if (unlikely(__gk_err))                     \
0390         goto err_label;                     \
0391 } while (0)
0392 
0393 #endif /* __S390_UACCESS_H */