aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2012-10-13 16:46:26 -0400
committerRalf Baechle <ralf@linux-mips.org>2012-10-16 16:21:27 -0400
commit02a5417751c31cd64197652c000a5ab0d3261465 (patch)
tree8f0ad16efad10d42ed45016baf517583d928e4e2 /arch/mips
parent5210edcd527773c227465ad18e416a894966324f (diff)
MIPS: tlbex: Deal with re-definition of label
The microassembler used in tlbex.c does not notice if a label is redefined resulting in relocations against such labels silently missrelocated. The issues exists since commit add6eb04776db4189ea89f596cbcde31b899be9d [Synthesize TLB exception handlers at runtime.] in 2.6.10 and went unnoticed for so long because the relocations for the affected branches got computed to do something *almost* sensible. The issue affects R4000, R4400, QED/IDT RM5230, RM5231, RM5260, RM5261, RM5270 and RM5271 processors. Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/mm/tlbex.c41
1 files changed, 34 insertions, 7 deletions
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 658a520364c..6ea152552e5 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -148,8 +148,8 @@ enum label_id {
148 label_leave, 148 label_leave,
149 label_vmalloc, 149 label_vmalloc,
150 label_vmalloc_done, 150 label_vmalloc_done,
151 label_tlbw_hazard, 151 label_tlbw_hazard_0,
152 label_split, 152 label_split = label_tlbw_hazard_0 + 8,
153 label_tlbl_goaround1, 153 label_tlbl_goaround1,
154 label_tlbl_goaround2, 154 label_tlbl_goaround2,
155 label_nopage_tlbl, 155 label_nopage_tlbl,
@@ -167,7 +167,7 @@ UASM_L_LA(_second_part)
167UASM_L_LA(_leave) 167UASM_L_LA(_leave)
168UASM_L_LA(_vmalloc) 168UASM_L_LA(_vmalloc)
169UASM_L_LA(_vmalloc_done) 169UASM_L_LA(_vmalloc_done)
170UASM_L_LA(_tlbw_hazard) 170/* _tlbw_hazard_x is handled differently. */
171UASM_L_LA(_split) 171UASM_L_LA(_split)
172UASM_L_LA(_tlbl_goaround1) 172UASM_L_LA(_tlbl_goaround1)
173UASM_L_LA(_tlbl_goaround2) 173UASM_L_LA(_tlbl_goaround2)
@@ -181,6 +181,30 @@ UASM_L_LA(_large_segbits_fault)
181UASM_L_LA(_tlb_huge_update) 181UASM_L_LA(_tlb_huge_update)
182#endif 182#endif
183 183
184static int __cpuinitdata hazard_instance;
185
186static void uasm_bgezl_hazard(u32 **p, struct uasm_reloc **r, int instance)
187{
188 switch (instance) {
189 case 0 ... 7:
190 uasm_il_bgezl(p, r, 0, label_tlbw_hazard_0 + instance);
191 return;
192 default:
193 BUG();
194 }
195}
196
197static void uasm_bgezl_label(struct uasm_label **l, u32 **p, int instance)
198{
199 switch (instance) {
200 case 0 ... 7:
201 uasm_build_label(l, *p, label_tlbw_hazard_0 + instance);
202 break;
203 default:
204 BUG();
205 }
206}
207
184/* 208/*
185 * For debug purposes. 209 * For debug purposes.
186 */ 210 */
@@ -478,9 +502,10 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,
478 * This branch uses up a mtc0 hazard nop slot and saves 502 * This branch uses up a mtc0 hazard nop slot and saves
479 * two nops after the tlbw instruction. 503 * two nops after the tlbw instruction.
480 */ 504 */
481 uasm_il_bgezl(p, r, 0, label_tlbw_hazard); 505 uasm_bgezl_hazard(p, r, hazard_instance);
482 tlbw(p); 506 tlbw(p);
483 uasm_l_tlbw_hazard(l, *p); 507 uasm_bgezl_label(l, p, hazard_instance);
508 hazard_instance++;
484 uasm_i_nop(p); 509 uasm_i_nop(p);
485 break; 510 break;
486 511
@@ -528,13 +553,15 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,
528 553
529 case CPU_NEVADA: 554 case CPU_NEVADA:
530 uasm_i_nop(p); /* QED specifies 2 nops hazard */ 555 uasm_i_nop(p); /* QED specifies 2 nops hazard */
556 uasm_i_nop(p); /* QED specifies 2 nops hazard */
531 /* 557 /*
532 * This branch uses up a mtc0 hazard nop slot and saves 558 * This branch uses up a mtc0 hazard nop slot and saves
533 * a nop after the tlbw instruction. 559 * a nop after the tlbw instruction.
534 */ 560 */
535 uasm_il_bgezl(p, r, 0, label_tlbw_hazard); 561 uasm_bgezl_hazard(p, r, hazard_instance);
536 tlbw(p); 562 tlbw(p);
537 uasm_l_tlbw_hazard(l, *p); 563 uasm_bgezl_label(l, p, hazard_instance);
564 hazard_instance++;
538 break; 565 break;
539 566
540 case CPU_RM7000: 567 case CPU_RM7000: