1 /* SPDX-License-Identifier: GPL-2.0 */ 2 3 #ifndef __ASM_CSKY_UACCESS_H 4 #define __ASM_CSKY_UACCESS_H 5 6 #define user_addr_max() (current_thread_info()->addr_limit.seg) 7 8 static inline int __access_ok(unsigned long addr, unsigned long size) 9 { 10 unsigned long limit = user_addr_max(); 11 12 return (size <= limit) && (addr <= (limit - size)); 13 } 14 #define __access_ok __access_ok 15 16 /* 17 * __put_user_fn 18 */ 19 extern int __put_user_bad(void); 20 21 #define __put_user_asm_b(x, ptr, err) \ 22 do { \ 23 int errcode; \ 24 __asm__ __volatile__( \ 25 "1: stb %1, (%2,0) \n" \ 26 " br 3f \n" \ 27 "2: mov %0, %3 \n" \ 28 " br 3f \n" \ 29 ".section __ex_table, \"a\" \n" \ 30 ".align 2 \n" \ 31 ".long 1b,2b \n" \ 32 ".previous \n" \ 33 "3: \n" \ 34 : "=r"(err), "=r"(x), "=r"(ptr), "=r"(errcode) \ 35 : "0"(err), "1"(x), "2"(ptr), "3"(-EFAULT) \ 36 : "memory"); \ 37 } while (0) 38 39 #define __put_user_asm_h(x, ptr, err) \ 40 do { \ 41 int errcode; \ 42 __asm__ __volatile__( \ 43 "1: sth %1, (%2,0) \n" \ 44 " br 3f \n" \ 45 "2: mov %0, %3 \n" \ 46 " br 3f \n" \ 47 ".section __ex_table, \"a\" \n" \ 48 ".align 2 \n" \ 49 ".long 1b,2b \n" \ 50 ".previous \n" \ 51 "3: \n" \ 52 : "=r"(err), "=r"(x), "=r"(ptr), "=r"(errcode) \ 53 : "0"(err), "1"(x), "2"(ptr), "3"(-EFAULT) \ 54 : "memory"); \ 55 } while (0) 56 57 #define __put_user_asm_w(x, ptr, err) \ 58 do { \ 59 int errcode; \ 60 __asm__ __volatile__( \ 61 "1: stw %1, (%2,0) \n" \ 62 " br 3f \n" \ 63 "2: mov %0, %3 \n" \ 64 " br 3f \n" \ 65 ".section __ex_table,\"a\" \n" \ 66 ".align 2 \n" \ 67 ".long 1b, 2b \n" \ 68 ".previous \n" \ 69 "3: \n" \ 70 : "=r"(err), "=r"(x), "=r"(ptr), "=r"(errcode) \ 71 : "0"(err), "1"(x), "2"(ptr), "3"(-EFAULT) \ 72 : "memory"); \ 73 } while (0) 74 75 #define __put_user_asm_64(x, ptr, err) \ 76 do { \ 77 int tmp; \ 78 int errcode; \ 79 \ 80 __asm__ __volatile__( \ 81 " ldw %3, (%1, 0) \n" \ 82 "1: stw %3, (%2, 0) \n" \ 83 " ldw %3, (%1, 4) \n" \ 84 "2: stw %3, (%2, 4) \n" \ 85 " br 4f \n" \ 86 "3: mov %0, %4 \n" \ 87 " br 4f \n" \ 88 ".section __ex_table, \"a\" \n" \ 89 ".align 2 \n" \ 90 ".long 1b, 3b \n" \ 91 ".long 2b, 3b \n" \ 92 ".previous \n" \ 93 "4: \n" \ 94 : "=r"(err), "=r"(x), "=r"(ptr), \ 95 "=r"(tmp), "=r"(errcode) \ 96 : "0"(err), "1"(x), "2"(ptr), "3"(0), \ 97 "4"(-EFAULT) \ 98 : "memory"); \ 99 } while (0) 100 101 static inline int __put_user_fn(size_t size, void __user *ptr, void *x) 102 { 103 int retval = 0; 104 u32 tmp; 105 106 switch (size) { 107 case 1: 108 tmp = *(u8 *)x; 109 __put_user_asm_b(tmp, ptr, retval); 110 break; 111 case 2: 112 tmp = *(u16 *)x; 113 __put_user_asm_h(tmp, ptr, retval); 114 break; 115 case 4: 116 tmp = *(u32 *)x; 117 __put_user_asm_w(tmp, ptr, retval); 118 break; 119 case 8: 120 __put_user_asm_64(x, (u64 *)ptr, retval); 121 break; 122 } 123 124 return retval; 125 } 126 #define __put_user_fn __put_user_fn 127 128 /* 129 * __get_user_fn 130 */ 131 extern int __get_user_bad(void); 132 133 #define __get_user_asm_common(x, ptr, ins, err) \ 134 do { \ 135 int errcode; \ 136 __asm__ __volatile__( \ 137 "1: " ins " %1, (%4, 0) \n" \ 138 " br 3f \n" \ 139 "2: mov %0, %2 \n" \ 140 " movi %1, 0 \n" \ 141 " br 3f \n" \ 142 ".section __ex_table,\"a\" \n" \ 143 ".align 2 \n" \ 144 ".long 1b, 2b \n" \ 145 ".previous \n" \ 146 "3: \n" \ 147 : "=r"(err), "=r"(x), "=r"(errcode) \ 148 : "0"(0), "r"(ptr), "2"(-EFAULT) \ 149 : "memory"); \ 150 } while (0) 151 152 #define __get_user_asm_64(x, ptr, err) \ 153 do { \ 154 int tmp; \ 155 int errcode; \ 156 \ 157 __asm__ __volatile__( \ 158 "1: ldw %3, (%2, 0) \n" \ 159 " stw %3, (%1, 0) \n" \ 160 "2: ldw %3, (%2, 4) \n" \ 161 " stw %3, (%1, 4) \n" \ 162 " br 4f \n" \ 163 "3: mov %0, %4 \n" \ 164 " br 4f \n" \ 165 ".section __ex_table, \"a\" \n" \ 166 ".align 2 \n" \ 167 ".long 1b, 3b \n" \ 168 ".long 2b, 3b \n" \ 169 ".previous \n" \ 170 "4: \n" \ 171 : "=r"(err), "=r"(x), "=r"(ptr), \ 172 "=r"(tmp), "=r"(errcode) \ 173 : "0"(err), "1"(x), "2"(ptr), "3"(0), \ 174 "4"(-EFAULT) \ 175 : "memory"); \ 176 } while (0) 177 178 static inline int __get_user_fn(size_t size, const void __user *ptr, void *x) 179 { 180 int retval; 181 u32 tmp; 182 183 switch (size) { 184 case 1: 185 __get_user_asm_common(tmp, ptr, "ldb", retval); 186 *(u8 *)x = (u8)tmp; 187 break; 188 case 2: 189 __get_user_asm_common(tmp, ptr, "ldh", retval); 190 *(u16 *)x = (u16)tmp; 191 break; 192 case 4: 193 __get_user_asm_common(tmp, ptr, "ldw", retval); 194 *(u32 *)x = (u32)tmp; 195 break; 196 case 8: 197 __get_user_asm_64(x, ptr, retval); 198 break; 199 } 200 201 return retval; 202 } 203 #define __get_user_fn __get_user_fn 204 205 unsigned long raw_copy_from_user(void *to, const void *from, unsigned long n); 206 unsigned long raw_copy_to_user(void *to, const void *from, unsigned long n); 207 208 unsigned long __clear_user(void __user *to, unsigned long n); 209 #define __clear_user __clear_user 210 211 #include <asm/segment.h> 212 #include <asm-generic/uaccess.h> 213 214 #endif /* __ASM_CSKY_UACCESS_H */ 215