Skip to main content

Provenance

Trait Provenance 

Source
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. create tells the compiler an allocation begins at that address, yielding fresh provenance; destroy tells it the allocation ends. Both must be opaque to the compiler - in practice an empty asm! block that launders the pointer, and without options(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; create recovers it with with_exposed_provenance_mut, and destroy reads the address back out. This fits a pool that is really a host allocation, as in this crate’s tests.

§Safety

  • create must return a pointer whose provenance covers the entire contiguous mapping starting at phys - not merely the first frame. A caller may access [phys, phys + len) through it for any len that stays within one physically-contiguous, exclusively-owned run (e.g. a multi-frame metadata bitmap carved from one usable range).
  • destroy must be called exactly once per pointer returned by create, after which the pointer must not be used.

Required Methods§

Source

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 phys to 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.

Source

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".

Implementors§