Subject: [PATCH] Label misplacement on an XTLB refill handler split

From: "Maciej W. Rozycki" <[email-masked]>
Date: Thu, 2 Dec 2004 18:03:35 +0000 (GMT)

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++;
 		}

---

From: Thiemo Seufer <[email-masked]>
Date: Thu, 2 Dec 2004 19:49:30 +0100

> branch.  Here's an example:
[snip]
> consistency) and using it to fix up relevant labels.  I'll apply it if 
[snip]
> +			move_labels(labels, f, f + 1, -1);

Thanks for catching this. Please apply.

Thiemo

---

From: Ralf Baechle <[email-masked]>
Date: Thu, 2 Dec 2004 21:30:00 +0100

>   f4:	42000018 	eret

Not directly related but seeing the eret here reminded me that we're still
not handling the R4000PC/SC v2.2/v3.0 erratum 6 where returning from a
cache error exception handler to the eret instruction of another exception
handler that was just about to return to user mode was not being
treated properly.

In case you care ;-)

  Ralf