frame-alloc 0.1.0

A no_std, dependency-free, const-constructible physical frame allocator for kernels
Documentation
extern crate std;

use crate::Provenance;
use alloc::alloc::{alloc, dealloc};
use core::alloc::Layout;
use core::num::NonZeroUsize;
use core::ptr;
use core::ptr::NonNull;

pub const N1: NonZeroUsize = NonZeroUsize::MIN;
pub fn n(v: usize) -> NonZeroUsize {
    NonZeroUsize::new(v).unwrap()
}

/// RAII wrapper for a heap-allocated region used as a fake physical memory pool.
/// Frees the region on drop.
pub struct OwnedRegion {
    ptr: NonNull<u8>,
    layout: Layout,
}

impl OwnedRegion {
    pub fn new(size: usize, align: usize) -> Self {
        let layout = Layout::from_size_align(size, align).unwrap();
        let ptr = NonNull::new(unsafe { alloc(layout) }).expect("region allocation failed");
        OwnedRegion { ptr, layout }
    }

    /// Physical address for identity-mapped provenance (`TestProvenance`).
    pub fn addr(&self) -> usize {
        self.ptr.as_ptr().expose_provenance()
    }
}

impl Drop for OwnedRegion {
    fn drop(&mut self) {
        unsafe { dealloc(self.ptr.as_ptr(), self.layout) }
    }
}

pub struct TestProvenance;

// with_exposed_provenance_mut is used here because the "physical" memory is
// actually a Rust heap allocation (OwnedRegion) whose provenance was exposed
// via expose_provenance() in OwnedRegion::addr().
// Likewise for destroy: the allocation's lifetime is managed by OwnedRegion::drop.
unsafe impl Provenance for TestProvenance {
    unsafe fn create(phys: usize) -> NonNull<u8> {
        unsafe { NonNull::new_unchecked(ptr::with_exposed_provenance_mut(phys)) }
    }

    unsafe fn destroy<T>(ptr: NonNull<T>) -> usize {
        ptr.addr().get()
    }
}