Skip to content

Fix S-mode ECALL delegation in medeleg - #3561

Open
124107157-KV wants to merge 4 commits into
openhwfoundation:masterfrom
124107157-KV:fix/3457-medeleg-s-ecall
Open

124107157-KV wants to merge 4 commits into
openhwfoundation:masterfrom
124107157-KV:fix/3457-medeleg-s-ecall

Conversation

@124107157-KV

Copy link
Copy Markdown
Contributor
  • I have searched for similar pull requests
  • I am a human engaging in an interpersonal interaction. During this interaction, my words are my own and are not generated. If relevant, I provide links to my sources.

Why is this PR needed?

The CSR_MEDELEG writable mask currently does not include ENV_CALL_SMODE, corresponding to exception cause 9 (ECALL from S-mode).

The decoder already generates ENV_CALL_SMODE for an ECALL executed in S-mode, and the trap-routing logic already uses medeleg[cause] to determine whether the exception is delegated to S-mode.

However, because ENV_CALL_SMODE is missing from the CSR_MEDELEG writable mask, writing medeleg[9] does not retain the bit. As a result, software cannot enable delegation of an S-mode ECALL even though the existing exception and trap-routing logic supports this path.

This PR adds ENV_CALL_SMODE to the CSR_MEDELEG writable mask so that medeleg[9] can retain writes and the existing S-mode ECALL delegation path can be used.

What does this PR change?

The writable mask for CSR_MEDELEG in core/csr_regfile.sv is extended with:

(1 << riscv::ENV_CALL_SMODE) |

No decoder or trap-routing changes are required because those paths already generate and handle ENV_CALL_SMODE.

A directed regression is also added to verify both CSR readback and actual trap delegation behavior.

Regression test

A new directed test is added:

verif/tests/custom/issues/medeleg-s-ecall-rv64.S

The test is registered in:

verif/tests/testlist_issues.yaml

The regression performs the following sequence:

  1. Installs separate M-mode and S-mode trap handlers.
  2. Configures PMP so the test image can execute after entering S-mode.
  3. Writes 0x200 to medeleg, corresponding to medeleg[9].
  4. Reads medeleg back and preserves the value.
  5. Sets mstatus.MPP to S-mode.
  6. Executes mret to enter S-mode.
  7. Executes an ECALL from S-mode.
  8. Verifies that the exception is handled by the S-mode trap handler.
  9. Verifies that scause contains exception cause 9.
  10. Verifies that sepc points to the S-mode ECALL instruction.
  11. Verifies that medeleg[9] was retained.

The regression also uses separate failure values to distinguish a CSR write/readback failure from an exception-routing failure.

Verification

Target:

cv64a6_imafdc_sv39

Spike reference

The directed regression was first executed using Spike as the architectural reference.

The Spike trace confirms that:

  • medeleg is written with 0x200.
  • medeleg[9] reads back as set.
  • execution enters S-mode.
  • the S-mode ECALL generates exception cause 9.
  • control reaches the S-mode trap handler.
  • scause reports 9.
  • sepc points to the ECALL instruction.
  • the test exits successfully.

Result:

Spike: PASS

CVA6 before the fix

The same directed-test ELF was executed on the Verilator model built from the original, unfixed CVA6 RTL.

Result:

*** FAILED *** (tohost = 91) after 642 cycles

The regression uses exit value 91 specifically when medeleg[9] does not read back as set.

This confirms the original RTL reproduces issue #3457.

CVA6 after the fix

ENV_CALL_SMODE was then added to the CSR_MEDELEG writable mask and the Verilator model was rebuilt.

The exact same directed-test ELF was executed again without modifying the test binary.

Result:

*** SUCCESS *** (tohost = 0) after 646 cycles

This confirms that adding ENV_CALL_SMODE to the CSR_MEDELEG writable mask fixes both:

  • medeleg[9] CSR readback
  • actual delegation of an S-mode ECALL to the S-mode trap handler

Additional validation

The following checks were completed:

  • git diff --check: PASS
  • Verilator build for cv64a6_imafdc_sv39: PASS
  • Spike directed regression: PASS
  • CVA6 before fix: expected FAIL with tohost = 91
  • CVA6 after fix: PASS with tohost = 0

History

git blame shows that ENV_CALL_UMODE was already present in the CSR_MEDELEG writable mask.

Later Hypervisor-extension work added conditional support for ENV_CALL_VSMODE.

ENV_CALL_SMODE remained absent from the writable mask even though S-mode ECALL generation and cause-based exception delegation are already implemented in the core.

The fix is therefore intentionally limited to adding the missing ENV_CALL_SMODE writable-mask entry.

Fixes #3457

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.

[BUG] medeleg[9] is not retained, so S-mode ecall delegation cannot be enabled

1 participant