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