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

Conversation

sorear
Copy link
Contributor

@sorear sorear commented Mar 11, 2024

The address behavior is dictated by the base ISA and the desire to keep Legacy and Capability mode as close as possible. This just defines metadata and CHERI exception behavior in some cases that aren't covered by Zcheri_purecap.


I think there are currently five semantically distinct places where representability checks are needed:

  1. SCADDR instruction
  2. Writes of capability CSRs through XLEN-bit aliases, using bitwise instructions, or after legalisation
  3. Predetermining truncation results for explicit writes to variable width capability CSRs
  4. Predetermining truncation results for writes to xepcc as a result of traps
  5. Truncation of pcc on trap return

Cases 3-5 are only possible if multiple XLEN values are supported. 3-4 are only possible if there are multiple SXLEN or (for 3 only) Zcmt is implemented. 3 can share significant logic with 2 since it operates on the same input capability. Depending on the pipeline design it may be possible to combine 1 with 2, 1 with 5, or 3 with 4.

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.
Copy link
Collaborator

Choose a reason for hiding this comment

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

or the CSR is sealed and the original and modulated addresses differ

The address behavior is dictated by the base ISA and the desire to keep
Legacy and Capability mode as close as possible. This just defines
metadata and CHERI exception behavior in some cases that aren't covered
by Zcheri_purecap.

Signed-off-by: Stefan O'Rear <[email protected]>
Copy link
Collaborator

@arichardson arichardson left a comment

Choose a reason for hiding this comment

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

Thanks this looks good to me, will merge if @jrtc27 is happy.

Comment on lines +316 to +319
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.
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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants