1*26d84a31SYJwu2023 //! PCI transport for VirtIO. 2*26d84a31SYJwu2023 use super::volatile::{ 3*26d84a31SYJwu2023 volread, volwrite, ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly, 4*26d84a31SYJwu2023 }; 5*26d84a31SYJwu2023 use crate::driver::pci::pci::{ 6*26d84a31SYJwu2023 capabilities_offset, pci_bar_init, CapabilityIterator, DeviceFunction, PciDeviceBar, PciError, 7*26d84a31SYJwu2023 PCI_CAP_ID_VNDR, 8*26d84a31SYJwu2023 }; 9*26d84a31SYJwu2023 use crate::include::bindings::bindings::pci_read_config; 10*26d84a31SYJwu2023 use core::{ 11*26d84a31SYJwu2023 fmt::{self, Display, Formatter}, 12*26d84a31SYJwu2023 mem::{align_of, size_of}, 13*26d84a31SYJwu2023 ptr::{self, addr_of_mut, NonNull}, 14*26d84a31SYJwu2023 }; 15*26d84a31SYJwu2023 use virtio_drivers::{ 16*26d84a31SYJwu2023 transport::{DeviceStatus, DeviceType, Transport}, 17*26d84a31SYJwu2023 Error, Hal, PhysAddr, VirtAddr, 18*26d84a31SYJwu2023 }; 19*26d84a31SYJwu2023 20*26d84a31SYJwu2023 /// The PCI vendor ID for VirtIO devices. 21*26d84a31SYJwu2023 /// PCI Virtio设备的vendor ID 22*26d84a31SYJwu2023 const VIRTIO_VENDOR_ID: u16 = 0x1af4; 23*26d84a31SYJwu2023 24*26d84a31SYJwu2023 /// The offset to add to a VirtIO device ID to get the corresponding PCI device ID. 25*26d84a31SYJwu2023 /// PCI Virtio设备的DEVICE_ID 的offset 26*26d84a31SYJwu2023 const PCI_DEVICE_ID_OFFSET: u16 = 0x1040; 27*26d84a31SYJwu2023 /// PCI Virtio 设备的DEVICE_ID及其对应的设备类型 28*26d84a31SYJwu2023 const TRANSITIONAL_NETWORK: u16 = 0x1000; 29*26d84a31SYJwu2023 const TRANSITIONAL_BLOCK: u16 = 0x1001; 30*26d84a31SYJwu2023 const TRANSITIONAL_MEMORY_BALLOONING: u16 = 0x1002; 31*26d84a31SYJwu2023 const TRANSITIONAL_CONSOLE: u16 = 0x1003; 32*26d84a31SYJwu2023 const TRANSITIONAL_SCSI_HOST: u16 = 0x1004; 33*26d84a31SYJwu2023 const TRANSITIONAL_ENTROPY_SOURCE: u16 = 0x1005; 34*26d84a31SYJwu2023 const TRANSITIONAL_9P_TRANSPORT: u16 = 0x1009; 35*26d84a31SYJwu2023 36*26d84a31SYJwu2023 /// The offset of the bar field within `virtio_pci_cap`. 37*26d84a31SYJwu2023 const CAP_BAR_OFFSET: u8 = 4; 38*26d84a31SYJwu2023 /// The offset of the offset field with `virtio_pci_cap`. 39*26d84a31SYJwu2023 const CAP_BAR_OFFSET_OFFSET: u8 = 8; 40*26d84a31SYJwu2023 /// The offset of the `length` field within `virtio_pci_cap`. 41*26d84a31SYJwu2023 const CAP_LENGTH_OFFSET: u8 = 12; 42*26d84a31SYJwu2023 /// The offset of the`notify_off_multiplier` field within `virtio_pci_notify_cap`. 43*26d84a31SYJwu2023 const CAP_NOTIFY_OFF_MULTIPLIER_OFFSET: u8 = 16; 44*26d84a31SYJwu2023 45*26d84a31SYJwu2023 /// Common configuration. 46*26d84a31SYJwu2023 const VIRTIO_PCI_CAP_COMMON_CFG: u8 = 1; 47*26d84a31SYJwu2023 /// Notifications. 48*26d84a31SYJwu2023 const VIRTIO_PCI_CAP_NOTIFY_CFG: u8 = 2; 49*26d84a31SYJwu2023 /// ISR Status. 50*26d84a31SYJwu2023 const VIRTIO_PCI_CAP_ISR_CFG: u8 = 3; 51*26d84a31SYJwu2023 /// Device specific configuration. 52*26d84a31SYJwu2023 const VIRTIO_PCI_CAP_DEVICE_CFG: u8 = 4; 53*26d84a31SYJwu2023 54*26d84a31SYJwu2023 ///@brief device id 转换为设备类型 55*26d84a31SYJwu2023 ///@param pci_device_id,device_id 56*26d84a31SYJwu2023 ///@return DeviceType 对应的设备类型 57*26d84a31SYJwu2023 fn device_type(pci_device_id: u16) -> DeviceType { 58*26d84a31SYJwu2023 match pci_device_id { 59*26d84a31SYJwu2023 TRANSITIONAL_NETWORK => DeviceType::Network, 60*26d84a31SYJwu2023 TRANSITIONAL_BLOCK => DeviceType::Block, 61*26d84a31SYJwu2023 TRANSITIONAL_MEMORY_BALLOONING => DeviceType::MemoryBalloon, 62*26d84a31SYJwu2023 TRANSITIONAL_CONSOLE => DeviceType::Console, 63*26d84a31SYJwu2023 TRANSITIONAL_SCSI_HOST => DeviceType::ScsiHost, 64*26d84a31SYJwu2023 TRANSITIONAL_ENTROPY_SOURCE => DeviceType::EntropySource, 65*26d84a31SYJwu2023 TRANSITIONAL_9P_TRANSPORT => DeviceType::_9P, 66*26d84a31SYJwu2023 id if id >= PCI_DEVICE_ID_OFFSET => DeviceType::from(id - PCI_DEVICE_ID_OFFSET), 67*26d84a31SYJwu2023 _ => DeviceType::Invalid, 68*26d84a31SYJwu2023 } 69*26d84a31SYJwu2023 } 70*26d84a31SYJwu2023 71*26d84a31SYJwu2023 /// PCI transport for VirtIO. 72*26d84a31SYJwu2023 /// 73*26d84a31SYJwu2023 /// Ref: 4.1 Virtio Over PCI Bus 74*26d84a31SYJwu2023 #[derive(Debug)] 75*26d84a31SYJwu2023 pub struct PciTransport { 76*26d84a31SYJwu2023 device_type: DeviceType, 77*26d84a31SYJwu2023 /// The bus, device and function identifier for the VirtIO device. 78*26d84a31SYJwu2023 device_function: DeviceFunction, 79*26d84a31SYJwu2023 /// The common configuration structure within some BAR. 80*26d84a31SYJwu2023 common_cfg: NonNull<CommonCfg>, 81*26d84a31SYJwu2023 /// The start of the queue notification region within some BAR. 82*26d84a31SYJwu2023 notify_region: NonNull<[WriteOnly<u16>]>, 83*26d84a31SYJwu2023 notify_off_multiplier: u32, 84*26d84a31SYJwu2023 /// The ISR status register within some BAR. 85*26d84a31SYJwu2023 isr_status: NonNull<Volatile<u8>>, 86*26d84a31SYJwu2023 /// The VirtIO device-specific configuration within some BAR. 87*26d84a31SYJwu2023 config_space: Option<NonNull<[u32]>>, 88*26d84a31SYJwu2023 } 89*26d84a31SYJwu2023 90*26d84a31SYJwu2023 impl PciTransport { 91*26d84a31SYJwu2023 /// Construct a new PCI VirtIO device driver for the given device function on the given PCI 92*26d84a31SYJwu2023 /// root controller. 93*26d84a31SYJwu2023 /// 94*26d84a31SYJwu2023 /// The PCI device must already have had its BARs allocated. 95*26d84a31SYJwu2023 pub fn new<H: Hal>(device_function: DeviceFunction) -> Result<Self, VirtioPciError> { 96*26d84a31SYJwu2023 let device_vendor = unsafe { 97*26d84a31SYJwu2023 let bar_temp = pci_read_config( 98*26d84a31SYJwu2023 device_function.bus, 99*26d84a31SYJwu2023 device_function.device, 100*26d84a31SYJwu2023 device_function.function, 101*26d84a31SYJwu2023 0, 102*26d84a31SYJwu2023 ); 103*26d84a31SYJwu2023 bar_temp 104*26d84a31SYJwu2023 }; 105*26d84a31SYJwu2023 let device_id = (device_vendor >> 16) as u16; 106*26d84a31SYJwu2023 let vendor_id = device_vendor as u16; 107*26d84a31SYJwu2023 if vendor_id != VIRTIO_VENDOR_ID { 108*26d84a31SYJwu2023 return Err(VirtioPciError::InvalidVendorId(vendor_id)); 109*26d84a31SYJwu2023 } 110*26d84a31SYJwu2023 let device_type = device_type(device_id); 111*26d84a31SYJwu2023 // Find the PCI capabilities we need. 112*26d84a31SYJwu2023 let mut common_cfg = None; 113*26d84a31SYJwu2023 let mut notify_cfg = None; 114*26d84a31SYJwu2023 let mut notify_off_multiplier = 0; 115*26d84a31SYJwu2023 let mut isr_cfg = None; 116*26d84a31SYJwu2023 let mut device_cfg = None; 117*26d84a31SYJwu2023 //device_capability为迭代器,遍历其相当于遍历所有的cap空间 118*26d84a31SYJwu2023 let device_capability = CapabilityIterator { 119*26d84a31SYJwu2023 device_function: device_function, 120*26d84a31SYJwu2023 next_capability_offset: capabilities_offset(device_function), 121*26d84a31SYJwu2023 }; 122*26d84a31SYJwu2023 let device_bar = pci_bar_init(device_function)?; 123*26d84a31SYJwu2023 124*26d84a31SYJwu2023 for capability in device_capability { 125*26d84a31SYJwu2023 if capability.id != PCI_CAP_ID_VNDR { 126*26d84a31SYJwu2023 continue; 127*26d84a31SYJwu2023 } 128*26d84a31SYJwu2023 let cap_len = capability.private_header as u8; 129*26d84a31SYJwu2023 let cfg_type = (capability.private_header >> 8) as u8; 130*26d84a31SYJwu2023 if cap_len < 16 { 131*26d84a31SYJwu2023 continue; 132*26d84a31SYJwu2023 } 133*26d84a31SYJwu2023 let struct_info = VirtioCapabilityInfo { 134*26d84a31SYJwu2023 bar: unsafe { 135*26d84a31SYJwu2023 let temp = pci_read_config( 136*26d84a31SYJwu2023 device_function.bus, 137*26d84a31SYJwu2023 device_function.device, 138*26d84a31SYJwu2023 device_function.function, 139*26d84a31SYJwu2023 capability.offset + CAP_BAR_OFFSET, 140*26d84a31SYJwu2023 ); 141*26d84a31SYJwu2023 temp as u8 142*26d84a31SYJwu2023 }, 143*26d84a31SYJwu2023 offset: unsafe { 144*26d84a31SYJwu2023 let temp = pci_read_config( 145*26d84a31SYJwu2023 device_function.bus, 146*26d84a31SYJwu2023 device_function.device, 147*26d84a31SYJwu2023 device_function.function, 148*26d84a31SYJwu2023 capability.offset + CAP_BAR_OFFSET_OFFSET, 149*26d84a31SYJwu2023 ); 150*26d84a31SYJwu2023 temp 151*26d84a31SYJwu2023 }, 152*26d84a31SYJwu2023 length: unsafe { 153*26d84a31SYJwu2023 let temp = pci_read_config( 154*26d84a31SYJwu2023 device_function.bus, 155*26d84a31SYJwu2023 device_function.device, 156*26d84a31SYJwu2023 device_function.function, 157*26d84a31SYJwu2023 capability.offset + CAP_LENGTH_OFFSET, 158*26d84a31SYJwu2023 ); 159*26d84a31SYJwu2023 temp 160*26d84a31SYJwu2023 }, 161*26d84a31SYJwu2023 }; 162*26d84a31SYJwu2023 163*26d84a31SYJwu2023 match cfg_type { 164*26d84a31SYJwu2023 VIRTIO_PCI_CAP_COMMON_CFG if common_cfg.is_none() => { 165*26d84a31SYJwu2023 common_cfg = Some(struct_info); 166*26d84a31SYJwu2023 } 167*26d84a31SYJwu2023 VIRTIO_PCI_CAP_NOTIFY_CFG if cap_len >= 20 && notify_cfg.is_none() => { 168*26d84a31SYJwu2023 notify_cfg = Some(struct_info); 169*26d84a31SYJwu2023 notify_off_multiplier = unsafe { 170*26d84a31SYJwu2023 let temp = pci_read_config( 171*26d84a31SYJwu2023 device_function.bus, 172*26d84a31SYJwu2023 device_function.device, 173*26d84a31SYJwu2023 device_function.function, 174*26d84a31SYJwu2023 capability.offset + CAP_NOTIFY_OFF_MULTIPLIER_OFFSET, 175*26d84a31SYJwu2023 ); 176*26d84a31SYJwu2023 temp 177*26d84a31SYJwu2023 }; 178*26d84a31SYJwu2023 } 179*26d84a31SYJwu2023 VIRTIO_PCI_CAP_ISR_CFG if isr_cfg.is_none() => { 180*26d84a31SYJwu2023 isr_cfg = Some(struct_info); 181*26d84a31SYJwu2023 } 182*26d84a31SYJwu2023 VIRTIO_PCI_CAP_DEVICE_CFG if device_cfg.is_none() => { 183*26d84a31SYJwu2023 device_cfg = Some(struct_info); 184*26d84a31SYJwu2023 } 185*26d84a31SYJwu2023 _ => {} 186*26d84a31SYJwu2023 } 187*26d84a31SYJwu2023 } 188*26d84a31SYJwu2023 189*26d84a31SYJwu2023 let common_cfg = get_bar_region::<_>( 190*26d84a31SYJwu2023 &device_bar, 191*26d84a31SYJwu2023 &common_cfg.ok_or(VirtioPciError::MissingCommonConfig)?, 192*26d84a31SYJwu2023 )?; 193*26d84a31SYJwu2023 194*26d84a31SYJwu2023 let notify_cfg = notify_cfg.ok_or(VirtioPciError::MissingNotifyConfig)?; 195*26d84a31SYJwu2023 if notify_off_multiplier % 2 != 0 { 196*26d84a31SYJwu2023 return Err(VirtioPciError::InvalidNotifyOffMultiplier( 197*26d84a31SYJwu2023 notify_off_multiplier, 198*26d84a31SYJwu2023 )); 199*26d84a31SYJwu2023 } 200*26d84a31SYJwu2023 let notify_region = get_bar_region_slice::<_>(&device_bar, ¬ify_cfg)?; 201*26d84a31SYJwu2023 let isr_status = get_bar_region::<_>( 202*26d84a31SYJwu2023 &device_bar, 203*26d84a31SYJwu2023 &isr_cfg.ok_or(VirtioPciError::MissingIsrConfig)?, 204*26d84a31SYJwu2023 )?; 205*26d84a31SYJwu2023 let config_space = if let Some(device_cfg) = device_cfg { 206*26d84a31SYJwu2023 Some(get_bar_region_slice::<_>(&device_bar, &device_cfg)?) 207*26d84a31SYJwu2023 } else { 208*26d84a31SYJwu2023 None 209*26d84a31SYJwu2023 }; 210*26d84a31SYJwu2023 Ok(Self { 211*26d84a31SYJwu2023 device_type, 212*26d84a31SYJwu2023 device_function, 213*26d84a31SYJwu2023 common_cfg, 214*26d84a31SYJwu2023 notify_region, 215*26d84a31SYJwu2023 notify_off_multiplier, 216*26d84a31SYJwu2023 isr_status, 217*26d84a31SYJwu2023 config_space, 218*26d84a31SYJwu2023 }) 219*26d84a31SYJwu2023 } 220*26d84a31SYJwu2023 } 221*26d84a31SYJwu2023 222*26d84a31SYJwu2023 impl Transport for PciTransport { 223*26d84a31SYJwu2023 fn device_type(&self) -> DeviceType { 224*26d84a31SYJwu2023 self.device_type 225*26d84a31SYJwu2023 } 226*26d84a31SYJwu2023 227*26d84a31SYJwu2023 fn read_device_features(&mut self) -> u64 { 228*26d84a31SYJwu2023 // Safe because the common config pointer is valid and we checked in get_bar_region that it 229*26d84a31SYJwu2023 // was aligned. 230*26d84a31SYJwu2023 unsafe { 231*26d84a31SYJwu2023 volwrite!(self.common_cfg, device_feature_select, 0); 232*26d84a31SYJwu2023 let mut device_features_bits = volread!(self.common_cfg, device_feature) as u64; 233*26d84a31SYJwu2023 volwrite!(self.common_cfg, device_feature_select, 1); 234*26d84a31SYJwu2023 device_features_bits |= (volread!(self.common_cfg, device_feature) as u64) << 32; 235*26d84a31SYJwu2023 device_features_bits 236*26d84a31SYJwu2023 } 237*26d84a31SYJwu2023 } 238*26d84a31SYJwu2023 239*26d84a31SYJwu2023 fn write_driver_features(&mut self, driver_features: u64) { 240*26d84a31SYJwu2023 // Safe because the common config pointer is valid and we checked in get_bar_region that it 241*26d84a31SYJwu2023 // was aligned. 242*26d84a31SYJwu2023 unsafe { 243*26d84a31SYJwu2023 volwrite!(self.common_cfg, driver_feature_select, 0); 244*26d84a31SYJwu2023 volwrite!(self.common_cfg, driver_feature, driver_features as u32); 245*26d84a31SYJwu2023 volwrite!(self.common_cfg, driver_feature_select, 1); 246*26d84a31SYJwu2023 volwrite!( 247*26d84a31SYJwu2023 self.common_cfg, 248*26d84a31SYJwu2023 driver_feature, 249*26d84a31SYJwu2023 (driver_features >> 32) as u32 250*26d84a31SYJwu2023 ); 251*26d84a31SYJwu2023 } 252*26d84a31SYJwu2023 } 253*26d84a31SYJwu2023 254*26d84a31SYJwu2023 fn max_queue_size(&self) -> u32 { 255*26d84a31SYJwu2023 // Safe because the common config pointer is valid and we checked in get_bar_region that it 256*26d84a31SYJwu2023 // was aligned. 257*26d84a31SYJwu2023 unsafe { volread!(self.common_cfg, queue_size) }.into() 258*26d84a31SYJwu2023 } 259*26d84a31SYJwu2023 260*26d84a31SYJwu2023 fn notify(&mut self, queue: u16) { 261*26d84a31SYJwu2023 // Safe because the common config and notify region pointers are valid and we checked in 262*26d84a31SYJwu2023 // get_bar_region that they were aligned. 263*26d84a31SYJwu2023 unsafe { 264*26d84a31SYJwu2023 volwrite!(self.common_cfg, queue_select, queue); 265*26d84a31SYJwu2023 // TODO: Consider caching this somewhere (per queue). 266*26d84a31SYJwu2023 let queue_notify_off = volread!(self.common_cfg, queue_notify_off); 267*26d84a31SYJwu2023 268*26d84a31SYJwu2023 let offset_bytes = usize::from(queue_notify_off) * self.notify_off_multiplier as usize; 269*26d84a31SYJwu2023 let index = offset_bytes / size_of::<u16>(); 270*26d84a31SYJwu2023 addr_of_mut!((*self.notify_region.as_ptr())[index]).vwrite(queue); 271*26d84a31SYJwu2023 } 272*26d84a31SYJwu2023 } 273*26d84a31SYJwu2023 274*26d84a31SYJwu2023 fn set_status(&mut self, status: DeviceStatus) { 275*26d84a31SYJwu2023 // Safe because the common config pointer is valid and we checked in get_bar_region that it 276*26d84a31SYJwu2023 // was aligned. 277*26d84a31SYJwu2023 unsafe { 278*26d84a31SYJwu2023 volwrite!(self.common_cfg, device_status, status.bits() as u8); 279*26d84a31SYJwu2023 } 280*26d84a31SYJwu2023 } 281*26d84a31SYJwu2023 282*26d84a31SYJwu2023 fn set_guest_page_size(&mut self, _guest_page_size: u32) { 283*26d84a31SYJwu2023 // No-op, the PCI transport doesn't care. 284*26d84a31SYJwu2023 } 285*26d84a31SYJwu2023 286*26d84a31SYJwu2023 fn queue_set( 287*26d84a31SYJwu2023 &mut self, 288*26d84a31SYJwu2023 queue: u16, 289*26d84a31SYJwu2023 size: u32, 290*26d84a31SYJwu2023 descriptors: PhysAddr, 291*26d84a31SYJwu2023 driver_area: PhysAddr, 292*26d84a31SYJwu2023 device_area: PhysAddr, 293*26d84a31SYJwu2023 ) { 294*26d84a31SYJwu2023 // Safe because the common config pointer is valid and we checked in get_bar_region that it 295*26d84a31SYJwu2023 // was aligned. 296*26d84a31SYJwu2023 unsafe { 297*26d84a31SYJwu2023 volwrite!(self.common_cfg, queue_select, queue); 298*26d84a31SYJwu2023 volwrite!(self.common_cfg, queue_size, size as u16); 299*26d84a31SYJwu2023 volwrite!(self.common_cfg, queue_desc, descriptors as u64); 300*26d84a31SYJwu2023 volwrite!(self.common_cfg, queue_driver, driver_area as u64); 301*26d84a31SYJwu2023 volwrite!(self.common_cfg, queue_device, device_area as u64); 302*26d84a31SYJwu2023 volwrite!(self.common_cfg, queue_enable, 1); 303*26d84a31SYJwu2023 } 304*26d84a31SYJwu2023 } 305*26d84a31SYJwu2023 306*26d84a31SYJwu2023 fn queue_unset(&mut self, queue: u16) { 307*26d84a31SYJwu2023 // Safe because the common config pointer is valid and we checked in get_bar_region that it 308*26d84a31SYJwu2023 // was aligned. 309*26d84a31SYJwu2023 unsafe { 310*26d84a31SYJwu2023 volwrite!(self.common_cfg, queue_enable, 0); 311*26d84a31SYJwu2023 volwrite!(self.common_cfg, queue_select, queue); 312*26d84a31SYJwu2023 volwrite!(self.common_cfg, queue_size, 0); 313*26d84a31SYJwu2023 volwrite!(self.common_cfg, queue_desc, 0); 314*26d84a31SYJwu2023 volwrite!(self.common_cfg, queue_driver, 0); 315*26d84a31SYJwu2023 volwrite!(self.common_cfg, queue_device, 0); 316*26d84a31SYJwu2023 } 317*26d84a31SYJwu2023 } 318*26d84a31SYJwu2023 319*26d84a31SYJwu2023 fn queue_used(&mut self, queue: u16) -> bool { 320*26d84a31SYJwu2023 // Safe because the common config pointer is valid and we checked in get_bar_region that it 321*26d84a31SYJwu2023 // was aligned. 322*26d84a31SYJwu2023 unsafe { 323*26d84a31SYJwu2023 volwrite!(self.common_cfg, queue_select, queue); 324*26d84a31SYJwu2023 volread!(self.common_cfg, queue_enable) == 1 325*26d84a31SYJwu2023 } 326*26d84a31SYJwu2023 } 327*26d84a31SYJwu2023 328*26d84a31SYJwu2023 fn ack_interrupt(&mut self) -> bool { 329*26d84a31SYJwu2023 // Safe because the common config pointer is valid and we checked in get_bar_region that it 330*26d84a31SYJwu2023 // was aligned. 331*26d84a31SYJwu2023 // Reading the ISR status resets it to 0 and causes the device to de-assert the interrupt. 332*26d84a31SYJwu2023 let isr_status = unsafe { self.isr_status.as_ptr().vread() }; 333*26d84a31SYJwu2023 // TODO: Distinguish between queue interrupt and device configuration interrupt. 334*26d84a31SYJwu2023 isr_status & 0x3 != 0 335*26d84a31SYJwu2023 } 336*26d84a31SYJwu2023 337*26d84a31SYJwu2023 fn config_space<T>(&self) -> Result<NonNull<T>, Error> { 338*26d84a31SYJwu2023 if let Some(config_space) = self.config_space { 339*26d84a31SYJwu2023 if size_of::<T>() > config_space.len() * size_of::<u32>() { 340*26d84a31SYJwu2023 Err(Error::ConfigSpaceTooSmall) 341*26d84a31SYJwu2023 } else if align_of::<T>() > 4 { 342*26d84a31SYJwu2023 // Panic as this should only happen if the driver is written incorrectly. 343*26d84a31SYJwu2023 panic!( 344*26d84a31SYJwu2023 "Driver expected config space alignment of {} bytes, but VirtIO only guarantees 4 byte alignment.", 345*26d84a31SYJwu2023 align_of::<T>() 346*26d84a31SYJwu2023 ); 347*26d84a31SYJwu2023 } else { 348*26d84a31SYJwu2023 // TODO: Use NonNull::as_non_null_ptr once it is stable. 349*26d84a31SYJwu2023 let config_space_ptr = NonNull::new(config_space.as_ptr() as *mut u32).unwrap(); 350*26d84a31SYJwu2023 Ok(config_space_ptr.cast()) 351*26d84a31SYJwu2023 } 352*26d84a31SYJwu2023 } else { 353*26d84a31SYJwu2023 Err(Error::ConfigSpaceMissing) 354*26d84a31SYJwu2023 } 355*26d84a31SYJwu2023 } 356*26d84a31SYJwu2023 } 357*26d84a31SYJwu2023 358*26d84a31SYJwu2023 /// `virtio_pci_common_cfg`, see 4.1.4.3 "Common configuration structure layout". 359*26d84a31SYJwu2023 /// 360*26d84a31SYJwu2023 #[repr(C)] 361*26d84a31SYJwu2023 struct CommonCfg { 362*26d84a31SYJwu2023 device_feature_select: Volatile<u32>, 363*26d84a31SYJwu2023 device_feature: ReadOnly<u32>, 364*26d84a31SYJwu2023 driver_feature_select: Volatile<u32>, 365*26d84a31SYJwu2023 driver_feature: Volatile<u32>, 366*26d84a31SYJwu2023 msix_config: Volatile<u16>, 367*26d84a31SYJwu2023 num_queues: ReadOnly<u16>, 368*26d84a31SYJwu2023 device_status: Volatile<u8>, 369*26d84a31SYJwu2023 config_generation: ReadOnly<u8>, 370*26d84a31SYJwu2023 queue_select: Volatile<u16>, 371*26d84a31SYJwu2023 queue_size: Volatile<u16>, 372*26d84a31SYJwu2023 queue_msix_vector: Volatile<u16>, 373*26d84a31SYJwu2023 queue_enable: Volatile<u16>, 374*26d84a31SYJwu2023 queue_notify_off: Volatile<u16>, 375*26d84a31SYJwu2023 queue_desc: Volatile<u64>, 376*26d84a31SYJwu2023 queue_driver: Volatile<u64>, 377*26d84a31SYJwu2023 queue_device: Volatile<u64>, 378*26d84a31SYJwu2023 } 379*26d84a31SYJwu2023 380*26d84a31SYJwu2023 /// Information about a VirtIO structure within some BAR, as provided by a `virtio_pci_cap`. 381*26d84a31SYJwu2023 ///cfg空间在哪个bar的多少偏移处,长度多少 382*26d84a31SYJwu2023 #[derive(Clone, Debug, Eq, PartialEq)] 383*26d84a31SYJwu2023 struct VirtioCapabilityInfo { 384*26d84a31SYJwu2023 /// The bar in which the structure can be found. 385*26d84a31SYJwu2023 bar: u8, 386*26d84a31SYJwu2023 /// The offset within the bar. 387*26d84a31SYJwu2023 offset: u32, 388*26d84a31SYJwu2023 /// The length in bytes of the structure within the bar. 389*26d84a31SYJwu2023 length: u32, 390*26d84a31SYJwu2023 } 391*26d84a31SYJwu2023 392*26d84a31SYJwu2023 /// An error encountered initialising a VirtIO PCI transport. 393*26d84a31SYJwu2023 /// VirtIO PCI transport 初始化时的错误 394*26d84a31SYJwu2023 #[derive(Clone, Debug, Eq, PartialEq)] 395*26d84a31SYJwu2023 pub enum VirtioPciError { 396*26d84a31SYJwu2023 /// PCI device vender ID was not the VirtIO vendor ID. 397*26d84a31SYJwu2023 InvalidVendorId(u16), 398*26d84a31SYJwu2023 /// No valid `VIRTIO_PCI_CAP_COMMON_CFG` capability was found. 399*26d84a31SYJwu2023 MissingCommonConfig, 400*26d84a31SYJwu2023 /// No valid `VIRTIO_PCI_CAP_NOTIFY_CFG` capability was found. 401*26d84a31SYJwu2023 MissingNotifyConfig, 402*26d84a31SYJwu2023 /// `VIRTIO_PCI_CAP_NOTIFY_CFG` capability has a `notify_off_multiplier` that is not a multiple 403*26d84a31SYJwu2023 /// of 2. 404*26d84a31SYJwu2023 InvalidNotifyOffMultiplier(u32), 405*26d84a31SYJwu2023 /// No valid `VIRTIO_PCI_CAP_ISR_CFG` capability was found. 406*26d84a31SYJwu2023 MissingIsrConfig, 407*26d84a31SYJwu2023 /// An IO BAR was provided rather than a memory BAR. 408*26d84a31SYJwu2023 UnexpectedBarType, 409*26d84a31SYJwu2023 /// A BAR which we need was not allocated an address. 410*26d84a31SYJwu2023 BarNotAllocated(u8), 411*26d84a31SYJwu2023 /// The offset for some capability was greater than the length of the BAR. 412*26d84a31SYJwu2023 BarOffsetOutOfRange, 413*26d84a31SYJwu2023 /// The virtual address was not aligned as expected. 414*26d84a31SYJwu2023 Misaligned { 415*26d84a31SYJwu2023 /// The virtual address in question. 416*26d84a31SYJwu2023 vaddr: VirtAddr, 417*26d84a31SYJwu2023 /// The expected alignment in bytes. 418*26d84a31SYJwu2023 alignment: usize, 419*26d84a31SYJwu2023 }, 420*26d84a31SYJwu2023 ///获取虚拟地址失败 421*26d84a31SYJwu2023 BarGetVaddrFailed, 422*26d84a31SYJwu2023 /// A generic PCI error, 423*26d84a31SYJwu2023 Pci(PciError), 424*26d84a31SYJwu2023 } 425*26d84a31SYJwu2023 426*26d84a31SYJwu2023 impl Display for VirtioPciError { 427*26d84a31SYJwu2023 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 428*26d84a31SYJwu2023 match self { 429*26d84a31SYJwu2023 Self::InvalidVendorId(vendor_id) => write!( 430*26d84a31SYJwu2023 f, 431*26d84a31SYJwu2023 "PCI device vender ID {:#06x} was not the VirtIO vendor ID {:#06x}.", 432*26d84a31SYJwu2023 vendor_id, VIRTIO_VENDOR_ID 433*26d84a31SYJwu2023 ), 434*26d84a31SYJwu2023 Self::MissingCommonConfig => write!( 435*26d84a31SYJwu2023 f, 436*26d84a31SYJwu2023 "No valid `VIRTIO_PCI_CAP_COMMON_CFG` capability was found." 437*26d84a31SYJwu2023 ), 438*26d84a31SYJwu2023 Self::MissingNotifyConfig => write!( 439*26d84a31SYJwu2023 f, 440*26d84a31SYJwu2023 "No valid `VIRTIO_PCI_CAP_NOTIFY_CFG` capability was found." 441*26d84a31SYJwu2023 ), 442*26d84a31SYJwu2023 Self::InvalidNotifyOffMultiplier(notify_off_multiplier) => { 443*26d84a31SYJwu2023 write!( 444*26d84a31SYJwu2023 f, 445*26d84a31SYJwu2023 "`VIRTIO_PCI_CAP_NOTIFY_CFG` capability has a `notify_off_multiplier` that is not a multiple of 2: {}", 446*26d84a31SYJwu2023 notify_off_multiplier 447*26d84a31SYJwu2023 ) 448*26d84a31SYJwu2023 } 449*26d84a31SYJwu2023 Self::MissingIsrConfig => { 450*26d84a31SYJwu2023 write!(f, "No valid `VIRTIO_PCI_CAP_ISR_CFG` capability was found.") 451*26d84a31SYJwu2023 } 452*26d84a31SYJwu2023 Self::UnexpectedBarType => write!(f, "Unexpected BAR (expected memory BAR)."), 453*26d84a31SYJwu2023 Self::BarNotAllocated(bar_index) => write!(f, "Bar {} not allocated.", bar_index), 454*26d84a31SYJwu2023 Self::BarOffsetOutOfRange => write!(f, "Capability offset greater than BAR length."), 455*26d84a31SYJwu2023 Self::Misaligned { vaddr, alignment } => write!( 456*26d84a31SYJwu2023 f, 457*26d84a31SYJwu2023 "Virtual address {:#018x} was not aligned to a {} byte boundary as expected.", 458*26d84a31SYJwu2023 vaddr, alignment 459*26d84a31SYJwu2023 ), 460*26d84a31SYJwu2023 Self::BarGetVaddrFailed => write!(f, "Get bar virtaddress failed"), 461*26d84a31SYJwu2023 Self::Pci(pci_error) => pci_error.fmt(f), 462*26d84a31SYJwu2023 } 463*26d84a31SYJwu2023 } 464*26d84a31SYJwu2023 } 465*26d84a31SYJwu2023 ///PCI error到VirtioPciError的转换,层层上报 466*26d84a31SYJwu2023 impl From<PciError> for VirtioPciError { 467*26d84a31SYJwu2023 fn from(error: PciError) -> Self { 468*26d84a31SYJwu2023 Self::Pci(error) 469*26d84a31SYJwu2023 } 470*26d84a31SYJwu2023 } 471*26d84a31SYJwu2023 472*26d84a31SYJwu2023 ///@brief 获取虚拟地址并将其转化为对应类型的指针 473*26d84a31SYJwu2023 ///@param device_bar 存储bar信息的结构体 struct_info 存储cfg空间的位置信息 474*26d84a31SYJwu2023 ///@return Result<NonNull<T>, VirtioPciError> 成功则返回对应类型的指针,失败则返回Error 475*26d84a31SYJwu2023 fn get_bar_region<T>( 476*26d84a31SYJwu2023 device_bar: &PciDeviceBar, 477*26d84a31SYJwu2023 struct_info: &VirtioCapabilityInfo, 478*26d84a31SYJwu2023 ) -> Result<NonNull<T>, VirtioPciError> { 479*26d84a31SYJwu2023 let bar_info = device_bar.get_bar(struct_info.bar)?; 480*26d84a31SYJwu2023 let (bar_address, bar_size) = bar_info 481*26d84a31SYJwu2023 .memory_address_size() 482*26d84a31SYJwu2023 .ok_or(VirtioPciError::UnexpectedBarType)?; 483*26d84a31SYJwu2023 if bar_address == 0 { 484*26d84a31SYJwu2023 return Err(VirtioPciError::BarNotAllocated(struct_info.bar)); 485*26d84a31SYJwu2023 } 486*26d84a31SYJwu2023 if struct_info.offset + struct_info.length > bar_size 487*26d84a31SYJwu2023 || size_of::<T>() > struct_info.length as usize 488*26d84a31SYJwu2023 { 489*26d84a31SYJwu2023 return Err(VirtioPciError::BarOffsetOutOfRange); 490*26d84a31SYJwu2023 } 491*26d84a31SYJwu2023 let vaddr = (bar_info 492*26d84a31SYJwu2023 .virtual_address() 493*26d84a31SYJwu2023 .ok_or(VirtioPciError::BarGetVaddrFailed)?) as usize 494*26d84a31SYJwu2023 + struct_info.offset as usize; 495*26d84a31SYJwu2023 if vaddr % align_of::<T>() != 0 { 496*26d84a31SYJwu2023 return Err(VirtioPciError::Misaligned { 497*26d84a31SYJwu2023 vaddr, 498*26d84a31SYJwu2023 alignment: align_of::<T>(), 499*26d84a31SYJwu2023 }); 500*26d84a31SYJwu2023 } 501*26d84a31SYJwu2023 Ok(NonNull::new((vaddr) as _).unwrap()) 502*26d84a31SYJwu2023 } 503*26d84a31SYJwu2023 504*26d84a31SYJwu2023 ///@brief 获取虚拟地址并将其转化为对应类型的指针 505*26d84a31SYJwu2023 ///@param device_bar 存储bar信息的结构体 struct_info 存储cfg空间的位置信息 506*26d84a31SYJwu2023 ///@return Result<NonNull<[T]>, VirtioPciError> 成功则返回对应类型的指针切片,失败则返回Error 507*26d84a31SYJwu2023 fn get_bar_region_slice<T>( 508*26d84a31SYJwu2023 device_bar: &PciDeviceBar, 509*26d84a31SYJwu2023 struct_info: &VirtioCapabilityInfo, 510*26d84a31SYJwu2023 ) -> Result<NonNull<[T]>, VirtioPciError> { 511*26d84a31SYJwu2023 let ptr = get_bar_region::<T>(device_bar, struct_info)?; 512*26d84a31SYJwu2023 let raw_slice = 513*26d84a31SYJwu2023 ptr::slice_from_raw_parts_mut(ptr.as_ptr(), struct_info.length as usize / size_of::<T>()); 514*26d84a31SYJwu2023 Ok(NonNull::new(raw_slice).unwrap()) 515*26d84a31SYJwu2023 } 516