ostd/mm/io/
util.rs

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