diff --git a/src/device/blk.rs b/src/device/blk.rs index 6fc9d252..d8e8d029 100644 --- a/src/device/blk.rs +++ b/src/device/blk.rs @@ -2,11 +2,10 @@ use crate::hal::Hal; use crate::queue::VirtQueue; -use crate::transport::Transport; +use crate::transport::{read_config, Transport}; use crate::volatile::Volatile; use crate::{Error, Result}; use bitflags::bitflags; -use core::mem::offset_of; use log::info; use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout}; @@ -57,12 +56,8 @@ impl VirtIOBlk { // Read configuration space. let capacity = transport.read_consistent(|| { - Ok( - transport.read_config_space::(offset_of!(BlkConfig, capacity_low))? as u64 - | (transport.read_config_space::(offset_of!(BlkConfig, capacity_high))? - as u64) - << 32, - ) + Ok(read_config!(transport, BlkConfig, capacity_low)? as u64 + | (read_config!(transport, BlkConfig, capacity_high)? as u64) << 32) })?; info!("found a block device of size {}KB", capacity / 2); diff --git a/src/device/console.rs b/src/device/console.rs index a8d6095a..8aaa520d 100644 --- a/src/device/console.rs +++ b/src/device/console.rs @@ -5,13 +5,12 @@ mod embedded_io; use crate::hal::Hal; use crate::queue::VirtQueue; -use crate::transport::Transport; +use crate::transport::{read_config, write_config, Transport}; use crate::volatile::{ReadOnly, WriteOnly}; use crate::{Error, Result, PAGE_SIZE}; use alloc::boxed::Box; use bitflags::bitflags; use core::fmt::{self, Display, Formatter, Write}; -use core::mem::offset_of; use log::error; const QUEUE_RECEIVEQ_PORT_0: u16 = 0; @@ -129,8 +128,8 @@ impl VirtIOConsole { if self.negotiated_features.contains(Features::SIZE) { self.transport.read_consistent(|| { Ok(Some(Size { - columns: self.transport.read_config_space(offset_of!(Config, cols))?, - rows: self.transport.read_config_space(offset_of!(Config, rows))?, + columns: read_config!(self.transport, Config, cols)?, + rows: read_config!(self.transport, Config, rows)?, })) }) } else { @@ -240,8 +239,7 @@ impl VirtIOConsole { /// Returns an error if the device doesn't support emergency write. pub fn emergency_write(&mut self, chr: u8) -> Result<()> { if self.negotiated_features.contains(Features::EMERG_WRITE) { - self.transport - .write_config_space::(offset_of!(Config, emerg_wr), chr.into())?; + write_config!(self.transport, Config, emerg_wr, chr.into())?; Ok(()) } else { Err(Error::Unsupported) diff --git a/src/device/gpu.rs b/src/device/gpu.rs index d299a990..4dc8344a 100644 --- a/src/device/gpu.rs +++ b/src/device/gpu.rs @@ -2,12 +2,11 @@ use crate::hal::{BufferDirection, Dma, Hal}; use crate::queue::VirtQueue; -use crate::transport::Transport; +use crate::transport::{read_config, Transport}; use crate::volatile::{ReadOnly, Volatile, WriteOnly}; use crate::{pages, Error, Result, PAGE_SIZE}; use alloc::boxed::Box; use bitflags::bitflags; -use core::mem::offset_of; use log::info; use zerocopy::{FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout}; @@ -44,8 +43,8 @@ impl VirtIOGpu { let negotiated_features = transport.begin_init(SUPPORTED_FEATURES); // read configuration space - let events_read = transport.read_config_space::(offset_of!(Config, events_read))?; - let num_scanouts = transport.read_config_space::(offset_of!(Config, num_scanouts))?; + let events_read = read_config!(transport, Config, events_read)?; + let num_scanouts = read_config!(transport, Config, num_scanouts)?; info!( "events_read: {:#x}, num_scanouts: {:#x}", events_read, num_scanouts diff --git a/src/device/input.rs b/src/device/input.rs index 6259e391..fedb220c 100644 --- a/src/device/input.rs +++ b/src/device/input.rs @@ -3,7 +3,7 @@ use super::common::Feature; use crate::hal::Hal; use crate::queue::VirtQueue; -use crate::transport::Transport; +use crate::transport::{read_config, write_config, Transport}; use crate::volatile::{ReadOnly, WriteOnly}; use crate::Error; use alloc::{boxed::Box, string::String}; @@ -103,11 +103,9 @@ impl VirtIOInput { subsel: u8, out: &mut [u8], ) -> Result { - self.transport - .write_config_space(offset_of!(Config, select), select as u8)?; - self.transport - .write_config_space(offset_of!(Config, subsel), subsel)?; - let size: u8 = self.transport.read_config_space(offset_of!(Config, size))?; + write_config!(self.transport, Config, select, select as u8)?; + write_config!(self.transport, Config, subsel, subsel)?; + let size: u8 = read_config!(self.transport, Config, size)?; // Safe because config points to a valid MMIO region for the config space. let size_to_copy = min(usize::from(size), out.len()); for (i, out_item) in out.iter_mut().take(size_to_copy).enumerate() { @@ -126,14 +124,9 @@ impl VirtIOInput { select: InputConfigSelect, subsel: u8, ) -> Result, Error> { - self.transport - .write_config_space(offset_of!(Config, select), select as u8)?; - self.transport - .write_config_space(offset_of!(Config, subsel), subsel)?; - let size = usize::from( - self.transport - .read_config_space::(offset_of!(Config, size))?, - ); + write_config!(self.transport, Config, select, select as u8)?; + write_config!(self.transport, Config, subsel, subsel)?; + let size = usize::from(read_config!(self.transport, Config, size)?); if size > CONFIG_DATA_MAX_LENGTH { return Err(Error::IoError); } diff --git a/src/device/net/dev_raw.rs b/src/device/net/dev_raw.rs index 58d30d8d..f74eeba7 100644 --- a/src/device/net/dev_raw.rs +++ b/src/device/net/dev_raw.rs @@ -1,11 +1,9 @@ use super::{Config, EthernetAddress, Features, VirtioNetHdr}; use super::{MIN_BUFFER_LEN, NET_HDR_SIZE, QUEUE_RECEIVE, QUEUE_TRANSMIT, SUPPORTED_FEATURES}; -use crate::device::net::Status; use crate::hal::Hal; use crate::queue::VirtQueue; -use crate::transport::Transport; +use crate::transport::{read_config, Transport}; use crate::{Error, Result}; -use core::mem::offset_of; use log::{debug, info, warn}; use zerocopy::IntoBytes; @@ -31,9 +29,8 @@ impl VirtIONetRaw(offset_of!(Config, status))?; + let mac = transport.read_consistent(|| read_config!(transport, Config, mac))?; + let status = read_config!(transport, Config, status)?; debug!("Got MAC={:02x?}, status={:?}", mac, status); let send_queue = VirtQueue::new( diff --git a/src/device/socket/vsock.rs b/src/device/socket/vsock.rs index 5270e82e..bc99add7 100644 --- a/src/device/socket/vsock.rs +++ b/src/device/socket/vsock.rs @@ -8,9 +8,9 @@ use super::protocol::{ use super::DEFAULT_RX_BUFFER_SIZE; use crate::hal::Hal; use crate::queue::{owning::OwningQueue, VirtQueue}; -use crate::transport::Transport; +use crate::transport::{read_config, Transport}; use crate::Result; -use core::mem::{offset_of, size_of}; +use core::mem::size_of; use log::debug; use zerocopy::{FromBytes, IntoBytes}; @@ -249,12 +249,8 @@ impl VirtIOSocket(offset_of!(VirtioVsockConfig, guest_cid_low))? - as u64 - | (transport - .read_config_space::(offset_of!(VirtioVsockConfig, guest_cid_high))? - as u64) - << 32, + read_config!(transport, VirtioVsockConfig, guest_cid_low)? as u64 + | (read_config!(transport, VirtioVsockConfig, guest_cid_high)? as u64) << 32, ) })?; debug!("guest cid: {guest_cid:?}"); diff --git a/src/device/sound.rs b/src/device/sound.rs index 1bd73e8c..07218044 100644 --- a/src/device/sound.rs +++ b/src/device/sound.rs @@ -6,7 +6,7 @@ mod fake; use super::common::Feature; use crate::{ queue::{owning::OwningQueue, VirtQueue}, - transport::Transport, + transport::{read_config, Transport}, volatile::ReadOnly, Error, Hal, Result, PAGE_SIZE, }; @@ -16,7 +16,7 @@ use core::{ array, fmt::{self, Debug, Display, Formatter}, hint::spin_loop, - mem::{offset_of, size_of}, + mem::size_of, ops::RangeInclusive, }; use enumn::N; @@ -96,9 +96,9 @@ impl VirtIOSound { )?; // read configuration space - let jacks = transport.read_config_space(offset_of!(VirtIOSoundConfig, jacks))?; - let streams = transport.read_config_space(offset_of!(VirtIOSoundConfig, streams))?; - let chmaps = transport.read_config_space(offset_of!(VirtIOSoundConfig, chmaps))?; + let jacks = read_config!(transport, VirtIOSoundConfig, jacks)?; + let streams = read_config!(transport, VirtIOSoundConfig, streams)?; + let chmaps = read_config!(transport, VirtIOSoundConfig, chmaps)?; info!( "[sound device] config: jacks: {}, streams: {}, chmaps: {}", jacks, streams, chmaps diff --git a/src/transport/mod.rs b/src/transport/mod.rs index b9fb7dfa..2f66a916 100644 --- a/src/transport/mod.rs +++ b/src/transport/mod.rs @@ -231,3 +231,46 @@ impl From for DeviceType { u32::from(virtio_device_id).into() } } + +#[inline(always)] +pub(crate) fn read_help( + transport: &T, + offset: usize, + _dummy_v: Option, +) -> Result { + transport.read_config_space(offset) +} + +#[inline(always)] +pub(crate) fn write_help( + transport: &mut T, + offset: usize, + value: V, + _dummy_v: Option, +) -> Result<()> { + transport.write_config_space(offset, value) +} + +macro_rules! read_config { + ($transport:expr, $struct:ty, $field:ident) => {{ + let dummy_struct: Option<$struct> = None; + let dummy_v = dummy_struct.map(|s| s.$field.0); + crate::transport::read_help(&$transport, core::mem::offset_of!($struct, $field), dummy_v) + }}; +} + +macro_rules! write_config { + ($transport:expr, $struct:ty, $field:ident, $value:expr) => {{ + let dummy_struct: Option<$struct> = None; + let dummy_v = dummy_struct.map(|s| s.$field.0); + crate::transport::write_help( + &mut $transport, + core::mem::offset_of!($struct, $field), + $value, + dummy_v, + ) + }}; +} + +pub(crate) use read_config; +pub(crate) use write_config; diff --git a/src/volatile.rs b/src/volatile.rs index 74f527b3..0acbad24 100644 --- a/src/volatile.rs +++ b/src/volatile.rs @@ -18,7 +18,7 @@ pub struct WriteOnly(pub(crate) T); /// An MMIO register which may be both read and written. #[derive(Default)] #[repr(transparent)] -pub struct Volatile(T); +pub struct Volatile(pub(crate) T); impl Volatile { /// Construct a new instance for testing.