Fixed the RISC-V64 trap frame size mismatch in the regression test BSP (#708)

The RISC-V64 port moved its interrupt frame to 528 bytes (65 slots plus 8
bytes of padding, so sp stays 16-byte aligned at a call) and published the
size as TX_RISCV_TRAP_FRAME_SIZE. The port sources were converted to use
it, but the shared regression test BSP was not: its trap_entry still
allocated a hardcoded 65 * REGBYTES, or 520 bytes.

Every interrupt therefore unwound 8 bytes more than it allocated:

    trap_entry:                   addi  sp,sp,-520
    _tx_thread_context_restore:   addi  sp,sp,528

On the RISC-V64 regression suite that left 24 of 95 tests failing in the
default configuration, typically as an illegal instruction once execution
reached a corrupted frame. The example BSP under the port directory was
converted with the port and was unaffected, which is why the functional
QEMU test kept passing.

The test BSP now takes both frame sizes from the port it is linked
against, so the two cannot drift apart again. A port that publishes no
contract keeps the historical layout, so the RISC-V32 side is unchanged
until its own port publishes one.

TX_RISCV_TRAP_CALL_FRAME_SIZE is restored to the RISC-V64 tx_port.h. It
was removed as unused when the frame sizes were introduced, but it is
part of the same contract: it is the space a trap entry reserves around a
call into C, and the psABI requires 16 bytes there rather than one
register slot.

Verified on QEMU with every linkable test built, comparing against the
commit before the port change:

    before the port change   2 failures out of 95 (both unlinkable)
    current dev              24 failures out of 95
    with this change          2 failures out of 95 (both unlinkable)

The two remaining failures predate all of this: newlib pulls _impure_ptr
out of R_RISCV_HI20 range for time(), so those two binaries do not link.
RISC-V32 is unchanged at 2 failures across all five configurations.

Assisted-by: Claude Code (Opus 5) <noreply@anthropic.com>
This commit is contained in:
Frédéric Desbiens
2026-09-09 10:56:57 -04:00
committed by GitHub
parent 9a03838381
commit 146d57b235
2 changed files with 31 additions and 7 deletions
@@ -1,5 +1,6 @@
/***************************************************************************
* Copyright (c) 2026 10xEngineers
* Copyright (c) 2026 Eclipse ThreadX contributors
*
* This program and the accompanying materials are made available under the
* terms of the MIT License which is available at
@@ -8,10 +9,13 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
// Some portions generated by Claude Code (Opus 5).
/* Trap entry and low-level init for RISC-V QEMU virt regression tests.
Supports both RV32 and RV64 via __riscv_xlen conditionals. */
#include "csr.h"
#include "tx_port.h"
#if __riscv_xlen == 64
#define STORE sd
@@ -33,12 +37,27 @@
.extern trap_handler
.extern _tx_thread_context_restore
trap_entry:
/* Take the interrupt frame size from the port that this BSP is linked
against, so the two can never disagree. A port that publishes no
contract keeps the historical layout. */
#ifndef TX_RISCV_TRAP_FRAME_SIZE
#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double)
addi sp, sp, -(65 * REGBYTES)
#define TX_RISCV_TRAP_FRAME_SIZE (65 * REGBYTES)
#else
addi sp, sp, -(32 * REGBYTES)
#define TX_RISCV_TRAP_FRAME_SIZE (32 * REGBYTES)
#endif
#endif
/* The RISC-V psABI requires sp to be 16-byte aligned at a call. */
#ifndef TX_RISCV_TRAP_CALL_FRAME_SIZE
#define TX_RISCV_TRAP_CALL_FRAME_SIZE 16
#endif
.equ TX_TRAP_FRAME_SIZE, TX_RISCV_TRAP_FRAME_SIZE
.equ TX_TRAP_CALL_FRAME_SIZE, TX_RISCV_TRAP_CALL_FRAME_SIZE
trap_entry:
addi sp, sp, -TX_TRAP_FRAME_SIZE
STORE x1, (28 * REGBYTES)(sp)
@@ -47,11 +66,11 @@ trap_entry:
csrr a0, mcause
csrr a1, mepc
csrr a2, mtval
addi sp, sp, -REGBYTES
addi sp, sp, -TX_TRAP_CALL_FRAME_SIZE
STORE ra, 0(sp)
call trap_handler
LOAD ra, 0(sp)
addi sp, sp, REGBYTES
addi sp, sp, TX_TRAP_CALL_FRAME_SIZE
call _tx_thread_context_restore
@@ -89,11 +108,11 @@ _tx_initialize_low_level:
fscsr x0
#endif
addi sp, sp, -REGBYTES
addi sp, sp, -TX_TRAP_CALL_FRAME_SIZE
STORE ra, 0(sp)
call board_init
LOAD ra, 0(sp)
addi sp, sp, REGBYTES
addi sp, sp, TX_TRAP_CALL_FRAME_SIZE
la t0, trap_entry
csrw mtvec, t0