Add the Zicfiss extension.#1408
Conversation
|
This depends on #1405, so leaving this as a draft until that is merged. It updates #377 by @ved-rivos. |
25152f7 to
5150cb2
Compare
|
|
||
| function clause execute SSPUSH(rs2) = { | ||
| // This is redundant with the decoding predicate, but is here to | ||
| // match the pseudo-code in the specification. |
There was a problem hiding this comment.
These comments could be removed.
There was a problem hiding this comment.
I think I would just remove this code. Add a comment explaining it maybe.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
I was suggesting removing the comment because it would look odd in the ISA manual.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
| // store/AMO access-fault exception." | ||
| // | ||
| // `vmem_write_addr` throws a SAMO_Addr_Align exception, | ||
| // so handle alignment checking here. |
There was a problem hiding this comment.
these comments could be removed.
ved-rivos
left a comment
There was a problem hiding this comment.
LGTM. Had a few nits noted.
|
@Timmmm @jordancarlin @nadime15 It would be good to get this reviewed soon. It would unblock work on the remaining Sv* extensions for RVA23. |
|
Sorry, my bad! I will take a look today. |
|
@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 |
Timmmm
left a comment
There was a problem hiding this comment.
Sorry, forgot about this. Could of minor comments & I think we can simplify the xSSE stuff a fair bit.
| // 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. |
There was a problem hiding this comment.
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.
| // Step 8 of VATP (see vmem.sail). | ||
|
|
||
| // Handle `mxr` (Make eXecutable Readable). | ||
| let pte_R = pte_R | (pte_X & mxr); |
There was a problem hiding this comment.
Does this line need to go before the new code?
There was a problem hiding this comment.
(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]) | ||
| } |
There was a problem hiding this comment.
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
}
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
There was a problem hiding this comment.
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()).
|
@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 |
|
Yeah sure, I made an issue. The change from your code is actually pretty minor in the end: #1582 |
This adds a
ShadowStackvariant to the memory access type to implement the PTE checks for the shadow stack page and the Zicfiss instructions. It also implements theSSEbit in the{ms}envcfgCSRs.The PMA check needs more PMA plumbing to be completed, but is straightforward once that is in place.