ostd/mm/frame/
untyped.rs

1// SPDX-License-Identifier: MPL-2.0
2
3//! Untyped physical memory management.
4//!
5//! As detailed in [`crate::mm::frame`], untyped memory can be accessed with
6//! relaxed rules but we cannot create references to them. This module provides
7//! the declaration of untyped frames and segments, and the implementation of
8//! extra functionalities (such as [`VmIo`]) for them.
9//!
10//! [`VmIo`]: crate::mm::VmIo
11
12use super::{Frame, Segment, meta::AnyFrameMeta};
13use crate::mm::{
14    HasPaddr, HasSize, Infallible,
15    io::{
16        VmReader, VmWriter,
17        util::{HasVmReaderWriter, VmReaderWriterIdentity},
18    },
19    paddr_to_vaddr,
20};
21
22/// The metadata of untyped frame.
23///
24/// If a structure `M` implements [`AnyUFrameMeta`], it can be used as the
25/// metadata of a type of untyped frames [`Frame<M>`]. All frames of such type
26/// will be accessible as untyped memory.
27pub trait AnyUFrameMeta: AnyFrameMeta {}
28
29/// A smart pointer to an untyped frame with any metadata.
30///
31/// The metadata of the frame is not known at compile time but the frame must
32/// be an untyped one. An [`UFrame`] as a parameter accepts any type of
33/// untyped frame metadata.
34///
35/// The usage of this frame will not be changed while this object is alive.
36pub type UFrame = Frame<dyn AnyUFrameMeta>;
37
38/// Makes a structure usable as untyped frame metadata.
39///
40/// If this macro is used for built-in typed frame metadata, it won't compile.
41#[macro_export]
42macro_rules! impl_untyped_frame_meta_for {
43    // Implement without specifying the drop behavior.
44    ($t:ty) => {
45        // SAFETY: Untyped frames can be safely read.
46        unsafe impl $crate::mm::frame::meta::AnyFrameMeta for $t {
47            fn is_untyped(&self) -> bool {
48                true
49            }
50        }
51        impl $crate::mm::frame::untyped::AnyUFrameMeta for $t {}
52
53        $crate::check_frame_meta_layout!($t);
54    };
55    // Implement with a customized drop function.
56    ($t:ty, $body:expr) => {
57        // SAFETY: Untyped frames can be safely read.
58        unsafe impl $crate::mm::frame::meta::AnyFrameMeta for $t {
59            fn on_drop(&mut self, reader: &mut $crate::mm::VmReader<$crate::mm::Infallible>) {
60                $body
61            }
62
63            fn is_untyped(&self) -> bool {
64                true
65            }
66        }
67        impl $crate::mm::frame::untyped::AnyUFrameMeta for $t {}
68
69        $crate::check_frame_meta_layout!($t);
70    };
71}
72
73// A special case of untyped metadata is the unit type.
74impl_untyped_frame_meta_for!(());
75
76macro_rules! impl_untyped_for {
77    ($t:ident) => {
78        impl<UM: AnyUFrameMeta + ?Sized> HasVmReaderWriter for $t<UM> {
79            type Types = VmReaderWriterIdentity;
80
81            fn reader(&self) -> VmReader<'_, Infallible> {
82                let ptr = paddr_to_vaddr(self.paddr()) as *const u8;
83                // SAFETY:
84                // - The memory range points to untyped memory.
85                // - The frame/segment is alive during the lifetime `'_`.
86                // - Using `VmReader` and `VmWriter` is the only way to access the frame/segment.
87                unsafe { VmReader::from_kernel_space(ptr, self.size()) }
88            }
89
90            fn writer(&self) -> VmWriter<'_, Infallible> {
91                let ptr = paddr_to_vaddr(self.paddr()) as *mut u8;
92                // SAFETY:
93                // - The memory range points to untyped memory.
94                // - The frame/segment is alive during the lifetime `'_`.
95                // - Using `VmReader` and `VmWriter` is the only way to access the frame/segment.
96                unsafe { VmWriter::from_kernel_space(ptr, self.size()) }
97            }
98        }
99    };
100}
101
102impl_untyped_for!(Frame);
103impl_untyped_for!(Segment);