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