Subject: [patch] Use XKPHYS for 64-bit TLB flushes

From: "Maciej W. Rozycki" <[email-masked]>
Date: Wed, 8 Jan 2003 14:27:05 +0100 (MET)

Hello,

 32-bit R4k TLB flush functions use KSEG0 as an impossible (unmapped) VPN2
value for invalidated TLB entries.  64-bit ones use KSEG0 as well, but
here KSEG0 is a valid XKSEG (mapped) value as it gets interpreted as
0xc00000ff80000000 when written into cp0.EntryHi.  The correct impossible
(unmapped) VPN2 value for the 64-bit mode is XKPHYS. 

 Here is a patch implementing it.  The code runs fine on my R4400SC.  OK
to apply?

 BTW, show_tlb() (in the same file) is buggy and redundant --
dump_tlb_all() is a correct equivalent.  I'd like to remove show_tlb() --
OK?

  Maciej

-- 
+  Maciej W. Rozycki, Technical University of Gdansk, Poland   +
+--------------------------------------------------------------+
+        e-mail: [email-masked], PGP key available        +

patch-mips-2.4.20-pre6-20021212-mips64-tlb-r4k-0
diff -up --recursive --new-file linux-mips-2.4.20-pre6-20021212.macro/arch/mips64/mm/tlb-r4k.c linux-mips-2.4.20-pre6-20021212/arch/mips64/mm/tlb-r4k.c
--- linux-mips-2.4.20-pre6-20021212.macro/arch/mips64/mm/tlb-r4k.c	2002-12-04 03:56:40.000000000 +0000
+++ linux-mips-2.4.20-pre6-20021212/arch/mips64/mm/tlb-r4k.c	2003-01-08 03:54:28.000000000 +0000
@@ -53,7 +53,7 @@ void local_flush_tlb_all(void)
 	__save_and_cli(flags);
 	/* Save old context and create impossible VPN2 value */
 	old_ctx = (read_c0_entryhi() & 0xff);
-	write_c0_entryhi(KSEG0);
+	write_c0_entryhi(XKPHYS);
 	write_c0_entrylo0(0);
 	write_c0_entrylo1(0);
 	BARRIER;
