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
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
use align_ext::AlignExt;
|
||||||
use inherit_methods_macro::inherit_methods;
|
use inherit_methods_macro::inherit_methods;
|
||||||
use pod::Pod;
|
use pod::Pod;
|
||||||
|
|
||||||
@ -65,6 +66,67 @@ pub trait VmIo: Send + Sync {
|
|||||||
let buf = unsafe { core::mem::transmute(slice) };
|
let buf = unsafe { core::mem::transmute(slice) };
|
||||||
self.write_bytes(offset, buf)
|
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 {
|
macro_rules! impl_vmio_pointer {
|
||||||
|
@ -6,7 +6,7 @@ use alloc::{
|
|||||||
sync::Arc,
|
sync::Arc,
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
use core::{fmt::Debug, mem};
|
use core::{fmt::Debug, iter, mem};
|
||||||
|
|
||||||
use aster_frame::{
|
use aster_frame::{
|
||||||
io_mem::IoMem,
|
io_mem::IoMem,
|
||||||
@ -244,10 +244,9 @@ impl EventTable {
|
|||||||
let vm_segment = VmAllocOptions::new(1).alloc_contiguous().unwrap();
|
let vm_segment = VmAllocOptions::new(1).alloc_contiguous().unwrap();
|
||||||
|
|
||||||
let default_event = VirtioInputEvent::default();
|
let default_event = VirtioInputEvent::default();
|
||||||
for idx in 0..num_events {
|
let iter = iter::repeat(&default_event);
|
||||||
let offset = idx * EVENT_SIZE;
|
let nr_written = vm_segment.write_vals(0, iter, 0).unwrap();
|
||||||
vm_segment.write_val(offset, &default_event).unwrap();
|
assert_eq!(nr_written, EVENT_SIZE);
|
||||||
}
|
|
||||||
|
|
||||||
let stream = DmaStream::map(vm_segment, DmaDirection::FromDevice, false).unwrap();
|
let stream = DmaStream::map(vm_segment, DmaDirection::FromDevice, false).unwrap();
|
||||||
Self { stream, num_events }
|
Self { stream, num_events }
|
||||||
|
Reference in New Issue
Block a user