mirror of
https://github.com/ARMSX2/ARMSX2.git
synced 2026-08-24 16:50:16 -07:00
* EE: the D-cache store-tag lookup dropped the top three bits of the tag DXSTG takes a guest physical page from TagLo and has to turn it into the host pointer our tags carry. It did that by routing the page through its KSEG0 alias, which meant masking the tag to 29 bits first -- and KSEG0 is only 512 MB wide, so the mask was not a formality. Every physical page at or above 0x20000000 folded into the low half of the map and resolved to whatever happened to live at the folded address. The consequence that matters is that a page past the end of the physical map folded onto real memory: 0x60129000 resolved to 0x00129000, and the eviction wrote 64 bytes of cache line into guest RAM the tag never named. Use vtlb_GetPhyPtr instead, which is what the debugger and PSM already use to ask this question. It covers the whole 1 GB physical map and answers null both for a handler page and for an address off the end of the map, so the unbacked case is now decided by the same lookup that produces the pointer rather than by a truncation. Where a tag naming one of our main-RAM mirrors resolves changes as a side effect of that, and is deliberately left unpinned. Those mirrors are our physical map's, not a console's: an SCPH-30001 has no RAM at those physical addresses, and an eviction steered at one reached nothing at all. There is no hardware answer to hold us to, so nothing asserts one. * Tests: point the DXSTG unresolvable-page check at a page that is unresolvable The check named 0x1FFFF000, described as "BIOS/unmapped territory at the top of the physical map". That page is the last one of the 4 MB BIOS ROM mapped at 0x1FC00000, so it is real backing memory: the test took the backed branch every time, wrote 64 bytes into the loaded BIOS image, and asserted only that nothing faulted. The branch it was named for -- the one carrying the safety property -- had no coverage at all. Name 0x60129000 instead. It is past the end of the physical map, and it is the page with teeth, because the old 29-bit fold sent it to 0x00129000 in main RAM. A witness there turns "we did not fault" into "we did not write somewhere the guest never named", which is the property worth holding. An SCPH-30001 agrees with that much: an eviction steered above the end of RAM puts nothing into RAM. Nothing beyond it is asserted -- where a tag naming one of our main-RAM mirrors resolves is emulator-specific, so it stays unpinned, with a comment saying so and why. * Tests: stop the DXSTG write-back check skipping on 16K-page hosts MapAt's candidate addresses are 4K-aligned and none is 16K-aligned, so on a 16K-page kernel -- Asahi, Apple Silicon, some Android, and one of our own CI jobs -- the kernel rejects every one of them and the mapping fails. The write-back check treated that as a precondition and skipped outright, which took its guest-side assertions with it: the ones that actually pin where a DXSTG-steered eviction lands, none of which need anything from the host. The mapping is only the negative control, there to show the write-back did not ALSO reach the host page carrying the same number. Make it optional. The guest-side half now runs everywhere and only the control drops out. DxstgDirtyStaysInsideGuestMemory still skips, and should: it is entirely about the host page. That leaves one skip here on a 16K-page host instead of two, and none at all on a 4K one.