Skip to content

Commit 1a64402

Browse files
committed
refactor(virtio/pci): migrate PciCapRaw to virtio-spec
Signed-off-by: Martin Kröning <[email protected]>
1 parent f10132a commit 1a64402

File tree

1 file changed

+18
-86
lines changed
  • src/drivers/virtio/transport

1 file changed

+18
-86
lines changed

src/drivers/virtio/transport/pci.rs

Lines changed: 18 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use core::{mem, ptr};
1010

1111
use pci_types::capability::PciCapability;
1212
use virtio_spec::pci::{
13-
CapCfgType, CommonCfg, CommonCfgVolatileFieldAccess, CommonCfgVolatileWideFieldAccess,
13+
Cap, CapCfgType, CommonCfg, CommonCfgVolatileFieldAccess, CommonCfgVolatileWideFieldAccess,
1414
IsrStatus as IsrStatusRaw,
1515
};
1616
use virtio_spec::DeviceStatus;
@@ -39,7 +39,7 @@ use crate::drivers::virtio::error::VirtioError;
3939
pub struct Origin {
4040
cfg_ptr: u16, // Register to be read to reach configuration structure of type cfg_type
4141
dev_id: u16,
42-
cap_struct: PciCapRaw,
42+
cap_struct: Cap,
4343
}
4444

4545
/// Maps a given device specific pci configuration structure and
@@ -172,45 +172,6 @@ impl PciCap {
172172
}
173173
}
174174

