Skip to content

aarch64: legacy MIPS JIT stalls during a stock IRIX 6.5.22 IP24 boot #84

Description

@srcshelton

The legacy jit CPU feature reproducibly stops making guest boot progress immediately after the IRIX 6.5.22 kernel banner on a native Linux/aarch64 build. The emulator remains CPU-active and continues compiling/promoting JIT blocks, but the serial console never reaches The system is coming up. or a login prompt.

The same current Iris revision, disk, PROM, NVRAM, machine configuration, and fresh-overlay procedure reach login with the interpreter/lightning build and with jitv2.

Revision and host

  • Iris main: cfd1728d11efcf16de6072bcd7e3f158b7df19c7 (fix lui-addiu-ori opcode fusion when first instruction is in bd slot)
  • Host hardware: Apple M1 Pro
  • Host OS: macOS 26.5.2 (Darwin 25.5.0, arm64)
  • Container runtime: Docker 29.7.2, native linux/arm64
  • Container kernel: LinuxKit 6.12.76, aarch64
  • Rust: 1.99.0-nightly (d453bdd8f 2026-08-14)
  • Cranelift: 0.134.3
  • Generated Cargo.lock SHA-256:
    b953d6606cfde79637e088c910b7ad5c0c01fba649986d5488b873692712057c

There is no amd64 container or Rosetta/QEMU translation layer in this test: both the container and the Iris executable are aarch64.

Guest and media

  • Machine profile: indy_ip24
  • CPU/memory profile: R4400, 256 MiB
  • Unmodified vendor IRIX 6.5.22 installation from the published worker image ghcr.io/sgidevnet/irix-worker@sha256:6be7c6c3f92d15705f2d08a3d1b919d6f6241b5364ced22ae0d962820e4724cd
  • Disk SHA-256: a31113aae5a0c27ba2ca2ac567c76659608329ba7d0de0243d358f3571a690f5
  • Guest banner: IRIX Release 6.5 IP22 Version 10070055 System V
  • Embedded Iris PROM
  • Disk overlay enabled

Each run starts with a newly created, empty snapshot/CAS volume. The image has no jit-profile.bin, and no saved JIT profile is supplied.

Build

cargo build --release --locked \
--features chd,jit,rex-jit \
--bin iris --bin iris-ci

The tested iris binary reports:

iris: build features: jit rex-jit tlbvmap chd

Its SHA-256 is:

ba162566d598cb005b697e5964cc26018a96fb3c382f4c01099211019b6d964b

Configuration

headless = trueno_audio = trueci = trueci_socket = "/tmp/iris.sock"banks = [128, 128, 0, 0]
nvram = "/path/to/nvram.bin"serial_log = "/tmp/console.log"
[machine]
profile = "indy_ip24"
[jit]
enabled = true
[scsi.1]
path = "/path/to/indy.chd"cdrom = falseoverlay = true

No other JIT settings are specified, so the current defaults apply:

  • max_tier = 2
  • compile_stores = false
  • verify = false
  • probe = 500
  • probe_min = 100

JitConfig::apply_env() converts this to IRIS_JIT=1, IRIS_JIT_MAX_TIER=2, and IRIS_JIT_NO_STORES=1 before machine creation.

Reproduction

  1. Remove any saved snapshot, COW overlay, CAS, and JIT profile.
  2. Start Iris with the build and configuration above.
  3. Wait for the serial login prompt.

Two independent clean runs both reached the release banner and then produced no further serial output for the remainder of a 600-second login wait:

Running power-on diagnostics...
Starting up the system...
To perform system maintenance instead, press <Esc>
IRIX Release 6.5 IP22 Version 10070055 System V
Copyright 1987-2003 Silicon Graphics, Inc.
All Rights Reserved.

The two console logs are byte-identical (314 bytes, SHA-256 69edecbe81dab5cb3d6493d77daae9a3a4ce63c239b3c35e131be5d768c1ecaf). There is no guest panic or Memory fault message in either run.

This is not an idle or crashed emulator. Iris continued consuming one host core, compiling blocks, and promoting tiers. The final periodic status from each run was:

JIT: 860007684 total (2.8% jit), 1135 blocks, 329↑ 0↓ 0⟲, probe=100(eff 100), pc=ffffffff88005840
JIT: 850008199 total (2.7% jit), 1185 blocks, 356↑ 0↓ 0⟲, probe=100(eff 100), pc=ffffffff88005840

Both waits ended only because iris-ci serial-wait reached its 600,000 ms deadline waiting for console login:.

Expected result and controls

A chd,lightning,rex-jit build from the exact same commit and base image reached login using the same procedure.

A chd,lightning,rex-jit,jitv2 build also reached login in two independent fresh runs. Its logs show JITv2 actively compiled at least 50,000 functions in each run, so those were not interpreter-only controls.

Aside: Architecture support

The README currently describes the legacy engine as translating MIPS to native x86_64. The implementation, however, uses cranelift_native::builder(), selects the host calling convention, and contains explicit aarch64 policies for speculative graduation and helper-diamond limits. It therefore builds and runs an aarch64 code generator rather than emitting x86_64 code on this host.

If Linux/aarch64 is intentionally unsupported for the legacy JIT, an explicit build-time or startup rejection would avoid silent guest misexecution. If it is intended to work, this appears to be an aarch64-specific boot regression.

Possibly related prior work

The repository already documents a legacy-JIT corruption class that can surface as an IRIX kernel TLB miss, plus architecture-specific Cranelift helper-diamond limits:

This reproduction differs in that it uses Linux/aarch64, a fresh stock 6.5.22 boot with no persisted profile, store compilation disabled, and stalls without printing a TLB-miss panic.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions