Thiemo,
The XTLB refill handler splitter misplaces labels associated with an
instruction that gets placed in the branch delay slot of the splitting
branch. Here's an example:
tlb-handler.img: file format binary
Disassembly of section .data:
0000000000000000 <.data>:
0: 001bd83c dsll32 k1,k1,0x0
4: 035bd02f dsubu k0,k0,k1
8: 3c1b803a lui k1,0x803a
c: 10000026 b 0xa8
10: 677b4000 daddiu k1,k1,16384
...
80: 403a4000 dmfc0 k0,c0_badvaddr
84: 403b5000 dmfc0 k1,c0_entryhi
88: 035bd026 xor k0,k0,k1
8c: 001ad37a dsrl k0,k0,0xd
90: 17400018 bnez k0,0xf4
94: 403a4000 dmfc0 k0,c0_badvaddr
98: 07400018 bltz k0,0xfc
9c: 403b2000 dmfc0 k1,c0_context
a0: 001bddfb dsra k1,k1,0x17
a4: df7b0000 ld k1,0(k1)
a8: 001ad73a dsrl k0,k0,0x1c
ac: 335a1ff8 andi k0,k0,0x1ff8
b0: 037ad82d daddu k1,k1,k0
b4: 403a4000 dmfc0 k0,c0_badvaddr
b8: df7b0000 ld k1,0(k1)
bc: 001ad4ba dsrl k0,k0,0x12
c0: 335a0ff8 andi k0,k0,0xff8
c4: 037ad82d daddu k1,k1,k0
c8: 403aa000 dmfc0 k0,c0_xcontext
cc: df7b0000 ld k1,0(k1)
d0: 335a0ff0 andi k0,k0,0xff0
d4: 037ad82d daddu k1,k1,k0
d8: df7a0000 ld k0,0(k1)
dc: df7b0008 ld k1,8(k1)
e0: 001ad1ba dsrl k0,k0,0x6
e4: 409a1000 mtc0 k0,c0_entrylo0
e8: 001bd9ba dsrl k1,k1,0x6
ec: 409b1800 mtc0 k1,c0_entrylo1
f0: 42000006 tlbwr
f4: 42000018 eret
f8: 1000ffc1 b 0x0
fc: 3c1bc000 lui k1,0xc000
I've fixed it by separating the label mover (and the reloc mover, for
consistency) and using it to fix up relevant labels. I'll apply it if
it's OK with you.
Maciej
patch-mips-2.6.10-rc2-20041124-mips-tlb-label-0
diff -up --recursive --new-file
linux-mips-2.6.10-rc2-20041124.macro/arch/mips/mm/tlbex.c
linux-mips-2.6.10-rc2-20041124/arch/mips/mm/tlbex.c
--- linux-mips-2.6.10-rc2-20041124.macro/arch/mips/mm/tlbex.c 2004-11-24
21:37:38.000000000 +0000
+++ linux-mips-2.6.10-rc2-20041124/arch/mips/mm/tlbex.c 2004-12-02
17:41:11.000000000 +0000
@@ -550,22 +550,33 @@ static __init void resolve_relocs(struct
__resolve_relocs(rel, l);
}
-static __init void copy_handler(struct reloc *rel, struct label *lab,
- u32 *first, u32 *end, u32* target)
+static __init void move_relocs(struct reloc *rel, u32 *first, u32 *end,
+ long off)
{
- long off = (long)(target - first);
-
- memcpy(target, first, (end - first) * sizeof(u32));
-
for (; rel->lab != label_invalid; rel++)
if (rel->addr >= first && rel->addr < end)
rel->addr += off;
+}
+static __init void move_labels(struct label *lab, u32 *first, u32 *end,
+ long off)
+{
for (; lab->lab != label_invalid; lab++)
if (lab->addr >= first && lab->addr < end)
lab->addr += off;
}
+static __init void copy_handler(struct reloc *rel, struct label *lab,
+ u32 *first, u32 *end, u32 *target)
+{
+ long off = (long)(target - first);
+
+ memcpy(target, first, (end - first) * sizeof(u32));
+
+ move_relocs(rel, first, end, off);
+ move_labels(lab, first, end, off);
+}
+
static __init int __attribute__((unused)) insn_has_bdelay(struct reloc *rel,
u32 *addr)
{
@@ -1110,6 +1121,7 @@ static void __init build_r4000_tlb_refil
i_nop(&f);
else {
copy_handler(relocs, labels, split, split + 1, f);
+ move_labels(labels, f, f + 1, -1);
f++;
split++;
}
|