Implement VmIoOnce for IoMem

This commit is contained in:
Ruihan Li
2024-08-24 10:36:38 +08:00
committed by Tate, Hongliang Tian
parent aa62f0a4e6
commit c8ba695c85
14 changed files with 190 additions and 149 deletions

View File

@ -81,10 +81,9 @@ impl aster_block::BlockDevice for BlockDevice {
}
fn metadata(&self) -> BlockDeviceMeta {
let device_config = self.device.config.read().unwrap();
BlockDeviceMeta {
max_nr_segments_per_bio: self.queue.max_nr_segments_per_bio(),
nr_sectors: device_config.capacity_sectors(),
nr_sectors: VirtioBlockConfig::read_capacity_sectors(&self.device.config).unwrap(),
}
}
}
@ -107,7 +106,7 @@ impl DeviceInner {
pub fn init(mut transport: Box<dyn VirtioTransport>) -> Result<Arc<Self>, VirtioDeviceError> {
let config = VirtioBlockConfig::new(transport.as_mut());
assert_eq!(
config.read().unwrap().block_size(),
VirtioBlockConfig::read_block_size(&config).unwrap(),
VirtioBlockConfig::sector_size(),
"currently not support customized device logical block size"
);

View File

@ -3,7 +3,7 @@
pub mod device;
use aster_block::SECTOR_SIZE;
use aster_util::safe_ptr::SafePtr;
use aster_util::{field_ptr, safe_ptr::SafePtr};
use bitflags::bitflags;
use int_to_c_enum::TryFromInt;
use ostd::{io_mem::IoMem, Pod};
@ -119,15 +119,17 @@ impl VirtioBlockConfig {
SECTOR_SIZE
}
pub(self) fn block_size(&self) -> usize {
self.blk_size as usize
pub(self) fn read_block_size(this: &SafePtr<Self, IoMem>) -> ostd::prelude::Result<usize> {
field_ptr!(this, Self, blk_size)
.read_once()
.map(|val| val as usize)
}
pub(self) fn capacity_sectors(&self) -> usize {
self.capacity as usize
}
pub(self) fn capacity_bytes(&self) -> usize {
self.capacity_sectors() * Self::sector_size()
pub(self) fn read_capacity_sectors(
this: &SafePtr<Self, IoMem>,
) -> ostd::prelude::Result<usize> {
field_ptr!(this, Self, capacity)
.read_once()
.map(|val| val as usize)
}
}

View File

@ -171,15 +171,17 @@ impl InputDevice {
/// result to `out`, return the result size.
pub fn query_config_select(&self, select: InputConfigSelect, subsel: u8, out: &mut [u8]) -> u8 {
field_ptr!(&self.config, VirtioInputConfig, select)
.write(&(select as u8))
.write_once(&(select as u8))
.unwrap();
field_ptr!(&self.config, VirtioInputConfig, subsel)
.write(&subsel)
.write_once(&subsel)
.unwrap();
let size = field_ptr!(&self.config, VirtioInputConfig, size)
.read()
.read_once()
.unwrap();
let data: [u8; 128] = field_ptr!(&self.config, VirtioInputConfig, data)
// FIXME: It is impossible to call `read_once` on `[u8; 128]`. What's the proper way to
// read this field out?
.read()
.unwrap();
out[..size as usize].copy_from_slice(&data[..size as usize]);

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: MPL-2.0
use aster_network::EthernetAddr;
use aster_util::safe_ptr::SafePtr;
use aster_util::{field_ptr, safe_ptr::SafePtr};
use bitflags::bitflags;
use ostd::{io_mem::IoMem, Pod};
@ -76,4 +76,25 @@ impl VirtioNetConfig {
let memory = transport.device_config_memory();
SafePtr::new(memory, 0)
}
pub(super) fn read(this: &SafePtr<Self, IoMem>) -> ostd::prelude::Result<Self> {
Ok(Self {
// FIXME: It is impossible to call `read_once` on `EthernetAddr`. What's the proper way
// to read this field out?
mac: field_ptr!(this, Self, mac).read()?,
status: field_ptr!(this, Self, status).read_once()?,
max_virtqueue_pairs: field_ptr!(this, Self, max_virtqueue_pairs).read_once()?,
mtu: field_ptr!(this, Self, mtu).read_once()?,
speed: field_ptr!(this, Self, speed).read_once()?,
duplex: field_ptr!(this, Self, duplex).read_once()?,
rss_max_key_size: field_ptr!(this, Self, rss_max_key_size).read_once()?,
rss_max_indirection_table_length: field_ptr!(
this,
Self,
rss_max_indirection_table_length
)
.read_once()?,
supported_hash_types: field_ptr!(this, Self, supported_hash_types).read_once()?,
})
}
}

View File

@ -7,9 +7,9 @@ use aster_network::{
AnyNetworkDevice, EthernetAddr, RxBuffer, TxBuffer, VirtioNetError, RX_BUFFER_POOL,
TX_BUFFER_POOL,
};
use aster_util::{field_ptr, slot_vec::SlotVec};
use aster_util::slot_vec::SlotVec;
use log::debug;
use ostd::{offset_of, sync::SpinLock, trap::TrapFrame};
use ostd::{sync::SpinLock, trap::TrapFrame};
use smoltcp::phy::{DeviceCapabilities, Medium};
use super::{config::VirtioNetConfig, header::VirtioNetHdr};
@ -44,13 +44,11 @@ impl NetworkDevice {
));
debug!("virtio_net_config = {:?}", virtio_net_config);
debug!("features = {:?}", features);
let mac_addr = field_ptr!(&virtio_net_config, VirtioNetConfig, mac)
.read()
.unwrap();
let status = field_ptr!(&virtio_net_config, VirtioNetConfig, status)
.read()
.unwrap();
debug!("mac addr = {:x?}, status = {:?}", mac_addr, status);
let config = VirtioNetConfig::read(&virtio_net_config).unwrap();
let mac_addr = config.mac;
debug!("mac addr = {:x?}, status = {:?}", mac_addr, config.status);
let mut recv_queue = VirtQueue::new(QUEUE_RECV, QUEUE_SIZE, transport.as_mut())
.expect("creating recv queue fails");
let send_queue = VirtQueue::new(QUEUE_SEND, QUEUE_SIZE, transport.as_mut())
@ -71,7 +69,7 @@ impl NetworkDevice {
recv_queue.notify();
}
let mut device = Self {
config: virtio_net_config.read().unwrap(),
config,
mac_addr,
send_queue,
recv_queue,

View File

@ -53,10 +53,10 @@ impl SocketDevice {
let virtio_vsock_config = VirtioVsockConfig::new(transport.as_mut());
debug!("virtio_vsock_config = {:?}", virtio_vsock_config);
let guest_cid = field_ptr!(&virtio_vsock_config, VirtioVsockConfig, guest_cid_low)
.read()
.read_once()
.unwrap() as u64
| (field_ptr!(&virtio_vsock_config, VirtioVsockConfig, guest_cid_high)
.read()
.read_once()
.unwrap() as u64)
<< 32;
@ -83,7 +83,7 @@ impl SocketDevice {
}
let mut device = Self {
config: virtio_vsock_config.read().unwrap(),
config: virtio_vsock_config.read_once().unwrap(),
guest_cid,
send_queue,
recv_queue,

View File

@ -342,7 +342,7 @@ impl VirtQueue {
/// notify that there are available rings
pub fn notify(&mut self) {
self.notify.write(&self.queue_idx).unwrap();
self.notify.write_once(&self.queue_idx).unwrap();
}
}

View File

@ -79,7 +79,7 @@ impl VirtioMmioTransport {
};
if device.common_device.version() == VirtioMmioVersion::Legacy {
field_ptr!(&device.layout, VirtioMmioLayout, legacy_guest_page_size)
.write(&(PAGE_SIZE as u32))
.write_once(&(PAGE_SIZE as u32))
.unwrap();
}
device
@ -100,11 +100,11 @@ impl VirtioTransport for VirtioMmioTransport {
device_ptr: &SafePtr<UsedRing, DmaCoherent>,
) -> Result<(), VirtioTransportError> {
field_ptr!(&self.layout, VirtioMmioLayout, queue_sel)
.write(&(idx as u32))
.write_once(&(idx as u32))
.unwrap();
let queue_num_max: u32 = field_ptr!(&self.layout, VirtioMmioLayout, queue_num_max)
.read()
.read_once()
.unwrap();
if queue_size as u32 > queue_num_max {
@ -117,7 +117,7 @@ impl VirtioTransport for VirtioMmioTransport {
let device_paddr = device_ptr.paddr();
field_ptr!(&self.layout, VirtioMmioLayout, queue_num)
.write(&(queue_size as u32))
.write_once(&(queue_size as u32))
.unwrap();
match self.common_device.version() {
@ -131,39 +131,39 @@ impl VirtioTransport for VirtioMmioTransport {
assert_eq!(descriptor_paddr % PAGE_SIZE, 0);
let pfn = (descriptor_paddr / PAGE_SIZE) as u32;
field_ptr!(&self.layout, VirtioMmioLayout, legacy_queue_align)
.write(&(PAGE_SIZE as u32))
.write_once(&(PAGE_SIZE as u32))
.unwrap();
field_ptr!(&self.layout, VirtioMmioLayout, legacy_queue_pfn)
.write(&pfn)
.write_once(&pfn)
.unwrap();
}
VirtioMmioVersion::Modern => {
field_ptr!(&self.layout, VirtioMmioLayout, queue_desc_low)
.write(&(descriptor_paddr as u32))
.write_once(&(descriptor_paddr as u32))
.unwrap();
field_ptr!(&self.layout, VirtioMmioLayout, queue_desc_high)
.write(&((descriptor_paddr >> 32) as u32))
.write_once(&((descriptor_paddr >> 32) as u32))
.unwrap();
field_ptr!(&self.layout, VirtioMmioLayout, queue_driver_low)
.write(&(driver_paddr as u32))
.write_once(&(driver_paddr as u32))
.unwrap();
field_ptr!(&self.layout, VirtioMmioLayout, queue_driver_high)
.write(&((driver_paddr >> 32) as u32))
.write_once(&((driver_paddr >> 32) as u32))
.unwrap();
field_ptr!(&self.layout, VirtioMmioLayout, queue_device_low)
.write(&(device_paddr as u32))
.write_once(&(device_paddr as u32))
.unwrap();
field_ptr!(&self.layout, VirtioMmioLayout, queue_device_high)
.write(&((device_paddr >> 32) as u32))
.write_once(&((device_paddr >> 32) as u32))
.unwrap();
// enable queue
field_ptr!(&self.layout, VirtioMmioLayout, queue_sel)
.write(&(idx as u32))
.write_once(&(idx as u32))
.unwrap();
field_ptr!(&self.layout, VirtioMmioLayout, queue_ready)
.write(&1u32)
.write_once(&1u32)
.unwrap();
}
};
@ -182,10 +182,10 @@ impl VirtioTransport for VirtioMmioTransport {
const MAX_QUEUES: u32 = 512;
while num_queues < MAX_QUEUES {
field_ptr!(&self.layout, VirtioMmioLayout, queue_sel)
.write(&num_queues)
.write_once(&num_queues)
.unwrap();
if field_ptr!(&self.layout, VirtioMmioLayout, queue_num_max)
.read()
.read_once()
.unwrap()
== 0u32
{
@ -207,17 +207,17 @@ impl VirtioTransport for VirtioMmioTransport {
fn device_features(&self) -> u64 {
// select low
field_ptr!(&self.layout, VirtioMmioLayout, device_features_select)
.write(&0u32)
.write_once(&0u32)
.unwrap();
let device_feature_low = field_ptr!(&self.layout, VirtioMmioLayout, device_features)
.read()
.read_once()
.unwrap();
// select high
field_ptr!(&self.layout, VirtioMmioLayout, device_features_select)
.write(&1u32)
.write_once(&1u32)
.unwrap();
let device_feature_high = field_ptr!(&self.layout, VirtioMmioLayout, device_features)
.read()
.read_once()
.unwrap() as u64;
device_feature_high << 32 | device_feature_low as u64
}
@ -226,16 +226,16 @@ impl VirtioTransport for VirtioMmioTransport {
let low = features as u32;
let high = (features >> 32) as u32;
field_ptr!(&self.layout, VirtioMmioLayout, driver_features_select)
.write(&0u32)
.write_once(&0u32)
.unwrap();
field_ptr!(&self.layout, VirtioMmioLayout, driver_features)
.write(&low)
.write_once(&low)
.unwrap();
field_ptr!(&self.layout, VirtioMmioLayout, driver_features_select)
.write(&1u32)
.write_once(&1u32)
.unwrap();
field_ptr!(&self.layout, VirtioMmioLayout, driver_features)
.write(&high)
.write_once(&high)
.unwrap();
Ok(())
}
@ -243,7 +243,7 @@ impl VirtioTransport for VirtioMmioTransport {
fn device_status(&self) -> DeviceStatus {
DeviceStatus::from_bits(
field_ptr!(&self.layout, VirtioMmioLayout, status)
.read()
.read_once()
.unwrap() as u8,
)
.unwrap()
@ -251,7 +251,7 @@ impl VirtioTransport for VirtioMmioTransport {
fn set_device_status(&mut self, status: DeviceStatus) -> Result<(), VirtioTransportError> {
field_ptr!(&self.layout, VirtioMmioLayout, status)
.write(&(status.bits() as u32))
.write_once(&(status.bits() as u32))
.unwrap();
Ok(())
}
@ -262,10 +262,10 @@ impl VirtioTransport for VirtioMmioTransport {
fn max_queue_size(&self, idx: u16) -> Result<u16, VirtioTransportError> {
field_ptr!(&self.layout, VirtioMmioLayout, queue_sel)
.write(&(idx as u32))
.write_once(&(idx as u32))
.unwrap();
Ok(field_ptr!(&self.layout, VirtioMmioLayout, queue_num_max)
.read()
.read_once()
.unwrap() as u16)
}

View File

@ -44,7 +44,7 @@ impl MultiplexIrq {
return;
};
let irq = multiplex_irq.read();
let interrupt_status = irq.interrupt_status.read().unwrap();
let interrupt_status = irq.interrupt_status.read_once().unwrap();
let callbacks = if interrupt_status & 0x01 == 1 {
// Used buffer notification
&irq.queue_callbacks
@ -55,7 +55,7 @@ impl MultiplexIrq {
for callback in callbacks.iter() {
callback.call((trap_frame,));
}
irq.interrupt_ack.write(&interrupt_status).unwrap();
irq.interrupt_ack.write_once(&interrupt_status).unwrap();
};
lock.irq.on_active(callback);
drop(lock);

View File

@ -80,30 +80,30 @@ impl VirtioTransport for VirtioPciTransport {
return Err(VirtioTransportError::InvalidArgs);
}
field_ptr!(&self.common_cfg, VirtioPciCommonCfg, queue_select)
.write(&idx)
.write_once(&idx)
.unwrap();
debug_assert_eq!(
field_ptr!(&self.common_cfg, VirtioPciCommonCfg, queue_select)
.read()
.read_once()
.unwrap(),
idx
);
field_ptr!(&self.common_cfg, VirtioPciCommonCfg, queue_size)
.write(&queue_size)
.write_once(&queue_size)
.unwrap();
field_ptr!(&self.common_cfg, VirtioPciCommonCfg, queue_desc)
.write(&(descriptor_ptr.paddr() as u64))
.write_once(&(descriptor_ptr.paddr() as u64))
.unwrap();
field_ptr!(&self.common_cfg, VirtioPciCommonCfg, queue_driver)
.write(&(avail_ring_ptr.paddr() as u64))
.write_once(&(avail_ring_ptr.paddr() as u64))
.unwrap();
field_ptr!(&self.common_cfg, VirtioPciCommonCfg, queue_device)
.write(&(used_ring_ptr.paddr() as u64))
.write_once(&(used_ring_ptr.paddr() as u64))
.unwrap();
// Enable queue
field_ptr!(&self.common_cfg, VirtioPciCommonCfg, queue_enable)
.write(&1u16)
.write_once(&1u16)
.unwrap();
Ok(())
}
@ -120,7 +120,7 @@ impl VirtioTransport for VirtioPciTransport {
fn num_queues(&self) -> u16 {
field_ptr!(&self.common_cfg, VirtioPciCommonCfg, num_queues)
.read()
.read_once()
.unwrap()
}
@ -142,17 +142,17 @@ impl VirtioTransport for VirtioPciTransport {
fn device_features(&self) -> u64 {
// select low
field_ptr!(&self.common_cfg, VirtioPciCommonCfg, device_feature_select)
.write(&0u32)
.write_once(&0u32)
.unwrap();
let device_feature_low = field_ptr!(&self.common_cfg, VirtioPciCommonCfg, device_features)
.read()
.read_once()
.unwrap();
// select high
field_ptr!(&self.common_cfg, VirtioPciCommonCfg, device_feature_select)
.write(&1u32)
.write_once(&1u32)
.unwrap();
let device_feature_high = field_ptr!(&self.common_cfg, VirtioPciCommonCfg, device_features)
.read()
.read_once()
.unwrap() as u64;
device_feature_high << 32 | device_feature_low as u64
}
@ -161,47 +161,47 @@ impl VirtioTransport for VirtioPciTransport {
let low = features as u32;
let high = (features >> 32) as u32;
field_ptr!(&self.common_cfg, VirtioPciCommonCfg, driver_feature_select)
.write(&0u32)
.write_once(&0u32)
.unwrap();
field_ptr!(&self.common_cfg, VirtioPciCommonCfg, driver_features)
.write(&low)
.write_once(&low)
.unwrap();
field_ptr!(&self.common_cfg, VirtioPciCommonCfg, driver_feature_select)
.write(&1u32)
.write_once(&1u32)
.unwrap();
field_ptr!(&self.common_cfg, VirtioPciCommonCfg, driver_features)
.write(&high)
.write_once(&high)
.unwrap();
Ok(())
}
fn device_status(&self) -> DeviceStatus {
let status = field_ptr!(&self.common_cfg, VirtioPciCommonCfg, device_status)
.read()
.read_once()
.unwrap();
DeviceStatus::from_bits(status).unwrap()
}
fn set_device_status(&mut self, status: DeviceStatus) -> Result<(), VirtioTransportError> {
field_ptr!(&self.common_cfg, VirtioPciCommonCfg, device_status)
.write(&(status.bits()))
.write_once(&(status.bits()))
.unwrap();
Ok(())
}
fn max_queue_size(&self, idx: u16) -> Result<u16, crate::transport::VirtioTransportError> {
field_ptr!(&self.common_cfg, VirtioPciCommonCfg, queue_select)
.write(&idx)
.write_once(&idx)
.unwrap();
debug_assert_eq!(
field_ptr!(&self.common_cfg, VirtioPciCommonCfg, queue_select)
.read()
.read_once()
.unwrap(),
idx
);
Ok(field_ptr!(&self.common_cfg, VirtioPciCommonCfg, queue_size)
.read()
.read_once()
.unwrap())
}
@ -223,16 +223,16 @@ impl VirtioTransport for VirtioPciTransport {
};
irq.on_active(func);
field_ptr!(&self.common_cfg, VirtioPciCommonCfg, queue_select)
.write(&index)
.write_once(&index)
.unwrap();
debug_assert_eq!(
field_ptr!(&self.common_cfg, VirtioPciCommonCfg, queue_select)
.read()
.read_once()
.unwrap(),
index
);
field_ptr!(&self.common_cfg, VirtioPciCommonCfg, queue_msix_vector)
.write(&vector)
.write_once(&vector)
.unwrap();
Ok(())
}