d-iii-s / msim

Light-weight MIPS R4000 and RISC-V system simulator
https://d3s.mff.cuni.cz/software/msim/
GNU General Public License v2.0
5 stars 4 forks source link

MIPS: add TLB debugging features #54

Open vhotspur opened 8 months ago

vhotspur commented 8 months ago

It would be useful if in some mode (perhaps we can abuse -t for this?) MSIM would warn about possibly wrong use of TLB.

vhotspur commented 8 months ago

Both of above should be checked when TLBWI and TLBWR are executed: if such combination of VPN and ASID already exists, we should print a warning.

Setting TS should be done only when entries are read, hence it is a more expensive check (but we might propagate this information from checks in TLBWI/TLBWR).

vhotspur commented 8 months ago

And for future reference, some interesting links:

https://student.cs.uwaterloo.ca/~cs350/common/sys161manual/mips.html

One must never load the TLB in such a fashion that two (or more) entries can match the same virtual address. If this happens, the processor shuts down and is unrecoverable except by hard reset. Since there is no way to prevent entries from matching, one should clear the TLB by loading each entry with a distinct VPAGE, and use VPAGEs from the kseg0 or kseg1 regions that will never be presented to the MMU for translation. To reset the TLB at startup, since it is not cleared by processor reset, one should use a second, potentially larger, set of distinct VPAGEs and check that each is not already present before loading it.

https://github.com/torvalds/linux/blob/master/arch/mips/mm/tlb-r4k.c (invalidation uses unique addresses from KSEG to mark entry as ignored/invalid; code below is simplified).

#define _UNIQUE_ENTRYHI(base, idx) (((base) + ((idx) << (PAGE_SHIFT + 1)))
#define UNIQUE_ENTRYHI(idx) _UNIQUE_ENTRYHI(0x80000000, idx)
write_c0_entryhi(UNIQUE_ENTRYHI(entry));

https://www.spinics.net/lists/mips/msg12390.html

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.

vhotspur commented 8 months ago

It might be best if TLB is initialized so that entry->vpn2 points to KSEG (the way Linux invalidates TLB entries) so that the check of if ((virt.lo & entry->mask) == entry->vpn2) { never hits on an entry that was not yet written to (at the moment, both entry->mask and entry->vpn2 are zero and the condition is always true).

Debug dump of TLB can still check for mask == 0 to print a special line for not yet initialized entry.