Skip to content

cpu-tests: User mode with UX=1 under a KX=0 kernel (IRIX 6 n32), and loads behind loads - #153

Merged
techomancer merged 3 commits into
mainfrom
cpu-tests-umode
Sep 30, 2026
Merged

techomancer merged 3 commits into
mainfrom
cpu-tests-umode

Conversation

@danifunker

Copy link
Copy Markdown
Collaborator

Two groups of tests that never made it upstream after #109, plus the docs for them. Tests only - no emulator changes.

umode: User mode the way IRIX 6 runs it (new group, 12 tests)

IRIX 6 runs n32 processes with Status.UX = 1 under a 32-bit kernel (KX = 0), so every exception and every ERET switches addressing mode. The rest of the suite runs with KX = SX = UX = 1, and IRIX 5's o32 processes run with all three clear, so nothing covered the switch.

Each test runs a few words at kuseg 0x00400000 in User mode under three Status settings - all64 (KX = SX = UX = 1), irix5 (all clear) and irix6 (UX alone). It records every exception taken: vector, Cause, EPC, BadVAddr, Context, XContext, EntryHi. Covered:

  • syscalls as the first and second instruction after ERET (the second is libc's _getuid: li v0,1024; syscall)
  • a break, then a syscall right after the handler's ERET
  • a software interrupt pending at the ERET
  • load and instruction-fetch TLB refills: XTLB vector with UX = 1, the 32-bit one without; fixed up and retried
  • KSEG0 and misaligned loads from User mode (AdEL)
  • 64-bit operations with UX set

Where it came from. IRIX 6.5's installer died on the sgiindy_MiSTer FPGA core with init died (why = 3, what = 0xb). init's saved frame showed a TLBL at the general exception vector's own address, reported on the syscall in _getuid: the core built the vector address in the kernel's 32-bit mode and fetched it under the process's UX = 1. Before the core's fix, umode/syscall_second reproduced that frame exactly. After it, the core passes all but umode/fetch_miss_entry, on the FPGA and in its simulator, and IRIX 6.2 and 6.5 install.

Also make ONLY=group_umode (any group): builds identity plus one group, for iterating on a slow target such as an HDL simulator.

Loads and stores right behind a load (4 tests)

mem/load_then_load, mem/load_then_load_evict, mem/load_then_store and tlb/load_then_mapped_load: the follow-on to #109's load_then_* tests. A load or store right behind a load, in four cache states, with evictions, an LWL merge, KSEG1 against KSEG0, and TLB walks on either load. mem/load_then_load found the FPGA core releasing a stalled load's execute hold on the completion of the load ahead of it.

Results

IRIS at this branch's base (08be293, default features, interpreter). The control is main's own suite on the same binary, per rules/testing/cpu-tests-known-failure-baseline.md:

main's suite (246 tests) this branch (262 tests) FAIL list
IRIS --cpu r4400 2132 passed / 124 failed 2622 / 124 identical
IRIS --cpu r5000 2119 / 108 2610 / 108 identical

All 16 new tests pass on both. An older IRIS build (2026-08-31) failed some umode refill-vector and KSEG0 checks; current main passes them.

None of the new tests has run on an Indy yet. They are derived from the R4000 manual, and the README's "not yet run on silicon" table and docs/status.md list them.

🤖 Generated with Claude Code

danifunker and others added 3 commits September 30, 2026 06:28
mem/load_then_load, mem/load_then_load_evict, mem/load_then_store and
tlb/load_then_mapped_load: the second access right behind a load that does
not name the loaded register, in every mix of cold and warm D-cache lines,
with an eviction and a write-back between the two, with LWL's merge, KSEG1
against KSEG0, and with a TLB walk on either side. Plain architecture; a
core whose memory stage reads a synchronous cache RAM is where these go
wrong.

On the sgiindy_MiSTer core (build 37 RTL) they found a stalled load being
released on the completion of the load ahead of it; with that fixed the
suite is 2409/0 over 250 tests in its simulator, as is the build 36 control
that stalls every load behind a load. Not yet run on an Indy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
IRIX 6 runs n32 processes with Status.UX = 1 under a 32-bit kernel with
KX = 0, so every exception and ERET switches addressing modes; the rest
of the suite runs KX = SX = UX = 1 and IRIX 5 runs all three clear, so
nothing covered the switch. Each test runs a few words at kuseg
0x00400000 in User mode under all64 / irix5 / irix6 Status settings and
records every exception (vector, Cause, EPC, BadVAddr, Context,
XContext, EntryHi): syscalls first/second after ERET (libc _getuid),
break, a pending interrupt, data and fetch TLB refills (fixed up and
retried), KSEG0 and misaligned loads, and 64-bit ops with UX.

`make ONLY=group_x` builds identity + one group for slow targets.

IRIS main passes all 12. An IRIS build from 2026-08-31 failed the
refill-vector and KSEG0-from-User checks; current main passes them.
On the sgiindy_MiSTer FPGA core, umode/syscall_second reproduced IRIX
6.5's init death exactly (TLBL at the general vector's own address,
EPC on _getuid's syscall) before the core's fix.
Derived from the R4000 manual; not yet measured on silicon.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
README: `make ONLY=`, the umode row in "not yet run on silicon", what
the group found on the FPGA core, and the tests/ layout line.
docs/status.md: mem 24, tlb 11, umode 12, total 262, and which tests
postdate the 2026-09-11 silicon run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@techomancer
techomancer merged commit 98a523e into main Sep 30, 2026
4 of 5 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