Skip to content

riscv: Mask mepc[0] and sepc[0] - #27

Closed
whensun wants to merge 2 commits into
antmicro:masterfrom
whensun:renode-csr-masking
Closed

riscv: Mask mepc[0] and sepc[0]#27
whensun wants to merge 2 commits into
antmicro:masterfrom
whensun:renode-csr-masking

Conversation

@whensun

@whensun whensun commented Jun 19, 2026

Copy link
Copy Markdown

This PR fixes RISC-V CSR field masking in tlib.

It masks mepc[0] and sepc[0], which are architecturally hardwired to zero.

Related to renode/renode#905
Related to renode/renode#906

@FW-Nagorko

Copy link
Copy Markdown

Thank You for your contribution.

We have been able to verify that the change to mask mepc[0] and sepc[0] is correct, and we will be merging it into the codebase.

We would like to ask you to explain the reasoning behind masking out the menvcfg and menvcfgh registers as the provided reason is too vague.
Specifically why do you think that this register should be zeroed on write?

@whensun

whensun commented Jul 6, 2026

Copy link
Copy Markdown
Author

Hello, thank you for your reply.

I should clarify that my intention wasn't to claim that the entire menvcfg register is zero-on-write. The intention was to enforce the read-only-zero behavior required for fields whose related functionality is not implemented by tlib.

Currently, tlib stores the full written value directly, so writing all ones makes every field read back as one.

The RISC-V Privileged Architecture specification requires the following fields to be read-only zero when their related extensions are not implemented:

  • STCE for Sstc
  • PBMTE for Svpbmt
  • ADUE for Svadu
  • CDE for Smcdeleg
  • CBZE for Zicboz
  • CBCFE and CBIE for Zicbom
  • PMM for Smnpm

From my inspection, tlib does not appear to explicitly support these extensions.

Svadu is slightly different because tlib already updates PTE A/D bits automatically, but this behavior is unconditional. I could not find any handling that connects menvcfg.ADUE to the page-table walker. Therefore, ADUE is currently stored and read back, but it does not control the behavior.

I agree that using a zero mask for the entire register is too broad because it also clears unrelated fields such as FIOM.

menvcfgh also needs XLEN-specific handling: it aliases bits 63:32 of menvcfg on RV32, but does not exist on RV64.

I will remove the current menvcfg and menvcfgh changes from this PR and handle them separately with field-specific and XLEN-specific logic.

@whensun whensun changed the title riscv: Fix CSR field masking riscv: Mask mepc[0] and sepc[0] Jul 6, 2026
@whensun

whensun commented Jul 6, 2026

Copy link
Copy Markdown
Author

I have updated the PR.

The menvcfg and menvcfgh changes have been removed and moved to [antmicro/tlib#33], so this PR now only contains the verified mepc[0] and sepc[0] fixes.

@FW-Nagorko

Copy link
Copy Markdown

Thank you for your contribution.

We have merged your changes in c2885ef.

@JanOlencki JanOlencki closed this Jul 8, 2026
ShahriarAhnaf pushed a commit to simantic-dev/tlib that referenced this pull request Jul 20, 2026
tlib bug antmicro#27. The IEEE-754-2008 min/maxNum quiet-NaN shortcut in softfloat-2's
MINMAX macro (floatN_maxnum/minnum) returns the non-NaN operand verbatim when
the other operand is a quiet NaN, WITHOUT applying float_squash_input_denormal.
The non-NaN float_max/float_min path already squashes both inputs, so only the
NaN shortcut skipped it. Under FPSCR.FZ=1 that returned an un-flushed denormal
(and never raised IDC/InputDenorm), diverging from the ARM ARM (DDI 0403E.e):
FPMaxNum(qNaN, x) substitutes the qNaN with -Infinity and calls FPMax, whose
FPUnpack flushes x's denormal to a signed zero and raises IDC.

Fix: squash both operands at the top of maxnum/minnum (mirroring float_minmax).
squash_input_denormal is a no-op unless FZ is set, so non-FZ behavior and other
targets are unchanged. Found by pyrite's rn-cpu VMAXNM/VMINNM differential
fuzzer (VMAXNM.F32(qNaN, +denormal), FZ=1: tlib kept the raw denormal, rn-cpu's
spec-first FPMaxNum yielded +0.0 with IDC). rn-cpu is not bent to the omission;
repro asserts the SPEC in crates/rn-cpu/tests/tlib_bug_repro.rs.
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.

3 participants