ostd/mm/
io_util.rs

1// SPDX-License-Identifier: MPL-2.0
2
3//! Utilities for types in [`super::io`].
4
5use inherit_methods_macro::inherit_methods;
6use ostd_pod::Pod;
7
8use super::{Infallible, PodOnce, VmIo, VmIoFill, VmIoOnce, VmReader, VmWriter};
9use crate::{
10    Error,
11    mm::{FallibleVmRead, FallibleVmWrite},
12    prelude::*,
13};
14
15/// A helper trait that denotes types that can provide [`VmReader`]s and [`VmWriter`]s.
16///
17/// Having the reader and writer means that the type is capable of performing a range of VM
18/// operations. Thus, several traits will be automatically and efficiently implemented, such as
19/// [`VmIo`], [`VmIoFill`], and [`VmIoOnce`].
20pub trait HasVmReaderWriter {
21    /// A marker type that denotes the return types of [`Self::reader`] and [`Self::writer`].
22    ///
23    /// This can be either [`VmReaderWriterIdentity`] or [`VmReaderWriterResult`].
24    //
25    // TODO: This exists because `DmaStream` and related types track the DMA direction at runtime.
26    // The goal is to achieve this at compile time, which would eliminate the need for
27    // `VmReaderWriterTypes`. See the discussion at
28    // <https://github.com/asterinas/asterinas/pull/2289#discussion_r2261801694>.
29    type Types: VmReaderWriterTypes;
30
31    /// Returns a reader to read data from it.
32    fn reader(&self) -> <Self::Types as VmReaderWriterTypes>::Reader<'_>;
33    /// Returns a writer to write data to it.
34    fn writer(&self) -> <Self::Types as VmReaderWriterTypes>::Writer<'_>;
35}
36
37/// A marker trait that denotes the return types for [`HasVmReaderWriter`].
38pub trait VmReaderWriterTypes {
39    /// The return type of [`HasVmReaderWriter::reader`].
40    type Reader<'a>;
41    /// The return type of [`HasVmReaderWriter::writer`].
42    type Writer<'a>;
43
44    /// Converts [`Self::Reader`] to [`Result<VmReader<Infallible>>`].
45    fn to_reader_result(reader: Self::Reader<'_>) -> Result<VmReader<'_, Infallible>>;
46    /// Converts [`Self::Writer`] to [`Result<VmWriter<Infallible>>`].
47    fn to_writer_result(writer: Self::Writer<'_>) -> Result<VmWriter<'_, Infallible>>;
48}
49
50/// A marker type that denotes reader and writer identities as [`HasVmReaderWriter`] return types.
51pub enum VmReaderWriterIdentity {}
52impl VmReaderWriterTypes for VmReaderWriterIdentity {
53    type Reader<'a> = VmReader<'a, Infallible>;
54    type Writer<'a> = VmWriter<'a, Infallible>;
55    fn to_reader_result(reader: Self::Reader<'_>) -> Result<VmReader<'_, Infallible>> {
56        Ok(reader)
57    }
58    fn to_writer_result(writer: Self::Writer<'_>) -> Result<VmWriter<'_, Infallible>> {
59        Ok(writer)
60    }
61}
62
63/// A marker type that denotes reader and writer results as [`HasVmReaderWriter`] return types.
64pub enum VmReaderWriterResult {}
65impl VmReaderWriterTypes for VmReaderWriterResult {
66    type Reader<'a> = Result<VmReader<'a, Infallible>>;
67    type Writer<'a> = Result<VmWriter<'a, Infallible>>;
68    fn to_reader_result(reader: Self::Reader<'_>) -> Result<VmReader<'_, Infallible>> {
69        reader
70    }
71    fn to_writer_result(writer: Self::Writer<'_>) -> Result<VmWriter<'_, Infallible>> {
72        writer
73    }
74}
75
76impl<S: HasVmReaderWriter + Send + Sync> VmIo for S {
77    fn read(&self, offset: usize, writer: &mut VmWriter) -> Result<()> {
78        let mut reader = <Self as HasVmReaderWriter>::Types::to_reader_result(self.reader())?;
79
80        let limit = offset.checked_add(writer.avail()).ok_or(Error::Overflow)?;
81        if limit > reader.remain() {
82            return Err(Error::InvalidArgs);
83        }
84
85        reader.skip(offset);
86        let _len = reader
87            .to_fallible()
88            .read_fallible(writer)
89            .map_err(|(err, _)| err)?;
90        debug_assert!(!writer.has_avail());
91        Ok(())
92    }
93
94    fn read_bytes(&self, offset: usize, buf: &mut [u8]) -> Result<()> {
95        let mut reader = <Self as HasVmReaderWriter>::Types::to_reader_result(self.reader())?;
96
97        let limit = offset.checked_add(buf.len()).ok_or(Error::Overflow)?;
98        if limit > reader.remain() {
99            return Err(Error::InvalidArgs);
100        }
101
102        let len = reader.skip(offset).read(&mut VmWriter::from(&mut *buf));
103        debug_assert_eq!(len, buf.len());
104        Ok(())
105    }
106
107    // No need to implement `read_slice`. Its default implementation is efficient enough by relying
108    // on `read_bytes`.
109
110    fn read_val<T: Pod>(&self, offset: usize) -> Result<T> {
111        let mut reader = <Self as HasVmReaderWriter>::Types::to_reader_result(self.reader())?;
112
113        if offset > reader.remain() {
114            return Err(Error::InvalidArgs);
115        }
116
117        reader.skip(offset).read_val()
118    }
119
120    fn write(&self, offset: usize, reader: &mut VmReader) -> Result<()> {
121        let mut writer = <Self as HasVmReaderWriter>::Types::to_writer_result(self.writer())?;
122
123        let limit = offset.checked_add(reader.remain()).ok_or(Error::Overflow)?;
124        if limit > writer.avail() {
125            return Err(Error::InvalidArgs);
126        }
127
128        writer.skip(offset);
129        let _len = writer
130            .to_fallible()
131            .write_fallible(reader)
132            .map_err(|(err, _)| err)?;
133        debug_assert!(!reader.has_remain());
134        Ok(())
135    }
136
137    fn write_bytes(&self, offset: usize, buf: &[u8]) -> Result<()> {
138        let mut writer = <Self as HasVmReaderWriter>::Types::to_writer_result(self.writer())?;
139
140        let limit = offset.checked_add(buf.len()).ok_or(Error::Overflow)?;
141        if limit > writer.avail() {
142            return Err(Error::InvalidArgs);
143        }
144
145        let len = writer.skip(offset).write(&mut VmReader::from(buf));
146        debug_assert_eq!(len, buf.len());
147        Ok(())
148    }
149
150    // No need to implement `write_slice`. Its default implementation is efficient enough by
151    // relying on `write_bytes`.
152
153    fn write_val<T: Pod>(&self, offset: usize, new_val: &T) -> Result<()> {
154        let mut writer = <Self as HasVmReaderWriter>::Types::to_writer_result(self.writer())?;
155
156        if offset > writer.avail() {
157            return Err(Error::InvalidArgs);
158        }
159
160        writer.skip(offset).write_val(new_val)
161    }
162}
163
164impl<S: HasVmReaderWriter> VmIoFill for S {
165    fn fill_zeros(&self, offset: usize, len: usize) -> core::result::Result<(), (Error, usize)> {
166        let mut writer = <Self as HasVmReaderWriter>::Types::to_writer_result(self.writer())
167            .map_err(|err| (err, 0))?;
168
169        if offset > writer.avail() {
170            return Err((Error::InvalidArgs, 0));
171        }
172
173        let filled_len = writer.skip(offset).fill_zeros(len);
174        if filled_len == len {
175            Ok(())
176        } else {
177            Err((Error::InvalidArgs, filled_len))
178        }
179    }
180}
181
182impl<S: HasVmReaderWriter> VmIoOnce for S {
183    fn read_once<T: PodOnce>(&self, offset: usize) -> Result<T> {
184        let mut reader = <Self as HasVmReaderWriter>::Types::to_reader_result(self.reader())?;
185        reader.skip(offset).read_once()
186    }
187
188    fn write_once<T: PodOnce>(&self, offset: usize, new_val: &T) -> Result<()> {
189        let mut writer = <Self as HasVmReaderWriter>::Types::to_writer_result(self.writer())?;
190        writer.skip(offset).write_once(new_val)
191    }
192}
193
194// The pointer implementations below (i.e., `impl_vm_io_pointer`/`impl_vm_io_once_pointer`) should
195// apply to the `VmIo`/`VmIoOnce` traits themselves, instead of these helper traits.
196//
197// However, there are some unexpected compiler errors that complain that downstream crates can
198// implement `HasVmReaderWriter` to cause conflict implementations.
199
200macro_rules! impl_vm_io_pointer {
201    ($typ:ty,$from:tt) => {
202        #[inherit_methods(from = $from)]
203        impl<T: HasVmReaderWriter> HasVmReaderWriter for $typ {
204            type Types = T::Types;
205            fn reader(&self) -> <Self::Types as VmReaderWriterTypes>::Reader<'_>;
206            fn writer(&self) -> <Self::Types as VmReaderWriterTypes>::Writer<'_>;
207        }
208    };
209}
210
211impl_vm_io_pointer!(&T, "(**self)");
212impl_vm_io_pointer!(&mut T, "(**self)");
213impl_vm_io_pointer!(Box<T>, "(**self)");
214impl_vm_io_pointer!(Arc<T>, "(**self)");