Skip to content

Add the Zicfiss extension.#1408

Merged
pmundkur merged 25 commits into
riscv:masterfrom
pmundkur:zicfiss
Mar 3, 2026
Merged

Add the Zicfiss extension.#1408
pmundkur merged 25 commits into
riscv:masterfrom
pmundkur:zicfiss

Conversation

@pmundkur
Copy link
Copy Markdown
Collaborator

@pmundkur pmundkur commented Nov 25, 2025

This adds a ShadowStack variant to the memory access type to implement the PTE checks for the shadow stack page and the Zicfiss instructions. It also implements the SSE bit in the {ms}envcfg CSRs.

The PMA check needs more PMA plumbing to be completed, but is straightforward once that is in place.

@pmundkur
Copy link
Copy Markdown
Collaborator Author

This depends on #1405, so leaving this as a draft until that is merged. It updates #377 by @ved-rivos.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Nov 25, 2025

Test Results

2 314 tests  ±0   2 314 ✅ ±0   31m 32s ⏱️ +23s
    1 suites ±0       0 💤 ±0 
    1 files   ±0       0 ❌ ±0 

Results for commit bb3e3bc. ± Comparison against base commit a33475a.

♻️ This comment has been updated with latest results.

@jordancarlin jordancarlin added the extension Adds support for a RISC-V extension label Jan 6, 2026
@pmundkur pmundkur force-pushed the zicfiss branch 4 times, most recently from 25152f7 to 5150cb2 Compare January 21, 2026 15:59
@pmundkur pmundkur marked this pull request as ready for review January 21, 2026 16:06
@pmundkur pmundkur requested a review from ved-rivos January 21, 2026 16:07
Comment thread model/extensions/cfi/zicfiss_insts.sail Outdated
Comment thread model/extensions/cfi/zicfiss_insts.sail Outdated

function clause execute SSPUSH(rs2) = {
// This is redundant with the decoding predicate, but is here to
// match the pseudo-code in the specification.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These comments could be removed.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I would just remove this code. Add a comment explaining it maybe.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to include the Sail code in the Sail-included fork of the manual to replace the pseudo-code. This condition would get lost if we removed this code, and it would not match the earlier pseudo-code. I'd rather keep the code. I'm not sure about the comment though. I'm leaning to keeping it, since it does point out the redundancy, so that we don't miss that too.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was suggesting removing the comment because it would look odd in the ISA manual.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same in other locations

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed that it would look odd in the manual. It indicates a need for a comment construct that is omitted when Sail code is inserted into documentation.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// store/AMO access-fault exception."
//
// `vmem_write_addr` throws a SAMO_Addr_Align exception,
// so handle alignment checking here.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these comments could be removed.

Comment thread model/extensions/cfi/zicfiss_regs.sail Outdated
Comment thread model/sys/vmem.sail Outdated
Copy link
Copy Markdown
Contributor

@ved-rivos ved-rivos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Had a few nits noted.

@pmundkur
Copy link
Copy Markdown
Collaborator Author

@Timmmm @jordancarlin @nadime15 It would be good to get this reviewed soon. It would unblock work on the remaining Sv* extensions for RVA23.

@nadime15
Copy link
Copy Markdown
Collaborator

Sorry, my bad! I will take a look today.

Copy link
Copy Markdown
Collaborator

@nadime15 nadime15 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will continue later!

Something else I noticed is the number of TODO's, does it make sense to wait for #1110? We dont have to wait for it, I am fine with both.

Comment thread model/extensions/cfi/zicfiss_insts.sail Outdated
Comment thread model/sys/mem.sail Outdated
Comment thread config/config.json.in Outdated
Comment thread model/postlude/validate_config.sail Outdated
Comment thread model/core/sys_regs.sail
Comment thread model/core/vmem_types.sail
Comment thread model/extensions/cfi/zicfiss_insts.sail Outdated
Comment thread model/extensions/cfi/zicfiss_insts.sail Outdated
Comment thread model/extensions/cfi/zicfiss_insts.sail
Comment thread model/extensions/cfi/zicfiss_insts.sail Outdated
Comment thread model/extensions/cfi/zicfiss_insts.sail Outdated
Comment thread model/extensions/cfi/zicfiss_regs.sail Outdated
Comment thread model/extensions/cfi/zicfiss_insts.sail
@pmundkur pmundkur mentioned this pull request Feb 2, 2026
Copy link
Copy Markdown
Collaborator

@nadime15 nadime15 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Comment thread model/extensions/cfi/zicfiss_insts.sail Outdated
@pmundkur
Copy link
Copy Markdown
Collaborator Author

@Timmmm I incorporated some of the changes you suggested in riscv/riscv-isa-manual#2646 I think the bits to handle virtual-instruction exception when accessing ssp could be handled by a more general scheme to deal with HS-qualified instructions, which this is a case of (I think).

Copy link
Copy Markdown
Collaborator

@Timmmm Timmmm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, forgot about this. Could of minor comments & I think we can simplify the xSSE stuff a fair bit.

Comment thread model/core/sys_regs.sail Outdated
// TODO: add a config option to clear senvcfg.SSE directly when menvcfg.SSE is cleared.
// For now, `senvcfg` is marked private and the same effect is achieved by
// using a `read_senvcfg` accessor. This might matter if there are alternate ways
// to access the CSR, e.g. directly from the C++ harness.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's the PR: riscv/riscv-isa-manual#2646

Actually it now changes both to be "read-only zero", but that actually does mean that we can do the zeroing in the read_senvcfg accessor. This isn't really different from any of our other cross-CSR WARL field legalisations, so I think I would just remove this comment. You have the comment on legalize_senvcfg anyway.

Comment thread model/sys/vmem_pte.sail
// Step 8 of VATP (see vmem.sail).

// Handle `mxr` (Make eXecutable Readable).
let pte_R = pte_R | (pte_X & mxr);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this line need to go before the new code?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I missed this comment) No it should not. The Zicfiss code in Step 7 needs to check the actual R,W,X bits in the PTE.

