lowRISC / lowRISC/ibex

[cheriot,rtl] ECC mismatch on CHERIoT mode switch

Open
#2,480 1 comment 0 reactions 1 assignee View on GitHub

@SamuelRiedel is already working on this.

Since Aug 21, 2026.

Dominant language
SystemVerilog
Stars
2.1k
Forks
810
Avg merge
5d 23h
Merged PRs (30d)
9

Description

Issue raised in this discussion: https://github.com/lowRISC/ibex/pull/2475#discussion_r3819859584

When switching from non-CHERIoT to CHERIoT mode (cheriot_enable), rf_shared may contain old rv32i data (x17–x31) that was ECC-encoded with prim_secded_inv_39_32. In CHERIoT mode, those same flops are read as capability metadata (x1–x15 caps) and checked with prim_secded_inv_64_57. The two generator matrices differ, so the stored ECC bits will be invalid for non-zero values, triggering a false major alert on the first capability read.

The zero case is safe: SecdedInv3932ZeroWord[38:32] == SecdedInv6457ZeroEcc == 7'h2A, so zeroing x17–x31 before/right after the switch produces valid cap ECC codewords. The x16 corner case is also fine. It is interpreted as x0 in CHERIot, but its cap output is hardwired to CapWordZeroVal, regardless of the stored value.

Options:

  1. Force SW to zero x17–x31 before/after the switch. The ZeroECC will match. A mode switch should be treated like a fresh boot where SW initializes registers anyway.
  2. Add hardware to reset the registers on the switch. At the switch, we have to flush the pipeline anyway, and we could also reset rf_shared to the correct cap reset values at that point.
  3. Use the same generator matrix for both ECC paths. If prim_secded_inv_64_57 were regenerated so that its first 32 data-bit columns matched those of prim_secded_inv_39_32, zero-extending a 32-bit word to 57 bits would produce the same ECC. This would make the ECC transparent to mode switches for any value, not just zero.
  4. Always route the full 35-bit cap width out of the register file and through the wide ECC path, even in non-CHERIoT mode. When writing x17–x31 in rv32i mode, compute the cap ECC as ECC_64_57({22'b0, 3'b0, data[31:0]}) instead of reusing the narrow data ECC path. Since the upper bits are zero in RV32I mode, the stored ECC is valid for the zero-extended value, and it remains valid when CHERIoT mode reads those same flops as capability metadata. This approach requires no SW zeroing and no generator changes, but it couples the write path to the cap ECC encoder even for plain data writes, which is architecturally awkward.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.