[PATCH] MIPS: mm: Prevent a TLB shutdown on initial uniquification

Maciej W. Rozycki posted 1 patch 3 months ago
There is a newer version of this series
arch/mips/mm/tlb-r4k.c |   92 +++++++++++++++++++++++++++++--------------------
1 file changed, 55 insertions(+), 37 deletions(-)
[PATCH] MIPS: mm: Prevent a TLB shutdown on initial uniquification
Posted by Maciej W. Rozycki 3 months ago
Depending on the particular CPU implementation a TLB shutdown may occur 
if multiple matching entries are detected upon the execution of a TLBP 
or the TLBWI/TLBWR instructions.  Given that we don't know what entries 
we have been handed we need to be very careful with the initial TLB 
setup and avoid all these instructions.

Therefore read all the TLB entries one by one with the TLBR instruction, 
bypassing the content addressing logic, and preinitialize the TLB using 
addresses outside our usual unique range and avoiding clashes with any 
incoming contents before making the usual call to local_flush_tlb_all().

This fixes (at least) R4x00 cores if TLBP hits multiple matching TLB 
entries (SGI IP22 PROM for examples sets up all TLBs to the same virtual 
address).

Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
Fixes: 35ad7e181541 ("MIPS: mm: tlb-r4k: Uniquify TLB entries on init")
Cc: stable@vger.kernel.org # v6.17+
---
Hi,

 I have verified this lightly, also with some diagnostics added so as to 
make sure things get set up correctly, with my Malta/74Kf system for a 
32-bit configuration and with my SWARM/BCM1250 system for a 64-bit one.  
Sadly the latter box does not finish booting either way, but it's to be 
bisected separately.

 Can you please give it a try with your systems?

  Maciej
---
 arch/mips/mm/tlb-r4k.c |   92 +++++++++++++++++++++++++++++--------------------
 1 file changed, 55 insertions(+), 37 deletions(-)

linux-mips-tlb-r4k-uniquify-fix.diff
Index: linux-macro/arch/mips/mm/tlb-r4k.c
===================================================================
--- linux-macro.orig/arch/mips/mm/tlb-r4k.c
+++ linux-macro/arch/mips/mm/tlb-r4k.c
@@ -15,6 +15,7 @@
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
 #include <linux/export.h>
+#include <linux/sort.h>
 
 #include <asm/cpu.h>
 #include <asm/cpu-type.h>
@@ -508,54 +509,70 @@ static int __init set_ntlb(char *str)
 
 __setup("ntlb=", set_ntlb);
 