// handle the special case of M+U systems
// raises illegal instruction otherwise
User => (currentlyEnabled(Ext_S) & bool_bit(read_senvcfg()[SSE])) | bool_bit(menvcfg[SSE])
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should use code like in the PR message here:

// "Raw" value of xenvcfg.SSE according to the current privilege.
// This is not the same as xSSE from the ISA manual becuase it is 1 for
// machine mode and it is not 0 if supervisor is not implemented.
function zicfiss_xSSE_raw(priv : Privilege) -> bool =
  bool_bits(match priv {
    Machine           => 0b1
    Supervisor        => menvcfg[SSE],
    VirtualSupervisor => read_henvcfg()[SSE], // The `read_` takes care of the "reads as 0".
    User              => read_senvcfg()[SSE],
    VirtualUser       => read_senvcfg()[SSE],
  })

// xSSE from the ISA manual. 0 in machine mode or if S-mode is not implemented.
function zicfiss_xSSE(priv : Privilege) -> bool =
  priv != Machine & extensionEnabled(Ext_S) & zicfiss_xSSE_raw()

// Return true if we should raise a virtual instruction exception instead
// of an illegal instruction.
function zicfiss_exception_is_virtual(priv : Privilege) -> bool =
  menvcfg[SSE] == 0b1 & (priv == VirtualSupervisor | priv == VirtualUser)

function access_ssp(priv : Privilege) = {
    if not(zicfiss_xSSE_raw(priv))
    then return (if zicfiss_exception_is_virtual(priv) then Virtual_Instruction else Illegal_Instruction);
    // ... ok
}

function execute_sspush() = {
    if not(zicfiss_xSSE(cur_privilege)) then return RETIRE_SUCCESS;

    // ... normal execution
}

function execute_ssamoswap() = {
    if not(zicfiss_xSSE(priv))
    then return (if zicfiss_exception_is_virtual(priv) then Virtual_Instruction else Illegal_Instruction);

    // ... normal execuion
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this code zicfiss_xSSE_raw() is the replacement for is_ssp_accessible, so I guess you could call it that, and then

function zicfiss_xSSE(priv : Privilege) -> bool =
  priv != Machine & extensionEnabled(Ext_S) & is_ssp_accessible(priv)

I don't know if that's easier to understand or not - up to you.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find the zicfiss_xSSE_raw() here confusing because it does a read_senvcfg() without checking for currentlyEnabled(Ext_S). In my version (zicfiss_xSSE()), that read is gated by the S-mode check.

Since zicfiss_zSSE and is_ssp_accessible differ slightly for both M-mode and U-mode (since access to ssp is not gated on S-mode being implemented), I kept them separate instead of trying to unify them.

I'd prefer to handle the virtual-instruction exception using the approach in #1556, and leave a comment here for it instead. With #1556, is_ssp_accessible() will not be restricted to returning a bool, and virtual-instruction exceptions will be more straightforward.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm that's a good point actually. My code exactly follows the spec as written - accessing ssp depends on senvcfg even if S mode is not implemented, which makes no sense at all. Probably needs a spec fix. I'll open an issue.

is_ssp_accessible() will not be restricted to returning a bool, and virtual-instruction exceptions will be more straightforward.

I dunno if that is simpler since none of the information that is_ssp_accessible() determines is needed to know the exception type. IMO it's simpler to have a separate function. I guess we can defer that anyway.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like I even noticed that:

it is not 0 if supervisor is not implemented.

I think probably they just meant to disable access if supervisor is not implemented.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the issue is more about how zicfiss_xSSE() is written. The way I have it exactly captures the Shadow-Stack-Enabled (SSE) State section of the spec. The boolean is_ssp_accessible() is an unfortunate artifact of the boolean functions we've used so far for CSR access checks, which #1556 rectifies. With #1556, the is_CSR_accessible (unfortunately named since it's no longer a boolean) can return success, illegal instruction or virtual instruction as the case may be. We would no longer need the is_ssp_accessible() in this PR and your zicfiss_exception_is_virtual() above (and hence also the zicfiss_xSSE_raw()).

@pmundkur
Copy link
Copy Markdown
Collaborator Author

pmundkur commented Mar 2, 2026

@Timmmm this PR is blocking pending work on extensions for virtual memory (e.g. Svnapot, Svpbmt), since those will build on the changes to virtual memory handling in this PR. As far as I understand, the clarifications (mainly simplifications, from what I can tell) you'd like to see in the manual would only affect xSSE and ssp access checking in extensions/cfi/Zicfiss_{regs,insts}.sail. Would it be okay if those could be made in a subsequent PR, after this is merged and the spec simplifications resolved?

@Timmmm
Copy link
Copy Markdown
Collaborator

Timmmm commented Mar 2, 2026

Yeah sure, I made an issue. The change from your code is actually pretty minor in the end: #1582

@Timmmm Timmmm added the will be merged Scheduled to be merged soon if nobody objects label Mar 2, 2026
@pmundkur pmundkur added this pull request to the merge queue Mar 3, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Mar 3, 2026
@pmundkur pmundkur added this pull request to the merge queue Mar 3, 2026
Merged via the queue into riscv:master with commit a8dc17b Mar 3, 2026
15 checks passed
@pmundkur pmundkur deleted the zicfiss branch March 4, 2026 17:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

extension Adds support for a RISC-V extension will be merged Scheduled to be merged soon if nobody objects

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants