ostd/mm/frame/
frame_ref.rs

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