mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-22 00:43:24 +00:00
Add write_vals for VmIo
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
abb377b695
commit
345ab8f838
@ -1,5 +1,6 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use align_ext::AlignExt;
|
||||
use inherit_methods_macro::inherit_methods;
|
||||
use pod::Pod;
|
||||
|
||||
@ -65,6 +66,67 @@ pub trait VmIo: Send + Sync {
|
||||
let buf = unsafe { core::mem::transmute(slice) };
|
||||
self.write_bytes(offset, buf)
|
||||
}
|
||||
|
||||
/// Write a sequence of values given by an iterator (`iter`) from the specified offset (`offset`).
|
||||
///
|
||||
/// The write process stops until the VM object does not have enough remaining space
|
||||
/// or the iterator returns `None`. If any value is written, the function returns `Ok(nr_written)`,
|
||||
/// where `nr_written` is the number of the written values.
|
||||
///
|
||||
/// The offset of every value written by this method is aligned to the `align`-byte boundary.
|
||||
/// Naturally, when `align` equals to `0` or `1`, then the argument takes no effect:
|
||||
/// the values will be written in the most compact way.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// Initializing an VM object with the same value can be done easily with `write_values`.
|
||||
///
|
||||
/// ```
|
||||
/// use core::iter::self;
|
||||
///
|
||||
/// let _nr_values = vm_obj.write_values(0, iter::repeat(0_u32), 0).unwrap();
|
||||
/// ```
|
||||
///
|
||||
/// # Panic
|
||||
///
|
||||
/// This method panics if `align` is greater than two,
|
||||
/// but not a power of two, in release mode.
|
||||
fn write_vals<'a, T: Pod + 'a, I: Iterator<Item = &'a T>>(
|
||||
&self,
|
||||
offset: usize,
|
||||
iter: I,
|
||||
align: usize,
|
||||
) -> Result<usize> {
|
||||
let mut nr_written = 0;
|
||||
|
||||
let (mut offset, item_size) = if (align >> 1) == 0 {
|
||||
// align is 0 or 1
|
||||
(offset, core::mem::size_of::<T>())
|
||||
} else {
|
||||
// align is more than 2
|
||||
(
|
||||
offset.align_up(align),
|
||||
core::mem::size_of::<T>().align_up(align),
|
||||
)
|
||||
};
|
||||
|
||||
for item in iter {
|
||||
match self.write_val(offset, item) {
|
||||
Ok(_) => {
|
||||
offset += item_size;
|
||||
nr_written += 1;
|
||||
}
|
||||
Err(e) => {
|
||||
if nr_written > 0 {
|
||||
return Ok(nr_written);
|
||||
}
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(nr_written)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_vmio_pointer {
|
||||
|
@ -6,7 +6,7 @@ use alloc::{
|
||||
sync::Arc,
|
||||
vec::Vec,
|
||||
};
|
||||
use core::{fmt::Debug, mem};
|
||||
use core::{fmt::Debug, iter, mem};
|
||||
|
||||
use aster_frame::{
|
||||
io_mem::IoMem,
|
||||
@ -244,10 +244,9 @@ impl EventTable {
|
||||
let vm_segment = VmAllocOptions::new(1).alloc_contiguous().unwrap();
|
||||
|
||||
let default_event = VirtioInputEvent::default();
|
||||
for idx in 0..num_events {
|
||||
let offset = idx * EVENT_SIZE;
|
||||
vm_segment.write_val(offset, &default_event).unwrap();
|
||||
}
|
||||
let iter = iter::repeat(&default_event);
|
||||
let nr_written = vm_segment.write_vals(0, iter, 0).unwrap();
|
||||
assert_eq!(nr_written, EVENT_SIZE);
|
||||
|
||||
let stream = DmaStream::map(vm_segment, DmaDirection::FromDevice, false).unwrap();
|
||||
Self { stream, num_events }
|
||||
|
Reference in New Issue
Block a user