riscv-cheri
riscv-cheri copied to clipboard
Simplifying WARL address CSR writes
In the base ISA, mepc and mtvec are defined as WARL fields that can hold any valid address; if a value is written to them which is not a valid address, the implementation has a fair amount of flexibility on how to map it to a valid address.
Right now we allow/require that if the address in a WARL CSR is changed by WARL legalization, the entire CSR must be updated as if by a CSETADDR. While we do need to restrict legalization to guarantee monotonicity, the CSETADDR representability checks are quite heavyweight and likely erase the entire advantage of restricting a register to valid addresses.
Instead, add a general rule that after the modification of a WARL address CSR, the new value of the CSR is either the value written if it was legal, derivable from the value written as if by a CSETADDR operation, or is an arbitrary value with a zero tag. This authorizes implementations to simply clear the tag and truncate on detection of an invalid address. It also authorizes implementations to not store reserved bits of zero-tagged values written to address CSRs in a way that may be clearer than presently.
Allowing the value to be used as if the result of a CSETADDR allows certain CSR legalizations to modify the low 7 (RV32) or 11 (RV64) bits of the address, which requires a sealing check but never affects bounds representability. In particular, with the new rule a write to xepcc can continue to mask off the low bit (IALIGN=16) or two bits (IALIGN=32), clearing the tag only if the masked bits were nonzero and the written capability was sealed.
Add an informative note to xtvecc that if Vectored mode is supported, the maximum interrupt cause is no larger than 31 (RV32) or 511 (RV64), and the implementation forces the Vectored mode trap vector to be aligned to its size, the last vector is guaranteed to be representable and no further checks are needed.
The present definition actually requires two CSETADDR representability checks in the CSR write pipeline, with the first being used for Legacy mode and bitwise operations. I would prefer eliminating both since depending on the timing of CSR read results it may be difficult to share either CSR CSETADDR with the execution CSETADDR. The early CSR CSETADDR is only truly needed when privileged code in Legacy mode writes a value to xtvecc or xepcc, and in these cases the existing value will have Infinity's bounds.
We can simplify the hardware requirements here by saying that any XLEN-bit write access to a CSR clears the CSR's tag unless the base and length of the value in the CSR are 0 and 2^XLENMAX. We can also simplify the descriptions by saying that this is performed before and independent of any WARL legalization specific to the CSR.
Add ddc as an address CSR; there is no reason to use it for anything else.
I understood the first part of your suggestion which basically clears the tag bit on illegal writes instead of legalizing and then clearing the tag bits if representability check fails. That seems like a good idea.
We can simplify the hardware requirements here by saying that any XLEN-bit write access to a CSR clears the CSR's tag unless the base and length of the value in the CSR are 0 and 2^XLENMAX.
I don't understand this. Are you saying only full-range capabilities should be written to CSRs?
We can simplify the hardware requirements here by saying that any XLEN-bit write access to a CSR clears the CSR's tag unless the base and length of the value in the CSR are 0 and 2^XLENMAX.
I don't understand this. Are you saying only full-range capabilities should be written to CSRs?
Stress on "XLEN-bit write access". CLEN-bit write accesses (from Capability mode) can write capabilities with arbitrary bounds, but XLEN-bit writes (from Legacy mode) write full-range capabilities or untagged capabilities with no middle ground.
This is primarily intended for xepc and xtvec, which are privileged CSRs. XLEN-bit (Legacy) writes to those CSRs will only appear if M/S mode is using the Legacy execution mode, which will require full-range capabilities to begin with if S-mode has the ability to set page tables.
Makes sense!
@sorear: Thanks for the ticket.
Right now we allow/require that if the address in a WARL CSR is changed, the entire CSR must be updated as if by a CSETADDR.
Please let us know which part of the specification indicates this because it was not the intention. The intention is instead that:
- If you write XLENMAX to a CSR, i.e. the whole capability, then change tag, metadata and address regardless as expected.
- If you write XLEN to a CSR, i.e. only the address, then clearly the address changes and also the tag changes depending on the representability/sealing checks -- the metadata is unchanged.
While we do need to restrict legalization to guarantee monotonicity, the CSETADDR representability checks are quite heavyweight and likely erase the entire advantage of restricting a register to valid addresses.
Are you referring to this kind of thing from the RISC-V Privileged spec? "mepc is a WARL register that must be able to hold all valid virtual addresses. It need not be capable of holding all possible invalid addresses. Prior to writing mepc, implementations may convert an invalid address into some other invalid address that mepc is capable of holding."
If so, could you concretely point out why you think that we "likely erase the entire advantage of restricting a register to valid addresses"? The "Invalid Address Handling" section in chapter 3 explains how we expect this to work in CHERI, and it does not require changing the whole capability when you write a CSR.
I've separated out this issue: https://github.com/riscv/riscv-cheri/issues/50
For the other part - I don't agree with the assessment of the cost of the CSETADDR and with this part:
We can simplify the hardware requirements here by saying that any XLEN-bit write access to a CSR clears the CSR's tag unless the base and length of the value in the CSR are 0 and 2^XLENMAX. We can also simplify the descriptions by saying that this is performed before and independent of any WARL legalization specific to the CSR.
because a legacy OS can legally be constrained by having restricted bounds on the exception handler capability
Please let us know which part of the specification indicates this because it was not the intention.
To be clear (and I edited it slightly) the first part is talking about changes to the address caused by WARL legalization, including changes caused by invalid address conversion.
The specification requirement I am referring to there is "If conversion was required, then A’s tag is cleared if A is sealed or if the new address is not representable — this is equivalent to the semantics of CSETADDR" in §3.12.1.
I don't agree with the assessment of the cost of the CSETADDR
Assuming that this is still about invalid address conversion (should I split the issue? They seemed related at the time but it's clearly causing confusion):
The question isn't about the cost of CSETADDR in an absolute sense, it's about relating the cost of the CSETADDR to the hardware benefits of invalid address conversion.
The purpose of invalid address conversion (riscv/riscv-isa-manual#49) is to save area by allowing implementations to omit flip-flops for the high bits of certain registers, e.g. a simple with-MMU implementation supporting Sv39 and M and S modes save 96 flops, 24 each from mtvec, mepc, stvec, sepc. Invalid address conversion is non-beneficial to software (it loses information potentially useful for debugging, say if you jump to ASCII text interpreted as an address), and implementations are allowed to provide full XLEN width for the registers in question (qemu does this).
If the shifters and comparators required to implement a CSETADDR check cost more than the 96 flops, in the best case, that are saved by invalid address conversion, then invalid address conversion as an implementation serves no purpose and should be redefined or removed.
because a legacy OS can legally be constrained by having restricted bounds on the exception handler capability
I considered this and was on the fence about this, but ultimately decided that if a legacy environment has a MMU then the legacy S-mode likely expects to be able to program arbitrary page tables, which means the kernel can relocate itself to any virtual address, and if a nontrivial legacy environment doesn't have a MMU the legacy hardware most likely has some form of PMP which is more natural to use for immutable bounds.
Many of the key observations from this ticket have been addressed although not necessarily in exactly the same way proposed here:
- CSETADDR is no longer required on CSR write
- The spec requires clearing the tag if writing the address of a non-infinity capability in a CSR
- The xtvecc check is for representability
- ddc is now an "address" CSR
There has not been activity in this ticket for a while, so I will close it. Please create new tickets if you'd like to propose further changes.