Skip to content

riscv64: spec compliance and regression test fix - #698

Merged
fdesbiens merged 3 commits into
eclipse-threadx:devfrom
akifejaz:rv64-fix
Sep 9, 2026
Merged

fdesbiens merged 3 commits into
eclipse-threadx:devfrom
akifejaz:rv64-fix

Conversation

@akifejaz

@akifejaz akifejaz commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

This PR corrects the RISC-V64 GNU port as per spec and its QEMU virt support.

  • Fix RISC-V64 GNU port and QEMU virt BSP for spec compliance and proper FP/vector context saving.
  • Enforce atomic interrupt state operations, correct stack frame layouts, and add compile-time ABI guards.
  • Refactor PLIC and CLINT drivers with volatile memory accesses, proper indexing, and exception skip logic.
  • Update linker scripts, global pointer initialization, and CMake functional test targets.

Regression 475/475 on QEMU 6.2 (5 configs x 95), compile matrix for lp64d, lp64f, lp64 and rv64gcv, ecall/ebreak skip checked on RV64 and RV32.

akifejaz and others added 3 commits September 7, 2026 15:27
Signed-off-by: Akif Ejaz <akifejaz40@gmail.com>
Signed-off-by: Akif Ejaz <akifejaz40@gmail.com>
The new check-functional-riscv64 target verifies FPU context switching by
watching fpu_test_val advance by 1.1f on each pass through
thread_6_and_7_entry. The GDB script deliberately treats a missing symbol
as a failure rather than silently skipping the check, but the demo no
longer defined it, so the target failed on every run:

    FPU_VERIFIED_FAIL_NO_SYMBOL

The definition and the increment are restored, matching what the risc-v32
demo already carries. The functional target now passes end to end.

Three small corrections are folded in:

- tx_port.h carried a comment stating that the ISA string must include
  Zicsr, but nothing enforced it, so an rv64imac build failed with a wall
  of assembler "unrecognized opcode" errors. It now stops at one clear
  diagnostic.
- Removed TX_RISCV_TRAP_CALL_FRAME_SIZE, which nothing referenced.
- The example .gitignore listed qemu-riscv32.log, but the runner writes
  qemu-riscv64.log, so the generated log showed up as an untracked file.

Assisted-by: Claude Code (Opus 5) <noreply@anthropic.com>
@fdesbiens

Copy link
Copy Markdown
Contributor

Thank you for this, @akifejaz — it is a thorough piece of work, and the parts that matter most are the parts that are easiest to get wrong. The atomic csrrc/csrrs rewrite of _tx_thread_interrupt_control, the bgtzbnez corrections on _tx_thread_preempt_disable and _tx_timer_time_slice (both of which silently mishandled a wrapped or negative value), and removing the duplicate vector save in _tx_thread_preempt_restore are all real bugs caught and correctly reasoned about.

Because the RISC-V jobs are still commented out in regression_test.yml, the green checks on this PR say nothing about this port, so I built and ran it locally.

One blocking issue, now fixed

The new check-functional-riscv64 target failed on every run:

FPU_VERIFIED_FAIL_NO_SYMBOL
FAILURE: Hit thread, but this demo defines no fpu_test_val, so the FPU result is unverifiable.

Commit 0e95233 added fpu_test_val to demo_threadx.c; 3a374f4 ("revert the demo changes") took it back out four minutes later. The GDB script deliberately treats the missing symbol as a failure rather than skipping the check — which is the right call — so the target could not pass with the demo as it stood. I suspect the functional run quoted in the description predates that revert; the 475/475 figure is the test/tx suite, which does not exercise this path.

I have restored those three lines, matching what the risc-v32 demo already carries. The target now passes end to end:

FPU_VERIFIED_OK value=1.100000 adds=1
MEPC_VERIFIED_OK mepc=0x80000720 frame_pc=0x80000720
SUCCESS: Time-slice handler verified.
SUCCESS: System timer increment verified.
PREEMPT_VERIFIED_OK ticks=1

Three small things folded into the same commit

  • tx_port.h carried a comment saying the ISA string must include Zicsr, but nothing enforced it, so an rv64imac build produced a wall of assembler unrecognized opcode errors. It now stops at one clear #error.
  • TX_RISCV_TRAP_CALL_FRAME_SIZE was defined and never referenced; removed.
  • The example .gitignore listed qemu-riscv32.log, but the runner writes qemu-riscv64.log.

Verified

I confirmed the ABI matrix from your description by assembling every port source:

Configuration Result
rv64gc / lp64d builds
rv64gc / lp64f builds
rv64imac_zicsr / lp64 builds
rv64gcv / lp64d builds
rv64gc / lp64 rejected by the soft-float guard, as documented
rv64imac / lp64 rejected by the new Zicsr guard

I also checked the frame-size unification for self-consistency across save, restore, schedule, stack build and system return (528 = 65×8 plus 8 bytes of padding with FP, 256 without; 240/128 for the solicited frame), and confirmed the branch still merges cleanly onto dev with the ra fix from #696 intact.

Merging shortly. Thanks again for the care that went into this one.

@fdesbiens
fdesbiens merged commit 164f211 into eclipse-threadx:dev Sep 9, 2026
12 checks passed
@fdesbiens

Copy link
Copy Markdown
Contributor

A correction on my part, @akifejaz, and an apology.

The commit I pushed to your branch (3b6fc4f) carried nine files it should not have. I had configured a local CMake build tree while verifying the functional test, and it was staged along with the fix — a compiled kernel.elf, build.ninja, the Ninja dependency and build logs, a QEMU run log, and some CPack scaffolding. Roughly 830 KB of generated output, none of it yours and none of it part of this port fix.

That is entirely my mistake, not a defect in your contribution. The RISC-V64 work itself is correct and stays as merged.

#706 removes the files from dev. It also replaces the .gitignore list of build directory names with a single build*/ pattern, which is what would have caught this in the first place.

Nothing is required from you here. Thanks again for the contribution, and sorry for the noise on your PR.

fdesbiens added a commit that referenced this pull request Sep 9, 2026
#706)

A local CMake build tree was staged by mistake alongside the RISC-V64
spec compliance work in #698, putting nine generated files on dev,
including a compiled kernel.elf, build.ninja, the Ninja dependency logs
and a QEMU run log. None of it belongs in the repository.

The root .gitignore listed build directories by name rather than by
pattern, so build/, build_qemu/, build_m7/ and the build_r52 variants
were covered but a differently named tree was not. Those entries are
replaced with a single build*/ pattern, which covers every existing name
and any future one. No tracked file matches the new pattern.

The artifacts remain reachable in history; only the working tree is
corrected, since rewriting a shared branch is the greater harm.

Assisted-by: Claude Code (Opus 5) <noreply@anthropic.com>
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