Files
k-os/crates/adapter-riscv/src/kernel_cell.rs
Gabriel Kaszewski 8d2c40cb1e feat(kernel): kernel-owned memory model
- FrameTable: per-frame owner/use, replaces PagePool + ProcessMemory
- Quota per process, page tables charged to owner
- Regions for shared mem + device MMIO, torn down w/ owner
- Platform: create/destroy AS, map/unmap, zero_frame; drop translate_va
- RequestPages/ReleasePages/MapPage(move) checked vs kernel records
- user window 0x1000..32MiB, private pts by construction
- boot loader + device setup go through kernel api
- kernel built in place, boot allocator bounded
- isolation tests, randomized invariant test, FrameTable kani proofs
- fixes: inflated release, unmapped release, dst va unchecked,
  heap overflow, unbounded pt alloc, unzeroed frames, double free
2026-10-26 19:40:50 +01:00

39 lines
1.2 KiB
Rust

use core::cell::UnsafeCell;
use core::mem::MaybeUninit;
use core::sync::atomic::{AtomicBool, Ordering};
pub struct KernelCell<T> {
initialized: AtomicBool,
inner: UnsafeCell<MaybeUninit<T>>,
}
// Single-core, interrupts disabled during kernel access.
unsafe impl<T> Sync for KernelCell<T> {}
impl<T> KernelCell<T> {
pub const fn uninit() -> Self {
Self {
initialized: AtomicBool::new(false),
inner: UnsafeCell::new(MaybeUninit::uninit()),
}
}
/// Initializes the cell by letting `build` write the value straight
/// into its storage, so a large `T` never lives on the stack.
///
/// # Safety
/// `build` must fully initialize the `T` behind the pointer.
pub unsafe fn init_with(&self, build: impl FnOnce(*mut T)) {
build(unsafe { (*self.inner.get()).as_mut_ptr() });
self.initialized.store(true, Ordering::Release);
}
/// Returns a raw pointer to the kernel. Callers must ensure
/// no aliasing `&mut` references exist. Safe on single-core
/// with interrupts disabled during kernel calls.
pub fn as_ptr(&self) -> *mut T {
debug_assert!(self.initialized.load(Ordering::Acquire));
unsafe { (*self.inner.get()).as_mut_ptr() }
}
}