ostd/mm/frame/
frame_ref.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// SPDX-License-Identifier: MPL-2.0

use core::{marker::PhantomData, mem::ManuallyDrop, ops::Deref, ptr::NonNull};

use super::{
    meta::{AnyFrameMeta, MetaSlot},
    Frame,
};
use crate::{mm::Paddr, sync::non_null::NonNullPtr};

/// A struct that can work as `&'a Frame<M>`.
#[derive(Debug)]
pub struct FrameRef<'a, M: AnyFrameMeta + ?Sized> {
    inner: ManuallyDrop<Frame<M>>,
    _marker: PhantomData<&'a Frame<M>>,
}

impl<M: AnyFrameMeta + ?Sized> FrameRef<'_, M> {
    /// Borrows the [`Frame`] at the physical address as a [`FrameRef`].
    ///
    /// # Safety
    ///
    /// The caller must ensure that:
    /// 1. the frame outlives the created reference, so that the reference can
    ///    be seen as borrowed from that frame.
    /// 2. the type of the [`FrameRef`] (`M`) matches the borrowed frame.
    pub(in crate::mm) unsafe fn borrow_paddr(raw: Paddr) -> Self {
        Self {
            // SAFETY: The caller ensures the safety.
            inner: ManuallyDrop::new(unsafe { Frame::from_raw(raw) }),
            _marker: PhantomData,
        }
    }
}

impl<M: AnyFrameMeta + ?Sized> Deref for FrameRef<'_, M> {
    type Target = Frame<M>;

    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}

// SAFETY: `Frame` is essentially a `*const MetaSlot` that could be used as a non-null
// `*const` pointer.
unsafe impl<M: AnyFrameMeta + ?Sized> NonNullPtr for Frame<M> {
    type Target = PhantomData<Self>;

    type Ref<'a>
        = FrameRef<'a, M>
    where
        Self: 'a;

    const ALIGN_BITS: u32 = core::mem::align_of::<MetaSlot>().trailing_zeros();

    fn into_raw(self) -> NonNull<Self::Target> {
        let ptr = NonNull::new(self.ptr.cast_mut()).unwrap();
        let _ = ManuallyDrop::new(self);
        ptr.cast()
    }

    unsafe fn from_raw(raw: NonNull<Self::Target>) -> Self {
        Self {
            ptr: raw.as_ptr().cast_const().cast(),
            _marker: PhantomData,
        }
    }

    unsafe fn raw_as_ref<'a>(raw: NonNull<Self::Target>) -> Self::Ref<'a> {
        Self::Ref {
            inner: ManuallyDrop::new(Frame {
                ptr: raw.as_ptr().cast_const().cast(),
                _marker: PhantomData,
            }),
            _marker: PhantomData,
        }
    }

    fn ref_as_raw(ptr_ref: Self::Ref<'_>) -> core::ptr::NonNull<Self::Target> {
        NonNull::new(ptr_ref.inner.ptr.cast_mut()).unwrap().cast()
    }
}