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