From 148cfe809dee585027c0f45fb4f30f195f817795 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Sun, 2 Jun 2024 11:06:34 +0200 Subject: [PATCH 1/3] refactor(virtio/pci): move `IsrStatusRaw` to `PciCap::map_isr_status` 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 | 43 ++++++++++++++--------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/src/drivers/virtio/transport/pci.rs b/src/drivers/virtio/transport/pci.rs index 871bfc2e14..b42439d2d7 100644 --- a/src/drivers/virtio/transport/pci.rs +++ b/src/drivers/virtio/transport/pci.rs @@ -249,6 +249,25 @@ impl PciCap { Some(com_cfg_raw) } + + fn map_isr_status(&self) -> Option<&'static mut IsrStatusRaw> { + if self.bar.length < u64::from(self.length + self.offset) { + error!("ISR status config with id {} of device {:x}, does not fit into memory specified by bar {:x}!", + self.id, + self.origin.dev_id, + self.bar.index + ); + return None; + } + + let virt_addr_raw: VirtMemAddr = self.bar.mem_addr + self.offset; + + // Create mutable reference to the PCI structure in the devices memory area + let isr_stat_raw: &mut IsrStatusRaw = + unsafe { &mut *(ptr::with_exposed_provenance_mut(virt_addr_raw.into())) }; + + Some(isr_stat_raw) + } } /// Virtio's PCI capabilities structure. @@ -842,28 +861,6 @@ struct IsrStatusRaw { } impl IsrStatusRaw { - /// Returns a mutable reference to the ISR status capability structure indicated by the - /// [PciCap] struct. Reference has a static lifetime as the structure is controlled by the - /// device and will not be moved. - fn map(cap: &PciCap) -> Option<&'static mut IsrStatusRaw> { - if cap.bar.length < u64::from(cap.length + cap.offset) { - error!("ISR status config with id {} of device {:x}, does not fit into memory specified by bar {:x}!", - cap.id, - cap.origin.dev_id, - cap.bar.index - ); - return None; - } - - let virt_addr_raw: VirtMemAddr = cap.bar.mem_addr + cap.offset; - - // Create mutable reference to the PCI structure in the devices memory area - let isr_stat_raw: &mut IsrStatusRaw = - unsafe { &mut *(ptr::with_exposed_provenance_mut(virt_addr_raw.into())) }; - - Some(isr_stat_raw) - } - // returns true if second bit, from left is 1. // read DOES reset flag fn cfg_event() -> bool { @@ -1252,7 +1249,7 @@ pub(crate) fn map_caps(device: &PciDevice) -> Result match IsrStatusRaw::map(&pci_cap) { + CfgType::VIRTIO_PCI_CAP_ISR_CFG => match pci_cap.map_isr_status() { Some(isr_stat) => caps.add_cfg_isr(IsrStatus::new(isr_stat, pci_cap.id)), None => error!( "ISR status config capability with id {}, of device {:x} could not be used!", From 7f86dce86c9347dfa76bfb06ea184e5ac17fe153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Sun, 2 Jun 2024 11:16:04 +0200 Subject: [PATCH 2/3] feat(virtio-spec/pci): add `IsrStatus` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- virtio-spec/src/pci.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/virtio-spec/src/pci.rs b/virtio-spec/src/pci.rs index f361bee7ff..b486f4fb7d 100644 --- a/virtio-spec/src/pci.rs +++ b/virtio-spec/src/pci.rs @@ -140,3 +140,14 @@ impl_wide_field_access! { queue_device: queue_device_low, queue_device_high; } } + +virtio_bitflags! { + /// ISR Status + pub struct IsrStatus: u8 { + /// Queue Interrupt + const QUEUE_INTERRUPT = 1 << 0; + + /// Device Configuration Interrupt + const DEVICE_CONFIGURATION_INTERRUPT = 1 << 1; + } +} From a34b006f0ab4536d7e614d2b3f0f6951b4c0d18c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Sun, 2 Jun 2024 11:16:40 +0200 Subject: [PATCH 3/3] refactor(virtio/pci): migrate `IsrStatusRaw` to `virtio-spec` 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 | 63 +++++++++-------------------- 1 file changed, 20 insertions(+), 43 deletions(-) diff --git a/src/drivers/virtio/transport/pci.rs b/src/drivers/virtio/transport/pci.rs index b42439d2d7..0417f0e306 100644 --- a/src/drivers/virtio/transport/pci.rs +++ b/src/drivers/virtio/transport/pci.rs @@ -8,7 +8,10 @@ use core::ptr::NonNull; use core::sync::atomic::{fence, Ordering}; use core::{mem, ptr}; -use virtio_spec::pci::{CommonCfg, CommonCfgVolatileFieldAccess, CommonCfgVolatileWideFieldAccess}; +use virtio_spec::pci::{ + CommonCfg, CommonCfgVolatileFieldAccess, CommonCfgVolatileWideFieldAccess, + IsrStatus as IsrStatusRaw, +}; use virtio_spec::DeviceStatus; use volatile::VolatileRef; @@ -250,7 +253,7 @@ impl PciCap { Some(com_cfg_raw) } - fn map_isr_status(&self) -> Option<&'static mut IsrStatusRaw> { + fn map_isr_status(&self) -> Option> { if self.bar.length < u64::from(self.length + self.offset) { error!("ISR status config with id {} of device {:x}, does not fit into memory specified by bar {:x}!", self.id, @@ -261,10 +264,13 @@ impl PciCap { } let virt_addr_raw: VirtMemAddr = self.bar.mem_addr + self.offset; + let ptr = NonNull::new(ptr::with_exposed_provenance_mut::( + virt_addr_raw.into(), + )) + .unwrap(); // Create mutable reference to the PCI structure in the devices memory area - let isr_stat_raw: &mut IsrStatusRaw = - unsafe { &mut *(ptr::with_exposed_provenance_mut(virt_addr_raw.into())) }; + let isr_stat_raw = unsafe { VolatileRef::new(ptr) }; Some(isr_stat_raw) } @@ -813,13 +819,13 @@ impl NotifCtrl { pub struct IsrStatus { /// 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. - isr_stat: &'static mut IsrStatusRaw, + isr_stat: VolatileRef<'static, IsrStatusRaw>, /// Preferences of the device for this config. From 1 (highest) to 2^7-1 (lowest) rank: u8, } impl IsrStatus { - fn new(raw: &'static mut IsrStatusRaw, rank: u8) -> Self { + fn new(raw: VolatileRef<'static, IsrStatusRaw>, rank: u8) -> Self { IsrStatus { isr_stat: raw, rank, @@ -827,11 +833,17 @@ impl IsrStatus { } pub fn is_interrupt(&self) -> bool { - self.isr_stat.flags & 1 << 0 == 1 + self.isr_stat + .as_ptr() + .read() + .contains(IsrStatusRaw::QUEUE_INTERRUPT) } pub fn is_cfg_change(&self) -> bool { - self.isr_stat.flags & 1 << 1 == 1 << 1 + self.isr_stat + .as_ptr() + .read() + .contains(IsrStatusRaw::DEVICE_CONFIGURATION_INTERRUPT) } pub fn acknowledge(&mut self) { @@ -839,41 +851,6 @@ impl IsrStatus { } } -/// ISR status structure of Virtio PCI devices. -/// See Virtio specification v1.1. - 4.1.4.5 -/// -/// Contains a single byte, containing the interrupt numbers used -/// for handling interrupts. -/// The 8-bit field is read as an bitmap and allows to distinguish between -/// interrupts triggered by changes in the configuration and interrupts -/// triggered by events of a virtqueue. -/// -/// Bitmap layout (from least to most significant bit in the byte): -/// -/// 0 : Queue interrupt -/// -/// 1 : Device configuration interrupt -/// -/// 2 - 31 : Reserved -#[repr(C)] -struct IsrStatusRaw { - flags: u8, -} - -impl IsrStatusRaw { - // returns true if second bit, from left is 1. - // read DOES reset flag - fn cfg_event() -> bool { - unimplemented!(); - } - - // returns true if first bit, from left is 1. - // read DOES reset flag - fn vqueue_event() -> bool { - unimplemented!(); - } -} - /// PCI configuration access structure of Virtio PCI devices. /// See Virtio specification v1.1. - 4.1.4.8 ///