@@ -63,7 +63,7 @@ void local_flush_tlb_all(void)
 	/* Blast 'em all away. */
 	while(entry < mips_cpu.tlbsize) {
 	        /* Make sure all entries differ. */
-	        write_c0_entryhi(KSEG0+entry*0x2000);
+	        write_c0_entryhi(XKPHYS+entry*0x2000);
 		write_c0_index(entry);
 		BARRIER;
 		tlb_write_indexed();
@@ -128,7 +128,7 @@ void local_flush_tlb_range(struct mm_str
 				if(idx < 0)
 					continue;
 				/* Make sure all entries differ. */
-				write_c0_entryhi(KSEG0+idx*0x2000);
+				write_c0_entryhi(XKPHYS+idx*0x2000);
 				BARRIER;
 				tlb_write_indexed();
 				BARRIER;
@@ -167,7 +167,7 @@ void local_flush_tlb_page(struct vm_area
 		if(idx < 0)
 			goto finish;
 		/* Make sure all entries differ. */
-		write_c0_entryhi(KSEG0+idx*0x2000);
+		write_c0_entryhi(XKPHYS+idx*0x2000);
 		BARRIER;
 		tlb_write_indexed();
 	finish:

---

From: Ralf Baechle <[email-masked]>
Date: Wed, 8 Jan 2003 14:59:53 +0100

> (unmapped) VPN2 value for the 64-bit mode is XKPHYS. 

That's a funny one.  Historically the idea was to use KSEG0 because the
for KSEG0 the TLB is not used for translation.  That already failed for
the Sibyte SB1 which is why we have to use different KSEG0 addresses for
each entry there.

>  Here is a patch implementing it.  The code runs fine on my R4400SC.  OK

Yes.

> dump_tlb_all() is a correct equivalent.  I'd like to remove show_tlb() --

Yes.  I'd eventually like to move the tlb dump functions away from the
lib directory into the mm directory which seems to be more the right
place for them.

  Ralf

---

From: Dominic Sweetman <[email-masked]>
Date: Wed, 8 Jan 2003 19:02:07 +0000

> the Sibyte SB1 which is why we have to use different KSEG0 addresses for

Amplification: some MIPS CPUs really hate having the same "virtual
address" in more than one TLB entry.  Some of MIPS Technologies' own
cores are the same.

It's probably better to use legal kuseg virtual addresses (but with
the invalid bit set) for initialising TLBs.  And to make them all
different...

--
Dominic Sweetman
mailto:[email-masked]

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Wed, 8 Jan 2003 20:18:46 +0100 (MET)

> It's probably better to use legal kuseg virtual addresses (but with

 I'd wait until there is an implementation that breaks with KSEG0 or
XKPHYS addresses.  Hopefully forever. 

> the invalid bit set) for initialising TLBs.  And to make them all

 They do are different: KSEG0+entry*0x2000, likewise for XKPHYS -- see the
patch.

---

From: "Mike Uhler" <[email-masked]>
Date: Wed, 08 Jan 2003 11:33:01 -0800

>  They do are different: KSEG0+entry*0x2000, likewise for XKPHYS -- see the

This is precisely what we use for our internal testing (which is also
exported to MIPS32 and MIPS64 architecture licensees) to initialize the
TLB.  I have not yet seen a case where this fails, and would be interested
in hearing about any case where it does fail.

/gmu

-- 

  =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
  Michael Uhler, VP, Systems, Architecture, and Software Products 
  MIPS Technologies, Inc.   Email: [email-masked]   Pager: [email-masked]
  1225 Charleston Road      Voice:  (650)567-5025   FAX:   (650)567-5225
  Mountain View, CA 94043   Mobile: (650)868-6870   Admin: (650)567-5085

---

From: Ralf Baechle <[email-masked]>
Date: Wed, 8 Jan 2003 20:44:08 +0100

> in hearing about any case where it does fail.

We used to use just KSEG0 instead of KSEG0+entry*0x2000.  That was running
fine over years but had to be changed for the sake of two CPUs afair.  There
was some discussion on this list about this and I accepted the change by that
time because Kevin imho correctly argued that the spec left it unspecified
if an implementation is feeding addresses in an unmapped address space
though the TLB.

  Ralf

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Wed, 8 Jan 2003 21:12:03 +0100 (MET)

> if an implementation is feeding addresses in an unmapped address space

 Well, like it or not, CAMs do not like multiple matches -- up to a
physical damage even.  So they should be avoided if possible.  While KSEG0
won't match for any real address translation, there is a non-zero
probability of executing a tlbp for it as a result of buggy code or
execution gone wild (root running crashme?).

---

From: Ralf Baechle <[email-masked]>
Date: Thu, 9 Jan 2003 02:36:01 +0100

> execution gone wild (root running crashme?). 

I'm told the TLB Shutdown bit in the R4000 is basically implemented as an
overcurrent protection.  That is on many chips even a hit on several
entries won't cause a tlb shutdown until the matches do result in the
TLB drawing more than a certain current.

A tlbp on a KSEG0 address shouldn't happen.  If it's attempted we already
have worse problems.

  Ralf

---

From: Carsten Langgaard <[email-masked]>
Date: Thu, 09 Jan 2003 21:10:01 +0100

> if an implementation is feeding addresses in an unmapped address space

All MIPS's CPUs need these unique TLB entries otherwise you get a machine check
error.
Inspired by Kevin Kissell's changes to openBSD, I made the above change
(KSEG0+entry*0x2000) to the TLB routine in linux. It was done when we first tried
to boot linux on the MIPS 4Kc CPU, a couple of years ago.