From 3c8ee6c34e2a15163429fe582554e184d4f2c979 Mon Sep 17 00:00:00 2001 From: atomchild411 <143453386+atomchild411@users.noreply.github.com> Date: Mon, 19 Oct 2026 16:23:27 -0800 Subject: [PATCH] cpu: decode the R10000's cache algorithms from its own table The R10000 is MIPS IV, so Config.K0 was read with the VR5000 table, where 4 and 5 are reserved and decode as uncached. On the R10000 they are the coherent algorithms (R10000 UM Table 4-1). An OS that runs KSEG0 with K0=5, as IRIX on the O2 does, had every kernel fetch, load and store sent uncached to the bus. Co-Authored-By: Claude Opus 5.5 --- src/cpu/mips_exec.rs | 16 ++++++++++++++-- src/cpu/mips_exec_test.rs | 17 +++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/cpu/mips_exec.rs b/src/cpu/mips_exec.rs index a23bbd63..794b2d39 100644 --- a/src/cpu/mips_exec.rs +++ b/src/cpu/mips_exec.rs @@ -4703,10 +4703,22 @@ va={:#018x} phys={:#010x} (code pfn {:#x}, page {:#010x}, word {}/{})", /// /// `C::MIPS4` is the model discriminator — R5000 is the MIPS IV part, /// R4400 the MIPS III one — matching how the rest of this file selects - /// per-model behaviour. + /// per-model behaviour. The R10000 is MIPS IV too and has a third table + /// (`R10000 UM` Table 4-1), selected by `C::R10K_CACHE_OPS`. #[inline] pub(crate) fn decode_cache_attr(c: u32) -> u32 { - if C::MIPS4 { + if C::R10K_CACHE_OPS { + // R10000 UM Table 4-1: MIPS IV like the R5000, but its own table. + // 4 and 5 are the coherent algorithms, not reserved: the O2's + // IRIX runs KSEG0 with K0=5, and reading that as uncached sent + // every kernel fetch, load and store to the bus. 7 (uncached + // accelerated) only gathers stores; a load is a plain uncached one. + match c & 0x7 { + 3 => TR_CACHEABLE, + 4 | 5 => TR_CACHEABLE_COH, + _ => TR_UNCACHED, // 2 and 7; 0, 1, 6 reserved + } + } else if C::MIPS4 { // VR5000 Table 6-6. match c & 0x7 { 0 | 1 => TR_CACHEABLE, // write-through -> write-back (see above) diff --git a/src/cpu/mips_exec_test.rs b/src/cpu/mips_exec_test.rs index 3d98a4f7..03e50423 100644 --- a/src/cpu/mips_exec_test.rs +++ b/src/cpu/mips_exec_test.rs @@ -5685,6 +5685,23 @@ mod tests { assert_eq!(E::decode_cache_attr(3), crate::cpu::mips_exec::TR_CACHEABLE); } + #[test] + fn test_decode_cache_attr_matches_the_r10000_table() { + type E = MipsExecutor; + // R10000 UM Table 4-1: MIPS IV, but 4/5 are the coherent algorithms + // (the O2's IRIX runs KSEG0 with K0=5) and 0/1 are reserved. + for (c, want) in [(0u32, crate::cpu::mips_exec::TR_UNCACHED), + (1, crate::cpu::mips_exec::TR_UNCACHED), + (2, crate::cpu::mips_exec::TR_UNCACHED), + (3, crate::cpu::mips_exec::TR_CACHEABLE), + (4, crate::cpu::mips_exec::TR_CACHEABLE_COH), + (5, crate::cpu::mips_exec::TR_CACHEABLE_COH), + (6, crate::cpu::mips_exec::TR_UNCACHED), + (7, crate::cpu::mips_exec::TR_UNCACHED)] { + assert_eq!(E::decode_cache_attr(c), want, "R10000 C={c} per UM Table 4-1"); + } + } + #[test] fn test_decode_cache_attr_matches_the_vr5000_table() { let (exec, _mem) = create_executor_m4(); // PassthroughCacheM4 => MIPS4 = true