Skip to content

Commit 35ad7e1

Browse files
FlyGoattsbogend
authored andcommitted
MIPS: mm: tlb-r4k: Uniquify TLB entries on init
Hardware or bootloader will initialize TLB entries to any value, which may collide with kernel's UNIQUE_ENTRYHI value. On MIPS microAptiv/M5150 family of cores this will trigger machine check exception and cause boot failure. On M5150 simulation this could happen 7 times out of 1000 boots. Replace local_flush_tlb_all() with r4k_tlb_uniquify() which probes each TLB ENTRIHI unique value for collisions before it's written, and in case of collision try a different ASID. Cc: [email protected] Signed-off-by: Jiaxun Yang <[email protected]> Signed-off-by: Thomas Bogendoerfer <[email protected]>
1 parent b9ace06 commit 35ad7e1

File tree

1 file changed

+55
-1
lines changed

1 file changed

+55
-1
lines changed

arch/mips/mm/tlb-r4k.c

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,60 @@ static int __init set_ntlb(char *str)
508508

509509
__setup("ntlb=", set_ntlb);
510510

511+
/* Initialise all TLB entries with unique values */
512+
static void r4k_tlb_uniquify(void)
513+
{
514+
int entry = num_wired_entries();
515+
516+
htw_stop();
517+
write_c0_entrylo0(0);
518+
write_c0_entrylo1(0);
519+
520+
while (entry < current_cpu_data.tlbsize) {
521+
unsigned long asid_mask = cpu_asid_mask(&current_cpu_data);
522+
unsigned long asid = 0;
523+
int idx;
524+
525+
/* Skip wired MMID to make ginvt_mmid work */
526+
if (cpu_has_mmid)
527+
asid = MMID_KERNEL_WIRED + 1;
528+
529+
/* Check for match before using UNIQUE_ENTRYHI */
530+
do {
531+
if (cpu_has_mmid) {
532+
write_c0_memorymapid(asid);
533+
write_c0_entryhi(UNIQUE_ENTRYHI(entry));
534+
} else {
535+
write_c0_entryhi(UNIQUE_ENTRYHI(entry) | asid);
536+
}
537+
mtc0_tlbw_hazard();
538+
tlb_probe();
539+
tlb_probe_hazard();
540+
idx = read_c0_index();
541+
/* No match or match is on current entry */
542+
if (idx < 0 || idx == entry)
543+
break;
544+
/*
545+
* If we hit a match, we need to try again with
546+
* a different ASID.
547+
*/
548+
asid++;
549+
} while (asid < asid_mask);
550+
551+
if (idx >= 0 && idx != entry)
552+
panic("Unable to uniquify TLB entry %d", idx);
553+
554+
write_c0_index(entry);
555+
mtc0_tlbw_hazard();
556+
tlb_write_indexed();
557+
entry++;
558+
}
559+
560+
tlbw_use_hazard();
561+
htw_start();
562+
flush_micro_tlb();
563+
}
564+
511565
/*
512566
* Configure TLB (for init or after a CPU has been powered off).
513567
*/
@@ -547,7 +601,7 @@ static void r4k_tlb_configure(void)
547601
temp_tlb_entry = current_cpu_data.tlbsize - 1;
548602

549603
/* From this point on the ARC firmware is dead. */
550-
local_flush_tlb_all();
604+
r4k_tlb_uniquify();
551605

552606
/* Did I tell you that ARC SUCKS? */
553607
}

0 commit comments

Comments
 (0)