1 /* 2 * This file is subject to the terms and conditions of the GNU General Public 3 * License. See the file COPYING in the main directory of this archive 4 * for more details. 5 */ 6 7 #include <linux/module.h> 8 #include <asm/uaccess.h> 9 10 unsigned long __generic_copy_from_user(void *to, const void __user *from, 11 unsigned long n) 12 { 13 unsigned long tmp, res; 14 15 asm volatile ("\n" 16 " tst.l %0\n" 17 " jeq 2f\n" 18 "1: moves.l (%1)+,%3\n" 19 " move.l %3,(%2)+\n" 20 " subq.l #1,%0\n" 21 " jne 1b\n" 22 "2: btst #1,%5\n" 23 " jeq 4f\n" 24 "3: moves.w (%1)+,%3\n" 25 " move.w %3,(%2)+\n" 26 "4: btst #0,%5\n" 27 " jeq 6f\n" 28 "5: moves.b (%1)+,%3\n" 29 " move.b %3,(%2)+\n" 30 "6:\n" 31 " .section .fixup,\"ax\"\n" 32 " .even\n" 33 "10: move.l %0,%3\n" 34 "7: clr.l (%2)+\n" 35 " subq.l #1,%3\n" 36 " jne 7b\n" 37 " lsl.l #2,%0\n" 38 " btst #1,%5\n" 39 " jeq 8f\n" 40 "30: clr.w (%2)+\n" 41 " addq.l #2,%0\n" 42 "8: btst #0,%5\n" 43 " jeq 6b\n" 44 "50: clr.b (%2)+\n" 45 " addq.l #1,%0\n" 46 " jra 6b\n" 47 " .previous\n" 48 "\n" 49 " .section __ex_table,\"a\"\n" 50 " .align 4\n" 51 " .long 1b,10b\n" 52 " .long 3b,30b\n" 53 " .long 5b,50b\n" 54 " .previous" 55 : "=d" (res), "+a" (from), "+a" (to), "=&r" (tmp) 56 : "0" (n / 4), "d" (n & 3)); 57 58 return res; 59 } 60 EXPORT_SYMBOL(__generic_copy_from_user); 61 62 unsigned long __generic_copy_to_user(void __user *to, const void *from, 63 unsigned long n) 64 { 65 unsigned long tmp, res; 66 67 asm volatile ("\n" 68 " tst.l %0\n" 69 " jeq 4f\n" 70 "1: move.l (%1)+,%3\n" 71 "2: moves.l %3,(%2)+\n" 72 "3: subq.l #1,%0\n" 73 " jne 1b\n" 74 "4: btst #1,%5\n" 75 " jeq 6f\n" 76 " move.w (%1)+,%3\n" 77 "5: moves.w %3,(%2)+\n" 78 "6: btst #0,%5\n" 79 " jeq 8f\n" 80 " move.b (%1)+,%3\n" 81 "7: moves.b %3,(%2)+\n" 82 "8:\n" 83 " .section .fixup,\"ax\"\n" 84 " .even\n" 85 "20: lsl.l #2,%0\n" 86 "50: add.l %5,%0\n" 87 " jra 8b\n" 88 " .previous\n" 89 "\n" 90 " .section __ex_table,\"a\"\n" 91 " .align 4\n" 92 " .long 2b,20b\n" 93 " .long 3b,20b\n" 94 " .long 5b,50b\n" 95 " .long 6b,50b\n" 96 " .long 7b,50b\n" 97 " .long 8b,50b\n" 98 " .previous" 99 : "=d" (res), "+a" (from), "+a" (to), "=&r" (tmp) 100 : "0" (n / 4), "d" (n & 3)); 101 102 return res; 103 } 104 EXPORT_SYMBOL(__generic_copy_to_user); 105 106 /* 107 * Copy a null terminated string from userspace. 108 */ 109 long strncpy_from_user(char *dst, const char __user *src, long count) 110 { 111 long res; 112 char c; 113 114 if (count <= 0) 115 return count; 116 117 asm volatile ("\n" 118 "1: moves.b (%2)+,%4\n" 119 " move.b %4,(%1)+\n" 120 " jeq 2f\n" 121 " subq.l #1,%3\n" 122 " jne 1b\n" 123 "2: sub.l %3,%0\n" 124 "3:\n" 125 " .section .fixup,\"ax\"\n" 126 " .even\n" 127 "10: move.l %5,%0\n" 128 " jra 3b\n" 129 " .previous\n" 130 "\n" 131 " .section __ex_table,\"a\"\n" 132 " .align 4\n" 133 " .long 1b,10b\n" 134 " .previous" 135 : "=d" (res), "+a" (dst), "+a" (src), "+r" (count), "=&d" (c) 136 : "i" (-EFAULT), "0" (count)); 137 138 return res; 139 } 140 EXPORT_SYMBOL(strncpy_from_user); 141 142 /* 143 * Return the size of a string (including the ending 0) 144 * 145 * Return 0 on exception, a value greater than N if too long 146 */ 147 long strnlen_user(const char __user *src, long n) 148 { 149 char c; 150 long res; 151 152 asm volatile ("\n" 153 "1: subq.l #1,%1\n" 154 " jmi 3f\n" 155 "2: moves.b (%0)+,%2\n" 156 " tst.b %2\n" 157 " jne 1b\n" 158 " jra 4f\n" 159 "\n" 160 "3: addq.l #1,%0\n" 161 "4: sub.l %4,%0\n" 162 "5:\n" 163 " .section .fixup,\"ax\"\n" 164 " .even\n" 165 "20: sub.l %0,%0\n" 166 " jra 5b\n" 167 " .previous\n" 168 "\n" 169 " .section __ex_table,\"a\"\n" 170 " .align 4\n" 171 " .long 2b,20b\n" 172 " .previous\n" 173 : "=&a" (res), "+d" (n), "=&d" (c) 174 : "0" (src), "r" (src)); 175 176 return res; 177 } 178 EXPORT_SYMBOL(strnlen_user); 179 180 /* 181 * Zero Userspace 182 */ 183 184 unsigned long __clear_user(void __user *to, unsigned long n) 185 { 186 unsigned long res; 187 188 asm volatile ("\n" 189 " tst.l %0\n" 190 " jeq 3f\n" 191 "1: moves.l %2,(%1)+\n" 192 "2: subq.l #1,%0\n" 193 " jne 1b\n" 194 "3: btst #1,%4\n" 195 " jeq 5f\n" 196 "4: moves.w %2,(%1)+\n" 197 "5: btst #0,%4\n" 198 " jeq 7f\n" 199 "6: moves.b %2,(%1)\n" 200 "7:\n" 201 " .section .fixup,\"ax\"\n" 202 " .even\n" 203 "10: lsl.l #2,%0\n" 204 "40: add.l %4,%0\n" 205 " jra 7b\n" 206 " .previous\n" 207 "\n" 208 " .section __ex_table,\"a\"\n" 209 " .align 4\n" 210 " .long 1b,10b\n" 211 " .long 2b,10b\n" 212 " .long 4b,40b\n" 213 " .long 5b,40b\n" 214 " .long 6b,40b\n" 215 " .long 7b,40b\n" 216 " .previous" 217 : "=d" (res), "+a" (to) 218 : "r" (0), "0" (n / 4), "d" (n & 3)); 219 220 return res; 221 } 222 EXPORT_SYMBOL(__clear_user); 223