Skip to content

snapshot: stop the l1d dirty bit aliasing physical address bit 31 - #66

Merged
techomancer merged 1 commit into
techomancer:mainfrom
sgidevnet:snapshot-restore-1
Jul 31, 2026
Merged

snapshot: stop the l1d dirty bit aliasing physical address bit 31#66
techomancer merged 1 commit into
techomancer:mainfrom
sgidevnet:snapshot-restore-1

Conversation

@mach-kernel

@mach-kernel mach-kernel commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

The serialized L1D tag mixed two layouts from the manual: PTag at [31:8] from the TagLo register, with the dirty bit at 27 from the physical cache line. Bit 27 is PTag bit 19 in the register layout, so it aliased physical address bit 31. Every dirty L1D line came back 2 GB from its own address, matches_phys never matched it again, and it was never written back.

Changes
  • Use Figure 11-4 throughout, so the dirty bit stays at 27 where the hardware puts W and PTag moves down out of its way:
    • [27] W, write-back
    • [25:24] CS
    • [23:0] PTag
  • W' and P are parity over fields this model does not compute, so they stay zero.
  • save_cache_state writes dc_tag_format; absent or 0 means the old layout and migrate_l1d_tag_word_v0 repacks it, 1 is current, anything else is an error rather than a silent misread.
  • A v0 word is ambiguous at bit 27, phys_bit31 | dirty, so migration resolves it in favour of dirty. Safe because no cacheable mapping exists at or above 0x8000_0000: the highest range in device_map is HIMEM_END at 0x3000_0000.
  • SCHEMA_VERSION 3 to 4. Without it a v3 reader takes a v4 tag as clean and drops the line without writing it back, which is this same bug running the other way. The bump makes it refuse the snapshot instead, per rules/snapshot/snapshot-manifest-format-snapshottoml-schema-version1.md.
  • rules/snapshot/l1d-tag-must-match-the-cache-line-layout.md records why a round-trip test cannot catch this.

R4000 primary D-cache line format, R4400 manual Figure 11-4

Coverage / needs eyes
  • l1d_tag_dirty_round_trips_address and l1d_tag_v0_word_migrates both fail with only the two From impls reverted. The first reports left: 2147483648 right: 0, the 2 GB offset.
  • Tests cover lomem, himem, 0x8000_0000 and cs 1-3. cs = 2 with dirty set is the dominant real state, since mark_l1d_dirty sets dirty without touching cs.
  • cargo test --release --features lightning,rex-jit,chd: 358 passed, 11 ignored, over 3 runs.
  • CS and W stay independent fields, so no state normalizes across a snapshot. An earlier revision of this PR folded dirty into PState and lost both Shared-with-dirty and CleanExclusive-with-dirty.
  • l1d_tag_invalid_stays_invalid survives that mutation. It is a guard, not a regression test.
  • L1ITag still uses the TagLo register layout ([31:8] PTag, [7:6] PState). It has no dirty bit so nothing aliases, but the two tags in this file now follow different figures.

@mach-kernel
mach-kernel force-pushed the snapshot-restore-1 branch 2 times, most recently from 15cc45a to 12bc6cd Compare July 30, 2026 14:00
@mach-kernel mach-kernel changed the title [Snapshot Restore] L1D cache tag must match the CP0 TagLo format [Snapshot Restore] encode the l1d dirty bit where the hardware puts it Jul 30, 2026
@mach-kernel
mach-kernel force-pushed the snapshot-restore-1 branch 2 times, most recently from e3f790c to 7a1cefc Compare July 30, 2026 14:11
The serialized L1D tag mixed two layouts from the R4400 manual: PTag at
[31:8] from the TagLo register (Figure 4-18) with the dirty bit at 27
from the physical cache line (Figure 11-4). Bit 27 is PTag bit 19 in the
register layout, so it aliased physical address bit 31 and every dirty
line came back 2 GB from its own address, never matched again, and was
never written back.

Use Figure 11-4 throughout: PTag [23:0], CS [25:24], W [27]. Snapshots
written before the dc_tag_format key are migrated.
@mach-kernel mach-kernel changed the title [Snapshot Restore] encode the l1d dirty bit where the hardware puts it [Snapshot Restore] Stop the L1D dirty bit aliasing physical address bit 31 Jul 30, 2026
@mach-kernel mach-kernel changed the title [Snapshot Restore] Stop the L1D dirty bit aliasing physical address bit 31 snapshot: stop the l1d dirty bit aliasing physical address bit 31 Jul 30, 2026
@techomancer
techomancer merged commit 2068fce into techomancer:main Jul 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants