Re: [PATCH] MIPS: mm: Prevent a TLB shutdown on initial uniquification
From: Maciej W. Rozycki
Date: Tue Nov 11 2025 - 10:41:51 EST
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);