pub unsafe trait Provenance {
// Required methods
unsafe fn create(phys: usize) -> NonNull<u8>;
unsafe fn destroy<T>(ptr: NonNull<T>) -> usize;
}Expand description
Strategy for obtaining and relinquishing compiler provenance on physical frame pointers.
Implement this trait to tell the allocator how to manage provenance when frames enter or leave its internal free structure.
Two stories satisfy this trait, and an implementation tells one of them:
- Create an allocation.
createtells the compiler an allocation begins at that address, yielding fresh provenance;destroytells it the allocation ends. Both must be opaque to the compiler - in practice an emptyasm!block that launders the pointer, and withoutoptions(nomem), because allocating and deallocating are memory effects. This is the story a kernel tells over its direct map, and the only one available when the memory is accessed atomically, since there are no volatile atomic accesses. - Recover exposed provenance. The memory is already one live allocation
whose provenance was exposed;
createrecovers it withwith_exposed_provenance_mut, anddestroyreads the address back out. This fits a pool that is really a host allocation, as in this crate’s tests.
§Safety
createmust return a pointer whose provenance covers the entire contiguous mapping starting atphys- not merely the first frame. A caller may access[phys, phys + len)through it for anylenthat stays within one physically-contiguous, exclusively-owned run (e.g. a multi-frame metadata bitmap carved from one usable range).destroymust be called exactly once per pointer returned bycreate, after which the pointer must not be used.
Required Methods§
Sourceunsafe fn create(phys: usize) -> NonNull<u8>
unsafe fn create(phys: usize) -> NonNull<u8>
Obtain a provenance-carrying pointer for a bare physical address before the allocator writes into the frame.
The correct implementation for a kernel depends on how physical memory is mapped:
- Convert
physto a virtual address. - Establish compiler provenance for it, by whichever of the two stories above this implementation tells.
§Safety
phys must be a physical address whose memory is exclusively owned and
accessible through the virtual address this function returns. The returned
pointer carries provenance over the whole contiguous run starting at
phys, so a caller may read/write any prefix of that run through it.
Provenance cannot simply be asserted onto an integer. Recovering exposed
provenance requires that whatever established the mapping exposed it;
creating an allocation requires that the creation be opaque to the
compiler. A bare phys as *mut u8 does neither and is unsound.
Sourceunsafe fn destroy<T>(ptr: NonNull<T>) -> usize
unsafe fn destroy<T>(ptr: NonNull<T>) -> usize
Relinquish a frame pointer and recover the raw physical address when ownership is transferred back to the caller.
Under the create-an-allocation story this is a real event, not
bookkeeping: the frame is about to reach a caller who will establish their
own allocation over it, and two live allocations covering the same memory
would entitle the compiler to assume they do not alias. Ending the first
one here is what rules that out, so the body must be opaque to the
compiler in the same way create is.
Under the recover-exposed-provenance story nothing ends - create never
began a new allocation - and reading the address back out is a complete
implementation.
The contract below is the intersection of the two, which is why it binds more tightly than the second story alone needs.
§Safety
ptr must have been returned by Self::create and must not be used
again after this call. Calling create again for the same
physical address is permitted and yields a fresh pointer.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".