Commit 02a54177 authored by Ralf Baechle's avatar Ralf Baechle

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: default avatarRalf Baechle <ralf@linux-mips.org>
parent 5210edcd
...@@ -148,8 +148,8 @@ enum label_id { ...@@ -148,8 +148,8 @@ enum label_id {
label_leave, label_leave,
label_vmalloc, label_vmalloc,
label_vmalloc_done, label_vmalloc_done,
label_tlbw_hazard, label_tlbw_hazard_0,
label_split, label_split = label_tlbw_hazard_0 + 8,
label_tlbl_goaround1, label_tlbl_goaround1,
label_tlbl_goaround2, label_tlbl_goaround2,
label_nopage_tlbl, label_nopage_tlbl,
...@@ -167,7 +167,7 @@ UASM_L_LA(_second_part) ...@@ -167,7 +167,7 @@ UASM_L_LA(_second_part)
UASM_L_LA(_leave) UASM_L_LA(_leave)
UASM_L_LA(_vmalloc) UASM_L_LA(_vmalloc)
UASM_L_LA(_vmalloc_done) UASM_L_LA(_vmalloc_done)
UASM_L_LA(_tlbw_hazard) /* _tlbw_hazard_x is handled differently. */
UASM_L_LA(_split) UASM_L_LA(_split)
UASM_L_LA(_tlbl_goaround1) UASM_L_LA(_tlbl_goaround1)
UASM_L_LA(_tlbl_goaround2) UASM_L_LA(_tlbl_goaround2)
...@@ -181,6 +181,30 @@ UASM_L_LA(_large_segbits_fault) ...@@ -181,6 +181,30 @@ UASM_L_LA(_large_segbits_fault)
UASM_L_LA(_tlb_huge_update) UASM_L_LA(_tlb_huge_update)
#endif #endif
static int __cpuinitdata hazard_instance;
static void uasm_bgezl_hazard(u32 **p, struct uasm_reloc **r, int instance)
{
switch (instance) {
case 0 ... 7:
uasm_il_bgezl(p, r, 0, label_tlbw_hazard_0 + instance);
return;
default:
BUG();
}
}
static void uasm_bgezl_label(struct uasm_label **l, u32 **p, int instance)
{
switch (instance) {
case 0 ... 7:
uasm_build_label(l, *p, label_tlbw_hazard_0 + instance);
break;
default:
BUG();
}
}
/* /*
* For debug purposes. * For debug purposes.
*/ */
...@@ -478,9 +502,10 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l, ...@@ -478,9 +502,10 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,
* This branch uses up a mtc0 hazard nop slot and saves * This branch uses up a mtc0 hazard nop slot and saves
* two nops after the tlbw instruction. * two nops after the tlbw instruction.
*/ */
uasm_il_bgezl(p, r, 0, label_tlbw_hazard); uasm_bgezl_hazard(p, r, hazard_instance);
tlbw(p); tlbw(p);
uasm_l_tlbw_hazard(l, *p); uasm_bgezl_label(l, p, hazard_instance);
hazard_instance++;
uasm_i_nop(p); uasm_i_nop(p);
break; break;
...@@ -527,14 +552,16 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l, ...@@ -527,14 +552,16 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,
break; break;
case CPU_NEVADA: case CPU_NEVADA:
uasm_i_nop(p); /* QED specifies 2 nops hazard */
uasm_i_nop(p); /* QED specifies 2 nops hazard */ uasm_i_nop(p); /* QED specifies 2 nops hazard */
/* /*
* This branch uses up a mtc0 hazard nop slot and saves * This branch uses up a mtc0 hazard nop slot and saves
* a nop after the tlbw instruction. * a nop after the tlbw instruction.
*/ */
uasm_il_bgezl(p, r, 0, label_tlbw_hazard); uasm_bgezl_hazard(p, r, hazard_instance);
tlbw(p); tlbw(p);
uasm_l_tlbw_hazard(l, *p); uasm_bgezl_label(l, p, hazard_instance);
hazard_instance++;
break; break;
case CPU_RM7000: case CPU_RM7000:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment