Skip to content

cpu: four fixes to the full R10000 cache model - #267

Merged
techomancer merged 4 commits into
techomancer:mainfrom
atomchild411:r10k-full-model
Oct 21, 2026
Merged

techomancer merged 4 commits into
techomancer:mainfrom
atomchild411:r10k-full-model

Conversation

@atomchild411

Copy link
Copy Markdown
Collaborator

cpu: four fixes to the full R10000 cache model

No machine runs the full R10000 model today (IP28 uses the shadow cache), so these are latent on main; they matter to anything that runs the full model, as the O2 does through its PROM. One commit each.

  1. Index cache ops reach both ways. On the R10000, Index_WB_Inv, Index_Load/Store_Tag and Index_Load/Store_Data take the way from address bit 0. The full model is direct-mapped at the full cache size and ignored that bit, so a whole-cache flush reached only the lower half of L1I, L1D and L2; dirty lines in the upper half were written back later, over reused pages (OpenBSD/sgi on an R10000 O2: forked ksh processes died with SIGBUS). Way 1 now maps to the upper half, for tag and data ops alike.
  2. 44 virtual address bits. CpuCache used CpuModel's default of 40 for every model; the shadow model already says 44 for the R10000. XContext's fields are laid out around that width, so a 64-bit kernel's TLB refill handler on a full-model R10000 would find the wrong page-table entry.
  3. No debug print on every secondary Index_Store_Tag. It printed 32768 lines each time firmware initialised the cache.
  4. No VCE on the R10000. Virtual coherency exceptions are an R4000/R4400 feature. On a secondary hit under a different virtual index, the R10000 writes back and drops the primary copies made under the old index and records the new one; the full model raised the R4400's VCEI/VCED instead, which an R10000 kernel never expects.

Tests

  • New unit tests: the_r10000_full_model_has_44_va_bits, and the_r10000_resolves_a_colour_mismatch_where_the_r4400_raises_vce (one line under two colours: VCE on the R4400; on the R10000 the load succeeds and a store under one colour is what a load under the other sees). r10000_index_flush_reaches_both_ways for the index ops (fails without the fix).
  • cargo test --lib: all pass, apart from the two tests that fail the same way on main here. Built in the three CI configurations.

🤖 Generated with Claude Code

atomchild411 and others added 4 commits October 20, 2026 23:12
On the R10000, Index_WB_Inv, Index_Load/Store_Tag and Index_Load/Store_Data
take the index within one way from the low address bits and the way from
bit 0. The full (data-carrying) R10000 model in mips_cache_v2 is
direct-mapped at the full cache size and ignored bit 0, so a whole-cache
flush -- every index of way 0, then of way 1 -- reached only the lower half
of L1I, L1D and L2. Dirty lines in the upper half outlived the flush and
were written back later, over pages that had been reused in the meantime.

Map way 1 to the upper half of each cache, for the tag ops and the data ops
alike, so the two still name the same line.

Only R10000Cache is affected. IP28 machines use R10000ShadowCache, which is
out of the data path and already decodes bit 0 as the way.

Found running OpenBSD/sgi 6.9 on an emulated O2 (R10000) that used
R10000Cache: forked ksh processes died with SIGBUS and "write after free"
as stale lines landed on their copy-on-write pages. With the fix, 3 x 300
subshells run clean.

Test: r10000_index_flush_reaches_both_ways (fails without the fix).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CpuCache took CpuModel's default of 40 for every model, while the shadow
model says 44 for the R10000, as the part implements. XContext's fields
are laid out around that width, so a 64-bit kernel's TLB refill handler
on a full-model R10000 would find the wrong page-table entry. Latent: no
machine runs the full R10000 model (IP28 uses the shadow).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The full R10000 model printed a line for every secondary-cache
Index_Store_Tag: 32768 of them each time firmware initialises the
cache.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… VCE

Virtual coherency exceptions are an R4000/R4400 feature. The R10000
keeps the virtual index in its secondary tags but, on a hit under a
different index, writes back and drops the primary copies made under the
old one and records the new one. The full model raised the R4400's
VCEI/VCED there, which an R10000 kernel never expects (OpenBSD dies on
the first page it maps at two colours). Test: one line under two
colours, VCE on the R4400, coherent on the R10000.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@techomancer
techomancer merged commit 4b254ee into techomancer:main Oct 21, 2026
14 checks passed
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