From f03c5ae08afdf9e39bff6df48899b806d2e4004c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Wed, 24 Apr 2024 16:50:30 +0200 Subject: [PATCH] refactor(virtio/pci): migrate `CommonCfg` to `virtio-def` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/drivers/virtio/transport/pci.rs | 132 ++++++++++++++++------------ 1 file changed, 74 insertions(+), 58 deletions(-) diff --git a/src/drivers/virtio/transport/pci.rs b/src/drivers/virtio/transport/pci.rs index 237d7c5be1..24717872b2 100644 --- a/src/drivers/virtio/transport/pci.rs +++ b/src/drivers/virtio/transport/pci.rs @@ -8,8 +8,9 @@ use core::ptr::NonNull; use core::sync::atomic::{fence, Ordering}; use core::{mem, ptr}; +use virtio_def::pci::{CommonCfg, CommonCfgVolatileFieldAccess}; use virtio_def::DeviceStatus; -use volatile::{map_field, VolatileRef}; +use volatile::VolatileRef; #[cfg(all(not(feature = "rtl8139"), any(feature = "tcp", feature = "udp")))] use crate::arch::kernel::interrupts::*; @@ -221,7 +222,7 @@ impl PciCap { } /// Returns a reference to the actual structure inside the PCI devices memory space. - fn map_common_cfg(&self) -> Option> { + fn map_common_cfg(&self) -> Option> { if self.bar.length < u64::from(self.length + self.offset) { error!("Common config of with id {} of device {:x}, does not fit into memory specified by bar {:x}!", self.id, @@ -231,15 +232,15 @@ impl PciCap { return None; } - // Using "as u32" is safe here as ComCfgRaw has a defined size smaller 2^31-1 + // Using "as u32" is safe here as CommonCfg has a defined size smaller 2^31-1 // Drivers MAY do this check. See Virtio specification v1.1. - 4.1.4.1 - if self.length < MemLen::from(mem::size_of::() * 8) { + if self.length < MemLen::from(mem::size_of::() * 8) { error!("Common config of with id {}, does not represent actual structure specified by the standard!", self.id); return None; } let virt_addr_raw = self.bar.mem_addr + self.offset; - let ptr = NonNull::new(ptr::with_exposed_provenance_mut::( + let ptr = NonNull::new(ptr::with_exposed_provenance_mut::( virt_addr_raw.into(), )) .unwrap(); @@ -410,7 +411,7 @@ impl UniCapsColl { } } -/// Wraps a [ComCfgRaw] in order to preserve +/// Wraps a [`CommonCfg`] in order to preserve /// the original structure. /// /// Provides a safe API for Raw structure and allows interaction with the device via @@ -418,28 +419,30 @@ impl UniCapsColl { pub struct ComCfg { /// References the raw structure in PCI memory space. Is static as /// long as the device is present, which is mandatory in order to let this code work. - com_cfg: VolatileRef<'static, ComCfgRaw>, + com_cfg: VolatileRef<'static, CommonCfg>, /// Preferences of the device for this config. From 1 (highest) to 2^7-1 (lowest) rank: u8, } // Private interface of ComCfg impl ComCfg { - fn new(raw: VolatileRef<'static, ComCfgRaw>, rank: u8) -> Self { + fn new(raw: VolatileRef<'static, CommonCfg>, rank: u8) -> Self { ComCfg { com_cfg: raw, rank } } } pub struct VqCfgHandler<'a> { vq_index: u16, - raw: VolatileRef<'a, ComCfgRaw>, + raw: VolatileRef<'a, CommonCfg>, } impl<'a> VqCfgHandler<'a> { // TODO: Create type for queue selected invariant to get rid of `self.select_queue()` everywhere. fn select_queue(&mut self) { - let raw = self.raw.as_mut_ptr(); - map_field!(raw.queue_select).write(self.vq_index); + self.raw + .as_mut_ptr() + .queue_select() + .write(self.vq_index.into()); } /// Sets the size of a given virtqueue. In case the provided size exceeds the maximum allowed @@ -448,44 +451,47 @@ impl<'a> VqCfgHandler<'a> { /// Returns the set size in form of a `u16`. pub fn set_vq_size(&mut self, size: u16) -> u16 { self.select_queue(); - let raw = self.raw.as_mut_ptr(); - let queue_size = map_field!(raw.queue_size); + let queue_size = self.raw.as_mut_ptr().queue_size(); - if queue_size.read() >= size { - queue_size.write(size); + if queue_size.read().get() >= size { + queue_size.write(size.into()); } - queue_size.read() + queue_size.read().get() } pub fn set_ring_addr(&mut self, addr: PhysAddr) { self.select_queue(); - let raw = self.raw.as_mut_ptr(); - map_field!(raw.queue_desc).write(addr.as_u64()); + self.raw + .as_mut_ptr() + .queue_desc() + .write(addr.as_u64().into()); } pub fn set_drv_ctrl_addr(&mut self, addr: PhysAddr) { self.select_queue(); - let raw = self.raw.as_mut_ptr(); - map_field!(raw.queue_driver).write(addr.as_u64()); + self.raw + .as_mut_ptr() + .queue_driver() + .write(addr.as_u64().into()); } pub fn set_dev_ctrl_addr(&mut self, addr: PhysAddr) { self.select_queue(); - let raw = self.raw.as_mut_ptr(); - map_field!(raw.queue_device).write(addr.as_u64()); + self.raw + .as_mut_ptr() + .queue_device() + .write(addr.as_u64().into()); } pub fn notif_off(&mut self) -> u16 { self.select_queue(); - let raw = self.raw.as_mut_ptr(); - map_field!(raw.queue_notify_off).read() + self.raw.as_mut_ptr().queue_notify_off().read().get() } pub fn enable_queue(&mut self) { self.select_queue(); - let raw = self.raw.as_mut_ptr(); - map_field!(raw.queue_enable).write(1); + self.raw.as_mut_ptr().queue_enable().write(1.into()); } } @@ -496,11 +502,9 @@ impl ComCfg { /// /// INFO: The queue size is automatically bounded by constant `src::config:VIRTIO_MAX_QUEUE_SIZE`. pub fn select_vq(&mut self, index: u16) -> Option> { - let com_cfg = self.com_cfg.as_mut_ptr(); - - map_field!(com_cfg.queue_select).write(index); + self.com_cfg.as_mut_ptr().queue_select().write(index.into()); - if map_field!(com_cfg.queue_size).read() == 0 { + if self.com_cfg.as_mut_ptr().queue_size().read().get() == 0 { None } else { Some(VqCfgHandler { @@ -512,15 +516,16 @@ impl ComCfg { /// Returns the device status field. pub fn dev_status(&self) -> u8 { - let com_cfg = self.com_cfg.as_ptr(); - map_field!(com_cfg.device_status).read().bits() + self.com_cfg.as_ptr().device_status().read().bits() } /// Resets the device status field to zero. pub fn reset_dev(&mut self) { memory_barrier(); - let com_cfg = self.com_cfg.as_mut_ptr(); - map_field!(com_cfg.device_status).write(DeviceStatus::empty()); + self.com_cfg + .as_mut_ptr() + .device_status() + .write(DeviceStatus::empty()); } /// Sets the device status field to FAILED. @@ -528,24 +533,30 @@ impl ComCfg { /// A driver MAY use the device again after a proper reset of the device. pub fn set_failed(&mut self) { memory_barrier(); - let com_cfg = self.com_cfg.as_mut_ptr(); - map_field!(com_cfg.device_status).write(DeviceStatus::FAILED); + self.com_cfg + .as_mut_ptr() + .device_status() + .write(DeviceStatus::FAILED); } /// Sets the ACKNOWLEDGE bit in the device status field. This indicates, the /// OS has notived the device pub fn ack_dev(&mut self) { memory_barrier(); - let com_cfg = self.com_cfg.as_mut_ptr(); - map_field!(com_cfg.device_status).update(|s| s | DeviceStatus::ACKNOWLEDGE); + self.com_cfg + .as_mut_ptr() + .device_status() + .update(|s| s | DeviceStatus::ACKNOWLEDGE); } /// Sets the DRIVER bit in the device status field. This indicates, the OS /// know how to run this device. pub fn set_drv(&mut self) { memory_barrier(); - let com_cfg = self.com_cfg.as_mut_ptr(); - map_field!(com_cfg.device_status).update(|s| s | DeviceStatus::DRIVER); + self.com_cfg + .as_mut_ptr() + .device_status() + .update(|s| s | DeviceStatus::DRIVER); } /// Sets the FEATURES_OK bit in the device status field. @@ -553,8 +564,10 @@ impl ComCfg { /// Drivers MUST NOT accept new features after this step. pub fn features_ok(&mut self) { memory_barrier(); - let com_cfg = self.com_cfg.as_mut_ptr(); - map_field!(com_cfg.device_status).update(|s| s | DeviceStatus::FEATURES_OK); + self.com_cfg + .as_mut_ptr() + .device_status() + .update(|s| s | DeviceStatus::FEATURES_OK); } /// In order to correctly check feature negotiaten, this function @@ -565,8 +578,9 @@ impl ComCfg { /// otherwise, the device does not support our subset of features and the device is unusable. pub fn check_features(&self) -> bool { memory_barrier(); - let com_cfg = self.com_cfg.as_ptr(); - map_field!(com_cfg.device_status) + self.com_cfg + .as_ptr() + .device_status() .read() .contains(DeviceStatus::FEATURES_OK) } @@ -576,32 +590,34 @@ impl ComCfg { /// After this call, the device is "live"! pub fn drv_ok(&mut self) { memory_barrier(); - let com_cfg = self.com_cfg.as_mut_ptr(); - map_field!(com_cfg.device_status).update(|s| s | DeviceStatus::DRIVER_OK); + self.com_cfg + .as_mut_ptr() + .device_status() + .update(|s| s | DeviceStatus::DRIVER_OK); } /// Returns the features offered by the device. Coded in a 64bit value. pub fn dev_features(&mut self) -> u64 { let com_cfg = self.com_cfg.as_mut_ptr(); - let device_feature_select = map_field!(com_cfg.device_feature_select); - let device_feature = map_field!(com_cfg.device_feature); + let device_feature_select = com_cfg.device_feature_select(); + let device_feature = com_cfg.device_feature(); // Indicate device to show high 32 bits in device_feature field. // See Virtio specification v1.1. - 4.1.4.3 memory_barrier(); - device_feature_select.write(1); + device_feature_select.write(1.into()); memory_barrier(); // read high 32 bits of device features - let mut dev_feat = u64::from(device_feature.read()) << 32; + let mut dev_feat = u64::from(device_feature.read().get()) << 32; // Indicate device to show low 32 bits in device_feature field. // See Virtio specification v1.1. - 4.1.4.3 - device_feature_select.write(0); + device_feature_select.write(0.into()); memory_barrier(); // read low 32 bits of device features - dev_feat |= u64::from(device_feature.read()); + dev_feat |= u64::from(device_feature.read().get()); dev_feat } @@ -609,8 +625,8 @@ impl ComCfg { /// Write selected features into driver_select field. pub fn set_drv_features(&mut self, feats: u64) { let com_cfg = self.com_cfg.as_mut_ptr(); - let driver_feature_select = map_field!(com_cfg.driver_feature_select); - let driver_feature = map_field!(com_cfg.driver_feature); + let driver_feature_select = com_cfg.driver_feature_select(); + let driver_feature = com_cfg.driver_feature(); let high: u32 = (feats >> 32) as u32; let low: u32 = feats as u32; @@ -618,19 +634,19 @@ impl ComCfg { // Indicate to device that driver_features field shows low 32 bits. // See Virtio specification v1.1. - 4.1.4.3 memory_barrier(); - driver_feature_select.write(0); + driver_feature_select.write(0.into()); memory_barrier(); // write low 32 bits of device features - driver_feature.write(low); + driver_feature.write(low.into()); // Indicate to device that driver_features field shows high 32 bits. // See Virtio specification v1.1. - 4.1.4.3 - driver_feature_select.write(1); + driver_feature_select.write(1.into()); memory_barrier(); // write high 32 bits of device features - driver_feature.write(high); + driver_feature.write(high.into()); } }