-/* Initialise all TLB entries with unique values */
+
+/* Comparison function for EntryHi VPN fields.  */
+static int r4k_vpn_cmp(const void *a, const void *b)
+{
+	return ((*(unsigned long *)a - *(unsigned long *)b) >>
+		(sizeof(unsigned long) - sizeof(int)) * 8);
+}
+
+/*
+ * Initialise all TLB entries with unique values that do not clash with
+ * what we have been handed over and what we'll be using ourselves.
+ */
 static void r4k_tlb_uniquify(void)
 {
-	int entry = num_wired_entries();
+	unsigned long tlb_vpns[1 << MIPS_CONF1_TLBS_SIZE];
+	int tlbsize = current_cpu_data.tlbsize;
+	int start = num_wired_entries();
+	unsigned long vpn_mask;
+	int cnt, ent, idx, i;
+
+	vpn_mask = GENMASK(cpu_vmbits - 1, 13);
+	vpn_mask |= IS_ENABLED(CONFIG_64BIT) ? 3ULL << 62 : 1 << 31;
 
 	htw_stop();
+
+	for (i = start, cnt = 0; i < tlbsize; i++, cnt++) {
+		unsigned long vpn;
+
+		write_c0_index(i);
+		mtc0_tlbr_hazard();
+		tlb_read();
+		tlb_read_hazard();
+		vpn = read_c0_entryhi();
+		vpn &= vpn_mask & PAGE_MASK;
+		tlb_vpns[cnt] = vpn;
+	}
+
+	sort(tlb_vpns, cnt, sizeof(tlb_vpns[0]), r4k_vpn_cmp, NULL);
+
 	write_c0_entrylo0(0);
 	write_c0_entrylo1(0);
 
-	while (entry < current_cpu_data.tlbsize) {
-		unsigned long asid_mask = cpu_asid_mask(&current_cpu_data);
-		unsigned long asid = 0;
-		int idx;
+	idx = 0;
+	ent = cnt;
+	for (i = start; i < tlbsize; i++)
+		while (1) {
+			unsigned long entryhi, vpn;
 
-		/* Skip wired MMID to make ginvt_mmid work */
-		if (cpu_has_mmid)
-			asid = MMID_KERNEL_WIRED + 1;
+			entryhi = UNIQUE_ENTRYHI(ent);
+			vpn = entryhi & vpn_mask & PAGE_MASK;
 
-		/* Check for match before using UNIQUE_ENTRYHI */
-		do {
-			if (cpu_has_mmid) {
-				write_c0_memorymapid(asid);
-				write_c0_entryhi(UNIQUE_ENTRYHI(entry));
+			if (idx >= cnt || vpn < tlb_vpns[idx]) {
+				write_c0_entryhi(entryhi);
+				write_c0_index(i);
+				mtc0_tlbw_hazard();
+				tlb_write_indexed();
+				ent++;
+				break;
+			} else if (vpn == tlb_vpns[idx]) {
+				ent++;
 			} else {
-				write_c0_entryhi(UNIQUE_ENTRYHI(entry) | asid);
+				idx++;
 			}
-			mtc0_tlbw_hazard();
-			tlb_probe();
-			tlb_probe_hazard();
-			idx = read_c0_index();
-			/* No match or match is on current entry */
-			if (idx < 0 || idx == entry)
-				break;
-			/*
-			 * If we hit a match, we need to try again with
-			 * a different ASID.
-			 */
-			asid++;
-		} while (asid < asid_mask);
-
-		if (idx >= 0 && idx != entry)
-			panic("Unable to uniquify TLB entry %d", idx);
-
-		write_c0_index(entry);
-		mtc0_tlbw_hazard();
-		tlb_write_indexed();
-		entry++;
-	}
+		}
 
 	tlbw_use_hazard();
 	htw_start();
@@ -602,6 +619,7 @@ static void r4k_tlb_configure(void)
 
 	/* From this point on the ARC firmware is dead.	 */
 	r4k_tlb_uniquify();
+	local_flush_tlb_all();
 
 	/* Did I tell you that ARC SUCKS?  */
 }
Re: [PATCH] MIPS: mm: Prevent a TLB shutdown on initial uniquification
Posted by Nick Bowler 3 months ago
On Tue, Nov 11, 2025 at 06:21:46AM +0000, Maciej W. Rozycki wrote:
>  I have verified this lightly, also with some diagnostics added so as to 
> make sure things get set up correctly, with my Malta/74Kf system for a 
> 32-bit configuration and with my SWARM/BCM1250 system for a 64-bit one.  
> Sadly the latter box does not finish booting either way, but it's to be 
> bisected separately.
> 
>  Can you please give it a try with your systems?

With this applied everything appears back to normal on my end, no
problems are immediately apparent at least.  Definitely not seeing
any kind of segfaults during boot.

Thanks, 
  Nick
Re: [PATCH] MIPS: mm: Prevent a TLB shutdown on initial uniquification
Posted by Thomas Bogendoerfer 3 months ago
On Tue, Nov 11, 2025 at 06:21:46AM +0000, Maciej W. Rozycki wrote:
> Depending on the particular CPU implementation a TLB shutdown may occur 
> if multiple matching entries are detected upon the execution of a TLBP 
> or the TLBWI/TLBWR instructions.  Given that we don't know what entries 
> we have been handed we need to be very careful with the initial TLB 
> setup and avoid all these instructions.
> 
> Therefore read all the TLB entries one by one with the TLBR instruction, 
> bypassing the content addressing logic, and preinitialize the TLB using 
> addresses outside our usual unique range and avoiding clashes with any 
> incoming contents before making the usual call to local_flush_tlb_all().
> 
> This fixes (at least) R4x00 cores if TLBP hits multiple matching TLB 
> entries (SGI IP22 PROM for examples sets up all TLBs to the same virtual 
> address).
> 
> Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
> Fixes: 35ad7e181541 ("MIPS: mm: tlb-r4k: Uniquify TLB entries on init")
> Cc: stable@vger.kernel.org # v6.17+
> ---
> Hi,
> 
>  I have verified this lightly, also with some diagnostics added so as to 
> make sure things get set up correctly, with my Malta/74Kf system for a 
> 32-bit configuration and with my SWARM/BCM1250 system for a 64-bit one.  
> Sadly the latter box does not finish booting either way, but it's to be 
> bisected separately.
> 
>  Can you please give it a try with your systems?

it's booting on my R4400 SGI Indy, but I see a lot of segmentation
faults during system start. If I comment out r4k_tlb_uniquify() every-
thing boots fine, which is kind of strange as there is a local_flush_tlb_all(),
which should leave the TLB in the same stage.... No idea why, yet.

>  arch/mips/mm/tlb-r4k.c |   92 +++++++++++++++++++++++++++++--------------------
>  1 file changed, 55 insertions(+), 37 deletions(-)
> 
> linux-mips-tlb-r4k-uniquify-fix.diff
> Index: linux-macro/arch/mips/mm/tlb-r4k.c
> ===================================================================
> --- linux-macro.orig/arch/mips/mm/tlb-r4k.c
> +++ linux-macro/arch/mips/mm/tlb-r4k.c
> @@ -15,6 +15,7 @@
>  #include <linux/mm.h>
>  #include <linux/hugetlb.h>
>  #include <linux/export.h>
> +#include <linux/sort.h>
>  
>  #include <asm/cpu.h>
>  #include <asm/cpu-type.h>
> @@ -508,54 +509,70 @@ static int __init set_ntlb(char *str)
>  
>  __setup("ntlb=", set_ntlb);
>  
> -/* Initialise all TLB entries with unique values */
> +
> +/* Comparison function for EntryHi VPN fields.  */
> +static int r4k_vpn_cmp(const void *a, const void *b)
> +{
> +	return ((*(unsigned long *)a - *(unsigned long *)b) >>
> +		(sizeof(unsigned long) - sizeof(int)) * 8);
> +}
> +
> +/*
> + * Initialise all TLB entries with unique values that do not clash with
> + * what we have been handed over and what we'll be using ourselves.
> + */
>  static void r4k_tlb_uniquify(void)
>  {
> -	int entry = num_wired_entries();
> +	unsigned long tlb_vpns[1 << MIPS_CONF1_TLBS_SIZE];
> +	int tlbsize = current_cpu_data.tlbsize;
> +	int start = num_wired_entries();
> +	unsigned long vpn_mask;
> +	int cnt, ent, idx, i;
> +
> +	vpn_mask = GENMASK(cpu_vmbits - 1, 13);
> +	vpn_mask |= IS_ENABLED(CONFIG_64BIT) ? 3ULL << 62 : 1 << 31;
>  
>  	htw_stop();
> +
> +	for (i = start, cnt = 0; i < tlbsize; i++, cnt++) {

shouldn't we read all TLB entries here ? 

Thomas.

-- 
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea.                                                [ RFC1925, 2.3 ]
Re: [PATCH] MIPS: mm: Prevent a TLB shutdown on initial uniquification
Posted by Maciej W. Rozycki 3 months ago
On Tue, 11 Nov 2025, Thomas Bogendoerfer wrote:

> >  Can you please give it a try with your systems?
> 
> it's booting on my R4400 SGI Indy, but I see a lot of segmentation
> faults during system start. If I comment out r4k_tlb_uniquify() every-
> thing boots fine, which is kind of strange as there is a local_flush_tlb_all(),
> which should leave the TLB in the same stage.... No idea why, yet.

 Can you try the diagnostic patch below, which is what I used to verify 
this change, and report the entries produced?  Otherwise I wonder whether 
I haven't missed a barrier somewhere.

> > +
> > +	for (i = start, cnt = 0; i < tlbsize; i++, cnt++) {
> 
> shouldn't we read all TLB entries here ? 

 Strictly speaking it won't change anything as we call `write_c0_wired(0)' 
in `r4k_tlb_configure' before getting here and wired entries make no sense 
for KSEG0, so whatever would otherwise be there should not clash with our 
unique entries.  But I guess it won't hurt.  OTOH `ent' ought to be set up 
from `tlbsize' rather than `cnt' should the Wired register setting ever 
change.  I'll have a look, but I we need to know why the current version 
causes troubles with your system first.

 NB I wonder how this is supposed to work with mapped kernels, I thought 
the setup made with MAPPED_KERNEL_SETUP_TLB was meant to be permanent 
through the life of the system, hmm...

  Maciej
---
 arch/mips/mm/tlb-r4k.c |   10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

linux-mips-tlb-r4k-uniquify-fix-debug.diff
Index: linux-macro/arch/mips/mm/tlb-r4k.c
===================================================================
--- linux-macro.orig/arch/mips/mm/tlb-r4k.c
+++ linux-macro/arch/mips/mm/tlb-r4k.c
@@ -535,19 +535,23 @@ static void r4k_tlb_uniquify(void)
 	htw_stop();
 
 	for (i = start, cnt = 0; i < tlbsize; i++, cnt++) {
-		unsigned long vpn;
+		unsigned long entryhi, vpn;
 
 		write_c0_index(i);
 		mtc0_tlbr_hazard();
 		tlb_read();
 		tlb_read_hazard();
-		vpn = read_c0_entryhi();
+		entryhi = vpn = read_c0_entryhi();
 		vpn &= vpn_mask & PAGE_MASK;
 		tlb_vpns[cnt] = vpn;
+		printk("[%02x/%02x]: %08lx/%08lx\n", i, cnt, entryhi, vpn);
 	}
 
 	sort(tlb_vpns, cnt, sizeof(tlb_vpns[0]), r4k_vpn_cmp, NULL);
 
+	for (idx = 0; idx < cnt; idx++)
+		printk("[%02x]: %08lx\n", idx, tlb_vpns[idx]);
+
 	write_c0_entrylo0(0);
 	write_c0_entrylo1(0);
 
@@ -560,6 +564,8 @@ static void r4k_tlb_uniquify(void)
 			entryhi = UNIQUE_ENTRYHI(ent);
 			vpn = entryhi & vpn_mask & PAGE_MASK;
 
+			printk("[%02x/%02x/%02x]: %08lx/%08lx\n", i, idx, ent,
+			       vpn, tlb_vpns[idx]);
 			if (idx >= cnt || vpn < tlb_vpns[idx]) {
 				write_c0_entryhi(entryhi);
 				write_c0_index(i);
Re: [PATCH] MIPS: mm: Prevent a TLB shutdown on initial uniquification
Posted by Thomas Bogendoerfer 2 months, 4 weeks ago
On Tue, Nov 11, 2025 at 03:41:50PM +0000, Maciej W. Rozycki wrote:
> On Tue, 11 Nov 2025, Thomas Bogendoerfer wrote:
> 
> > >  Can you please give it a try with your systems?
> > 
> > it's booting on my R4400 SGI Indy, but I see a lot of segmentation
> > faults during system start. If I comment out r4k_tlb_uniquify() every-
> > thing boots fine, which is kind of strange as there is a local_flush_tlb_all(),
> > which should leave the TLB in the same stage.... No idea why, yet.
> 
>  Can you try the diagnostic patch below, which is what I used to verify 
> this change, and report the entries produced?  Otherwise I wonder whether 
> I haven't missed a barrier somewhere.

Update on the issue: Your patch is good and the segmentation faults,
I'm seeing, have IMHO a different reason. Instead of removing the call
to r4k_tlb_uniquify() I've replaced the jal in the binary with a nop.
And the issue is still there with this patched kernel. I've seen
something similair on a R12k Octanes, which comes and goes probably
depeding on code layout. So far I wasn't able to nail this down :-(

Do you want to send a v2 of the patch ? I'm fine with the current version
for applying...

Thomas.

-- 
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea.                                                [ RFC1925, 2.3 ]
Re: [PATCH] MIPS: mm: Prevent a TLB shutdown on initial uniquification
Posted by Maciej W. Rozycki 2 months, 4 weeks ago
On Wed, 12 Nov 2025, Thomas Bogendoerfer wrote:

> >  Can you try the diagnostic patch below, which is what I used to verify 
> > this change, and report the entries produced?  Otherwise I wonder whether 
> > I haven't missed a barrier somewhere.
> 
> Update on the issue: Your patch is good and the segmentation faults,
> I'm seeing, have IMHO a different reason. Instead of removing the call
> to r4k_tlb_uniquify() I've replaced the jal in the binary with a nop.
> And the issue is still there with this patched kernel. I've seen
> something similair on a R12k Octanes, which comes and goes probably
> depeding on code layout. So far I wasn't able to nail this down :-(

 Oh dear!  Something to do with the cache?  Or code alignment perhaps?

 It reminds me of this stuff: 
<https://lore.kernel.org/r/Pine.GSO.3.96.1010625125007.20469D-100000@delta.ds2.pg.gda.pl/>.  

 Building a particular version of binutils freezed the machine solid ~11h 
into the build -- a power cycle was required (there's no hardware reset 
button).  At least it was fully reproducible and always at the same place 
in a `configure' script and changing the shell script in a trivial way, 
such as adding a new-line character, ahead of the place of the lock-up 
made the freeze go away.

 I used the machine's 8-position diagnostic LED display to debug this, by
making it show the syscall and hardware interrupt numbers as the exception 
handlers were entered, so as to narrow the origin down (only to realise 
later on I could have used a 1MiB NVRAM module the system has to store 
more data across a power cycle and retrieve it afterwards, a persistent 
kernel log of sorts).  IIRC it triggered in the exit(2) path.

 The most painful was the need to wait said ~11h for the next piece of 
data in debugging this.

 NB the machine in question is still alive in my lab.  Throwing memory SBE 
ECC errors again recently, but coping regardless, so more memory connector 
cleaning required upon next visit.

> Do you want to send a v2 of the patch ? I'm fine with the current version
> for applying...

 I'll send v2 with an update for the Wired register as we talked.  It may 
take a day or two.

  Maciej
Re: [PATCH] MIPS: mm: Prevent a TLB shutdown on initial uniquification
Posted by Thomas Bogendoerfer 2 months, 4 weeks ago
On Wed, Nov 12, 2025 at 12:16:28PM +0000, Maciej W. Rozycki wrote:
> On Wed, 12 Nov 2025, Thomas Bogendoerfer wrote:
> 
> > >  Can you try the diagnostic patch below, which is what I used to verify 
> > > this change, and report the entries produced?  Otherwise I wonder whether 
> > > I haven't missed a barrier somewhere.
> > 
> > Update on the issue: Your patch is good and the segmentation faults,
> > I'm seeing, have IMHO a different reason. Instead of removing the call
> > to r4k_tlb_uniquify() I've replaced the jal in the binary with a nop.
> > And the issue is still there with this patched kernel. I've seen
> > something similair on a R12k Octanes, which comes and goes probably
> > depeding on code layout. So far I wasn't able to nail this down :-(
> 
>  Oh dear!  Something to do with the cache?  Or code alignment perhaps?

code alignment is probably the trigger. It's reproducible on an R4400SC
and R5000 Indy, but not on a R4000SC Indy. Main difference other than
clock speed is L1 cache size...

And I've missremembered the R12k Octane problem. It's not a segmentation
fault but a bus error, because of an illegal instruction. I tracked it
down to a incorrect data in I-Cache (all 0 cache line, iirc), but never
found the reason for that.

> > Do you want to send a v2 of the patch ? I'm fine with the current version
> > for applying...
> 
>  I'll send v2 with an update for the Wired register as we talked.  It may 
> take a day or two.

no problem, thank you.

Thomas.

-- 
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea.                                                [ RFC1925, 2.3 ]
Re: [PATCH] MIPS: mm: Prevent a TLB shutdown on initial uniquification
Posted by Maciej W. Rozycki 2 months, 4 weeks ago
On Wed, 12 Nov 2025, Thomas Bogendoerfer wrote:

> > > Update on the issue: Your patch is good and the segmentation faults,
> > > I'm seeing, have IMHO a different reason. Instead of removing the call
> > > to r4k_tlb_uniquify() I've replaced the jal in the binary with a nop.
> > > And the issue is still there with this patched kernel. I've seen
> > > something similair on a R12k Octanes, which comes and goes probably
> > > depeding on code layout. So far I wasn't able to nail this down :-(
> > 
> >  Oh dear!  Something to do with the cache?  Or code alignment perhaps?
> 
> code alignment is probably the trigger. It's reproducible on an R4400SC
> and R5000 Indy, but not on a R4000SC Indy. Main difference other than
> clock speed is L1 cache size...

 So both combined!  Trust my guts' feeling. ;)  At least you now have a 
reproducer you can fiddle with.  But good luck with debugging as this 
stuff can be tough!

> And I've missremembered the R12k Octane problem. It's not a segmentation
> fault but a bus error, because of an illegal instruction. I tracked it
> down to a incorrect data in I-Cache (all 0 cache line, iirc), but never
> found the reason for that.

 Bummer!

> > > Do you want to send a v2 of the patch ? I'm fine with the current version
> > > for applying...
> > 
> >  I'll send v2 with an update for the Wired register as we talked.  It may 
> > take a day or two.
> 
> no problem, thank you.

 Now posted.  It's often good to sleep on things (an afternoon nap in this 
case).  Thanks for taking the Malta fix BTW.

  Maciej
Re: [PATCH] MIPS: mm: Prevent a TLB shutdown on initial uniquification
Posted by Thomas Bogendoerfer 3 months ago
On Tue, Nov 11, 2025 at 03:41:50PM +0000, Maciej W. Rozycki wrote:
> On Tue, 11 Nov 2025, Thomas Bogendoerfer wrote:
> 
> > >  Can you please give it a try with your systems?
> > 
> > it's booting on my R4400 SGI Indy, but I see a lot of segmentation
> > faults during system start. If I comment out r4k_tlb_uniquify() every-
> > thing boots fine, which is kind of strange as there is a local_flush_tlb_all(),
> > which should leave the TLB in the same stage.... No idea why, yet.
> 
>  Can you try the diagnostic patch below, which is what I used to verify 
> this change, and report the entries produced?  Otherwise I wonder whether 
> I haven't missed a barrier somewhere.

output below, I don't see anything obvious. I dumped the TLB after the
local_flush_tlb_all() and everything looks as before.

> 
> > > +
> > > +	for (i = start, cnt = 0; i < tlbsize; i++, cnt++) {
> > 
> > shouldn't we read all TLB entries here ? 
> 
>  Strictly speaking it won't change anything as we call `write_c0_wired(0)' 
> in `r4k_tlb_configure' before getting here and wired entries make no sense 
> for KSEG0, so whatever would otherwise be there should not clash with our 
> unique entries.

I see

>  NB I wonder how this is supposed to work with mapped kernels, I thought 
> the setup made with MAPPED_KERNEL_SETUP_TLB was meant to be permanent 
> through the life of the system, hmm...

I looked at it once some time ago and already forgot details :-(

Thomas.


[00/00]: 80000000/80000000
[01/01]: 80000000/80000000
[02/02]: 80000000/80000000
[03/03]: 80000000/80000000
[04/04]: 80000000/80000000
[05/05]: 80000000/80000000
[06/06]: 80000000/80000000
[07/07]: 80000000/80000000
[08/08]: 80000000/80000000
[09/09]: 80000000/80000000
[0a/0a]: 80000000/80000000
[0b/0b]: 80000000/80000000
[0c/0c]: 80000000/80000000
[0d/0d]: 80000000/80000000
[0e/0e]: 80000000/80000000
[0f/0f]: 80000000/80000000
[10/10]: 80000000/80000000
[11/11]: 80000000/80000000
[12/12]: 80000000/80000000
[13/13]: 80000000/80000000
[14/14]: 80000000/80000000
[15/15]: 80000000/80000000
[16/16]: 80000000/80000000
[17/17]: 80000000/80000000
[18/18]: 80000000/80000000
[19/19]: 80000000/80000000
[1a/1a]: 80000000/80000000
[1b/1b]: 80000000/80000000
[1c/1c]: 80000000/80000000
[1d/1d]: 80000000/80000000
[1e/1e]: 80000000/80000000
[1f/1f]: 80000000/80000000
[20/20]: 80000000/80000000
[21/21]: 80000000/80000000
[22/22]: 80000000/80000000
[23/23]: 80000000/80000000
[24/24]: 80000000/80000000
[25/25]: 80000000/80000000
[26/26]: 80000000/80000000
[27/27]: 80000000/80000000
[28/28]: 80000000/80000000
[29/29]: 80000000/80000000
[2a/2a]: 80000000/80000000
[2b/2b]: 80000000/80000000
[2c/2c]: 80000000/80000000
[2d/2d]: 80000000/80000000
[2e/2e]: 80000000/80000000
[2f/2f]: 80000000/80000000
[00]: 80000000
[01]: 80000000
[02]: 80000000
[03]: 80000000
[04]: 80000000
[05]: 80000000
[06]: 80000000
[07]: 80000000
[08]: 80000000
[09]: 80000000
[0a]: 80000000
[0b]: 80000000
[0c]: 80000000
[0d]: 80000000
[0e]: 80000000
[0f]: 80000000
[10]: 80000000
[11]: 80000000
[12]: 80000000
[13]: 80000000
[14]: 80000000
[15]: 80000000
[16]: 80000000
[17]: 80000000
[18]: 80000000
[19]: 80000000
[1a]: 80000000
[1b]: 80000000
[1c]: 80000000
[1d]: 80000000
[1e]: 80000000
[1f]: 80000000
[20]: 80000000
[21]: 80000000
[22]: 80000000
[23]: 80000000
[24]: 80000000
[25]: 80000000
[26]: 80000000
[27]: 80000000
[28]: 80000000
[29]: 80000000
[2a]: 80000000
[2b]: 80000000
[2c]: 80000000
[2d]: 80000000
[2e]: 80000000
[2f]: 80000000
[00/00/30]: 80060000/80000000
[00/01/30]: 80060000/80000000
[00/02/30]: 80060000/80000000
[00/03/30]: 80060000/80000000
[00/04/30]: 80060000/80000000
[00/05/30]: 80060000/80000000
[00/06/30]: 80060000/80000000
[00/07/30]: 80060000/80000000
[00/08/30]: 80060000/80000000
[00/09/30]: 80060000/80000000
[00/0a/30]: 80060000/80000000
[00/0b/30]: 80060000/80000000
[00/0c/30]: 80060000/80000000
[00/0d/30]: 80060000/80000000
[00/0e/30]: 80060000/80000000
[00/0f/30]: 80060000/80000000
[00/10/30]: 80060000/80000000
[00/11/30]: 80060000/80000000
[00/12/30]: 80060000/80000000
[00/13/30]: 80060000/80000000
[00/14/30]: 80060000/80000000
[00/15/30]: 80060000/80000000
[00/16/30]: 80060000/80000000
[00/17/30]: 80060000/80000000
[00/18/30]: 80060000/80000000
[00/19/30]: 80060000/80000000
[00/1a/30]: 80060000/80000000
[00/1b/30]: 80060000/80000000
[00/1c/30]: 80060000/80000000
[00/1d/30]: 80060000/80000000
[00/1e/30]: 80060000/80000000
[00/1f/30]: 80060000/80000000
[00/20/30]: 80060000/80000000
[00/21/30]: 80060000/80000000
[00/22/30]: 80060000/80000000
[00/23/30]: 80060000/80000000
[00/24/30]: 80060000/80000000
[00/25/30]: 80060000/80000000
[00/26/30]: 80060000/80000000
[00/27/30]: 80060000/80000000
[00/28/30]: 80060000/80000000
[00/29/30]: 80060000/80000000
[00/2a/30]: 80060000/80000000
[00/2b/30]: 80060000/80000000
[00/2c/30]: 80060000/80000000
[00/2d/30]: 80060000/80000000
[00/2e/30]: 80060000/80000000
[00/2f/30]: 80060000/80000000
[00/30/30]: 80060000/00010000
[01/30/31]: 80062000/00010000
[02/30/32]: 80064000/00010000
[03/30/33]: 80066000/00010000
[04/30/34]: 80068000/00010000
[05/30/35]: 8006a000/00010000
[06/30/36]: 8006c000/00010000
[07/30/37]: 8006e000/00010000
[08/30/38]: 80070000/00010000
[09/30/39]: 80072000/00010000
[0a/30/3a]: 80074000/00010000
[0b/30/3b]: 80076000/00010000
[0c/30/3c]: 80078000/00010000
[0d/30/3d]: 8007a000/00010000
[0e/30/3e]: 8007c000/00010000
[0f/30/3f]: 8007e000/00010000
[10/30/40]: 80080000/00010000
[11/30/41]: 80082000/00010000
[12/30/42]: 80084000/00010000
[13/30/43]: 80086000/00010000
[14/30/44]: 80088000/00010000
[15/30/45]: 8008a000/00010000
[16/30/46]: 8008c000/00010000
[17/30/47]: 8008e000/00010000
[18/30/48]: 80090000/00010000
[19/30/49]: 80092000/00010000
[1a/30/4a]: 80094000/00010000
[1b/30/4b]: 80096000/00010000
[1c/30/4c]: 80098000/00010000
[1d/30/4d]: 8009a000/00010000
[1e/30/4e]: 8009c000/00010000
[1f/30/4f]: 8009e000/00010000
[20/30/50]: 800a0000/00010000
[21/30/51]: 800a2000/00010000
[22/30/52]: 800a4000/00010000
[23/30/53]: 800a6000/00010000
[24/30/54]: 800a8000/00010000
[25/30/55]: 800aa000/00010000
[26/30/56]: 800ac000/00010000
[27/30/57]: 800ae000/00010000
[28/30/58]: 800b0000/00010000
[29/30/59]: 800b2000/00010000
[2a/30/5a]: 800b4000/00010000
[2b/30/5b]: 800b6000/00010000
[2c/30/5c]: 800b8000/00010000
[2d/30/5d]: 800ba000/00010000
[2e/30/5e]: 800bc000/00010000
[2f/30/5f]: 800be000/00010000

-- 
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea.                                                [ RFC1925, 2.3 ]