diff options
Diffstat (limited to 'arch/mips/mm/tlbex.c')
-rw-r--r-- | arch/mips/mm/tlbex.c | 42 |
1 files changed, 30 insertions, 12 deletions
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 511107f92d9..f8925ba0b39 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * Synthesize TLB refill handlers at runtime. | 6 | * Synthesize TLB refill handlers at runtime. |
7 | * | 7 | * |
8 | * Copyright (C) 2004,2005,2006 by Thiemo Seufer | 8 | * Copyright (C) 2004,2005,2006 by Thiemo Seufer |
9 | * Copyright (C) 2005 Maciej W. Rozycki | 9 | * Copyright (C) 2005, 2007 Maciej W. Rozycki |
10 | * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org) | 10 | * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org) |
11 | * | 11 | * |
12 | * ... and the days got worse and worse and now you see | 12 | * ... and the days got worse and worse and now you see |
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/string.h> | 27 | #include <linux/string.h> |
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | 29 | ||
30 | #include <asm/bugs.h> | ||
30 | #include <asm/pgtable.h> | 31 | #include <asm/pgtable.h> |
31 | #include <asm/cacheflush.h> | 32 | #include <asm/cacheflush.h> |
32 | #include <asm/mmu_context.h> | 33 | #include <asm/mmu_context.h> |
@@ -293,7 +294,7 @@ static void __init build_insn(u32 **buf, enum opcode opc, ...) | |||
293 | break; | 294 | break; |
294 | } | 295 | } |
295 | 296 | ||
296 | if (!ip) | 297 | if (!ip || (opc == insn_daddiu && r4k_daddiu_bug())) |
297 | panic("Unsupported TLB synthesizer instruction %d", opc); | 298 | panic("Unsupported TLB synthesizer instruction %d", opc); |
298 | 299 | ||
299 | op = ip->match; | 300 | op = ip->match; |
@@ -525,23 +526,33 @@ L_LA(_r3000_write_probe_fail) | |||
525 | #define i_ssnop(buf) i_sll(buf, 0, 0, 1) | 526 | #define i_ssnop(buf) i_sll(buf, 0, 0, 1) |
526 | #define i_ehb(buf) i_sll(buf, 0, 0, 3) | 527 | #define i_ehb(buf) i_sll(buf, 0, 0, 3) |
527 | 528 | ||
528 | #ifdef CONFIG_64BIT | ||
529 | static __init int __maybe_unused in_compat_space_p(long addr) | 529 | static __init int __maybe_unused in_compat_space_p(long addr) |
530 | { | 530 | { |
531 | /* Is this address in 32bit compat space? */ | 531 | /* Is this address in 32bit compat space? */ |
532 | #ifdef CONFIG_64BIT | ||
532 | return (((addr) & 0xffffffff00000000L) == 0xffffffff00000000L); | 533 | return (((addr) & 0xffffffff00000000L) == 0xffffffff00000000L); |
534 | #else | ||
535 | return 1; | ||
536 | #endif | ||
533 | } | 537 | } |
534 | 538 | ||
535 | static __init int __maybe_unused rel_highest(long val) | 539 | static __init int __maybe_unused rel_highest(long val) |
536 | { | 540 | { |
541 | #ifdef CONFIG_64BIT | ||
537 | return ((((val + 0x800080008000L) >> 48) & 0xffff) ^ 0x8000) - 0x8000; | 542 | return ((((val + 0x800080008000L) >> 48) & 0xffff) ^ 0x8000) - 0x8000; |
543 | #else | ||
544 | return 0; | ||
545 | #endif | ||
538 | } | 546 | } |
539 | 547 | ||
540 | static __init int __maybe_unused rel_higher(long val) | 548 | static __init int __maybe_unused rel_higher(long val) |
541 | { | 549 | { |
550 | #ifdef CONFIG_64BIT | ||
542 | return ((((val + 0x80008000L) >> 32) & 0xffff) ^ 0x8000) - 0x8000; | 551 | return ((((val + 0x80008000L) >> 32) & 0xffff) ^ 0x8000) - 0x8000; |
543 | } | 552 | #else |
553 | return 0; | ||
544 | #endif | 554 | #endif |
555 | } | ||
545 | 556 | ||
546 | static __init int rel_hi(long val) | 557 | static __init int rel_hi(long val) |
547 | { | 558 | { |
@@ -555,7 +566,6 @@ static __init int rel_lo(long val) | |||
555 | 566 | ||
556 | static __init void i_LA_mostly(u32 **buf, unsigned int rs, long addr) | 567 | static __init void i_LA_mostly(u32 **buf, unsigned int rs, long addr) |
557 | { | 568 | { |
558 | #ifdef CONFIG_64BIT | ||
559 | if (!in_compat_space_p(addr)) { | 569 | if (!in_compat_space_p(addr)) { |
560 | i_lui(buf, rs, rel_highest(addr)); | 570 | i_lui(buf, rs, rel_highest(addr)); |
561 | if (rel_higher(addr)) | 571 | if (rel_higher(addr)) |
@@ -567,16 +577,18 @@ static __init void i_LA_mostly(u32 **buf, unsigned int rs, long addr) | |||
567 | } else | 577 | } else |
568 | i_dsll32(buf, rs, rs, 0); | 578 | i_dsll32(buf, rs, rs, 0); |
569 | } else | 579 | } else |
570 | #endif | ||
571 | i_lui(buf, rs, rel_hi(addr)); | 580 | i_lui(buf, rs, rel_hi(addr)); |
572 | } | 581 | } |
573 | 582 | ||
574 | static __init void __maybe_unused i_LA(u32 **buf, unsigned int rs, | 583 | static __init void __maybe_unused i_LA(u32 **buf, unsigned int rs, long addr) |
575 | long addr) | ||
576 | { | 584 | { |
577 | i_LA_mostly(buf, rs, addr); | 585 | i_LA_mostly(buf, rs, addr); |
578 | if (rel_lo(addr)) | 586 | if (rel_lo(addr)) { |
579 | i_ADDIU(buf, rs, rs, rel_lo(addr)); | 587 | if (!in_compat_space_p(addr)) |
588 | i_daddiu(buf, rs, rs, rel_lo(addr)); | ||
589 | else | ||
590 | i_addiu(buf, rs, rs, rel_lo(addr)); | ||
591 | } | ||
580 | } | 592 | } |
581 | 593 | ||
582 | /* | 594 | /* |
@@ -1085,7 +1097,10 @@ build_get_pgd_vmalloc64(u32 **p, struct label **l, struct reloc **r, | |||
1085 | } else { | 1097 | } else { |
1086 | i_LA_mostly(p, ptr, modd); | 1098 | i_LA_mostly(p, ptr, modd); |
1087 | il_b(p, r, label_vmalloc_done); | 1099 | il_b(p, r, label_vmalloc_done); |
1088 | i_daddiu(p, ptr, ptr, rel_lo(modd)); | 1100 | if (in_compat_space_p(modd)) |
1101 | i_addiu(p, ptr, ptr, rel_lo(modd)); | ||
1102 | else | ||
1103 | i_daddiu(p, ptr, ptr, rel_lo(modd)); | ||
1089 | } | 1104 | } |
1090 | 1105 | ||
1091 | l_vmalloc(l, *p); | 1106 | l_vmalloc(l, *p); |
@@ -1106,7 +1121,10 @@ build_get_pgd_vmalloc64(u32 **p, struct label **l, struct reloc **r, | |||
1106 | } else { | 1121 | } else { |
1107 | i_LA_mostly(p, ptr, swpd); | 1122 | i_LA_mostly(p, ptr, swpd); |
1108 | il_b(p, r, label_vmalloc_done); | 1123 | il_b(p, r, label_vmalloc_done); |
1109 | i_daddiu(p, ptr, ptr, rel_lo(swpd)); | 1124 | if (in_compat_space_p(swpd)) |
1125 | i_addiu(p, ptr, ptr, rel_lo(swpd)); | ||
1126 | else | ||
1127 | i_daddiu(p, ptr, ptr, rel_lo(swpd)); | ||
1110 | } | 1128 | } |
1111 | } | 1129 | } |
1112 | 1130 | ||