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