CTSRD-CHERI / cheri-specification

CHERI ISA Specification
Other
23 stars 7 forks source link

misaligned load/store capabilities can't be emulated #91

Open tariqkurd-repo opened 1 year ago

tariqkurd-repo commented 1 year ago

Misaligned load/store capabilities take the normal RISC-V misaligned exception.

Normally the misaligned exception allows handler software to fix-up the misaligned load/store in software - but this is not permitted for capabilities.

Therefore it may be worth making misaligned load/store capabilities into a specific CHERI exception, to make it clear that they can't be emulated.

bsdjhb commented 1 year ago

I think you could still emulate a misaligned load/store. The result of a load would be an untagged capability, and the tag would be lost on the store. You would just use CGetHi and CSetHi along with the x register for the lower half to load/store the two halves.

tariqkurd-repo commented 1 year ago

Doesn't this situation mean that you've used the wrong encoding though? Would you really extend the exception handler to execute misaligned load/store capabilities? It sounds to me like intentionality is broken in this case.

Essentially it's a choice, so the choice should be documented either way.

bsdjhb commented 1 year ago

Oh, I think mostly likely it just means you have a bug. We actually see this not too uncommon now in userspace where people write their own caching slab allocators that wrap malloc() but assume that they only need to align sub-allocations on a uint64_t boundary which inevitably results in a lost tags, etc. The compiler emits lc/sc because it assumes the buffer will be suitably aligned, but the allocator broke that assumption.

You can still get lost tags without raising an alignment trap btw if the code in question uses memcpy instead of a simple store as typical memcpy implementations usually have a preamble to handle any non-aligned start before a loop that does an aligned block copy followed by a postamble to handle any remaining trailer. Thus, memcpy(&my_unaligned_dest, &cap, sizeof(cap)) will just lose tag without faulting. I think it is less confusing if unaligned accesses give the same result as in C my_unaligned_dest = cap generally has the same semantics as the memcpy invocation.