Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Corner cases for narrow XLENs #141

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions src/riscv-legacy-integration.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,73 @@ NOTE: Disabling CHERI register access prevents a low-privileged Legacy mode
from interfering with the correct operation of higher-privileged Legacy modes
that do not perform <<ddc>> switches on trap entry and return.

=== CHERI execution with XLEN less than XLENMAX

While XLEN is less than XLENMAX CHERI register access is disabled as described
in xref:section_cheri_disable[xrefstyle=short]. Base ISA instructions still
need to perform capability checks on XLEN-wide addresses.

==== Addresses in pcc

The `pc` width is the current XLEN. The address field of <<pcc>> is the `pc`
sign extended to XLENMAX bits at all times. All changes to the `pc`, including
jumps, conditional branches, trap returns, and sequential execution, sign
extend `pc` to set the <<pcc>> address, and a <<pcc>> address which is not sign
extended is an impossible state.

[NOTE]
====
Sign extension of `pc` into `__x__epc` is a requirement imposed by the base
ISA.

Sequential execution across 2^XLEN^/2 or from 2^XLEN^ to 0 when XLEN is less
than XLENMAX and <<pcc>> does not hold an infinite-bounds capability has
different effects depending on whether the addressing boundary coincides with
an instruction boundary. A single instruction which spans the address boundary
will be treated as a length violation and is reported as a CHERI exception with
`__x__epcc` the starting address of the instruction. If an instruction ends
exactly at the addressing boundary, the instruction will complete successfully
but the <<pcc>> becomes unrepresentable afterward, and a tag violation CHERI
exception is taken on the next instruction unless an interrupt or higher
priority synchronous exception is taken instead; in all cases `__x__epcc` will
have an address of 0 or 2^XLEN^/2 and a tag of zero.
Comment on lines +316 to +319
Copy link
Collaborator

Choose a reason for hiding this comment

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

It won't always be unrepresentable, e.g. if PCC's bounds are [0, (2^XLEN)/2) and you attempt to cross the middle of the address space?

Suggested change
but the <<pcc>> becomes unrepresentable afterward, and a tag violation CHERI
exception is taken on the next instruction unless an interrupt or higher
priority synchronous exception is taken instead; in all cases `__x__epcc` will
have an address of 0 or 2^XLEN^/2 and a tag of zero.
but the <<pcc>> becomes out of bounds or unrepresentable afterward, and a length or tag violation CHERI
exception is taken on the next instruction unless an interrupt or higher
priority synchronous exception is taken instead; in all cases `__x__epcc` will
have an address of 0 or 2^XLEN^/2 and, in the unrepresentable case, a tag of zero.

Also that "all cases" doesn't apply to the "unless an interrupt or ..." case.

====

==== Bounds checking

Each byte address of a load, store, or instruction fetch is individually sign
extended from XLEN bits to XLENMAX bits prior to bounds checking.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Hm, the Supervisor spec says:

If UXLEN \(<\) SXLEN, user-mode instruction-fetch addresses and load and store effective addresses are taken modulo \(2^{\text{UXLEN}}\). For example, when UXLEN=32 and SXLEN=64, user-mode memory accesses reference the lowest 4 GiB of the address space.

Should we not do the same here? Otherwise this lets you access memory that is in reality outside the bounds of the capability in use. Though I note this is at odds with:

Similarly, pc bits above XLEN are ignored, and when the pc is written, it is sign-extended to fill the widest supported XLEN.

So an OS needs to know to mask those bits off in xEPC when figuring out what actual address was being fetched from (but not xTVAL). Which is particularly silly when switching to RV32 then back to RV64 in the more privileged mode discards said upper bits of xEPC. This sounds to me like an oversight in the spec and that PC should have been regarded like a CSR not a GPR (or at least in the cases where it is used for CSRs, as opposed to AUIPC and JALR where I can understand the desire to have it pre-sign-extended, but that's a hardware implementation optimisation and already specified by virtue of writes to GPRs sign-extending the value).

I wonder if there's appetite for making that saner in the base spec. Otherwise we probably need some ludicrous "PCC's address will be sign-extended, as visible when put into xEPCC, but gets masked when the bounds check is performed, so both need to be representable (though only the latter in bounds)" requirement.


NOTE: A load, store, or instruction fetch which spans 2^XLEN^/2 or wraps from
2^XLEN^ to 0 will always fail bounds checking when XLEN is less than XLENMAX
unless the authorising capability has infinite bounds since the mantissa width
for all XLENMAX is less than 32.

==== CSR width modulation

Address CSRs have a width defined by the base ISA which may be variable,
depending on the implementation's supported XLEN and mode combinations. The
corresponding extended CSRs have a variable width address field. If the width
changes, the address field is truncated to the new width and zero extended to
XLENMAX bits. The CSR's tag will be cleared at the time of the width change if
the new address is not representable or if the CSR is sealed and the original
and modulated addresses differ.

[NOTE]
====
The extension behavior differs between extended CSRs and <<pcc>>.

It is suggested that implementations which need width modulation determine at
the time of CSR writes whether the new address would still be representable if
truncated, and store this alongside the CSR value.

Extended CSR width modulation is possible for <<jvtc>> if the Zcmt extension is
implemented and more than one XLEN value is supported. Extended CSR width
modulation is possible for <<stvecc>>, <<sscratchc>>, and <<sepcc>> if more
than one SXLEN is supported. Extended CSR width modulation is possible for
<<mtvecc>>, <<mscratchc>>, and <<mepcc>> if more than one MXLEN is supported.
====

=== Added CLEN-wide CSRs

{cheri_legacy_ext_name} adds the CLEN-wide CSRs shown in
Expand Down
Loading