{cheri_base_ext_name} is an extension to the RISC-V ISA. The extension adds a carefully selected set of instructions and CSRs that are sufficient to implement new security features in the ISA. To ensure compatibility, {cheri_base_ext_name} also requires some changes to the primary base integer variants: RV32I, providing 32-bit addresses with 64-bit capabilities, and RV64I, providing 64-bit addresses with 128-bit capabilities. The remainder of this chapter describes these changes for both the unprivileged and privileged components of the base integer RISC-V ISAs.
Note
|
The changes described in this specification also ensure that {cheri_base_ext_name} is compatible with RV32E. |
Note
|
RV128 is not currently supported by any CHERI extension. |
Note
|
In line with the base RISC-V ISA, the unprivileged component with its corresponding {cheri_base_ext_name} changes as described in this chapter can be used with an entirely different privileged-level design. The changes for the privileged component described in this chapter are designed to support existing popular operating systems, and assume the standard privileged architecture specified in the RISC-V ISA. |
A hart supporting {cheri_base_ext_name} has a single byte-addressable address space of 2XLEN bytes for all memory accesses. Each memory region capable of holding a capability also stores a tag bit for each naturally aligned CLEN bits (e.g. 16 bytes in RV64), so that capabilities with their tag set can only be stored in naturally aligned addresses. Tags must be atomically bound to the data they protect.
The memory address space is circular, so the byte at address 2XLEN - 1 is adjacent to the byte at address zero. A capability’s [section_cap_representable_check] described in [section_cap_encoding] is also circular, so address 0 is within the [section_cap_representable_check] of a capability where address 2MXLEN - 1 is within the bounds. However, the decoded top field of a capability is MXLEN + 1 bits wide and does not wrap, so a capability with base 2MXLEN - 1 and top 2MXLEN + 1 is not a subset of the [infinite-cap] capability and does not authorize access to the byte at address 0. Like malformed bounds (see [section_cap_malformed]), it is impossible for a CHERI core to generate a tagged capability with top > 2MXLEN. If such a capability exists then it must have been caused by a logic or memory fault. Unlike malformed bounds, the top overflowing is not treated as a special case in the architecture: normal bounds check rules should be followed.
For {cheri_base_ext_name}, the 32 unprivileged x registers of the base integer ISA are extended so that they are able to hold a capability as well as renamed to c registers. Therefore, each c register is CLEN bits wide and has an out-of-band tag bit. The x notation refers to the address field of the capability in an unprivileged register while the c notation is used to refer to the full capability (i.e. address, metadata and tag) held in the same unprivileged register.
The tag of the unprivileged c registers must be reset to zero. The reset values of the metadata and address fields are UNSPECIFIED for all unprivileged c registers except c0.
Register c0 is hardwired with all bits, including the capability metadata and tag, equal to 0. In other words, c0 is hardwired to the [null-cap] capability.
An authorizing capability with appropriate permissions is required to execute instructions in {cheri_base_ext_name}. Therefore, the unprivileged program counter (pc) register is extended so that it is able to hold a capability. The extended register is called the program counter capability (pcc). The pcc address field is effectively the pc in the base RISC-V ISA so that the hardware automatically increments as instructions are executed. The pcc's metadata and tag are reset to the [infinite-cap] capability metadata and tag with the address field set to the core boot address.
The hardware performs the following checks on pcc for each instruction executed in addition to the checks already required by the base RISC-V ISA. A failing check causes a CHERI exception.
-
The tag must be set
-
The capability must not be sealed
-
The capability must grant execute permission
-
All bytes of the instruction must be in bounds
Note
|
Operations that update pcc, such as changing privilege or executing jump instructions, unseal capabilities prior to writing. Therefore, implementations do not need to check that that pcc is unsealed when executing each instruction. However, this property has not yet been formally verified and may not hold if additional CHERI extensions beyond {cheri_base_ext_name} are implemented. |
Note
|
It is common for implementations to not allow executing pc relative instructions, such as [AUIPC] or [JAL], in debug mode. |
pcc is an executable vector, so it need not be able to hold all possible invalid addresses.
{cheri_base_ext_name} introduces new instructions to the base RISC-V integer ISA to inspect and operate on capabilities held in registers.
These instructions allow software to inspect the fields of a capability held in a c register. The output is an integer value written to an x register representing the decoded field of the capability, such as the permissions or bounds. These instructions do not cause exceptions.
-
[GCTAG]: inspects the tag of the input capability. The output is 1 if the tag is set and 0 otherwise
-
[GCPERM]: outputs the architectural (AP) and software-defined (SDP) permission fields of the input capability
-
[GCTYPE]: outputs the type (e.g. unsealed or sentry) of the input capability
-
[GCBASE]: outputs the expanded base address of the input capability
-
[GCLEN]: outputs the length of the input capability. Length is defined as
top - base
. The output is 2MXLEN-1 when the capability’s length is 2MXLEN -
[CRAM]: outputs the nearest bounds alignment that a valid capability can represent
-
[GCHI]: outputs the compressed capability metadata
-
[SCEQ]: compares two capabilities including tag, metadata and address
-
[SCSS]: tests whether the bounds and permissions of a capability are a subset of those from another capability
Note
|
[GCBASE] and [GCLEN] output 0 when a capability with malformed bounds is provided as an input (see [section_cap_malformed]). |
These instructions allow software to manipulate the fields of a capability held in a c register. The output is a capability written to a c register with its fields modified. The output capability has its tag set to 0 if the input capability did not have a tag set, the output capability has more permissions or larger bounds compared to the input capability, or the operation results in a capability with malformed bounds. These instructions do not give rise to exceptions.
-
[SCADDR]: set the address of a capability to an arbitrary address
-
[CADD], [CADDI]: increment the address of the input capability by an arbitrary offset
-
[SCHI]: replace a capability’s metadata with an arbitrary value. The output tag is always 0
-
[ACPERM]: bitwise AND of a mask value with a bit map representation of the architectural (AP) and software-defined (SDP) permissions fields
-
[SCBNDS]: set the base and length of a capability. The tag is cleared, if the encoding cannot represent the bounds exactly
-
[SCBNDSR]: set the base and length of a capability. The base will be rounded down and/or the length will be rounded up if the encoding cannot represent the bounds exactly
-
[SENTRY]: seal capability as a sentry capability
-
[CBLD]: replace the base, top, address, permissions and mode fields of a capability with the fields from another capability
-
[CMV]: move a capability from a c register to another c register
A load capability instruction, [LC], reads CLEN bits from memory together with its tag and writes the result to a c register. The capability authorizing the memory access is provided in a c source register, so the effective address is obtained by incrementing that capability with the sign-extended 12-bit offset.
A store capability instruction, [SC], writes CLEN bits and the tag in a c register to memory. The capability authorizing the memory access is provided in a c source register, so the effective address is obtained by incrementing that capability with the sign-extended 12-bit offset.
[LC] and [SC] instructions cause CHERI exceptions if the authorizing capability fails any of the following checks:
-
The tag is zero
-
The capability is sealed
-
At least one byte of the memory access is outside the capability’s bounds
-
For loads, the read permission must be set in AP
-
For stores, the write permission must be set in AP
Capability load and store instructions also cause load or store/AMO address misaligned exceptions if the address is not naturally aligned to a CLEN boundary.
Misaligned capability loads and stores are errors. Implementations must generate exceptions for misaligned capability loads and stores even if they allow misaligned integer loads and stores to complete normally. Execution environments must report misaligned capability loads and stores as errors and not attempt to emulate them using byte access. The Zicclsm extension does not affect capability loads and stores. Software which uses capability loads and stores to copy data other than capabilities must ensure that addresses are aligned.
Note
|
Since there is only one tag per aligned CLEN bit block in memory, it is not possible to represent a capability value complete with its tag at an address not aligned to CLEN. Therefore, [LC] and [SC] give rise to misaligned address fault exceptions when the effective address to access is misaligned, even if the implementation supports Zicclsm. To transfer CLEN misaligned bits without a tag, use integer loads and stores. |
Warning
|
TODO: these cases may cause exceptions in the future - we need a way for software to discover and/or control the behavior |
The operands or behavior of some instructions in the base RISC-V ISA changes in {cheri_base_ext_name}.
Most integer computational instructions operate on XLEN bits of values held in x registers. Therefore, these instructions only operate on the address field if the input register of the instruction holds a capability. The output is XLEN bits written to an x register; the tag and capability metadata of that register are zeroed.
The add upper immediate to pcc instruction ([AUIPC]) is used to build pcc-relative capabilities. [AUIPC] forms a 32-bit offset from the 20-bit immediate and filling the lowest 12 bits with zeros. The pcc address is then incremented by the offset and a representability check is performed so the capability’s tag is cleared if the new address is outside the pcc's [section_cap_representable_check]. The resulting CLEN value along with the new tag are written to a c register.
Control transfer instructions operate as described in the base RISC-V ISA. They also may cause metadata updates and/or cause exceptions in addition to the base behavior as described below.
[JAL] sign-extends the offset and adds it to the address of the jump instruction to form the target address. The target address is installed in the address field of pcc. The capability with the address of the instruction following the jump is sealed and written to a c register.
[JALR] allows unconditional, indirect jumps to a target capability. The target capability is obtained by incrementing the capability in the c register operand by the sign-extended 12-bit offset, then setting the least significant bit of the result to zero. The target capability is unsealed if it is a sentry with zero offset. The capability with the address of the instruction following the jump is sealed and written to a c register.
All jumps cause CHERI exceptions when a minimum sized instruction at the target address is not within the bounds of the pcc.
[JALR] causes a CHERI exception when:
-
The target capability’s tag is zero
-
The target capability is sealed and the immediate is not zero
-
A minimum sized instruction at the target capability’s address is not within bounds
-
The target capability does not grant execute permission
Branch instructions (see [insns-conbr-32bit]) encode signed offsets in multiples of 2 bytes. The offset is sign-extended and added to the address of the branch instruction to form the target address.
Branch instructions compare two x registers as described in the base RISC-V ISA, so the metadata and tag values are disregarded in the comparison if the operand registers hold capabilities. If the comparison evaluates to true, then the target address is installed in the pcc's address field. These instructions cause CHERI exceptions when a minimum sized instruction at the target address is not within the pcc's bounds.
Integer load and store instructions transfer the amount of integer data described in the base RISC-V ISA between the registers and memory. For example, [LD] and [LW] load 64-bit and 32-bit values respectively from memory into an x register. However, the address operands for load and store instructions are interpreted differently in {cheri_base_ext_name}: the capability authorizing the access is in the c register operand and the memory address is given by incrementing the address of that capability by the sign-extended 12-bit immediate offset.
All load and store instructions cause CHERI exceptions if the authorizing capability fails any of the following checks:
-
The tag is set
-
The capability is unsealed
-
All bytes of accessed memory are inside the capability’s bounds
-
For loads, the read permission must be set in AP
-
For stores, the write permission must be set in AP
Integer load instructions always zero the tag and metadata of the result register.
Integer stores write zero to the tag associated with the memory locations that are naturally aligned to CLEN. Therefore, misaligned stores may clear up to two tag bits in memory.
{cheri_base_ext_name} requires that RISC-V CSRs intended to hold addresses, like mtvec, are now able to hold capabilities. Therefore, such registers are renamed and extended to CLEN-bit in {cheri_base_ext_name}.
Reading or writing any part of a CLEN-bit CSR may cause side effects. For example, the CSR’s tag bit may be cleared if a new address is outside the [section_cap_representable_check] of a CSR capability being written.
This section describes how the CSR instructions operate on these CSRs in {cheri_base_ext_name}.
The CLEN-bit CSRs are summarized in [clen_csr_summary].
All CSR instructions atomically read-modify-write a single CSR. If the CSR accessed is of capability size then the capability’s tag, metadata and address are all accessed atomically.
When the [CSRRW] instruction is accessing a capability width CSR, then the source and destination operands are c registers and it atomically swaps the values in the whole CSR with the CLEN width register operand.
There are special rules for updating specific CLEN-wide CSRs as shown in [extended_CSR_writing].
When [CSRRS] and [CSRRC] instructions are accessing a capability width CSR, such as mtvecc, then the destination operand is a c register and the source operand is an x register. Therefore, the instructions atomically read CLEN bits from the CSR, calculate the final address using standard RISC-V behavior (set bits, clear bits, etc.), and that final address is written to the CSR capability’s address field. The update typically uses the semantics of a [SCADDR] instruction which clears the tag if the capability is sealed, or if the updated address is not representable. [extended_CSR_writing] shows the exact action taken for each capability width CSR.
The [CSRRWI], [CSRRSI] and [CSRRCI] variants are similar to [CSRRW], [CSRRS], and [CSRRC] respectively, when accessing a capability width CSR except that they update the capability’s address only using an XLEN-bit value obtained by zero-extending a 5-bit unsigned immediate field.
All CSR instructions cause CHERI exceptions if the pcc does not grant [asr_perm] and the CSR accessed is privileged.
{cheri_base_ext_name} extends the CSRs listed in Table 1, Table 2, Table 3, Table 4 and Table 5 from the base RISC-V ISA and its extensions. The CSRs are renamed to reflect the fact that they are extended to CLEN+1 bits wide, as the x registers are renamed to c registers.
{cheri_base_ext_name} extends some M-mode CSRs to hold capabilities or otherwise add new functions. [asr_perm] in the pcc is typically required for access.
The mstatus and mstatush registers operate as described in cite:[riscv-priv-spec] except for the SXL and UXL fields that control the value of XLEN for S-mode and U-mode, respectively, and the MBE, SBE, and UBE fields that control the memory system endianness for M-mode, S-mode, and U-mode, respectively.
The encoding of the SXL and UXL fields is the same as the MXL field of misa. Only 1 and 2 are supported values for SXL and UXL and the fields must be read-only in implementations supporting {cheri_base_ext_name}. The effective XLEN in S-mode and U-mode are termed SXLEN and UXLEN, respectively.
The MBE, SBE, and UBE fields determine the endianness of memory accesses other than instruction fetches performed from M-mode, S-mode, or U-mode, respectively. xBE=0 indicates little endian and xBE=1 is big endian. MBE must be read-only. SBE and UBE must be read only and equal to MBE, if S-mode or U-mode, respectively, is implemented, or read-only zero otherwise.
Note
|
A further CHERI extension, {cheri_default_ext_name}, optionally makes SXL, UXL, MBE, SBE, and UBE writeable, so implementations that support multiple base ISAs must support both {cheri_base_ext_name} and {cheri_default_ext_name}. |
The mtvec register is as defined in cite:[riscv-priv-spec]. It is an MXLEN-bit register used as the executable vector jumped to when taking traps into machine mode. It is extended into mtvecc.
The mtvecc register is a renamed extension of mtvec that holds a capability. Its reset value is the [infinite-cap] capability. The capability represents an executable vector.
The metadata is WARL as not all fields need to be implemented, for example the reserved fields will always read as zero.
When interpreting mtvecc as a capability, as for mtvec, address bits [1:0] are always zero (as they are reused by the MODE field).
When MODE=Vectored, all synchronous exceptions into machine mode cause the pcc to be set to the capability, whereas interrupts cause the pcc to be set to the capability with its address incremented by four times the interrupt cause number.
Capabilities written to mtvecc also include writing the MODE field in mtvecc.address[1:0]. As a result, a representability and sealing check is performed on the capability with the legalized (WARL) MODE field included in the address. The tag of the capability written to mtvecc is cleared if either check fails.
Additionally, when MODE=Vectored the capability has its tag bit cleared if the capability address + 4 x HICAUSE is not within the representable bounds. HICAUSE is the largest exception cause value that the implementation can write to mcause when an interrupt is taken.
Note
|
When MODE=Vectored, it is only required that address + 4 x HICAUSE is within representable bounds instead of the capability’s bounds. This ensures that software is not forced to allocate a capability granting access to more memory for the trap-vector than necessary to handle the trap causes that actually occur in the system. |
The mscratch register is as defined in cite:[riscv-priv-spec]. It is an MXLEN-bit read/write register dedicated for use by machine mode. Typically, it is used to hold a pointer to a machine-mode hart-local context space and swapped with a user register upon entry to an M-mode trap handler. mscratch is extended into mscratchc.
{TAG_RESET_CSR}
It is not WARL, all capability fields must be implemented.
The mepcc register is a renamed extension of mepc that is able to hold a capability. Its reset value is the [infinite-cap] capability.
Capabilities written to mepcc must be legalized by implicitly zeroing bit mepcc[0]. Additionally, if an implementation allows IALIGN to be either 16 or 32, then whenever IALIGN=32, the capability read from mepcc must be legalized by implicitly zeroing mepcc[1]. Therefore, the capability read or written has its tag bit cleared if the legalized address is not within the [section_cap_representable_check] or if the legalization changes the address and the capability is sealed.
Note
|
When reading or writing a sealed capability in mepcc, the tag is not cleared if the original address equals the legalized address. |
When a trap is taken into M-mode, mepcc is written with the pcc including the virtual address of the instruction that was interrupted or that encountered an exception. Otherwise, mepcc is never written by the implementation, though it may be explicitly written by software.
As shown in [CSR_exevectors], mepcc is an executable vector, so it does not need to be able to hold all possible invalid addresses. Additionally, the capability in mepcc is unsealed when it is installed in pcc on execution of an [MRET] instruction.
{cheri_base_ext_name} adds a new exception code for CHERI exceptions that mcause must be able to represent. The new exception code and its priority are listed in Table 6 and Table 7 respectively. The behavior and usage of mcause otherwise remains as described in cite:[riscv-priv-spec].
Interrupt | Exception Code | Description |
---|---|---|
1 |
0 |
Reserved |
1 |
4 |
Reserved |
1 |
8 |
Reserved |
1 |
12-15 |
Reserved |
0 |
0 |
Instruction address misaligned |
Priority | Exc.Code | Description |
---|---|---|
Highest |
3 |
Instruction address breakpoint |
{cheri_excep_mcause} |
Prior to instruction address translation: |
|
12, 1 |
During instruction address translation: |
|
1 |
With physical address for instruction: |
|
2 |
Illegal instruction |
|
{cheri_excep_mcause} |
CHERI faults due to: |
|
{cheri_excep_mcause} |
Prior to address translation for an explicit memory access: |
|
4,6 |
Load/store/AMO capability address misaligned |
|
13, 15, 5, 7 |
During address translation for an explicit memory access: |
|
5,7 |
With physical address for an explicit memory access: |
|
4,6 |
If not higher priority: |
|
Lowest |
13 |
If not higher priority: |
1 The higher priority CHERI PTE page fault covers capability loads or atomics where the loaded tag is not checked, and all capability stores and atomics where the stored tag is set.
2 CHERI PTE page fault exceptions have the same priority against access faults as normal RISC-V page faults. If a normal RISC-V page fault and a CHERI PTE fault are both detected simultaneously, then both are recorded as shown in mtval2 for page faults.
3 The lower priority PTE fault only covers capability loads and atomics where the loaded tag is checked.
Note
|
The full details of the CHERI exceptions with cause value {cheri_excep_mcause} are in Table 12. |
Bit 28 of medeleg now refers to a valid exception and so can be used to delegate CHERI exceptions to supervisor mode.
The mtval register is an MXLEN-bit read-write register formatted as shown in Machine trap value register. When a data memory access gives rise to a CHERI fault taken into M-mode, mtval is written with the MXLEN-bit effective address which caused the fault according to the existing rules for reporting load/store addresses from cite:[riscv-priv-spec]. In this case the TYPE field of mtval2 shown in Table 8 is set to {cheri_excep_type_data}. For all other CHERI faults mtval is set to zero.
The behavior of mtval is otherwise as described in cite:[riscv-priv-spec].
If the hardware platform specifies that no exceptions set mtval to a non-zero value, then mtval is read-only zero for all CHERI exceptions.
The mtval2 register is an MXLEN-bit read-write register, which is added as part of the Hypervisor extension cite:[riscv-priv-spec]. {cheri_base_ext_name} also requires the implementation of this CSR.
When a CHERI fault is taken into M-mode, mtval2 is written with additional CHERI-specific exception information with the format shown in Machine trap value register 2 format for CHERI Faults to assist software in handling the trap.
If mtval is read-only zero for CHERI exceptions then mtval2 is also read-only zero for CHERI exceptions.
Note
|
mtval2 is also used for Hypervisor guest physical addresses, and so the implemented bits must also cover that use case. If Hypervisor is not implemented then all WPRI fields in Machine trap value register 2 format for CHERI Faults are read-only-zero. |
TYPE is a CHERI-specific fault type that caused the exception while CAUSE is the cause of the fault. The possible CHERI types and causes are encoded as shown in Table 8 and Table 9 respectively.
CHERI Type Code | Description |
---|---|
{cheri_excep_type_pcc} |
CHERI instruction fetch fault |
{cheri_excep_type_data} |
CHERI data fault due to load, store or AMO |
{cheri_excep_type_jump} |
CHERI jump or branch fault |
3-15 |
Reserved |
CHERI Cause Code | Description |
---|---|
{cheri_excep_cause_tag} |
Tag violation |
{cheri_excep_cause_seal} |
Seal violation |
{cheri_excep_cause_perm} |
Permission violation |
{cheri_excep_cause_inv_addr} |
Invalid address violation |
{cheri_excep_cause_bounds} |
Bounds violation |
5-15 |
Reserved |
CHERI violations have the following order in priority:
-
Tag violation (Highest)
-
Seal violation
-
Permission violation
-
Invalid address violation
-
Bounds violation (Lowest)
Page faults can be caused by normal RISC-V page faults and also by CHERI PTE faults. If both are detected at once, then both are recorded.
Fault | Value |
---|---|
RISC-V page fault |
0 |
CHERI PTE fault |
1 |
RISC-V page fault and CHERI PTE fault |
2 |
Note
|
Reporting both allows the software the choice about which action to take first, for example a write to a page with no write permission, and the incorrect value of PTE.CRG requires two actions. Software can then decide whether to prioritize the copy-on-write procedure to fix the lack of write permission, or to sweep the page. |
{cheri_base_ext_name} extends some of the existing RISC-V CSRs to be able to hold capabilities or with other new functions. [asr_perm] in the pcc is typically required for access.
The stvec register is as defined in cite:[riscv-priv-spec]. It is an SXLEN-bit register used as the executable vector jumped to when taking traps into supervisor mode. It is extended into stvecc.
The stvec register is an SXLEN-bit WARL read/write register that holds the trap vector configuration, consisting of a vector base address (BASE) and a vector mode (MODE). The stvecc register is a renamed extension of stvec that is able to hold a capability. Its reset value is the [infinite-cap] capability.
The sscratch register is as defined in cite:[riscv-priv-spec]. It is an MXLEN-bit read/write register dedicated for use by supervisor mode. Typically, it is used to hold a pointer to a supervisor-mode hart-local context space and swapped with a user register upon entry to an S-mode trap handler. sscratch is extended into sscratchc.
{TAG_RESET_CSR}
It is not WARL, all capability fields must be implemented.
The sepcc register is a renamed extension of sepc that is able to hold a capability. Its reset value is the [infinite-cap] capability.
As shown in [CSR_exevectors], sepcc is an executable vector, so it need not be able to hold all possible invalid addresses. Additionally, the capability in sepcc is unsealed when it is installed in pcc on execution of an [SRET] instruction. The handling of sepcc is otherwise identical to mepcc, but in supervisor mode.
{cheri_base_ext_name} adds a new exception code for CHERI exceptions that scause must be able to represent. The new exception code and its priority are listed in Table 11 and Table 7 respectively. The behavior and usage of scause otherwise remains as described in cite:[riscv-priv-spec].
Interrupt | Exception Code | Description |
---|---|---|
1 |
0 |
Reserved |
0 |
0 |
Instruction address misaligned |
The stval register is an SXLEN-bit read-write register formatted as shown in Supervisor trap value register.
stval is updated following the same rules as mtval for CHERI exceptions which are delegated to S-mode.
The stval2 register is an SXLEN-bit read-write register, which is added as part of {cheri_base_ext_name} when the implementation supports S-mode. Its CSR address is 0x14b.
stval2 is updated following the same rules as mtval2 for CHERI exceptions which are delegated to S-mode.
The fields are identical to mtval2 for CHERI exceptions, and for load and store/AMO page fault exceptions if {cheri_pte_ext_name} is implemented.
In {cheri_base_ext_name}, the only register that requires [asr_perm] is [utidc] (for updates but not for reads), and all other unprivileged CSRs do not require pcc to grant [asr_perm] to access unprivileged CSRs.
Note
|
auth_cap is [ddc] for {cheri_int_mode_name} and cs1 for {cheri_cap_mode_name}
|
Instructions | Xcause | Xtval2. TYPE | Xtval2. CAUSE | Description | Check |
---|---|---|---|---|---|
All instructions have these exception checks first |
|||||
All |
{cheri_excep_mcause} |
{cheri_excep_type_pcc} |
{cheri_excep_cause_tag} |
pcc tag |
not(pcc.tag) |
All |
{cheri_excep_mcause} |
{cheri_excep_type_pcc} |
{cheri_excep_cause_seal} |
pcc seal |
isCapSealed(pcc)1 |
All |
{cheri_excep_mcause} |
{cheri_excep_type_pcc} |
{cheri_excep_cause_perm} |
pcc permission |
|
All |
{cheri_excep_mcause} |
{cheri_excep_type_pcc} |
{cheri_excep_cause_inv_addr} |
pcc invalid address |
pcc holds an invalid address |
All |
{cheri_excep_mcause} |
{cheri_excep_type_pcc} |
{cheri_excep_cause_bounds} |
pcc bounds |
Any byte of current instruction out of pcc bounds |
CSR/Xret additional exception check |
|||||
{cheri_excep_mcause} |
{cheri_excep_type_pcc} |
{cheri_excep_cause_perm} |
pcc permission |
not(pcc.[asr_perm]) when required for CSR access or execution of [MRET]/[SRET] |
|
direct jumps additional exception check |
|||||
{cheri_excep_mcause} |
{cheri_excep_type_jump} |
{cheri_excep_cause_bounds} |
pcc bounds |
any byte of minimum length instruction at target out of pcc bounds |
|
indirect jumps additional exception checks |
|||||
indirect jumps |
{cheri_excep_mcause} |
{cheri_excep_type_jump} |
{cheri_excep_cause_tag} |
|
not( |
indirect jumps |
{cheri_excep_mcause} |
{cheri_excep_type_jump} |
{cheri_excep_cause_seal} |
|
isCapSealed( |
indirect jumps |
{cheri_excep_mcause} |
{cheri_excep_type_jump} |
{cheri_excep_cause_perm} |
|
not( |
indirect jumps |
{cheri_excep_mcause} |
{cheri_excep_type_jump} |
{cheri_excep_cause_inv_addr} |
|
target address is an invalid address |
indirect jumps |
{cheri_excep_mcause} |
{cheri_excep_type_jump} |
{cheri_excep_cause_bounds} |
|
any byte of minimum length instruction at target out of |
Load additional exception checks |
|||||
all loads |
{cheri_excep_mcause} |
{cheri_excep_type_data} |
{cheri_excep_cause_tag} |
|
not( |
all loads |
{cheri_excep_mcause} |
{cheri_excep_type_data} |
{cheri_excep_cause_seal} |
|
isCapSealed( |
all loads |
{cheri_excep_mcause} |
{cheri_excep_type_data} |
{cheri_excep_cause_perm} |
|
not( |
all loads |
{cheri_excep_mcause} |
{cheri_excep_type_data} |
{cheri_excep_cause_inv_addr} |
|
Address is invalid (see Invalid address conversion) |
all loads |
{cheri_excep_mcause} |
{cheri_excep_type_data} |
{cheri_excep_cause_bounds} |
|
Any byte of load access out of |
capability loads |
4 |
N/A |
N/A |
load address misaligned |
Misaligned capability load |
Store/atomic/cache-block-operation additional exception checks |
|||||
all stores, all atomics, all cbos |
{cheri_excep_mcause} |
{cheri_excep_type_data} |
{cheri_excep_cause_tag} |
|
not( |
all stores, all atomics, all cbos |
{cheri_excep_mcause} |
{cheri_excep_type_data} |
{cheri_excep_cause_seal} |
|
isCapSealed( |
all atomics, CBO.INVAL* |
{cheri_excep_mcause} |
{cheri_excep_type_data} |
{cheri_excep_cause_perm} |
|
not( |
all stores, all atomics, CBO.INVAL*, CBO.ZERO* |
{cheri_excep_mcause} |
{cheri_excep_type_data} |
{cheri_excep_cause_perm} |
|
not( |
CBO.CLEAN*, CBO.FLUSH* |
{cheri_excep_mcause} |
{cheri_excep_type_data} |
{cheri_excep_cause_perm} |
|
|
all stores, all atomics, all cbos |
{cheri_excep_mcause} |
{cheri_excep_type_data} |
{cheri_excep_cause_inv_addr} |
|
Address is invalid (see Invalid address conversion) |
all stores, all atomics |
{cheri_excep_mcause} |
{cheri_excep_type_data} |
{cheri_excep_cause_bounds} |
|
any byte of access out of |
CBO.ZERO*, CBO.INVAL* |
{cheri_excep_mcause} |
{cheri_excep_type_data} |
{cheri_excep_cause_bounds} |
|
any byte of cache block out of |
CBO.CLEAN*, CBO.FLUSH* |
{cheri_excep_mcause} |
{cheri_excep_type_data} |
{cheri_excep_cause_bounds} |
|
all bytes of cache block out of |
CBO.INVAL* |
{cheri_excep_mcause} |
{cheri_excep_type_pcc} |
{cheri_excep_cause_perm} |
pcc permission |
not(pcc.[asr_perm]) |
capability stores |
6 |
N/A |
N/A |
capability alignment |
Misaligned capability store |
1 This check is architecturally required, but is impossible to encounter so may not required in an implementation.
Note
|
Indirect branches are [JALR], conditional branches are [insns-conbr-32bit]. |
Note
|
[CBO.ZERO] issues as a cache block wide store. All CMOs operate on the cache block which contains the address. Prefetches check that the capability is tagged, not sealed, has the permission ([r_perm], [w_perm], [x_perm]) corresponding to the instruction, and has bounds which include at least one byte of the cache block; if any check fails, the prefetch is not performed but no exception is generated. |
CHERI adds architectural guarantees that can prove to be microarchitecturally useful. Speculative-execution attacks can — among other factors — rely on instructions that fail CHERI permission checks not to take effect. When implementing any of the extensions proposed here, microarchitects need to carefully consider the interaction of late-exception raising and side-channel attacks.
Typically, the entire memory space need not support tagged data. Therefore, it is desirable that harts supporting {cheri_base_ext_name} extend PMAs with a taggable attribute indicating whether a memory region allows storing tagged data.
Data loaded from memory regions that are not taggable will always have the tag cleared. When the hart attempts to store data with the tag set to memory regions that are not taggable, the implementation may:
-
Cause an access fault exception
-
Implicitly set the stored tag to 0
RISC-V’s page-based virtual-memory management is generally orthogonal to CHERI. In {cheri_base_ext_name}, capability addresses are interpreted with respect to the privilege level of the processor in line with RISC-V’s handling of integer addresses. In machine mode, capability addresses are generally interpreted as physical addresses; if the mstatus MPRV flag is asserted, then data accesses (but not instruction accesses) will be interpreted as if performed by the privilege mode in mstatus’s MPP. In supervisor and user modes, capability addresses are interpreted as dictated by the current satp configuration: addresses are virtual if paging is enabled and physical if not.
{cheri_base_ext_name} requires that the pcc grants the [asr_perm] to change the page-table root satp and other virtual-memory parameters as described in Supervisor-Level CSRs.
When address translation is in effect and XLEN=64, the upper bits of virtual memory addresses must match for the address to be valid:
-
For Sv39, bits [63:39] must equal bit 38
-
For Sv48, bits [63:48] must equal bit 47
-
For Sv57, bits [63:57] must equal bit 56
RISC-V permits that CSRs holding addresses, such as mtvec and mepc (see [CSR_exevectors]) as well as pc, need not hold all possible invalid addresses. Implementations may convert an invalid address into some other invalid address that the register is capable of holding. Therefore, implementations often support area and power optimizations by compressing invalid addresses in a lossy fashion.
Where compressed addresses are implemented, there must be also sufficient address bits to represent all valid physical addresses. The following description is for both virtual and physical addresses.
Note
|
Compressing invalid addresses allows implementations to reduce the number of flip-flops required to hold some CSRs, such as mtvec. In CHERI, invalid addresses may also be used to reduce the number of bits to compare during a bounds check, for example, to 40 bits if using Sv39, assuming that this also covers all valid physical addresses. |
Note
|
Care needs to be taken not to truncate physical addresses to the implemented number of physical addresses bits without also checking that the capability is still valid following the rules in this section, as the capability bounds and representable range always cover the entire MXLEN-bit address bits, but the address is likely not to. |
However, the bounds encoding of capabilities in {cheri_base_ext_name} depends on the address value, so implementations must not convert invalid addresses to other arbitrary invalid address in an unrestricted manner. The remainder of this section describes how invalid address handling must be supported in {cheri_base_ext_name} when accessing CSRs, branching and jumping, and accessing memory.
Some capability-holding CSRs need not be able to hold all invalid virtual addresses. Prior to writing to those CSRs, implementations may convert an invalid address into some other invalid address that the CSR is capable of holding. This is problematic for CHERI as updating the address may invalidate the bounds as a result, if the bounds are not those of the [infinite-cap] capability.
Some situations may require that a CSR may be updated to hold a capability with an invalid address:
In order to satisfy the definitions of such CSRs and preserve capability system invariants, the following procedure must be used as part of write-back to the CSR:
-
If A’s address is invalid and A does not have infinite bounds (see [section_cap_encoding]), then A’s tag is set to 0.
-
Write the final (potentially modified) version of capability A to the CSR e.g. mtvecc, mepcc, etc.
Note
|
When A’s address is invalid and happens to match an invalid address which the CSR can hold, then it is implementation defined whether to clear A’s tag. |
Control transfer instructions jump or branch to a capability A which can be:
-
pcc for branches, direct jumps and any branch when in {cheri_int_mode_name} (see [section_cheri_hybrid_ext]).
-
The capability in the c input register of a jump when in {cheri_cap_mode_name} (see [section_cheri_hybrid_ext]).
The following procedure must be used when jumping or branching to the target capability A if the pcc cannot hold all invalid addresses:
-
Calculate the effective target address T of the jump or branch as required by the instruction’s behavior.
-
If T is invalid and A does not have infinite bounds (see [section_cap_encoding]), then the instruction gives rise to a CHERI fault; the CHERI jump or branch fault is reported in the TYPE field and invalid address violation is reported in the CAUSE field of mtval2 or stval2.
-
If T is invalid and A has infinite bounds (see [section_cap_encoding]), then A’s tag is unchanged and T is written into A’s address field. Attempting to execute the instruction at address T gives rise to an instruction access fault or page fault as is usual in RISC-V.
-
Otherwise T is valid and the instruction behaves as normal.
Note
|
RISC-V harts that do not support {cheri_base_ext_name} normally raise an instruction access fault or page fault after jumping or branching to an invalid address. Therefore, {cheri_base_ext_name} aims to preserve that behavior to ensure that harts supporting {cheri_base_ext_name} and {cheri_default_ext_name} are fully compatible with RISC-V harts provided that pcc and [ddc] are set to the [infinite-cap] capability. |
The following procedure must be used while loading or storing to memory with a capability A when the implementation supports invalid address optimizations:
-
Calculate the effective address range R of the memory access as required by the instruction’s behavior.
-
If any byte in R is invalid and A does not have infinite bounds (see [section_cap_encoding]), then the instruction gives rise to a CHERI fault; the CHERI data fault is reported in the TYPE field and invalid address violation is reported in the CAUSE field of mtval2 or stval2.
-
If any byte in R is invalid and A has infinite bounds (see [section_cap_encoding]), the hart will raise an access fault or page fault as is usual in RISC-V.
-
Otherwise all bytes in R are valid and the instruction behaves as normal.