ostd/mm/frame/
frame_ref.rs

1// SPDX-License-Identifier: MPL-2.0
2
3use core::{marker::PhantomData, mem::ManuallyDrop, ops::Deref, ptr::NonNull};
4
5use super::{
6    Frame,
7    meta::{AnyFrameMeta, MetaSlot},
8};
9use crate::{mm::Paddr, sync::non_null::NonNullPtr};
10
11/// A struct that can work as `&'a Frame<M>`.
12#[derive(Debug)]
13pub struct FrameRef<'a, M: AnyFrameMeta + ?Sized> {
14    inner: ManuallyDrop<Frame<M>>,
15    _marker: PhantomData<&'a Frame<M>>,
16}
17
18impl<M: AnyFrameMeta + ?Sized> FrameRef<'_, M> {
19    /// Borrows the [`Frame`] at the physical address as a [`FrameRef`].
20    ///
21    /// # Safety
22    ///
23    /// The caller must ensure that:
24    ///  - the frame outlives the created reference, so that the reference can
25    ///    be seen as borrowed from that frame.
26    ///  - the type of the [`FrameRef`] (`M`) matches the borrowed frame.
27    pub(in crate::mm) unsafe fn borrow_paddr(raw: Paddr) -> Self {
28        Self {
29            // SAFETY: The caller ensures the safety.
30            inner: ManuallyDrop::new(unsafe { Frame::from_raw(raw) }),
31            _marker: PhantomData,
32        }
33    }
34}
35
36impl<M: AnyFrameMeta + ?Sized> Deref for FrameRef<'_, M> {
37    type Target = Frame<M>;
38
39    fn deref(&self) -> &Self::Target {
40        &self.inner
41    }
42}
43
44// SAFETY: `Frame` is essentially a `*const MetaSlot` that could be used as a non-null
45// `*const` pointer.
46unsafe impl<M: AnyFrameMeta + ?Sized> NonNullPtr for Frame<M> {
47    type Target = PhantomData<Self>;
48
49    type Ref<'a>
50        = FrameRef<'a, M>
51    where
52        Self: 'a;
53
54    const ALIGN_BITS: u32 = align_of::<MetaSlot>().trailing_zeros();
55
56    fn into_raw(self) -> NonNull<Self::Target> {
57        let ptr = NonNull::new(self.ptr.cast_mut()).unwrap();
58        let _ = ManuallyDrop::new(self);
59        ptr.cast()
60    }
61
62    unsafe fn from_raw(raw: NonNull<Self::Target>) -> Self {
63        Self {
64            ptr: raw.as_ptr().cast_const().cast(),
65            _marker: PhantomData,
66        }
67    }
68
69    unsafe fn raw_as_ref<'a>(raw: NonNull<Self::Target>) -> Self::Ref<'a> {
70        Self::Ref {
71            inner: ManuallyDrop::new(Frame {
72                ptr: raw.as_ptr().cast_const().cast(),
73                _marker: PhantomData,
74            }),
75            _marker: PhantomData,
76        }
77    }
78
79    fn ref_as_raw(ptr_ref: Self::Ref<'_>) -> core::ptr::NonNull<Self::Target> {
80        NonNull::new(ptr_ref.inner.ptr.cast_mut()).unwrap().cast()
81    }
82}