- C++ 96.7%
- Shell 1.2%
- Python 0.7%
- C 0.6%
- CMake 0.4%
- Other 0.4%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
HARDWARE-ACCELERATED OPENGL NOW RUNS ON THE EMULATED SUN XVR-100:
OpenGL renderer string: Mesa DRI R100 (RV100 5159) SPARC DRI2
OpenGL version string: 1.3 Mesa 21.3.9 Amber
direct rendering: Yes Accelerated: yes
mesa-amber's classic radeon driver, on the emulated GPU, on an emulated UltraSPARC IIIi.
The ring test and IB test pass, r100_cp_init returns 0, accel_working is true, and an
UNMODIFIED xf86-video-ati 22.0.0 comes up with EXA + DRI2 + direct rendering. Xorg loads
the same driver server-side: "AIGLX: Loaded and initialized radeon".
PAIRED with rv100 5437f10. Either half alone leaves the ring test failing with the
identical symptom; merging one without the other is not useful.
NEITHER BUG WAS "THE RING", which is why checking first was worth it. rv100 already had
a complete ring walk, GART walk, PACKET0/1/2/3 decode and IB submission, and its own
handoff records the test passing under QEMU. What was missing was on either side of it.
THIS HALF: softsparc never wired the card's DMA. dev/xvr100.cpp handed rv100 an all-null
HostOps, with a comment saying as much --
rv100::HostOps host{}; // all null: the FCode path does registers and DDC, no
// bus mastering. ... DMA gets wired when Linux radeon needs it.
-- and that day arrived. With sysmem_read null, rv100's dev_cp_sysmem_read zero-fills,
so the CP walked the ring, decoded zero dwords and stopped. The addresses are not
physical either: they are DVMA out of the Fire leaf's IOMMU aperture
(dma_alloc_coherent for the GART table, dma_map_page for each page it points at). The
driver names one itself -- "PCI GART of 512M enabled (table at 0x00000000C4DBC000)",
which is not RAM on a 2 GB machine.
sysmem_read/sysmem_write now go through a new Xvr100State::bus and translate every
access through the leaf-A Fire IOMMU, using the same find_fire_state() walk, the same
leaf and the same raw-DVMA fallback that dev/mpt.cpp and dev/rtl8139.cpp already use,
split at 8 KiB IOMMU page boundaries. No new mechanism -- the third user of an existing
one.
THE OTHER HALF (rv100 5437f10) is the big-endian one: CP_RB_CNTL[17:16] is a byte-swap
field, and r100_cp_init sets RADEON_BUF_SWAP_32BIT under `#ifdef __BIG_ENDIAN` -- the
only such hit in the entire radeon driver. Unmodelled, a sparc64 guest's first ring
packet decodes as garbage.
irq_set IS LEFT NULL, deliberately and measured, not overlooked: r100 runs with
writeback disabled (radeon_device.c:503-505; the guest prints "WB disabled"), so fences
are read from a scratch register over MMIO and radeon_fence_check_lockup()'s delayed
work polls them. Ring test, IB test and a full X session all pass with no interrupt. Not
established for anything that genuinely waits on vblank.
TESTS THAT PROVE THE SEAM, one per side. tests/test_xvr100.cpp drives r100_ring_test()'s
sequence through softsparc's OWN BAR callbacks and BusState -- not rv100's vector-backed
harness -- with a big-endian ring, the swap bit set, and a little-endian GART entry in
the same run. With only the HostOps wiring removed it fails on both the register value
AND on dma_reads not advancing; dma_reads is the discriminator, because the register
value alone would not prove DMA happened.
EVIDENCE. A sorted diff of every [drm] line, before vs after, is exactly: +ring test
succeeded, +ib test succeeded, -ring test failed, -cp isn't working, -cp finalized,
-Unable to find PCI I/O BAR (that last already fixed by WI-DRMBIND). Zero [W cp]/[E cp]
lines in the whole run. Xorg goes from "Acceleration disabled" / "Direct rendering
disabled" / "Screen 0 is not DRI2 capable" to "Acceleration enabled" / "Direct rendering
enabled" / "[DRI2] Setup complete" / "Render acceleration enabled for R100 type cards".
Verified independently on the MERGED tree: gate 39b8b81c57e9bee9e0391ed315b0f73f on
default and every stick-divisor form; ctest 61/61 with the slow tests actually running
(233/240/268/303/602 s, not 0.00 s); rv100 ctest 15/15 after its own merge, and 15/15
again cross-compiled BIG-ENDIAN (s390x + qemu-user), which is the right way to test a
byte-order fix.
HOW FAR SHORT, stated plainly. glxgears ABORTS THE X SERVER, reproducibly, ~300 s after
DRI2 initialises:
Xorg: ../../../../include/privates.h:122: dixGetPrivateAddr:
Assertion `key->initialized' failed.
glxinfo -- context creation and queries, no window -- works in the same session, so the
failure sits between "a GL context exists" and "the first frame is drawn". The kernel
reports nothing: no CS rejection, no GPU lockup, no reset, and rv100 logs zero halts.
TWO HYPOTHESES WERE TESTED AND ELIMINATED rather than argued: no vblank interrupt
(disabling EnablePageFlip and SwapbuffersWait changes nothing) and AIGLX lacking a DRI2
provider (fixing that outright leaves the abort unchanged). It is NOT diagnosed, and no
claim is made either way about whether the device model is at fault. The stock-Mesa
control arm does not settle it either -- X survives glxgears there only because that
stack never gets a GL context on this card at all ("radeon: Invalid PCI ID.").
One userspace addition was needed for amber's libGL: libxcb-dri2.so.0, which Debian 13
does not ship.
No screenshot of hardware-rendered 3D exists: --gpu-screenshot only writes on a clean
exit and these runs end in an interactive shell.
TWO TRAPS WORTH CARRYING. disks/drm-y.img has a DIRTY EXT4 JOURNAL: a debugfs edit of
/drmtest verifies correctly on the host (stat, and a dump+cmp round trip both agree) and
is then SILENTLY TRUNCATED to 3122 bytes by the guest's own journal replay -- 3122 being
the length of WI-DRMBIND's drmtest2.sh, which owns that inode in the journal. Two guest
runs were lost to it; e2fsck cannot repair it. And `rc=$?` after a pipeline reports
head's status, not the command's, which made a batch of "glxgears rc=0" lines meaningless.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FHazRUnQUw1PpsqVjzcH7K
|
||
| docs | ||
| fcode | ||
| include/softsparc | ||
| investigation | ||
| scripts | ||
| src | ||
| tests | ||
| third_party/softfloat | ||
| tools | ||
| .gitignore | ||
| AGENTS.md | ||
| CMakeLists.txt | ||
| PERFORMANCE.md | ||
| README.md | ||
| ROADMAP.md | ||
softsparc
An architecturally-exact SPARC64 full-system emulator, written in C++17.
The first target is a Sun Ultra 25 workstation (UltraSPARC IIIi), booting
the machine's real 2 MiB OpenBoot PROM (OBP) firmware dump — 4.25.9 — from
cold reset through the ok prompt and beyond. The bus scope for this target
is PCI/PCIe only (no ISA, no SBus). A T4-1 / sun4v target is a deliberately
deferred stretch goal: sun4v has a different MMU/trap architecture and blocks
direct ROM access on real hardware, so it is out of scope until the
UltraSPARC IIIi path is solid.
"Architecturally exact" means: correctness is measured against the SPARC V9
architecture manual, the JPS1 commonality specification, and the
UltraSPARC-IIIi processor user's manual — not against "good enough to run
some code". See include/softsparc/common/inventory.h for the running ledger
of which instructions, ASIs, and traps are implemented, and against which
manual section each was verified.
Building
cmake -B build -S .
cmake --build build -j
Requires a C++17 compiler and CMake >= 3.16. No third-party dependencies are
required to build; a later work item vendors Berkeley SoftFloat 3e under
third_party/softfloat for IEEE-754 semantics matching real UltraSPARC IIIi
hardware (see the guarded stanza at the bottom of CMakeLists.txt).
For stricter warnings-as-errors builds (used in CI):
cmake -B build -S . -DSOFTSPARC_WERROR=ON
cmake --build build -j
Testing
ctest --test-dir build --output-on-failure
That is the fast tier: every tests/test_*.cpp is registered automatically and
the whole set runs in a few seconds. Some cases inside it are gated on
environment variables and skip silently without them, printing a SKIP
line that names what is missing — a 0.00 s pass on one of those proves
nothing, so read the skip lines.
The gate set
Three tiers, in increasing cost. All three should be green before a branch is merged.
1. Fast unit tests — the ctest line above. No environment needed.
2. Slow real-ROM and real-OS gates — need the real Ultra 25 OBP dump, and
SOFTSPARC_SLOW_TESTS=1 to acknowledge the minutes they cost:
env SOFTSPARC_SLOW_TESTS=1 \
SOFTSPARC_U25_ROM=/path/to/ultra25-obp.rom \
SOFTSPARC_LINUX_BOOT_MEDIA=/path/to/dbn10-instB.iso \
ctest --test-dir build --output-on-failure
SOFTSPARC_U25_ROM alone unlocks the ROM decode/FCode sweeps; adding
SOFTSPARC_SLOW_TESTS=1 unlocks the full boot-to-ok gates
(test_real_rom_console, test_real_rom_pci_probe, test_pci_config_boot,
test_machine's clean-ok case). SOFTSPARC_LINUX_BOOT_MEDIA additionally
unlocks test_linux_boot_pbm, which boots a real Debian 10 sparc64 kernel
until it has enumerated both Fire PCIe leaves — the only gate in the tree that
exercises what a kernel reads out of OBP's device tree, and the one that would
have caught WI-BRIDGED3's missing IO PBM range regression. See that file's
header for exactly which strings it requires and forbids, and why its step
budget is tight.
3. The OBP equivalence gate — every execution lane must produce a
byte-identical console transcript over a 200M-step OBP boot. --trace-ring 0
is required: without it the run takes ~18 minutes instead of ~30 seconds
and hashes differently.
./build/softsparc --rom /path/to/ultra25-obp.rom \
--ram-mb 2048 --trace-ring 0 --serial-stdout --steps 200000000 2>&1 | md5sum
Run it six times — plain, --dynarec, SOFTSPARC_NO_OPT=1, --dynarec with
SOFTSPARC_NO_BUSFAST=1, --jit, and --jit with SOFTSPARC_NO_OPT=1 — and
all six hashes must match. PERFORMANCE.md records the current expected value
and the reasoning behind each arm. Always pass --ram-mb 2048: below that OBP
still believes it has 2 GB, so the machine is misconfigured rather than
smaller.
Running
./build/softsparc # prints current status
./build/softsparc --inventory # prints the instruction/ASI/trap accuracy ledger
Nothing is emulated yet — WI-01 is scaffold plus the common module only.
Where to look next
AGENTS.md— house style and working rules for anyone (human or agent) implementing a module.docs/SOURCES.md— index of every reference manual underdocs/, with provenance and integrity hashes.ROADMAP.md— work item sequencing (added as work items land; not present in WI-01).