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