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