From 582d95a3106caa3a159be4ceff2c35bc0c80c034 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Mon, 10 Jun 2024 11:03:26 +0200 Subject: [PATCH 1/5] refactor(virtio/pci): remove `offset`, `length` fields 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 | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/drivers/virtio/transport/pci.rs b/src/drivers/virtio/transport/pci.rs index 3a77eac295..b1b92ca4cd 100644 --- a/src/drivers/virtio/transport/pci.rs +++ b/src/drivers/virtio/transport/pci.rs @@ -90,8 +90,6 @@ pub struct PciCap { cfg_type: CapCfgType, bar: PciBar, id: u8, - offset: MemOff, - length: MemLen, device: PciDevice, // Following field can be used to retrieve original structure // from the config space. Needed by some structures and f @@ -101,11 +99,11 @@ pub struct PciCap { impl PciCap { pub fn offset(&self) -> MemOff { - self.offset + self.origin.cap_struct.offset.to_ne().into() } pub fn len(&self) -> MemLen { - self.length + self.origin.cap_struct.length.to_ne().into() } pub fn bar_len(&self) -> u64 { @@ -122,7 +120,7 @@ impl PciCap { /// Returns a reference to the actual structure inside the PCI devices memory space. fn map_common_cfg(&self) -> Option> { - if self.bar.length < u64::from(self.length + self.offset) { + if self.bar.length < u64::from(self.len() + self.offset()) { error!("Common config of the capability with id {} of device {:x} does not fit into memory specified by bar {:x}!", self.id, self.origin.dev_id, @@ -132,12 +130,12 @@ impl PciCap { } // Drivers MAY do this check. See Virtio specification v1.1. - 4.1.4.1 - if self.length < MemLen::from(mem::size_of::()) { + if self.len() < MemLen::from(mem::size_of::()) { 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 virt_addr_raw = self.bar.mem_addr + self.offset(); let ptr = NonNull::new(ptr::with_exposed_provenance_mut::( virt_addr_raw.into(), )) @@ -150,7 +148,7 @@ impl PciCap { } fn map_isr_status(&self) -> Option> { - if self.bar.length < u64::from(self.length + self.offset) { + if self.bar.length < u64::from(self.len() + 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, @@ -159,7 +157,7 @@ impl PciCap { return None; } - let virt_addr_raw: VirtMemAddr = self.bar.mem_addr + self.offset; + let virt_addr_raw: VirtMemAddr = self.bar.mem_addr + self.offset(); let ptr = NonNull::new(ptr::with_exposed_provenance_mut::( virt_addr_raw.into(), )) @@ -546,7 +544,7 @@ pub struct NotifCfg { impl NotifCfg { fn new(cap: &PciCap) -> Option { - if cap.bar.length < u64::from(u32::from(cap.length + cap.offset)) { + if cap.bar.length < u64::from(u32::from(cap.len() + cap.offset())) { error!("Notification config with id {} of device {:x}, does not fit into memory specified by bar {:x}!", cap.id, cap.origin.dev_id, @@ -568,13 +566,13 @@ impl NotifCfg { // See Virtio specification v1.1. - 4.1.4.4 // // Base address here already includes offset! - let base_addr = cap.bar.mem_addr + cap.offset; + let base_addr = cap.bar.mem_addr + cap.offset(); Some(NotifCfg { base_addr, notify_off_multiplier, rank: cap.id, - length: cap.length, + length: cap.len(), }) } @@ -733,7 +731,7 @@ pub struct ShMemCfg { impl ShMemCfg { fn new(cap: &PciCap) -> Option { - if cap.bar.length < u64::from(cap.length + cap.offset) { + if cap.bar.length < u64::from(cap.len() + cap.offset()) { error!("Shared memory config of with id {} of device {:x}, does not fit into memory specified by bar {:x}!", cap.id, cap.origin.dev_id, @@ -783,7 +781,7 @@ impl ShMemCfg { Some(ShMemCfg { mem_addr: virt_addr_raw, - length: cap.length, + length: cap.len(), sh_mem: ShMem { ptr: raw_ptr, len: cap.bar.length as usize, @@ -874,8 +872,6 @@ fn read_caps( cfg_type: CapCfgType::from(capability.cfg_type), bar: *bars.iter().find(|bar| bar.index == capability.bar).unwrap(), id: capability.id, - offset: MemOff::from(capability.offset.to_ne()), - length: MemLen::from(capability.length.to_ne()), device: *device, origin: Origin { cfg_ptr: ptr, From a9d88539ea956df932312d6cbf3df6554a3bab37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Mon, 10 Jun 2024 11:17:01 +0200 Subject: [PATCH 2/5] refactor(virtio/pci): inline `Origin` into `PciCap` 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 | 57 +++++++++++------------------ 1 file changed, 21 insertions(+), 36 deletions(-) diff --git a/src/drivers/virtio/transport/pci.rs b/src/drivers/virtio/transport/pci.rs index b1b92ca4cd..9a009a7864 100644 --- a/src/drivers/virtio/transport/pci.rs +++ b/src/drivers/virtio/transport/pci.rs @@ -33,15 +33,6 @@ use crate::drivers::pci::PciDevice; use crate::drivers::virtio::env::memory::{MemLen, MemOff, VirtMemAddr}; use crate::drivers::virtio::error::VirtioError; -/// Public structure to allow drivers to read the configuration space -/// safely -#[derive(Clone)] -pub struct Origin { - cfg_ptr: u16, // Register to be read to reach configuration structure of type cfg_type - dev_id: u16, - cap_struct: Cap, -} - /// Maps a given device specific pci configuration structure and /// returns a static reference to it. pub fn map_dev_cfg(cap: &PciCap) -> Option<&'static mut T> { @@ -91,19 +82,18 @@ pub struct PciCap { bar: PciBar, id: u8, device: PciDevice, - // Following field can be used to retrieve original structure - // from the config space. Needed by some structures and f - // device specific configs. - origin: Origin, + cfg_ptr: u16, // Register to be read to reach configuration structure of type cfg_type + dev_id: u16, + cap_struct: Cap, } impl PciCap { pub fn offset(&self) -> MemOff { - self.origin.cap_struct.offset.to_ne().into() + self.cap_struct.offset.to_ne().into() } pub fn len(&self) -> MemLen { - self.origin.cap_struct.length.to_ne().into() + self.cap_struct.length.to_ne().into() } pub fn bar_len(&self) -> u64 { @@ -115,7 +105,7 @@ impl PciCap { } pub fn dev_id(&self) -> u16 { - self.origin.dev_id + self.dev_id } /// Returns a reference to the actual structure inside the PCI devices memory space. @@ -123,7 +113,7 @@ impl PciCap { if self.bar.length < u64::from(self.len() + self.offset()) { error!("Common config of the capability with id {} of device {:x} does not fit into memory specified by bar {:x}!", self.id, - self.origin.dev_id, + self.dev_id, self.bar.index ); return None; @@ -151,7 +141,7 @@ impl PciCap { if self.bar.length < u64::from(self.len() + 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.dev_id, self.bar.index ); return None; @@ -547,7 +537,7 @@ impl NotifCfg { if cap.bar.length < u64::from(u32::from(cap.len() + cap.offset())) { error!("Notification config with id {} of device {:x}, does not fit into memory specified by bar {:x}!", cap.id, - cap.origin.dev_id, + cap.dev_id, cap.bar.index ); return None; @@ -555,8 +545,7 @@ impl NotifCfg { // Assumes the cap_len is a multiple of 8 // This read MIGHT be slow, as it does NOT ensure 32 bit alignment. - let notify_off_multiplier_ptr = - cap.origin.cfg_ptr + u16::try_from(mem::size_of::()).unwrap(); + let notify_off_multiplier_ptr = cap.cfg_ptr + u16::try_from(mem::size_of::()).unwrap(); let notify_off_multiplier = cap.device.read_register(notify_off_multiplier_ptr); // define base memory address from which the actual Queue Notify address can be derived via @@ -734,7 +723,7 @@ impl ShMemCfg { if cap.bar.length < u64::from(cap.len() + cap.offset()) { error!("Shared memory config of with id {} of device {:x}, does not fit into memory specified by bar {:x}!", cap.id, - cap.origin.dev_id, + cap.dev_id, cap.bar.index ); return None; @@ -744,24 +733,22 @@ impl ShMemCfg { // Assumes the cap_len is a multiple of 8 // This read MIGHT be slow, as it does NOT ensure 32 bit alignment. - let offset_hi_ptr = cap.origin.cfg_ptr + u16::try_from(mem::size_of::()).unwrap(); + let offset_hi_ptr = cap.cfg_ptr + u16::try_from(mem::size_of::()).unwrap(); let offset_hi = cap.device.read_register(offset_hi_ptr); // Create 64 bit offset from high and low 32 bit values - let offset = MemOff::from( - (u64::from(offset_hi) << 32) ^ u64::from(cap.origin.cap_struct.offset.to_ne()), - ); + let offset = + MemOff::from((u64::from(offset_hi) << 32) ^ u64::from(cap.cap_struct.offset.to_ne())); // Assumes the cap_len is a multiple of 8 // This read MIGHT be slow, as it does NOT ensure 32 bit alignment. - let length_hi_ptr = cap.origin.cfg_ptr - + u16::try_from(mem::size_of::() + mem::size_of::()).unwrap(); + let length_hi_ptr = + cap.cfg_ptr + u16::try_from(mem::size_of::() + mem::size_of::()).unwrap(); let length_hi = cap.device.read_register(length_hi_ptr); // Create 64 bit length from high and low 32 bit values - let length = MemLen::from( - (u64::from(length_hi) << 32) ^ u64::from(cap.origin.cap_struct.length.to_ne()), - ); + let length = + MemLen::from((u64::from(length_hi) << 32) ^ u64::from(cap.cap_struct.length.to_ne())); let virt_addr_raw = cap.bar.mem_addr + offset; let raw_ptr = ptr::with_exposed_provenance_mut::(virt_addr_raw.into()); @@ -873,11 +860,9 @@ fn read_caps( bar: *bars.iter().find(|bar| bar.index == capability.bar).unwrap(), id: capability.id, device: *device, - origin: Origin { - cfg_ptr: ptr, - dev_id: device_id, - cap_struct: capability, - }, + cfg_ptr: ptr, + dev_id: device_id, + cap_struct: capability, }) .collect::>(); From a85b245d0a38d4709231aac02d3384999998b732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Mon, 10 Jun 2024 11:19:08 +0200 Subject: [PATCH 3/5] refactor(virtio/pci): rename `PciCap::cap_struct` to `PciCap::cap` 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 | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/drivers/virtio/transport/pci.rs b/src/drivers/virtio/transport/pci.rs index 9a009a7864..e31ffe0643 100644 --- a/src/drivers/virtio/transport/pci.rs +++ b/src/drivers/virtio/transport/pci.rs @@ -84,16 +84,16 @@ pub struct PciCap { device: PciDevice, cfg_ptr: u16, // Register to be read to reach configuration structure of type cfg_type dev_id: u16, - cap_struct: Cap, + cap: Cap, } impl PciCap { pub fn offset(&self) -> MemOff { - self.cap_struct.offset.to_ne().into() + self.cap.offset.to_ne().into() } pub fn len(&self) -> MemLen { - self.cap_struct.length.to_ne().into() + self.cap.length.to_ne().into() } pub fn bar_len(&self) -> u64 { @@ -737,8 +737,7 @@ impl ShMemCfg { let offset_hi = cap.device.read_register(offset_hi_ptr); // Create 64 bit offset from high and low 32 bit values - let offset = - MemOff::from((u64::from(offset_hi) << 32) ^ u64::from(cap.cap_struct.offset.to_ne())); + let offset = MemOff::from((u64::from(offset_hi) << 32) ^ u64::from(cap.cap.offset.to_ne())); // Assumes the cap_len is a multiple of 8 // This read MIGHT be slow, as it does NOT ensure 32 bit alignment. @@ -747,8 +746,7 @@ impl ShMemCfg { let length_hi = cap.device.read_register(length_hi_ptr); // Create 64 bit length from high and low 32 bit values - let length = - MemLen::from((u64::from(length_hi) << 32) ^ u64::from(cap.cap_struct.length.to_ne())); + let length = MemLen::from((u64::from(length_hi) << 32) ^ u64::from(cap.cap.length.to_ne())); let virt_addr_raw = cap.bar.mem_addr + offset; let raw_ptr = ptr::with_exposed_provenance_mut::(virt_addr_raw.into()); @@ -862,7 +860,7 @@ fn read_caps( device: *device, cfg_ptr: ptr, dev_id: device_id, - cap_struct: capability, + cap: capability, }) .collect::>(); From 93ba6798cb763ad8f8dc6e2693d6d71512800bc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Mon, 10 Jun 2024 11:23:20 +0200 Subject: [PATCH 4/5] refactor(virtio/pci): remove `cfg_type`, `id` from `PciCap` 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 | 38 +++++++++++++---------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/src/drivers/virtio/transport/pci.rs b/src/drivers/virtio/transport/pci.rs index e31ffe0643..ef7bc6ec7f 100644 --- a/src/drivers/virtio/transport/pci.rs +++ b/src/drivers/virtio/transport/pci.rs @@ -36,7 +36,7 @@ use crate::drivers::virtio::error::VirtioError; /// Maps a given device specific pci configuration structure and /// returns a static reference to it. pub fn map_dev_cfg(cap: &PciCap) -> Option<&'static mut T> { - if cap.cfg_type != CapCfgType::Device { + if CapCfgType::from(cap.cap.cfg_type) != CapCfgType::Device { error!("Capability of device config has wrong id. Mapping not possible..."); return None; }; @@ -78,9 +78,7 @@ pub fn map_dev_cfg(cap: &PciCap) -> Option<&'static mut T> { /// corresponding config type into address space. #[derive(Clone)] pub struct PciCap { - cfg_type: CapCfgType, bar: PciBar, - id: u8, device: PciDevice, cfg_ptr: u16, // Register to be read to reach configuration structure of type cfg_type dev_id: u16, @@ -112,7 +110,7 @@ impl PciCap { fn map_common_cfg(&self) -> Option> { if self.bar.length < u64::from(self.len() + self.offset()) { error!("Common config of the capability with id {} of device {:x} does not fit into memory specified by bar {:x}!", - self.id, + self.cap.id, self.dev_id, self.bar.index ); @@ -121,7 +119,7 @@ impl PciCap { // Drivers MAY do this check. See Virtio specification v1.1. - 4.1.4.1 if self.len() < MemLen::from(mem::size_of::()) { - error!("Common config of with id {}, does not represent actual structure specified by the standard!", self.id); + error!("Common config of with id {}, does not represent actual structure specified by the standard!", self.cap.id); return None; } @@ -140,7 +138,7 @@ impl PciCap { fn map_isr_status(&self) -> Option> { if self.bar.length < u64::from(self.len() + self.offset()) { error!("ISR status config with id {} of device {:x}, does not fit into memory specified by bar {:x}!", - self.id, + self.cap.id, self.dev_id, self.bar.index ); @@ -226,7 +224,7 @@ impl UniCapsColl { // This should not be to expensive, as "rational" devices will hold an // acceptable amount of configuration structures. self.pci_cfg_acc_list - .sort_by(|a, b| b.pci_cap.id.cmp(&a.pci_cap.id)); + .sort_by(|a, b| b.pci_cap.cap.id.cmp(&a.pci_cap.cap.id)); } fn add_cfg_sh_mem(&mut self, sh_mem: ShMemCfg) { @@ -244,7 +242,7 @@ impl UniCapsColl { // // This should not be to expensive, as "rational" devices will hold an // acceptable amount of configuration structures. - self.dev_cfg_list.sort_by(|a, b| b.id.cmp(&a.id)); + self.dev_cfg_list.sort_by(|a, b| b.cap.id.cmp(&a.cap.id)); } } @@ -536,7 +534,7 @@ impl NotifCfg { fn new(cap: &PciCap) -> Option { if cap.bar.length < u64::from(u32::from(cap.len() + cap.offset())) { error!("Notification config with id {} of device {:x}, does not fit into memory specified by bar {:x}!", - cap.id, + cap.cap.id, cap.dev_id, cap.bar.index ); @@ -560,7 +558,7 @@ impl NotifCfg { Some(NotifCfg { base_addr, notify_off_multiplier, - rank: cap.id, + rank: cap.cap.id, length: cap.len(), }) } @@ -722,7 +720,7 @@ impl ShMemCfg { fn new(cap: &PciCap) -> Option { if cap.bar.length < u64::from(cap.len() + cap.offset()) { error!("Shared memory config of with id {} of device {:x}, does not fit into memory specified by bar {:x}!", - cap.id, + cap.cap.id, cap.dev_id, cap.bar.index ); @@ -771,7 +769,7 @@ impl ShMemCfg { ptr: raw_ptr, len: cap.bar.length as usize, }, - id: cap.id, + id: cap.cap.id, }) } } @@ -854,9 +852,7 @@ fn read_caps( }) .filter(|(_ptr, capability)| capability.cfg_type != CapCfgType::Pci.into()) .map(|(ptr, capability)| PciCap { - cfg_type: CapCfgType::from(capability.cfg_type), bar: *bars.iter().find(|bar| bar.index == capability.bar).unwrap(), - id: capability.id, device: *device, cfg_ptr: ptr, dev_id: device_id, @@ -913,26 +909,26 @@ pub(crate) fn map_caps(device: &PciDevice) -> Result match pci_cap.map_common_cfg() { - Some(cap) => caps.add_cfg_common(ComCfg::new(cap, pci_cap.id)), + Some(cap) => caps.add_cfg_common(ComCfg::new(cap, pci_cap.cap.id)), None => error!( "Common config capability with id {}, of device {:x}, could not be mapped!", - pci_cap.id, device_id + pci_cap.cap.id, device_id ), }, CapCfgType::Notify => match NotifCfg::new(&pci_cap) { Some(notif) => caps.add_cfg_notif(notif), None => error!( "Notification config capability with id {}, of device {:x} could not be used!", - pci_cap.id, device_id + pci_cap.cap.id, device_id ), }, CapCfgType::Isr => match pci_cap.map_isr_status() { - Some(isr_stat) => caps.add_cfg_isr(IsrStatus::new(isr_stat, pci_cap.id)), + Some(isr_stat) => caps.add_cfg_isr(IsrStatus::new(isr_stat, pci_cap.cap.id)), None => error!( "ISR status config capability with id {}, of device {:x} could not be used!", - pci_cap.id, device_id + pci_cap.cap.id, device_id ), }, CapCfgType::Pci => caps.add_cfg_alt(PciCfgAlt::new(&pci_cap)), @@ -940,7 +936,7 @@ pub(crate) fn map_caps(device: &PciDevice) -> Result caps.add_cfg_sh_mem(sh_mem), None => error!( "Shared Memory config capability with id {}, of device {:x} could not be used!", - pci_cap.id, device_id + pci_cap.cap.id, device_id ), }, CapCfgType::Device => caps.add_cfg_dev(pci_cap), From 1f1fe9c2d9016b2cebcb9c4e0aaf7ee0961c43c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Mon, 10 Jun 2024 11:37:41 +0200 Subject: [PATCH 5/5] refactor(virtio/pci): migrate extra cap data reading 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 | 50 +++++++---------------------- 1 file changed, 12 insertions(+), 38 deletions(-) diff --git a/src/drivers/virtio/transport/pci.rs b/src/drivers/virtio/transport/pci.rs index ef7bc6ec7f..f58215994d 100644 --- a/src/drivers/virtio/transport/pci.rs +++ b/src/drivers/virtio/transport/pci.rs @@ -10,7 +10,7 @@ use core::{mem, ptr}; use pci_types::capability::PciCapability; use virtio_spec::pci::{ - Cap, CapCfgType, CommonCfg, CommonCfgVolatileFieldAccess, CommonCfgVolatileWideFieldAccess, + CapCfgType, CapData, CommonCfg, CommonCfgVolatileFieldAccess, CommonCfgVolatileWideFieldAccess, IsrStatus as IsrStatusRaw, }; use virtio_spec::{le32, DeviceStatus}; @@ -36,7 +36,7 @@ use crate::drivers::virtio::error::VirtioError; /// Maps a given device specific pci configuration structure and /// returns a static reference to it. pub fn map_dev_cfg(cap: &PciCap) -> Option<&'static mut T> { - if CapCfgType::from(cap.cap.cfg_type) != CapCfgType::Device { + if cap.cap.cfg_type != CapCfgType::Device { error!("Capability of device config has wrong id. Mapping not possible..."); return None; }; @@ -79,10 +79,8 @@ pub fn map_dev_cfg(cap: &PciCap) -> Option<&'static mut T> { #[derive(Clone)] pub struct PciCap { bar: PciBar, - device: PciDevice, - cfg_ptr: u16, // Register to be read to reach configuration structure of type cfg_type dev_id: u16, - cap: Cap, + cap: CapData, } impl PciCap { @@ -541,10 +539,7 @@ impl NotifCfg { return None; } - // Assumes the cap_len is a multiple of 8 - // This read MIGHT be slow, as it does NOT ensure 32 bit alignment. - let notify_off_multiplier_ptr = cap.cfg_ptr + u16::try_from(mem::size_of::()).unwrap(); - let notify_off_multiplier = cap.device.read_register(notify_off_multiplier_ptr); + let notify_off_multiplier = cap.cap.notify_off_multiplier?.to_ne(); // define base memory address from which the actual Queue Notify address can be derived via // base_addr + queue_notify_off * notify_off_multiplier. @@ -727,24 +722,8 @@ impl ShMemCfg { return None; } - // Read the PciCap64 fields after the PciCap structure to get the right offset and length - - // Assumes the cap_len is a multiple of 8 - // This read MIGHT be slow, as it does NOT ensure 32 bit alignment. - let offset_hi_ptr = cap.cfg_ptr + u16::try_from(mem::size_of::()).unwrap(); - let offset_hi = cap.device.read_register(offset_hi_ptr); - - // Create 64 bit offset from high and low 32 bit values - let offset = MemOff::from((u64::from(offset_hi) << 32) ^ u64::from(cap.cap.offset.to_ne())); - - // Assumes the cap_len is a multiple of 8 - // This read MIGHT be slow, as it does NOT ensure 32 bit alignment. - let length_hi_ptr = - cap.cfg_ptr + u16::try_from(mem::size_of::() + mem::size_of::()).unwrap(); - let length_hi = cap.device.read_register(length_hi_ptr); - - // Create 64 bit length from high and low 32 bit values - let length = MemLen::from((u64::from(length_hi) << 32) ^ u64::from(cap.cap.length.to_ne())); + let offset = MemOff::from(cap.cap.offset.to_ne()); + let length = MemLen::from(cap.cap.length.to_ne()); let virt_addr_raw = cap.bar.mem_addr + offset; let raw_ptr = ptr::with_exposed_provenance_mut::(virt_addr_raw.into()); @@ -846,17 +825,12 @@ fn read_caps( PciCapability::Vendor(capability) => Some(capability), _ => None, }) - .map(|addr| { - let cap = Cap::read(addr.clone(), device.access()).unwrap(); - (addr.offset, cap) - }) - .filter(|(_ptr, capability)| capability.cfg_type != CapCfgType::Pci.into()) - .map(|(ptr, capability)| PciCap { - bar: *bars.iter().find(|bar| bar.index == capability.bar).unwrap(), - device: *device, - cfg_ptr: ptr, + .map(|addr| CapData::read(addr.clone(), device.access()).unwrap()) + .filter(|cap| cap.cfg_type != CapCfgType::Pci) + .map(|cap| PciCap { + bar: *bars.iter().find(|bar| bar.index == cap.bar).unwrap(), dev_id: device_id, - cap: capability, + cap, }) .collect::>(); @@ -909,7 +883,7 @@ pub(crate) fn map_caps(device: &PciDevice) -> Result match pci_cap.map_common_cfg() { Some(cap) => caps.add_cfg_common(ComCfg::new(cap, pci_cap.cap.id)), None => error!(