175-
/// Virtio's PCI capabilities structure.
176-
/// See Virtio specification v.1.1 - 4.1.4
177-
///
178-
/// WARN: endianness of this structure should be seen as little endian.
179-
/// As this structure is not meant to be used outside of this module and for
180-
/// ease of conversion from reading data into struct from PCI configuration
181-
/// space, no conversion is made for struct fields.
182-
#[derive(Clone, Debug)]
183-
#[repr(C)]
184-
struct PciCapRaw {
185-
cap_vndr: u8,
186-
cap_next: u8,
187-
cap_len: u8,
188-
cfg_type: u8,
189-
bar_index: u8,
190-
id: u8,
191-
padding: [u8; 2],
192-
offset: u32,
193-
length: u32,
194-
}
195-
196-
// This only shows compiler, that structs are identical
197-
// with themselves.
198-
impl Eq for PciCapRaw {}
199-
200-
// In order to compare two PciCapRaw structs PartialEq is needed
201-
impl PartialEq for PciCapRaw {
202-
fn eq(&self, other: &Self) -> bool {
203-
self.cap_vndr == other.cap_vndr
204-
&& self.cap_next == other.cap_next
205-
&& self.cap_len == other.cap_len
206-
&& self.cfg_type == other.cfg_type
207-
&& self.bar_index == other.bar_index
208-
&& self.id == other.id
209-
&& self.offset == other.offset
210-
&& self.length == other.length
211-
}
212-
}
213-
214175
/// Universal Caplist Collections holds all universal capability structures for
215176
/// a given Virtio PCI device.
216177
///
@@ -597,7 +558,7 @@ impl NotifCfg {
597558
// Assumes the cap_len is a multiple of 8
598559
// This read MIGHT be slow, as it does NOT ensure 32 bit alignment.
599560
let notify_off_multiplier_ptr =
600-
cap.origin.cfg_ptr + u16::try_from(mem::size_of::<PciCapRaw>()).unwrap();
561+
cap.origin.cfg_ptr + u16::try_from(mem::size_of::<Cap>()).unwrap();
601562
let notify_off_multiplier = cap.device.read_register(notify_off_multiplier_ptr);
602563

603564
// define base memory address from which the actual Queue Notify address can be derived via
@@ -790,23 +751,24 @@ impl ShMemCfg {
790751

791752
// Assumes the cap_len is a multiple of 8
792753
// This read MIGHT be slow, as it does NOT ensure 32 bit alignment.
793-
let offset_hi_ptr =
794-
cap.origin.cfg_ptr + u16::try_from(mem::size_of::<PciCapRaw>()).unwrap();
754+
let offset_hi_ptr = cap.origin.cfg_ptr + u16::try_from(mem::size_of::<Cap>()).unwrap();
795755
let offset_hi = cap.device.read_register(offset_hi_ptr);
796756

797757
// Create 64 bit offset from high and low 32 bit values
798-
let offset =
799-
MemOff::from((u64::from(offset_hi) << 32) ^ u64::from(cap.origin.cap_struct.offset));
758+
let offset = MemOff::from(
759+
(u64::from(offset_hi) << 32) ^ u64::from(cap.origin.cap_struct.offset.to_ne()),
760+
);
800761

801762
// Assumes the cap_len is a multiple of 8
802763
// This read MIGHT be slow, as it does NOT ensure 32 bit alignment.
803764
let length_hi_ptr = cap.origin.cfg_ptr
804-
+ u16::try_from(mem::size_of::<PciCapRaw>() + mem::size_of::<u32>()).unwrap();
765+
+ u16::try_from(mem::size_of::<Cap>() + mem::size_of::<u32>()).unwrap();
805766
let length_hi = cap.device.read_register(length_hi_ptr);
806767

807768
// Create 64 bit length from high and low 32 bit values
808-
let length =
809-
MemLen::from((u64::from(length_hi) << 32) ^ u64::from(cap.origin.cap_struct.length));
769+
let length = MemLen::from(
770+
(u64::from(length_hi) << 32) ^ u64::from(cap.origin.cap_struct.length.to_ne()),
771+
);
810772

811773
let virt_addr_raw = cap.bar.mem_addr + offset;
812774
let raw_ptr = ptr::with_exposed_provenance_mut::<u8>(virt_addr_raw.into());
@@ -890,36 +852,6 @@ impl PciBar {
890852
}
891853
}
892854

893-
/// Reads a raw capability struct [PciCapRaw] out of a PCI device's configuration space.
894-
fn read_cap_raw(device: &PciDevice<PciConfigRegion>, register: u16) -> PciCapRaw {
895-
let mut quadruple_word: [u8; 16] = [0; 16];
896-
897-
debug!("Converting read word from PCI device config space into native endian bytes.");
898-
899-
// Write words sequentially into array
900-
for i in 0..4 {
901-
// Read word need to be converted to little endian bytes as PCI is little endian.
902-
// Interpretation of multi byte values needs to be swapped for big endian machines
903-
let word: [u8; 4] = device.read_register(register + 4 * i).to_le_bytes();
904-
let i = 4 * i as usize;
905-
quadruple_word[i..i + 4].copy_from_slice(&word);
906-
}
907-
908-
PciCapRaw {
909-
cap_vndr: quadruple_word[0],
910-
cap_next: quadruple_word[1],
911-
cap_len: quadruple_word[2],
912-
cfg_type: quadruple_word[3],
913-
bar_index: quadruple_word[4],
914-
id: quadruple_word[5],
915-
// Unwrapping is okay here, as transformed array slice is always 2 * u8 long and initialized
916-
padding: quadruple_word[6..8].try_into().unwrap(),
917-
// Unwrapping is okay here, as transformed array slice is always 4 * u8 long and initialized
918-
offset: u32::from_le_bytes(quadruple_word[8..12].try_into().unwrap()),
919-
length: u32::from_le_bytes(quadruple_word[12..16].try_into().unwrap()),
920-
}
921-
}
922-
923855
/// Reads all PCI capabilities, starting at the capabilities list pointer from the
924856
/// PCI device.
925857
///
@@ -938,17 +870,17 @@ fn read_caps(
938870
PciCapability::Vendor(capability) => Some(capability),
939871
_ => None,
940872
})
941-
.map(|capability| (capability.offset, read_cap_raw(device, capability.offset)))
873+
.map(|addr| {
874+
let cap = Cap::read(addr.clone(), device.access()).unwrap();
875+
(addr.offset, cap)
876+
})
942877
.filter(|(_ptr, capability)| capability.cfg_type != CapCfgType::Pci.into())
943878
.map(|(ptr, capability)| PciCap {
944879
cfg_type: CapCfgType::from(capability.cfg_type),
945-
bar: *bars
946-
.iter()
947-
.find(|bar| bar.index == capability.bar_index)
948-
.unwrap(),
880+
bar: *bars.iter().find(|bar| bar.index == capability.bar).unwrap(),
949881
id: capability.id,
950-
offset: MemOff::from(capability.offset),
951-
length: MemLen::from(capability.length),
882+
offset: MemOff::from(capability.offset.to_ne()),
883+
length: MemLen::from(capability.length.to_ne()),
952884
device: *device,
953885
origin: Origin {
954886
cfg_ptr: ptr,

0 commit comments

Comments
 (0)