diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-10 14:40:36 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-10 14:40:36 -0400 |
| commit | f94c128eefcce2e3448d543f13cd7d7b8aa660a5 (patch) | |
| tree | 720dcaa8bbc2a663fe96b1d1c23f7b3720be7d16 | |
| parent | c44b59430393c38873fd933333d945f426857a59 (diff) | |
| parent | e3cd7f013bac3105d44b8bd5a90359989d45b5a5 (diff) | |
Merge tag 'metag-for-v4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/jhogan/metag
Pull metag updates from James Hogan:
"These patches primarily make some usercopy improvements (following on
from the recent usercopy fixes):
- reformat and simplify rapf copy loops
- add 64-bit get_user support
And fix a couple more uaccess issues, partily pointed out by Al:
- fix access_ok() serious shortcomings
- fix strncpy_from_user() address validation
Also included is a trivial removal of a redundant increment"
* tag 'metag-for-v4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/jhogan/metag:
metag/mm: Drop pointless increment
metag/uaccess: Check access_ok in strncpy_from_user
metag/uaccess: Fix access_ok()
metag/usercopy: Add 64-bit get_user support
metag/usercopy: Simplify rapf loop fixup corner case
metag/usercopy: Reformat rapf loop inline asm
| -rw-r--r-- | arch/metag/include/asm/uaccess.h | 58 | ||||
| -rw-r--r-- | arch/metag/lib/usercopy.c | 236 | ||||
| -rw-r--r-- | arch/metag/mm/mmu-meta1.c | 1 |
3 files changed, 143 insertions, 152 deletions
diff --git a/arch/metag/include/asm/uaccess.h b/arch/metag/include/asm/uaccess.h index 5ebc2850690e..9c8fbf8fb5aa 100644 --- a/arch/metag/include/asm/uaccess.h +++ b/arch/metag/include/asm/uaccess.h | |||
| @@ -24,24 +24,32 @@ | |||
| 24 | 24 | ||
| 25 | #define segment_eq(a, b) ((a).seg == (b).seg) | 25 | #define segment_eq(a, b) ((a).seg == (b).seg) |
| 26 | 26 | ||
| 27 | #define __kernel_ok (uaccess_kernel()) | ||
| 28 | /* | ||
| 29 | * Explicitly allow NULL pointers here. Parts of the kernel such | ||
| 30 | * as readv/writev use access_ok to validate pointers, but want | ||
| 31 | * to allow NULL pointers for various reasons. NULL pointers are | ||
| 32 | * safe to allow through because the first page is not mappable on | ||
| 33 | * Meta. | ||
| 34 | * | ||
| 35 | * We also wish to avoid letting user code access the system area | ||
| 36 | * and the kernel half of the address space. | ||
| 37 | */ | ||
| 38 | #define __user_bad(addr, size) (((addr) > 0 && (addr) < META_MEMORY_BASE) || \ | ||
| 39 | ((addr) > PAGE_OFFSET && \ | ||
| 40 | (addr) < LINCORE_BASE)) | ||
| 41 | |||
| 42 | static inline int __access_ok(unsigned long addr, unsigned long size) | 27 | static inline int __access_ok(unsigned long addr, unsigned long size) |
| 43 | { | 28 | { |
| 44 | return __kernel_ok || !__user_bad(addr, size); | 29 | /* |
| 30 | * Allow access to the user mapped memory area, but not the system area | ||
| 31 | * before it. The check extends to the top of the address space when | ||
| 32 | * kernel access is allowed (there's no real reason to user copy to the | ||
| 33 | * system area in any case). | ||
| 34 | */ | ||
| 35 | if (likely(addr >= META_MEMORY_BASE && addr < get_fs().seg && | ||
| 36 | size <= get_fs().seg - addr)) | ||
| 37 | return true; | ||
| 38 | /* | ||
| 39 | * Explicitly allow NULL pointers here. Parts of the kernel such | ||
| 40 | * as readv/writev use access_ok to validate pointers, but want | ||
| 41 | * to allow NULL pointers for various reasons. NULL pointers are | ||
| 42 | * safe to allow through because the first page is not mappable on | ||
| 43 | * Meta. | ||
| 44 | */ | ||
| 45 | if (!addr) | ||
| 46 | return true; | ||
| 47 | /* Allow access to core code memory area... */ | ||
| 48 | if (addr >= LINCORE_CODE_BASE && addr <= LINCORE_CODE_LIMIT && | ||
| 49 | size <= LINCORE_CODE_LIMIT + 1 - addr) | ||
| 50 | return true; | ||
| 51 | /* ... but no other areas. */ | ||
| 52 | return false; | ||
| 45 | } | 53 | } |
| 46 | 54 | ||
| 47 | #define access_ok(type, addr, size) __access_ok((unsigned long)(addr), \ | 55 | #define access_ok(type, addr, size) __access_ok((unsigned long)(addr), \ |
| @@ -113,7 +121,8 @@ extern long __get_user_bad(void); | |||
| 113 | 121 | ||
| 114 | #define __get_user_nocheck(x, ptr, size) \ | 122 | #define __get_user_nocheck(x, ptr, size) \ |
| 115 | ({ \ | 123 | ({ \ |
| 116 | long __gu_err, __gu_val; \ | 124 | long __gu_err; \ |
| 125 | long long __gu_val; \ | ||
| 117 | __get_user_size(__gu_val, (ptr), (size), __gu_err); \ | 126 | __get_user_size(__gu_val, (ptr), (size), __gu_err); \ |
| 118 | (x) = (__force __typeof__(*(ptr)))__gu_val; \ | 127 | (x) = (__force __typeof__(*(ptr)))__gu_val; \ |
| 119 | __gu_err; \ | 128 | __gu_err; \ |
| @@ -121,7 +130,8 @@ extern long __get_user_bad(void); | |||
| 121 | 130 | ||
| 122 | #define __get_user_check(x, ptr, size) \ | 131 | #define __get_user_check(x, ptr, size) \ |
| 123 | ({ \ | 132 | ({ \ |
| 124 | long __gu_err = -EFAULT, __gu_val = 0; \ | 133 | long __gu_err = -EFAULT; \ |
| 134 | long long __gu_val = 0; \ | ||
| 125 | const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ | 135 | const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ |
| 126 | if (access_ok(VERIFY_READ, __gu_addr, size)) \ | 136 | if (access_ok(VERIFY_READ, __gu_addr, size)) \ |
| 127 | __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ | 137 | __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ |
| @@ -132,6 +142,7 @@ extern long __get_user_bad(void); | |||
| 132 | extern unsigned char __get_user_asm_b(const void __user *addr, long *err); | 142 | extern unsigned char __get_user_asm_b(const void __user *addr, long *err); |
| 133 | extern unsigned short __get_user_asm_w(const void __user *addr, long *err); | 143 | extern unsigned short __get_user_asm_w(const void __user *addr, long *err); |
| 134 | extern unsigned int __get_user_asm_d(const void __user *addr, long *err); | 144 | extern unsigned int __get_user_asm_d(const void __user *addr, long *err); |
| 145 | extern unsigned long long __get_user_asm_l(const void __user *addr, long *err); | ||
| 135 | 146 | ||
| 136 | #define __get_user_size(x, ptr, size, retval) \ | 147 | #define __get_user_size(x, ptr, size, retval) \ |
| 137 | do { \ | 148 | do { \ |
| @@ -143,6 +154,8 @@ do { \ | |||
| 143 | x = __get_user_asm_w(ptr, &retval); break; \ | 154 | x = __get_user_asm_w(ptr, &retval); break; \ |
| 144 | case 4: \ | 155 | case 4: \ |
| 145 | x = __get_user_asm_d(ptr, &retval); break; \ | 156 | x = __get_user_asm_d(ptr, &retval); break; \ |
| 157 | case 8: \ | ||
| 158 | x = __get_user_asm_l(ptr, &retval); break; \ | ||
| 146 | default: \ | 159 | default: \ |
| 147 | (x) = __get_user_bad(); \ | 160 | (x) = __get_user_bad(); \ |
| 148 | } \ | 161 | } \ |
| @@ -161,8 +174,13 @@ do { \ | |||
| 161 | extern long __must_check __strncpy_from_user(char *dst, const char __user *src, | 174 | extern long __must_check __strncpy_from_user(char *dst, const char __user *src, |
| 162 | long count); | 175 | long count); |
| 163 | 176 | ||
| 164 | #define strncpy_from_user(dst, src, count) __strncpy_from_user(dst, src, count) | 177 | static inline long |
| 165 | 178 | strncpy_from_user(char *dst, const char __user *src, long count) | |
| 179 | { | ||
| 180 | if (!access_ok(VERIFY_READ, src, 1)) | ||
| 181 | return -EFAULT; | ||
| 182 | return __strncpy_from_user(dst, src, count); | ||
| 183 | } | ||
| 166 | /* | 184 | /* |
| 167 | * Return the size of a string (including the ending 0) | 185 | * Return the size of a string (including the ending 0) |
| 168 | * | 186 | * |
diff --git a/arch/metag/lib/usercopy.c b/arch/metag/lib/usercopy.c index e8a4ea83cabb..c941abdb8f85 100644 --- a/arch/metag/lib/usercopy.c +++ b/arch/metag/lib/usercopy.c | |||
| @@ -246,65 +246,47 @@ | |||
| 246 | #define __asm_copy_user_64bit_rapf_loop( \ | 246 | #define __asm_copy_user_64bit_rapf_loop( \ |
| 247 | to, from, ret, n, id, FIXUP) \ | 247 | to, from, ret, n, id, FIXUP) \ |
| 248 | asm volatile ( \ | 248 | asm volatile ( \ |
| 249 | ".balign 8\n" \ | 249 | ".balign 8\n" \ |
| 250 | "MOV RAPF, %1\n" \ | 250 | " MOV RAPF, %1\n" \ |
| 251 | "MSETL [A0StP++], D0Ar6, D0FrT, D0.5, D0.6, D0.7\n" \ | 251 | " MSETL [A0StP++], D0Ar6, D0FrT, D0.5, D0.6, D0.7\n" \ |
| 252 | "MOV D0Ar6, #0\n" \ | 252 | " MOV D0Ar6, #0\n" \ |
| 253 | "LSR D1Ar5, %3, #6\n" \ | 253 | " LSR D1Ar5, %3, #6\n" \ |
| 254 | "SUB TXRPT, D1Ar5, #2\n" \ | 254 | " SUB TXRPT, D1Ar5, #2\n" \ |
| 255 | "MOV RAPF, %1\n" \ | 255 | " MOV RAPF, %1\n" \ |
| 256 | "$Lloop"id":\n" \ | 256 | "$Lloop"id":\n" \ |
| 257 | "ADD RAPF, %1, #64\n" \ | 257 | " ADD RAPF, %1, #64\n" \ |
| 258 | "21:\n" \ | 258 | "21: MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ |
| 259 | "MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ | 259 | "22: MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ |
| 260 | "22:\n" \ | 260 | "23: SUB %3, %3, #32\n" \ |
| 261 | "MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ | 261 | "24: MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ |
| 262 | "23:\n" \ | 262 | "25: MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ |
| 263 | "SUB %3, %3, #32\n" \ | 263 | "26: SUB %3, %3, #32\n" \ |
| 264 | "24:\n" \ | 264 | " DCACHE [%1+#-64], D0Ar6\n" \ |
| 265 | "MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ | 265 | " BR $Lloop"id"\n" \ |
| 266 | "25:\n" \ | ||
| 267 | "MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ | ||
| 268 | "26:\n" \ | ||
| 269 | "SUB %3, %3, #32\n" \ | ||
| 270 | "DCACHE [%1+#-64], D0Ar6\n" \ | ||
| 271 | "BR $Lloop"id"\n" \ | ||
| 272 | \ | 266 | \ |
| 273 | "MOV RAPF, %1\n" \ | 267 | " MOV RAPF, %1\n" \ |
| 274 | "27:\n" \ | 268 | "27: MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ |
| 275 | "MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ | 269 | "28: MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ |
| 276 | "28:\n" \ | 270 | "29: SUB %3, %3, #32\n" \ |
| 277 | "MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ | 271 | "30: MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ |
| 278 | "29:\n" \ | 272 | "31: MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ |
| 279 | "SUB %3, %3, #32\n" \ | 273 | "32: SETL [%0+#-8], D0.7, D1.7\n" \ |
| 280 | "30:\n" \ | 274 | " SUB %3, %3, #32\n" \ |
| 281 | "MGETL D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ | 275 | "1: DCACHE [%1+#-64], D0Ar6\n" \ |
| 282 | "31:\n" \ | 276 | " GETL D0Ar6, D1Ar5, [A0StP+#-40]\n" \ |
| 283 | "MSETL [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ | 277 | " GETL D0FrT, D1RtP, [A0StP+#-32]\n" \ |
| 284 | "32:\n" \ | 278 | " GETL D0.5, D1.5, [A0StP+#-24]\n" \ |
| 285 | "SUB %0, %0, #8\n" \ | 279 | " GETL D0.6, D1.6, [A0StP+#-16]\n" \ |
| 286 | "33:\n" \ | 280 | " GETL D0.7, D1.7, [A0StP+#-8]\n" \ |
| 287 | "SETL [%0++], D0.7, D1.7\n" \ | 281 | " SUB A0StP, A0StP, #40\n" \ |
| 288 | "SUB %3, %3, #32\n" \ | ||
| 289 | "1:" \ | ||
| 290 | "DCACHE [%1+#-64], D0Ar6\n" \ | ||
| 291 | "GETL D0Ar6, D1Ar5, [A0StP+#-40]\n" \ | ||
| 292 | "GETL D0FrT, D1RtP, [A0StP+#-32]\n" \ | ||
| 293 | "GETL D0.5, D1.5, [A0StP+#-24]\n" \ | ||
| 294 | "GETL D0.6, D1.6, [A0StP+#-16]\n" \ | ||
| 295 | "GETL D0.7, D1.7, [A0StP+#-8]\n" \ | ||
| 296 | "SUB A0StP, A0StP, #40\n" \ | ||
| 297 | " .section .fixup,\"ax\"\n" \ | 282 | " .section .fixup,\"ax\"\n" \ |
| 298 | "4:\n" \ | 283 | "3: MOV D0Ar2, TXSTATUS\n" \ |
| 299 | " ADD %0, %0, #8\n" \ | ||
| 300 | "3:\n" \ | ||
| 301 | " MOV D0Ar2, TXSTATUS\n" \ | ||
| 302 | " MOV D1Ar1, TXSTATUS\n" \ | 284 | " MOV D1Ar1, TXSTATUS\n" \ |
| 303 | " AND D1Ar1, D1Ar1, #0xFFFFF8FF\n" \ | 285 | " AND D1Ar1, D1Ar1, #0xFFFFF8FF\n" \ |
| 304 | " MOV TXSTATUS, D1Ar1\n" \ | 286 | " MOV TXSTATUS, D1Ar1\n" \ |
| 305 | FIXUP \ | 287 | FIXUP \ |
| 306 | " MOVT D0Ar2,#HI(1b)\n" \ | 288 | " MOVT D0Ar2, #HI(1b)\n" \ |
| 307 | " JUMP D0Ar2,#LO(1b)\n" \ | 289 | " JUMP D0Ar2, #LO(1b)\n" \ |
| 308 | " .previous\n" \ | 290 | " .previous\n" \ |
| 309 | " .section __ex_table,\"a\"\n" \ | 291 | " .section __ex_table,\"a\"\n" \ |
| 310 | " .long 21b,3b\n" \ | 292 | " .long 21b,3b\n" \ |
| @@ -319,7 +301,6 @@ | |||
| 319 | " .long 30b,3b\n" \ | 301 | " .long 30b,3b\n" \ |
| 320 | " .long 31b,3b\n" \ | 302 | " .long 31b,3b\n" \ |
| 321 | " .long 32b,3b\n" \ | 303 | " .long 32b,3b\n" \ |
| 322 | " .long 33b,4b\n" \ | ||
| 323 | " .previous\n" \ | 304 | " .previous\n" \ |
| 324 | : "=r" (to), "=r" (from), "=r" (ret), "=d" (n) \ | 305 | : "=r" (to), "=r" (from), "=r" (ret), "=d" (n) \ |
| 325 | : "0" (to), "1" (from), "2" (ret), "3" (n) \ | 306 | : "0" (to), "1" (from), "2" (ret), "3" (n) \ |
| @@ -397,89 +378,59 @@ | |||
| 397 | #define __asm_copy_user_32bit_rapf_loop( \ | 378 | #define __asm_copy_user_32bit_rapf_loop( \ |
| 398 | to, from, ret, n, id, FIXUP) \ | 379 | to, from, ret, n, id, FIXUP) \ |
| 399 | asm volatile ( \ | 380 | asm volatile ( \ |
| 400 | ".balign 8\n" \ | 381 | ".balign 8\n" \ |
| 401 | "MOV RAPF, %1\n" \ | 382 | " MOV RAPF, %1\n" \ |
| 402 | "MSETL [A0StP++], D0Ar6, D0FrT, D0.5, D0.6, D0.7\n" \ | 383 | " MSETL [A0StP++], D0Ar6, D0FrT, D0.5, D0.6, D0.7\n" \ |
| 403 | "MOV D0Ar6, #0\n" \ | 384 | " MOV D0Ar6, #0\n" \ |
| 404 | "LSR D1Ar5, %3, #6\n" \ | 385 | " LSR D1Ar5, %3, #6\n" \ |
| 405 | "SUB TXRPT, D1Ar5, #2\n" \ | 386 | " SUB TXRPT, D1Ar5, #2\n" \ |
| 406 | "MOV RAPF, %1\n" \ | 387 | " MOV RAPF, %1\n" \ |
| 407 | "$Lloop"id":\n" \ | 388 | "$Lloop"id":\n" \ |
| 408 | "ADD RAPF, %1, #64\n" \ | 389 | " ADD RAPF, %1, #64\n" \ |
| 409 | "21:\n" \ | 390 | "21: MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ |
| 410 | "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ | 391 | "22: MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ |
| 411 | "22:\n" \ | 392 | "23: SUB %3, %3, #16\n" \ |
| 412 | "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ | 393 | "24: MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ |
| 413 | "23:\n" \ | 394 | "25: MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ |
| 414 | "SUB %3, %3, #16\n" \ | 395 | "26: SUB %3, %3, #16\n" \ |
| 415 | "24:\n" \ | 396 | "27: MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ |
| 416 | "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ | 397 | "28: MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ |
| 417 | "25:\n" \ | 398 | "29: SUB %3, %3, #16\n" \ |
| 418 | "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ | 399 | "30: MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ |
| 419 | "26:\n" \ | 400 | "31: MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ |
| 420 | "SUB %3, %3, #16\n" \ | 401 | "32: SUB %3, %3, #16\n" \ |
| 421 | "27:\n" \ | 402 | " DCACHE [%1+#-64], D0Ar6\n" \ |
| 422 | "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ | 403 | " BR $Lloop"id"\n" \ |
| 423 | "28:\n" \ | ||
| 424 | "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ | ||
| 425 | "29:\n" \ | ||
| 426 | "SUB %3, %3, #16\n" \ | ||
| 427 | "30:\n" \ | ||
| 428 | "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ | ||
| 429 | "31:\n" \ | ||
| 430 | "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ | ||
| 431 | "32:\n" \ | ||
| 432 | "SUB %3, %3, #16\n" \ | ||
| 433 | "DCACHE [%1+#-64], D0Ar6\n" \ | ||
| 434 | "BR $Lloop"id"\n" \ | ||
| 435 | \ | 404 | \ |
| 436 | "MOV RAPF, %1\n" \ | 405 | " MOV RAPF, %1\n" \ |
| 437 | "33:\n" \ | 406 | "33: MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ |
| 438 | "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ | 407 | "34: MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ |
| 439 | "34:\n" \ | 408 | "35: SUB %3, %3, #16\n" \ |
| 440 | "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ | 409 | "36: MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ |
| 441 | "35:\n" \ | 410 | "37: MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ |
| 442 | "SUB %3, %3, #16\n" \ | 411 | "38: SUB %3, %3, #16\n" \ |
| 443 | "36:\n" \ | 412 | "39: MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ |
| 444 | "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ | 413 | "40: MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ |
| 445 | "37:\n" \ | 414 | "41: SUB %3, %3, #16\n" \ |
| 446 | "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ | 415 | "42: MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ |
| 447 | "38:\n" \ | 416 | "43: MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ |
| 448 | "SUB %3, %3, #16\n" \ | 417 | "44: SETD [%0+#-4], D0.7\n" \ |
| 449 | "39:\n" \ | 418 | " SUB %3, %3, #16\n" \ |
| 450 | "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ | 419 | "1: DCACHE [%1+#-64], D0Ar6\n" \ |
| 451 | "40:\n" \ | 420 | " GETL D0Ar6, D1Ar5, [A0StP+#-40]\n" \ |
| 452 | "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ | 421 | " GETL D0FrT, D1RtP, [A0StP+#-32]\n" \ |
| 453 | "41:\n" \ | 422 | " GETL D0.5, D1.5, [A0StP+#-24]\n" \ |
| 454 | "SUB %3, %3, #16\n" \ | 423 | " GETL D0.6, D1.6, [A0StP+#-16]\n" \ |
| 455 | "42:\n" \ | 424 | " GETL D0.7, D1.7, [A0StP+#-8]\n" \ |
| 456 | "MGETD D0FrT, D0.5, D0.6, D0.7, [%1++]\n" \ | 425 | " SUB A0StP, A0StP, #40\n" \ |
| 457 | "43:\n" \ | ||
| 458 | "MSETD [%0++], D0FrT, D0.5, D0.6, D0.7\n" \ | ||
| 459 | "44:\n" \ | ||
| 460 | "SUB %0, %0, #4\n" \ | ||
| 461 | "45:\n" \ | ||
| 462 | "SETD [%0++], D0.7\n" \ | ||
| 463 | "SUB %3, %3, #16\n" \ | ||
| 464 | "1:" \ | ||
| 465 | "DCACHE [%1+#-64], D0Ar6\n" \ | ||
| 466 | "GETL D0Ar6, D1Ar5, [A0StP+#-40]\n" \ | ||
| 467 | "GETL D0FrT, D1RtP, [A0StP+#-32]\n" \ | ||
| 468 | "GETL D0.5, D1.5, [A0StP+#-24]\n" \ | ||
| 469 | "GETL D0.6, D1.6, [A0StP+#-16]\n" \ | ||
| 470 | "GETL D0.7, D1.7, [A0StP+#-8]\n" \ | ||
| 471 | "SUB A0StP, A0StP, #40\n" \ | ||
| 472 | " .section .fixup,\"ax\"\n" \ | 426 | " .section .fixup,\"ax\"\n" \ |
| 473 | "4:\n" \ | 427 | "3: MOV D0Ar2, TXSTATUS\n" \ |
| 474 | " ADD %0, %0, #4\n" \ | ||
| 475 | "3:\n" \ | ||
| 476 | " MOV D0Ar2, TXSTATUS\n" \ | ||
| 477 | " MOV D1Ar1, TXSTATUS\n" \ | 428 | " MOV D1Ar1, TXSTATUS\n" \ |
| 478 | " AND D1Ar1, D1Ar1, #0xFFFFF8FF\n" \ | 429 | " AND D1Ar1, D1Ar1, #0xFFFFF8FF\n" \ |
| 479 | " MOV TXSTATUS, D1Ar1\n" \ | 430 | " MOV TXSTATUS, D1Ar1\n" \ |
| 480 | FIXUP \ | 431 | FIXUP \ |
| 481 | " MOVT D0Ar2,#HI(1b)\n" \ | 432 | " MOVT D0Ar2, #HI(1b)\n" \ |
| 482 | " JUMP D0Ar2,#LO(1b)\n" \ | 433 | " JUMP D0Ar2, #LO(1b)\n" \ |
| 483 | " .previous\n" \ | 434 | " .previous\n" \ |
| 484 | " .section __ex_table,\"a\"\n" \ | 435 | " .section __ex_table,\"a\"\n" \ |
| 485 | " .long 21b,3b\n" \ | 436 | " .long 21b,3b\n" \ |
| @@ -506,7 +457,6 @@ | |||
| 506 | " .long 42b,3b\n" \ | 457 | " .long 42b,3b\n" \ |
| 507 | " .long 43b,3b\n" \ | 458 | " .long 43b,3b\n" \ |
| 508 | " .long 44b,3b\n" \ | 459 | " .long 44b,3b\n" \ |
| 509 | " .long 45b,4b\n" \ | ||
| 510 | " .previous\n" \ | 460 | " .previous\n" \ |
| 511 | : "=r" (to), "=r" (from), "=r" (ret), "=d" (n) \ | 461 | : "=r" (to), "=r" (from), "=r" (ret), "=d" (n) \ |
| 512 | : "0" (to), "1" (from), "2" (ret), "3" (n) \ | 462 | : "0" (to), "1" (from), "2" (ret), "3" (n) \ |
| @@ -1094,6 +1044,30 @@ unsigned int __get_user_asm_d(const void __user *addr, long *err) | |||
| 1094 | } | 1044 | } |
| 1095 | EXPORT_SYMBOL(__get_user_asm_d); | 1045 | EXPORT_SYMBOL(__get_user_asm_d); |
| 1096 | 1046 | ||
| 1047 | unsigned long long __get_user_asm_l(const void __user *addr, long *err) | ||
| 1048 | { | ||
| 1049 | register unsigned long long x asm ("D0Re0") = 0; | ||
| 1050 | asm volatile ( | ||
| 1051 | " GETL %0,%t0,[%2]\n" | ||
| 1052 | "1:\n" | ||
| 1053 | " GETL %0,%t0,[%2]\n" | ||
| 1054 | "2:\n" | ||
| 1055 | " .section .fixup,\"ax\"\n" | ||
| 1056 | "3: MOV D0FrT,%3\n" | ||
| 1057 | " SETD [%1],D0FrT\n" | ||
| 1058 | " MOVT D0FrT,#HI(2b)\n" | ||
| 1059 | " JUMP D0FrT,#LO(2b)\n" | ||
| 1060 | " .previous\n" | ||
| 1061 | " .section __ex_table,\"a\"\n" | ||
| 1062 | " .long 1b,3b\n" | ||
| 1063 | " .previous\n" | ||
| 1064 | : "=r" (x) | ||
| 1065 | : "r" (err), "r" (addr), "P" (-EFAULT) | ||
| 1066 | : "D0FrT"); | ||
| 1067 | return x; | ||
| 1068 | } | ||
| 1069 | EXPORT_SYMBOL(__get_user_asm_l); | ||
| 1070 | |||
| 1097 | long __put_user_asm_b(unsigned int x, void __user *addr) | 1071 | long __put_user_asm_b(unsigned int x, void __user *addr) |
| 1098 | { | 1072 | { |
| 1099 | register unsigned int err asm ("D0Re0") = 0; | 1073 | register unsigned int err asm ("D0Re0") = 0; |
diff --git a/arch/metag/mm/mmu-meta1.c b/arch/metag/mm/mmu-meta1.c index 91f4255bcb5c..62ebab90924d 100644 --- a/arch/metag/mm/mmu-meta1.c +++ b/arch/metag/mm/mmu-meta1.c | |||
| @@ -152,6 +152,5 @@ void __init mmu_init(unsigned long mem_end) | |||
| 152 | 152 | ||
| 153 | p_swapper_pg_dir++; | 153 | p_swapper_pg_dir++; |
| 154 | addr += PGDIR_SIZE; | 154 | addr += PGDIR_SIZE; |
| 155 | entry++; | ||
| 156 | } | 155 | } |
| 157 | } | 156 | } |
