pvh 0.1.0

Xen's x86/HVM direct boot ABI (PVH).
Documentation
use core::alloc::Layout;
use core::ptr;

/// A memory map.
///
/// This trait is used for acquiring pointers corresponding to physical
/// addresses.
//
// The current design is inspired by `GlobalAlloc`. The design could be
// revisited once `allocator_api` stabilizes:
// https://github.com/rust-lang/rust/issues/32838
pub trait MemMap {
    /// Returns a pointer corresponding to a physical address.
    ///
    /// This method returns a pointer that is valid for reading at the physical
    /// address `paddr` with the layout `layout`, or null to indicate failure.
    #[must_use]
    fn ptr(&self, paddr: usize, layout: Layout) -> *const u8;
}

impl<M: MemMap + ?Sized> MemMap for &M {
    #[inline]
    fn ptr(&self, paddr: usize, layout: Layout) -> *const u8 {
        (**self).ptr(paddr, layout)
    }
}

impl<M: MemMap + ?Sized> MemMap for &mut M {
    #[inline]
    fn ptr(&self, paddr: usize, layout: Layout) -> *const u8 {
        (**self).ptr(paddr, layout)
    }
}

/// The identity-mapped memory map.
///
/// This [`MemMap`] implementation returns pointers with exposed provenance
/// and the virtual address of the requested physical address. This is useful
/// on systems without paging and on systems that have identity-mapped all
/// physical memory to virtual memory.
#[derive(Default, Copy, Clone, Debug)]
pub struct IdentityMap;

impl MemMap for IdentityMap {
    #[inline]
    fn ptr(&self, paddr: usize, layout: Layout) -> *const u8 {
        let ptr = ptr::with_exposed_provenance_mut(paddr);

        if !ptr_is_aligned_to(ptr, layout.align()) {
            return ptr::null();
        }

        ptr
    }
}

// Replace with `pointer_is_aligned_to`, once stable:
// https://github.com/rust-lang/rust/issues/96284
#[inline]
#[must_use]
fn ptr_is_aligned_to<T>(ptr: *const T, align: usize) -> bool {
    assert!(
        align.is_power_of_two(),
        "ptr_is_aligned_to: align is not a power-of-two"
    );

    ptr.addr() & (align - 1) == 0
}