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 38 void set_fs(mm_segment_t fs); 39 40 static 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 53 unsigned long __must_check 54 raw_copy_from_user(void *to, const void __user *from, unsigned long n); 55 56 unsigned long __must_check 57 raw_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 85 static 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 115 static 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 147 static 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 153 static 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 192 int __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 240 int __get_user_bad(void) __attribute__((noreturn)); 241 242 unsigned long __must_check 243 raw_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 249 long __strncpy_from_user(char *dst, const char __user *src, long count); 250 251 static inline long __must_check 252 strncpy_from_user(char *dst, const char __user *src, long count) 253 { 254 might_fault(); 255 return __strncpy_from_user(dst, src, count); 256 } 257 258 unsigned long __must_check __strnlen_user(const char __user *src, unsigned long count); 259 260 static 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 */ 269 unsigned long __must_check __clear_user(void __user *to, unsigned long size); 270 271 static 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 277 int copy_to_user_real(void __user *dest, void *src, unsigned long count); 278 void s390_kernel_write(void *dst, const void *src, size_t size); 279 280 #endif /* __S390_UACCESS_H */ 281