1 // Copyright 2018 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use std::collections::BTreeMap; 6 use std::convert::TryFrom; 7 use std::convert::TryInto; 8 use std::sync::Arc; 9 10 use anyhow::bail; 11 use anyhow::Context; 12 use base::custom_serde::deserialize_seq_to_arr; 13 use base::custom_serde::serialize_arr; 14 use base::error; 15 use base::warn; 16 use base::MemoryMapping; 17 use base::MemoryMappingBuilder; 18 use base::SharedMemory; 19 use downcast_rs::impl_downcast; 20 use downcast_rs::Downcast; 21 use remain::sorted; 22 use serde::Deserialize; 23 use serde::Serialize; 24 use sync::Mutex; 25 use thiserror::Error; 26 27 use crate::pci::PciInterruptPin; 28 29 // The number of 32bit registers in the config space, 256 bytes. 30 const NUM_CONFIGURATION_REGISTERS: usize = 64; 31 32 pub const PCI_ID_REG: usize = 0; 33 pub const COMMAND_REG: usize = 1; 34 pub const COMMAND_REG_IO_SPACE_MASK: u32 = 0x0000_0001; 35 pub const COMMAND_REG_MEMORY_SPACE_MASK: u32 = 0x0000_0002; 36 const STATUS_REG: usize = 1; 37 pub const STATUS_REG_CAPABILITIES_USED_MASK: u32 = 0x0010_0000; 38 #[allow(dead_code)] 39 #[cfg(any(target_os = "android", target_os = "linux"))] 40 pub const CLASS_REG: usize = 2; 41 pub const HEADER_TYPE_REG: usize = 3; 42 pub const HEADER_TYPE_REG_OFFSET: usize = 2; 43 pub const HEADER_TYPE_MULTIFUNCTION_MASK: u8 = 0x80; 44 pub const BAR0_REG: usize = 4; 45 const BAR_IO_ADDR_MASK: u32 = 0xffff_fffc; 46 const BAR_IO_MIN_SIZE: u64 = 4; 47 const BAR_MEM_ADDR_MASK: u32 = 0xffff_fff0; 48 const BAR_MEM_MIN_SIZE: u64 = 16; 49 const BAR_ROM_MIN_SIZE: u64 = 2048; 50 pub const NUM_BAR_REGS: usize = 7; // 6 normal BARs + expansion ROM BAR. 51 pub const ROM_BAR_IDX: PciBarIndex = 6; 52 pub const ROM_BAR_REG: usize = 12; 53 pub const CAPABILITY_LIST_HEAD_OFFSET: usize = 0x34; 54 #[cfg(any(target_os = "android", target_os = "linux"))] 55 pub const PCI_CAP_NEXT_POINTER: usize = 0x1; 56 const FIRST_CAPABILITY_OFFSET: usize = 0x40; 57 pub const CAPABILITY_MAX_OFFSET: usize = 255; 58 59 const INTERRUPT_LINE_PIN_REG: usize = 15; 60 61 /// Represents the types of PCI headers allowed in the configuration registers. 62 #[allow(dead_code)] 63 #[derive(Copy, Clone)] 64 pub enum PciHeaderType { 65 Device, 66 Bridge, 67 } 68 69 /// Classes of PCI nodes. 70 #[allow(dead_code)] 71 #[derive(Copy, Clone, Debug, enumn::N, Serialize, Deserialize, PartialEq, Eq)] 72 pub enum PciClassCode { 73 TooOld, 74 MassStorage, 75 NetworkController, 76 DisplayController, 77 MultimediaController, 78 MemoryController, 79 BridgeDevice, 80 SimpleCommunicationController, 81 BaseSystemPeripheral, 82 InputDevice, 83 DockingStation, 84 Processor, 85 SerialBusController, 86 WirelessController, 87 IntelligentIoController, 88 SatelliteCommunicationController, 89 EncryptionController, 90 DataAcquisitionSignalProcessing, 91 ProcessingAccelerator, 92 NonEssentialInstrumentation, 93 Other = 0xff, 94 } 95 96 impl PciClassCode { get_register_value(&self) -> u897 pub fn get_register_value(&self) -> u8 { 98 *self as u8 99 } 100 } 101 102 #[sorted] 103 #[derive(Error, Debug)] 104 pub enum PciClassCodeParseError { 105 #[error("Unknown class code")] 106 Unknown, 107 } 108 109 impl TryFrom<u8> for PciClassCode { 110 type Error = PciClassCodeParseError; try_from(v: u8) -> std::result::Result<PciClassCode, PciClassCodeParseError>111 fn try_from(v: u8) -> std::result::Result<PciClassCode, PciClassCodeParseError> { 112 match PciClassCode::n(v) { 113 Some(class) => Ok(class), 114 None => Err(PciClassCodeParseError::Unknown), 115 } 116 } 117 } 118 119 /// A PCI sublcass. Each class in `PciClassCode` can specify a unique set of subclasses. This trait 120 /// is implemented by each subclass. It allows use of a trait object to generate configurations. 121 pub trait PciSubclass { 122 /// Convert this subclass to the value used in the PCI specification. get_register_value(&self) -> u8123 fn get_register_value(&self) -> u8; 124 } 125 126 /// Subclasses of the MassStorage class. 127 #[allow(dead_code)] 128 #[derive(Copy, Clone)] 129 pub enum PciMassStorageSubclass { 130 Scsi = 0x00, 131 NonVolatileMemory = 0x08, 132 Other = 0x80, 133 } 134 135 impl PciSubclass for PciMassStorageSubclass { get_register_value(&self) -> u8136 fn get_register_value(&self) -> u8 { 137 *self as u8 138 } 139 } 140 141 /// Subclasses of the NetworkController class. 142 #[allow(dead_code)] 143 #[derive(Copy, Clone)] 144 pub enum PciNetworkControllerSubclass { 145 Other = 0x80, 146 } 147 148 impl PciSubclass for PciNetworkControllerSubclass { get_register_value(&self) -> u8149 fn get_register_value(&self) -> u8 { 150 *self as u8 151 } 152 } 153 154 /// Subclasses of the DisplayController class. 155 #[allow(dead_code)] 156 #[derive(Copy, Clone)] 157 pub enum PciDisplaySubclass { 158 VgaCompatibleController = 0x00, 159 XgaCompatibleController = 0x01, 160 ThreeDController = 0x02, 161 Other = 0x80, 162 } 163 164 impl PciSubclass for PciDisplaySubclass { get_register_value(&self) -> u8165 fn get_register_value(&self) -> u8 { 166 *self as u8 167 } 168 } 169 170 /// Subclasses of the MultimediaController class. 171 #[allow(dead_code)] 172 #[derive(Copy, Clone)] 173 pub enum PciMultimediaSubclass { 174 VideoController = 0x00, 175 AudioController = 0x01, 176 TelephonyDevice = 0x02, 177 AudioDevice = 0x03, 178 Other = 0x80, 179 } 180 181 impl PciSubclass for PciMultimediaSubclass { get_register_value(&self) -> u8182 fn get_register_value(&self) -> u8 { 183 *self as u8 184 } 185 } 186 187 /// Subclasses of the BridgeDevice 188 #[allow(dead_code)] 189 #[derive(Copy, Clone)] 190 pub enum PciBridgeSubclass { 191 HostBridge = 0x00, 192 IsaBridge = 0x01, 193 EisaBridge = 0x02, 194 McaBridge = 0x03, 195 PciToPciBridge = 0x04, 196 PcmciaBridge = 0x05, 197 NuBusBridge = 0x06, 198 CardBusBridge = 0x07, 199 RaceWayBridge = 0x08, 200 PciToPciSemiTransparentBridge = 0x09, 201 InfiniBrandToPciHostBridge = 0x0a, 202 OtherBridgeDevice = 0x80, 203 } 204 205 impl PciSubclass for PciBridgeSubclass { get_register_value(&self) -> u8206 fn get_register_value(&self) -> u8 { 207 *self as u8 208 } 209 } 210 211 /// Subclasses of the SimpleCommunicationController class. 212 #[allow(dead_code)] 213 #[derive(Copy, Clone)] 214 pub enum PciSimpleCommunicationControllerSubclass { 215 Other = 0x80, 216 } 217 218 impl PciSubclass for PciSimpleCommunicationControllerSubclass { get_register_value(&self) -> u8219 fn get_register_value(&self) -> u8 { 220 *self as u8 221 } 222 } 223 224 /// Subclasses of the BaseSystemPeripheral class. 225 #[allow(dead_code)] 226 #[derive(Copy, Clone)] 227 pub enum PciBaseSystemPeripheralSubclass { 228 Iommu = 0x06, 229 Other = 0x80, 230 } 231 232 impl PciSubclass for PciBaseSystemPeripheralSubclass { get_register_value(&self) -> u8233 fn get_register_value(&self) -> u8 { 234 *self as u8 235 } 236 } 237 238 /// Subclasses of the InputDevice class. 239 #[allow(dead_code)] 240 #[derive(Copy, Clone)] 241 pub enum PciInputDeviceSubclass { 242 Other = 0x80, 243 } 244 245 impl PciSubclass for PciInputDeviceSubclass { get_register_value(&self) -> u8246 fn get_register_value(&self) -> u8 { 247 *self as u8 248 } 249 } 250 251 /// Subclass of the SerialBus 252 #[allow(dead_code)] 253 #[derive(Copy, Clone)] 254 pub enum PciSerialBusSubClass { 255 Firewire = 0x00, 256 AccessBus = 0x01, 257 Ssa = 0x02, 258 Usb = 0x03, 259 } 260 261 impl PciSubclass for PciSerialBusSubClass { get_register_value(&self) -> u8262 fn get_register_value(&self) -> u8 { 263 *self as u8 264 } 265 } 266 267 /// Subclasses of the WirelessController class. 268 #[allow(dead_code)] 269 #[derive(Copy, Clone)] 270 pub enum PciWirelessControllerSubclass { 271 Other = 0x80, 272 } 273 274 impl PciSubclass for PciWirelessControllerSubclass { get_register_value(&self) -> u8275 fn get_register_value(&self) -> u8 { 276 *self as u8 277 } 278 } 279 280 /// Subclasses for PciClassCode Other. 281 #[allow(dead_code)] 282 #[derive(Copy, Clone)] 283 #[repr(u8)] 284 pub enum PciOtherSubclass { 285 Other = 0xff, 286 } 287 288 impl PciSubclass for PciOtherSubclass { get_register_value(&self) -> u8289 fn get_register_value(&self) -> u8 { 290 *self as u8 291 } 292 } 293 294 /// A PCI class programming interface. Each combination of `PciClassCode` and 295 /// `PciSubclass` can specify a set of register-level programming interfaces. 296 /// This trait is implemented by each programming interface. 297 /// It allows use of a trait object to generate configurations. 298 pub trait PciProgrammingInterface { 299 /// Convert this programming interface to the value used in the PCI specification. get_register_value(&self) -> u8300 fn get_register_value(&self) -> u8; 301 } 302 303 /// Types of PCI capabilities. 304 pub enum PciCapabilityID { 305 ListID = 0, 306 PowerManagement = 0x01, 307 AcceleratedGraphicsPort = 0x02, 308 VitalProductData = 0x03, 309 SlotIdentification = 0x04, 310 MessageSignalledInterrupts = 0x05, 311 CompactPciHotSwap = 0x06, 312 Pcix = 0x07, 313 HyperTransport = 0x08, 314 VendorSpecific = 0x09, 315 Debugport = 0x0A, 316 CompactPciCentralResourceControl = 0x0B, 317 PciStandardHotPlugController = 0x0C, 318 BridgeSubsystemVendorDeviceID = 0x0D, 319 AgpTargetPciPciBridge = 0x0E, 320 SecureDevice = 0x0F, 321 PciExpress = 0x10, 322 Msix = 0x11, 323 SataDataIndexConf = 0x12, 324 PciAdvancedFeatures = 0x13, 325 PciEnhancedAllocation = 0x14, 326 } 327 328 /// A PCI capability list. Devices can optionally specify capabilities in their configuration space. 329 pub trait PciCapability { bytes(&self) -> &[u8]330 fn bytes(&self) -> &[u8]; id(&self) -> PciCapabilityID331 fn id(&self) -> PciCapabilityID; writable_bits(&self) -> Vec<u32>332 fn writable_bits(&self) -> Vec<u32>; 333 } 334 335 pub trait PciCapConfigWriteResult: Downcast {} 336 impl_downcast!(PciCapConfigWriteResult); 337 338 /// A trait for implementing complex PCI capabilities. 339 pub trait PciCapConfig: Send { 340 /// Reads a 32bit register from the capability. Only the bits set in the 341 /// read mask will be used, while the rest of the bits will be taken from 342 /// the `PciConfiguration`'s register data. 343 /// `reg_idx` - index into the capability read_reg(&self, reg_idx: usize) -> u32344 fn read_reg(&self, reg_idx: usize) -> u32; 345 346 /// Returns the read mask used by `read_reg`. read_mask(&self) -> &'static [u32]347 fn read_mask(&self) -> &'static [u32]; 348 349 /// Writes data to the capability. 350 /// `reg_idx` - index into PciConfiguration.registers. 351 /// `offset` - PciConfiguration.registers is in unit of DWord, offset define byte 352 /// offset in the DWord. 353 /// `data` - The data to write. write_reg( &mut self, reg_idx: usize, offset: u64, data: &[u8], ) -> Option<Box<dyn PciCapConfigWriteResult>>354 fn write_reg( 355 &mut self, 356 reg_idx: usize, 357 offset: u64, 358 data: &[u8], 359 ) -> Option<Box<dyn PciCapConfigWriteResult>>; 360 361 /// Used to pass the mmio region for the capability to the implementation. 362 /// If any external events update the capability's registers, then 363 /// `PciCapMapping.set_reg` must be called to make the changes visible 364 /// to the guest. set_cap_mapping(&mut self, _mapping: PciCapMapping)365 fn set_cap_mapping(&mut self, _mapping: PciCapMapping) {} 366 num_regs(&self) -> usize367 fn num_regs(&self) -> usize { 368 self.read_mask().len() 369 } 370 } 371 372 /// Contains the configuration space of a PCI node. 373 /// See the [specification](https://en.wikipedia.org/wiki/PCI_configuration_space). 374 /// The configuration space is accessed with DWORD reads and writes from the guest. 375 pub struct PciConfiguration { 376 registers: [u32; NUM_CONFIGURATION_REGISTERS], 377 writable_bits: [u32; NUM_CONFIGURATION_REGISTERS], // writable bits for each register. 378 bar_used: [bool; NUM_BAR_REGS], 379 bar_configs: [Option<PciBarConfiguration>; NUM_BAR_REGS], 380 // Contains the byte offset and size of the last capability. 381 last_capability: Option<(usize, usize)>, 382 capability_configs: BTreeMap<usize, Box<dyn PciCapConfig>>, 383 mmio_mapping: Option<(Arc<Mutex<MemoryMapping>>, usize)>, 384 } 385 386 #[derive(Serialize, Deserialize)] 387 pub struct PciConfigurationSerialized { 388 #[serde( 389 serialize_with = "serialize_arr", 390 deserialize_with = "deserialize_seq_to_arr" 391 )] 392 registers: [u32; NUM_CONFIGURATION_REGISTERS], 393 #[serde( 394 serialize_with = "serialize_arr", 395 deserialize_with = "deserialize_seq_to_arr" 396 )] 397 writable_bits: [u32; NUM_CONFIGURATION_REGISTERS], 398 bar_used: [bool; NUM_BAR_REGS], 399 bar_configs: [Option<PciBarConfiguration>; NUM_BAR_REGS], 400 last_capability: Option<(usize, usize)>, 401 } 402 403 /// See pci_regs.h in kernel 404 #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] 405 pub enum PciBarRegionType { 406 Memory32BitRegion = 0, 407 IoRegion = 0x01, 408 Memory64BitRegion = 0x04, 409 } 410 411 #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] 412 pub enum PciBarPrefetchable { 413 NotPrefetchable = 0, 414 Prefetchable = 0x08, 415 } 416 417 pub type PciBarIndex = usize; 418 419 #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] 420 pub struct PciBarConfiguration { 421 addr: u64, 422 size: u64, 423 bar_idx: PciBarIndex, 424 region_type: PciBarRegionType, 425 prefetchable: PciBarPrefetchable, 426 } 427 428 pub struct PciBarIter<'a> { 429 config: &'a PciConfiguration, 430 bar_num: PciBarIndex, 431 } 432 433 impl<'a> Iterator for PciBarIter<'a> { 434 type Item = PciBarConfiguration; 435 next(&mut self) -> Option<Self::Item>436 fn next(&mut self) -> Option<Self::Item> { 437 while self.bar_num < NUM_BAR_REGS { 438 let bar_config = self.config.get_bar_configuration(self.bar_num); 439 self.bar_num += 1; 440 if let Some(bar_config) = bar_config { 441 return Some(bar_config); 442 } 443 } 444 445 None 446 } 447 } 448 449 #[sorted] 450 #[derive(Error, Debug, PartialEq, Eq)] 451 pub enum Error { 452 #[error("address {0} size {1} too big")] 453 BarAddressInvalid(u64, u64), 454 #[error("address {0} is not aligned to size {1}")] 455 BarAlignmentInvalid(u64, u64), 456 #[error("bar {0} already used")] 457 BarInUse(PciBarIndex), 458 #[error("64bit bar {0} already used (requires two regs)")] 459 BarInUse64(PciBarIndex), 460 #[error("bar {0} invalid, max {}", NUM_BAR_REGS - 1)] 461 BarInvalid(PciBarIndex), 462 #[error("64bitbar {0} invalid, requires two regs, max {}", ROM_BAR_IDX - 1)] 463 BarInvalid64(PciBarIndex), 464 #[error("expansion rom bar must be a memory region")] 465 BarInvalidRomType, 466 #[error("bar address {0} not a power of two")] 467 BarSizeInvalid(u64), 468 #[error("empty capabilities are invalid")] 469 CapabilityEmpty, 470 #[error("Invalid capability length {0}")] 471 CapabilityLengthInvalid(usize), 472 #[error("capability of size {0} doesn't fit")] 473 CapabilitySpaceFull(usize), 474 } 475 476 pub type Result<T> = std::result::Result<T, Error>; 477 478 impl PciConfiguration { new( vendor_id: u16, device_id: u16, class_code: PciClassCode, subclass: &dyn PciSubclass, programming_interface: Option<&dyn PciProgrammingInterface>, header_type: PciHeaderType, subsystem_vendor_id: u16, subsystem_id: u16, revision_id: u8, ) -> Self479 pub fn new( 480 vendor_id: u16, 481 device_id: u16, 482 class_code: PciClassCode, 483 subclass: &dyn PciSubclass, 484 programming_interface: Option<&dyn PciProgrammingInterface>, 485 header_type: PciHeaderType, 486 subsystem_vendor_id: u16, 487 subsystem_id: u16, 488 revision_id: u8, 489 ) -> Self { 490 let mut registers = [0u32; NUM_CONFIGURATION_REGISTERS]; 491 let mut writable_bits = [0u32; NUM_CONFIGURATION_REGISTERS]; 492 registers[0] = u32::from(device_id) << 16 | u32::from(vendor_id); 493 // TODO(dverkamp): Status should be write-1-to-clear 494 writable_bits[1] = 0x0000_ffff; // Status (r/o), command (r/w) 495 let pi = if let Some(pi) = programming_interface { 496 pi.get_register_value() 497 } else { 498 0 499 }; 500 registers[2] = u32::from(class_code.get_register_value()) << 24 501 | u32::from(subclass.get_register_value()) << 16 502 | u32::from(pi) << 8 503 | u32::from(revision_id); 504 writable_bits[3] = 0x0000_00ff; // Cacheline size (r/w) 505 match header_type { 506 PciHeaderType::Device => { 507 registers[3] = 0x0000_0000; // Header type 0 (device) 508 writable_bits[15] = 0x0000_00ff; // Interrupt line (r/w) 509 registers[11] = u32::from(subsystem_id) << 16 | u32::from(subsystem_vendor_id); 510 } 511 PciHeaderType::Bridge => { 512 registers[3] = 0x0001_0000; // Header type 1 (bridge) 513 writable_bits[6] = 0x00ff_ffff; // Primary/secondary/subordinate bus number, 514 // secondary latency timer 515 registers[7] = 0x0000_00f0; // IO base > IO Limit, no IO address on secondary side at initialize 516 writable_bits[7] = 0xf900_0000; // IO base and limit, secondary status, 517 registers[8] = 0x0000_fff0; // mem base > mem Limit, no MMIO address on secondary side at initialize 518 writable_bits[8] = 0xfff0_fff0; // Memory base and limit 519 registers[9] = 0x0001_fff1; // pmem base > pmem Limit, no prefetch MMIO address on secondary side at initialize 520 writable_bits[9] = 0xfff0_fff0; // Prefetchable base and limit 521 writable_bits[10] = 0xffff_ffff; // Prefetchable base upper 32 bits 522 writable_bits[11] = 0xffff_ffff; // Prefetchable limit upper 32 bits 523 writable_bits[15] = 0xffff_00ff; // Bridge control (r/w), interrupt line (r/w) 524 } 525 }; 526 527 PciConfiguration { 528 registers, 529 writable_bits, 530 bar_used: [false; NUM_BAR_REGS], 531 bar_configs: [None; NUM_BAR_REGS], 532 last_capability: None, 533 capability_configs: BTreeMap::new(), 534 mmio_mapping: None, 535 } 536 } 537 538 /// Reads a 32bit register from `reg_idx` in the register map. read_reg(&self, reg_idx: usize) -> u32539 pub fn read_reg(&self, reg_idx: usize) -> u32 { 540 let mut data = *(self.registers.get(reg_idx).unwrap_or(&0xffff_ffff)); 541 if let Some((idx, cfg)) = self.capability_configs.range(..=reg_idx).last() { 542 if reg_idx < idx + cfg.num_regs() { 543 let cap_idx = reg_idx - idx; 544 let mask = cfg.read_mask()[cap_idx]; 545 data = (data & !mask) | (cfg.read_reg(cap_idx) & mask); 546 } 547 } 548 data 549 } 550 551 /// Writes data to PciConfiguration.registers. 552 /// `reg_idx` - index into PciConfiguration.registers. 553 /// `offset` - PciConfiguration.registers is in unit of DWord, offset define byte 554 /// offset in the DWord. 555 /// `data` - The data to write. write_reg( &mut self, reg_idx: usize, offset: u64, data: &[u8], ) -> Option<Box<dyn PciCapConfigWriteResult>>556 pub fn write_reg( 557 &mut self, 558 reg_idx: usize, 559 offset: u64, 560 data: &[u8], 561 ) -> Option<Box<dyn PciCapConfigWriteResult>> { 562 let reg_offset = reg_idx * 4 + offset as usize; 563 match data.len() { 564 1 => self.write_byte(reg_offset, data[0]), 565 2 => self.write_word(reg_offset, u16::from_le_bytes(data.try_into().unwrap())), 566 4 => self.write_dword(reg_offset, u32::from_le_bytes(data.try_into().unwrap())), 567 _ => (), 568 } 569 if let Some((idx, cfg)) = self.capability_configs.range_mut(..=reg_idx).last() { 570 if reg_idx < idx + cfg.num_regs() { 571 let cap_idx = reg_idx - idx; 572 let ret = cfg.write_reg(cap_idx, offset, data); 573 let new_val = cfg.read_reg(cap_idx); 574 let mask = cfg.read_mask()[cap_idx]; 575 self.set_reg(reg_idx, new_val, mask); 576 return ret; 577 } 578 } 579 None 580 } 581 582 /// Writes a 32bit dword to `offset`. `offset` must be 32bit aligned. write_dword(&mut self, offset: usize, value: u32)583 fn write_dword(&mut self, offset: usize, value: u32) { 584 if offset % 4 != 0 { 585 warn!("bad PCI config dword write offset {}", offset); 586 return; 587 } 588 let reg_idx = offset / 4; 589 if reg_idx < NUM_CONFIGURATION_REGISTERS { 590 let old_value = self.registers[reg_idx]; 591 let new_value = 592 (old_value & !self.writable_bits[reg_idx]) | (value & self.writable_bits[reg_idx]); 593 self.do_write(reg_idx, new_value) 594 } else { 595 warn!("bad PCI dword write {}", offset); 596 } 597 } 598 599 /// Writes a 16bit word to `offset`. `offset` must be 16bit aligned. write_word(&mut self, offset: usize, value: u16)600 fn write_word(&mut self, offset: usize, value: u16) { 601 let shift = match offset % 4 { 602 0 => 0, 603 2 => 16, 604 _ => { 605 warn!("bad PCI config word write offset {}", offset); 606 return; 607 } 608 }; 609 let reg_idx = offset / 4; 610 611 if reg_idx < NUM_CONFIGURATION_REGISTERS { 612 let old_value = self.registers[reg_idx]; 613 let writable_mask = self.writable_bits[reg_idx]; 614 let mask = (0xffffu32 << shift) & writable_mask; 615 let shifted_value = (u32::from(value) << shift) & writable_mask; 616 let new_value = old_value & !mask | shifted_value; 617 self.do_write(reg_idx, new_value) 618 } else { 619 warn!("bad PCI config word write offset {}", offset); 620 } 621 } 622 623 /// Writes a byte to `offset`. write_byte(&mut self, offset: usize, value: u8)624 fn write_byte(&mut self, offset: usize, value: u8) { 625 self.write_byte_internal(offset, value, true); 626 } 627 628 /// Writes a byte to `offset`, optionally enforcing read-only bits. write_byte_internal(&mut self, offset: usize, value: u8, apply_writable_mask: bool)629 fn write_byte_internal(&mut self, offset: usize, value: u8, apply_writable_mask: bool) { 630 let shift = (offset % 4) * 8; 631 let reg_idx = offset / 4; 632 633 if reg_idx < NUM_CONFIGURATION_REGISTERS { 634 let writable_mask = if apply_writable_mask { 635 self.writable_bits[reg_idx] 636 } else { 637 0xffff_ffff 638 }; 639 let old_value = self.registers[reg_idx]; 640 let mask = (0xffu32 << shift) & writable_mask; 641 let shifted_value = (u32::from(value) << shift) & writable_mask; 642 let new_value = old_value & !mask | shifted_value; 643 self.do_write(reg_idx, new_value) 644 } else { 645 warn!("bad PCI config byte write offset {}", offset); 646 } 647 } 648 649 /// Sets the value of a PciConfiguration register. This should be used when 650 /// device-internal events require changing the configuration space - as such, 651 /// the writable bits masks do not apply. 652 /// `reg_idx` - index into PciConfiguration.registers. 653 /// `data` - The data to write. 654 /// `mask` - The mask of which bits to modify. set_reg(&mut self, reg_idx: usize, data: u32, mask: u32)655 pub fn set_reg(&mut self, reg_idx: usize, data: u32, mask: u32) { 656 if reg_idx >= NUM_CONFIGURATION_REGISTERS { 657 return; 658 } 659 let new_val = (self.registers[reg_idx] & !mask) | (data & mask); 660 self.do_write(reg_idx, new_val); 661 } 662 663 /// Adds a region specified by `config`. Configures the specified BAR(s) to 664 /// report this region and size to the guest kernel. Enforces a few constraints 665 /// (i.e, region size must be power of two, register not already used). Returns 'None' on 666 /// failure all, `Some(BarIndex)` on success. add_pci_bar(&mut self, config: PciBarConfiguration) -> Result<PciBarIndex>667 pub fn add_pci_bar(&mut self, config: PciBarConfiguration) -> Result<PciBarIndex> { 668 if config.bar_idx >= NUM_BAR_REGS { 669 return Err(Error::BarInvalid(config.bar_idx)); 670 } 671 672 if self.bar_used[config.bar_idx] { 673 return Err(Error::BarInUse(config.bar_idx)); 674 } 675 676 if config.size.count_ones() != 1 { 677 return Err(Error::BarSizeInvalid(config.size)); 678 } 679 680 if config.is_expansion_rom() && config.region_type != PciBarRegionType::Memory32BitRegion { 681 return Err(Error::BarInvalidRomType); 682 } 683 684 let min_size = if config.is_expansion_rom() { 685 BAR_ROM_MIN_SIZE 686 } else if config.region_type == PciBarRegionType::IoRegion { 687 BAR_IO_MIN_SIZE 688 } else { 689 BAR_MEM_MIN_SIZE 690 }; 691 692 if config.size < min_size { 693 return Err(Error::BarSizeInvalid(config.size)); 694 } 695 696 if config.addr % config.size != 0 { 697 return Err(Error::BarAlignmentInvalid(config.addr, config.size)); 698 } 699 700 let reg_idx = config.reg_index(); 701 let end_addr = config 702 .addr 703 .checked_add(config.size) 704 .ok_or(Error::BarAddressInvalid(config.addr, config.size))?; 705 match config.region_type { 706 PciBarRegionType::Memory32BitRegion | PciBarRegionType::IoRegion => { 707 if end_addr > u64::from(u32::MAX) { 708 return Err(Error::BarAddressInvalid(config.addr, config.size)); 709 } 710 } 711 PciBarRegionType::Memory64BitRegion => { 712 // The expansion ROM BAR cannot be used for part of a 64-bit BAR. 713 if config.bar_idx + 1 >= ROM_BAR_IDX { 714 return Err(Error::BarInvalid64(config.bar_idx)); 715 } 716 717 if self.bar_used[config.bar_idx + 1] { 718 return Err(Error::BarInUse64(config.bar_idx)); 719 } 720 721 self.do_write(reg_idx + 1, (config.addr >> 32) as u32); 722 self.writable_bits[reg_idx + 1] = !((config.size - 1) >> 32) as u32; 723 self.bar_used[config.bar_idx + 1] = true; 724 } 725 } 726 727 let (mask, lower_bits) = match config.region_type { 728 PciBarRegionType::Memory32BitRegion | PciBarRegionType::Memory64BitRegion => { 729 self.registers[COMMAND_REG] |= COMMAND_REG_MEMORY_SPACE_MASK; 730 ( 731 BAR_MEM_ADDR_MASK, 732 config.prefetchable as u32 | config.region_type as u32, 733 ) 734 } 735 PciBarRegionType::IoRegion => { 736 self.registers[COMMAND_REG] |= COMMAND_REG_IO_SPACE_MASK; 737 (BAR_IO_ADDR_MASK, config.region_type as u32) 738 } 739 }; 740 741 self.do_write(reg_idx, ((config.addr as u32) & mask) | lower_bits); 742 self.writable_bits[reg_idx] = !(config.size - 1) as u32; 743 if config.is_expansion_rom() { 744 self.writable_bits[reg_idx] |= 1; // Expansion ROM enable bit. 745 } 746 self.bar_used[config.bar_idx] = true; 747 self.bar_configs[config.bar_idx] = Some(config); 748 Ok(config.bar_idx) 749 } 750 751 /// Returns an iterator of the currently configured base address registers. 752 #[allow(dead_code)] // TODO(dverkamp): remove this once used get_bars(&self) -> PciBarIter753 pub fn get_bars(&self) -> PciBarIter { 754 PciBarIter { 755 config: self, 756 bar_num: 0, 757 } 758 } 759 760 /// Returns the configuration of a base address register, if present. get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration>761 pub fn get_bar_configuration(&self, bar_num: usize) -> Option<PciBarConfiguration> { 762 let config = self.bar_configs.get(bar_num)?; 763 764 if let Some(mut config) = config { 765 let command = self.read_reg(COMMAND_REG); 766 if (config.is_memory() && (command & COMMAND_REG_MEMORY_SPACE_MASK == 0)) 767 || (config.is_io() && (command & COMMAND_REG_IO_SPACE_MASK == 0)) 768 { 769 return None; 770 } 771 772 // The address may have been modified by the guest, so the value in bar_configs 773 // may be outdated. Replace it with the current value. 774 config.addr = self.get_bar_addr(bar_num); 775 Some(config) 776 } else { 777 None 778 } 779 } 780 781 /// Returns the type of the given BAR region. get_bar_type(&self, bar_num: PciBarIndex) -> Option<PciBarRegionType>782 pub fn get_bar_type(&self, bar_num: PciBarIndex) -> Option<PciBarRegionType> { 783 self.bar_configs.get(bar_num)?.map(|c| c.region_type) 784 } 785 786 /// Returns the address of the given BAR region. get_bar_addr(&self, bar_num: PciBarIndex) -> u64787 pub fn get_bar_addr(&self, bar_num: PciBarIndex) -> u64 { 788 let bar_idx = if bar_num == ROM_BAR_IDX { 789 ROM_BAR_REG 790 } else { 791 BAR0_REG + bar_num 792 }; 793 794 let bar_type = match self.get_bar_type(bar_num) { 795 Some(t) => t, 796 None => return 0, 797 }; 798 799 match bar_type { 800 PciBarRegionType::IoRegion => u64::from(self.registers[bar_idx] & BAR_IO_ADDR_MASK), 801 PciBarRegionType::Memory32BitRegion => { 802 u64::from(self.registers[bar_idx] & BAR_MEM_ADDR_MASK) 803 } 804 PciBarRegionType::Memory64BitRegion => { 805 u64::from(self.registers[bar_idx] & BAR_MEM_ADDR_MASK) 806 | u64::from(self.registers[bar_idx + 1]) << 32 807 } 808 } 809 } 810 811 /// Configures the IRQ line and pin used by this device. set_irq(&mut self, line: u8, pin: PciInterruptPin)812 pub fn set_irq(&mut self, line: u8, pin: PciInterruptPin) { 813 // `pin` is 1-based in the pci config space. 814 let pin_idx = (pin as u32) + 1; 815 let new_val = (self.registers[INTERRUPT_LINE_PIN_REG] & 0xffff_0000) 816 | (pin_idx << 8) 817 | u32::from(line); 818 self.do_write(INTERRUPT_LINE_PIN_REG, new_val) 819 } 820 821 /// Adds the capability `cap_data` to the list of capabilities. 822 /// `cap_data` should include the two-byte PCI capability header (type, next), 823 /// but not populate it. Correct values will be generated automatically based 824 /// on `cap_data.id()`. add_capability( &mut self, cap_data: &dyn PciCapability, cap_config: Option<Box<dyn PciCapConfig>>, ) -> Result<()>825 pub fn add_capability( 826 &mut self, 827 cap_data: &dyn PciCapability, 828 cap_config: Option<Box<dyn PciCapConfig>>, 829 ) -> Result<()> { 830 let total_len = cap_data.bytes().len(); 831 // Check that the length is valid. 832 if cap_data.bytes().is_empty() { 833 return Err(Error::CapabilityEmpty); 834 } 835 let (cap_offset, tail_offset) = match self.last_capability { 836 Some((offset, len)) => (Self::next_dword(offset, len), offset + 1), 837 None => (FIRST_CAPABILITY_OFFSET, CAPABILITY_LIST_HEAD_OFFSET), 838 }; 839 let end_offset = cap_offset 840 .checked_add(total_len) 841 .ok_or(Error::CapabilitySpaceFull(total_len))?; 842 if end_offset > CAPABILITY_MAX_OFFSET { 843 return Err(Error::CapabilitySpaceFull(total_len)); 844 } 845 self.do_write( 846 STATUS_REG, 847 self.registers[STATUS_REG] | STATUS_REG_CAPABILITIES_USED_MASK, 848 ); 849 self.write_byte_internal(tail_offset, cap_offset as u8, false); 850 self.write_byte_internal(cap_offset, cap_data.id() as u8, false); 851 self.write_byte_internal(cap_offset + 1, 0, false); // Next pointer. 852 for (i, byte) in cap_data.bytes().iter().enumerate().skip(2) { 853 self.write_byte_internal(cap_offset + i, *byte, false); 854 } 855 let reg_idx = cap_offset / 4; 856 for (i, dword) in cap_data.writable_bits().iter().enumerate() { 857 self.writable_bits[reg_idx + i] = *dword; 858 } 859 self.last_capability = Some((cap_offset, total_len)); 860 if let Some(mut cap_config) = cap_config { 861 if let Some((mapping, offset)) = &self.mmio_mapping { 862 cap_config.set_cap_mapping(PciCapMapping { 863 mapping: mapping.clone(), 864 offset: reg_idx * 4 + offset, 865 num_regs: total_len / 4, 866 }); 867 } 868 self.capability_configs.insert(cap_offset / 4, cap_config); 869 } 870 Ok(()) 871 } 872 873 // Find the next aligned offset after the one given. next_dword(offset: usize, len: usize) -> usize874 fn next_dword(offset: usize, len: usize) -> usize { 875 let next = offset + len; 876 (next + 3) & !3 877 } 878 do_write(&mut self, reg_idx: usize, value: u32)879 fn do_write(&mut self, reg_idx: usize, value: u32) { 880 self.registers[reg_idx] = value; 881 if let Some((mmio_mapping, offset)) = self.mmio_mapping.as_ref() { 882 let mmio_mapping = mmio_mapping.lock(); 883 let reg_offset = offset + reg_idx * 4; 884 if reg_idx == HEADER_TYPE_REG { 885 // Skip writing the header type byte (reg_idx=2/offset=3) as 886 // per the requirements of PciDevice.setup_pci_config_mapping. 887 mmio_mapping 888 .write_obj_volatile((value & 0xffff) as u16, reg_offset) 889 .expect("bad register offset"); 890 // Skip HEADER_TYPE_REG_OFFSET (i.e. header+mfd byte) 891 mmio_mapping 892 .write_obj_volatile(((value >> 24) & 0xff) as u8, reg_offset + 3) 893 .expect("bad register offset"); 894 } else { 895 mmio_mapping 896 .write_obj_volatile(value, reg_offset) 897 .expect("bad register offset"); 898 } 899 if let Err(err) = mmio_mapping.flush_region(reg_offset, 4) { 900 error!( 901 "failed to flush write to pci mmio register ({}): {}", 902 reg_idx, err 903 ); 904 } 905 } 906 } 907 snapshot(&mut self) -> anyhow::Result<serde_json::Value>908 pub fn snapshot(&mut self) -> anyhow::Result<serde_json::Value> { 909 serde_json::to_value(PciConfigurationSerialized { 910 registers: self.registers, 911 writable_bits: self.writable_bits, 912 bar_used: self.bar_used, 913 bar_configs: self.bar_configs, 914 last_capability: self.last_capability, 915 }) 916 .context("failed to serialize PciConfiguration") 917 } 918 restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>919 pub fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> { 920 let deser: PciConfigurationSerialized = 921 serde_json::from_value(data).context("failed to deserialize PciConfiguration")?; 922 self.registers = deser.registers; 923 self.writable_bits = deser.writable_bits; 924 self.bar_used = deser.bar_used; 925 self.bar_configs = deser.bar_configs; 926 self.last_capability = deser.last_capability; 927 // Restore everything via do_write to avoid writing to the header type register 928 // and clobbering the multi-function device bit, as that bit is managed by the 929 // PciRoot. Since restore doesn't change the types or layout of PCI devices, the 930 // header type bits in the register are already correct anyway. 931 for i in 0..NUM_CONFIGURATION_REGISTERS { 932 self.do_write(i, self.registers[i]); 933 } 934 Ok(()) 935 } 936 setup_mapping( &mut self, shmem: &SharedMemory, base: usize, len: usize, ) -> anyhow::Result<()>937 pub fn setup_mapping( 938 &mut self, 939 shmem: &SharedMemory, 940 base: usize, 941 len: usize, 942 ) -> anyhow::Result<()> { 943 if self.mmio_mapping.is_some() { 944 bail!("PCIe config mmio mapping already initialized"); 945 } 946 let mapping = MemoryMappingBuilder::new(base::pagesize()) 947 .from_shared_memory(shmem) 948 .build() 949 .context("Failed to create mapping")?; 950 for i in 0..(len / 4) { 951 let val = self.registers.get(i).unwrap_or(&0xffff_ffff); 952 mapping 953 .write_obj_volatile(*val, base + i * 4) 954 .expect("memcpy failed"); 955 } 956 let mapping = Arc::new(Mutex::new(mapping)); 957 for (idx, cap) in self.capability_configs.iter_mut() { 958 let mut cap_mapping = PciCapMapping { 959 mapping: mapping.clone(), 960 offset: idx * 4 + base, 961 num_regs: cap.num_regs(), 962 }; 963 for i in 0..cap.num_regs() { 964 let val = cap.read_reg(i); 965 let mask = cap.read_mask()[i]; 966 cap_mapping.set_reg(i, val, mask); 967 } 968 cap.set_cap_mapping(cap_mapping); 969 } 970 self.mmio_mapping = Some((mapping, base)); 971 Ok(()) 972 } 973 } 974 975 impl PciBarConfiguration { new( bar_idx: PciBarIndex, size: u64, region_type: PciBarRegionType, prefetchable: PciBarPrefetchable, ) -> Self976 pub fn new( 977 bar_idx: PciBarIndex, 978 size: u64, 979 region_type: PciBarRegionType, 980 prefetchable: PciBarPrefetchable, 981 ) -> Self { 982 PciBarConfiguration { 983 bar_idx, 984 addr: 0, 985 size, 986 region_type, 987 prefetchable, 988 } 989 } 990 bar_index(&self) -> PciBarIndex991 pub fn bar_index(&self) -> PciBarIndex { 992 self.bar_idx 993 } 994 reg_index(&self) -> usize995 pub fn reg_index(&self) -> usize { 996 if self.bar_idx == ROM_BAR_IDX { 997 ROM_BAR_REG 998 } else { 999 BAR0_REG + self.bar_idx 1000 } 1001 } 1002 address(&self) -> u641003 pub fn address(&self) -> u64 { 1004 self.addr 1005 } 1006 address_range(&self) -> std::ops::Range<u64>1007 pub fn address_range(&self) -> std::ops::Range<u64> { 1008 self.addr..self.addr + self.size 1009 } 1010 set_address(mut self, addr: u64) -> Self1011 pub fn set_address(mut self, addr: u64) -> Self { 1012 self.addr = addr; 1013 self 1014 } 1015 size(&self) -> u641016 pub fn size(&self) -> u64 { 1017 self.size 1018 } 1019 is_expansion_rom(&self) -> bool1020 pub fn is_expansion_rom(&self) -> bool { 1021 self.bar_idx == ROM_BAR_IDX 1022 } 1023 is_memory(&self) -> bool1024 pub fn is_memory(&self) -> bool { 1025 matches!( 1026 self.region_type, 1027 PciBarRegionType::Memory32BitRegion | PciBarRegionType::Memory64BitRegion 1028 ) 1029 } 1030 is_64bit_memory(&self) -> bool1031 pub fn is_64bit_memory(&self) -> bool { 1032 self.region_type == PciBarRegionType::Memory64BitRegion 1033 } 1034 is_io(&self) -> bool1035 pub fn is_io(&self) -> bool { 1036 self.region_type == PciBarRegionType::IoRegion 1037 } 1038 is_prefetchable(&self) -> bool1039 pub fn is_prefetchable(&self) -> bool { 1040 self.is_memory() && self.prefetchable == PciBarPrefetchable::Prefetchable 1041 } 1042 } 1043 1044 impl<T: PciCapConfig + ?Sized> PciCapConfig for Arc<Mutex<T>> { read_mask(&self) -> &'static [u32]1045 fn read_mask(&self) -> &'static [u32] { 1046 self.lock().read_mask() 1047 } read_reg(&self, reg_idx: usize) -> u321048 fn read_reg(&self, reg_idx: usize) -> u32 { 1049 self.lock().read_reg(reg_idx) 1050 } write_reg( &mut self, reg_idx: usize, offset: u64, data: &[u8], ) -> Option<Box<dyn PciCapConfigWriteResult>>1051 fn write_reg( 1052 &mut self, 1053 reg_idx: usize, 1054 offset: u64, 1055 data: &[u8], 1056 ) -> Option<Box<dyn PciCapConfigWriteResult>> { 1057 self.lock().write_reg(reg_idx, offset, data) 1058 } set_cap_mapping(&mut self, mapping: PciCapMapping)1059 fn set_cap_mapping(&mut self, mapping: PciCapMapping) { 1060 self.lock().set_cap_mapping(mapping) 1061 } 1062 } 1063 1064 /// Struct for updating a capabilitiy's mmio mapping. 1065 pub struct PciCapMapping { 1066 mapping: Arc<Mutex<MemoryMapping>>, 1067 offset: usize, 1068 num_regs: usize, 1069 } 1070 1071 impl PciCapMapping { 1072 /// Set the bits of register `reg_idx` specified by `mask` to `data`. set_reg(&mut self, reg_idx: usize, data: u32, mask: u32)1073 pub fn set_reg(&mut self, reg_idx: usize, data: u32, mask: u32) { 1074 if reg_idx >= self.num_regs { 1075 error!( 1076 "out of bounds register write {} vs {}", 1077 self.num_regs, reg_idx 1078 ); 1079 return; 1080 } 1081 let mapping = self.mapping.lock(); 1082 let offset = self.offset + reg_idx * 4; 1083 let cur_value = mapping.read_obj::<u32>(offset).expect("memcpy failed"); 1084 let new_val = (cur_value & !mask) | (data & mask); 1085 mapping 1086 .write_obj_volatile(new_val, offset) 1087 .expect("memcpy failed"); 1088 if let Err(err) = mapping.flush_region(offset, 4) { 1089 error!( 1090 "failed to flush write to pci cap in mmio register ({}): {}", 1091 reg_idx, err 1092 ); 1093 } 1094 } 1095 } 1096 1097 #[cfg(test)] 1098 mod tests { 1099 use zerocopy::AsBytes; 1100 1101 use super::*; 1102 1103 #[repr(C, packed)] 1104 #[derive(Clone, Copy, AsBytes)] 1105 #[allow(dead_code)] 1106 struct TestCap { 1107 _vndr: u8, 1108 _next: u8, 1109 len: u8, 1110 foo: u8, 1111 } 1112 1113 impl PciCapability for TestCap { bytes(&self) -> &[u8]1114 fn bytes(&self) -> &[u8] { 1115 self.as_bytes() 1116 } 1117 id(&self) -> PciCapabilityID1118 fn id(&self) -> PciCapabilityID { 1119 PciCapabilityID::VendorSpecific 1120 } 1121 writable_bits(&self) -> Vec<u32>1122 fn writable_bits(&self) -> Vec<u32> { 1123 vec![0u32; 1] 1124 } 1125 } 1126 1127 #[test] add_capability()1128 fn add_capability() { 1129 let mut cfg = PciConfiguration::new( 1130 0x1234, 1131 0x5678, 1132 PciClassCode::MultimediaController, 1133 &PciMultimediaSubclass::AudioController, 1134 None, 1135 PciHeaderType::Device, 1136 0xABCD, 1137 0x2468, 1138 0, 1139 ); 1140 1141 // Add two capabilities with different contents. 1142 let cap1 = TestCap { 1143 _vndr: 0, 1144 _next: 0, 1145 len: 4, 1146 foo: 0xAA, 1147 }; 1148 let cap1_offset = 64; 1149 cfg.add_capability(&cap1, None).unwrap(); 1150 1151 let cap2 = TestCap { 1152 _vndr: 0, 1153 _next: 0, 1154 len: 0x04, 1155 foo: 0x55, 1156 }; 1157 let cap2_offset = 68; 1158 cfg.add_capability(&cap2, None).unwrap(); 1159 1160 // The capability list head should be pointing to cap1. 1161 let cap_ptr = cfg.read_reg(CAPABILITY_LIST_HEAD_OFFSET / 4) & 0xFF; 1162 assert_eq!(cap1_offset, cap_ptr as usize); 1163 1164 // Verify the contents of the capabilities. 1165 let cap1_data = cfg.read_reg(cap1_offset / 4); 1166 assert_eq!(cap1_data & 0xFF, 0x09); // capability ID 1167 assert_eq!((cap1_data >> 8) & 0xFF, cap2_offset as u32); // next capability pointer 1168 assert_eq!((cap1_data >> 16) & 0xFF, 0x04); // cap1.len 1169 assert_eq!((cap1_data >> 24) & 0xFF, 0xAA); // cap1.foo 1170 1171 let cap2_data = cfg.read_reg(cap2_offset / 4); 1172 assert_eq!(cap2_data & 0xFF, 0x09); // capability ID 1173 assert_eq!((cap2_data >> 8) & 0xFF, 0x00); // next capability pointer 1174 assert_eq!((cap2_data >> 16) & 0xFF, 0x04); // cap2.len 1175 assert_eq!((cap2_data >> 24) & 0xFF, 0x55); // cap2.foo 1176 } 1177 1178 #[derive(Copy, Clone)] 1179 enum TestPI { 1180 Test = 0x5a, 1181 } 1182 1183 impl PciProgrammingInterface for TestPI { get_register_value(&self) -> u81184 fn get_register_value(&self) -> u8 { 1185 *self as u8 1186 } 1187 } 1188 1189 #[test] class_code()1190 fn class_code() { 1191 let cfg = PciConfiguration::new( 1192 0x1234, 1193 0x5678, 1194 PciClassCode::MultimediaController, 1195 &PciMultimediaSubclass::AudioController, 1196 Some(&TestPI::Test), 1197 PciHeaderType::Device, 1198 0xABCD, 1199 0x2468, 1200 0, 1201 ); 1202 1203 let class_reg = cfg.read_reg(2); 1204 let class_code = (class_reg >> 24) & 0xFF; 1205 let subclass = (class_reg >> 16) & 0xFF; 1206 let prog_if = (class_reg >> 8) & 0xFF; 1207 assert_eq!(class_code, 0x04); 1208 assert_eq!(subclass, 0x01); 1209 assert_eq!(prog_if, 0x5a); 1210 } 1211 1212 #[test] read_only_bits()1213 fn read_only_bits() { 1214 let mut cfg = PciConfiguration::new( 1215 0x1234, 1216 0x5678, 1217 PciClassCode::MultimediaController, 1218 &PciMultimediaSubclass::AudioController, 1219 Some(&TestPI::Test), 1220 PciHeaderType::Device, 1221 0xABCD, 1222 0x2468, 1223 0, 1224 ); 1225 1226 // Attempt to overwrite vendor ID and device ID, which are read-only 1227 cfg.write_reg(0, 0, &[0xBA, 0xAD, 0xF0, 0x0D]); 1228 // The original vendor and device ID should remain. 1229 assert_eq!(cfg.read_reg(0), 0x56781234); 1230 } 1231 1232 #[test] query_unused_bar()1233 fn query_unused_bar() { 1234 let cfg = PciConfiguration::new( 1235 0x1234, 1236 0x5678, 1237 PciClassCode::MultimediaController, 1238 &PciMultimediaSubclass::AudioController, 1239 Some(&TestPI::Test), 1240 PciHeaderType::Device, 1241 0xABCD, 1242 0x2468, 1243 0, 1244 ); 1245 1246 // No BAR 0 has been configured, so these should return None or 0 as appropriate. 1247 assert_eq!(cfg.get_bar_type(0), None); 1248 assert_eq!(cfg.get_bar_addr(0), 0); 1249 1250 let mut bar_iter = cfg.get_bars(); 1251 assert_eq!(bar_iter.next(), None); 1252 } 1253 1254 #[test] add_pci_bar_mem_64bit()1255 fn add_pci_bar_mem_64bit() { 1256 let mut cfg = PciConfiguration::new( 1257 0x1234, 1258 0x5678, 1259 PciClassCode::MultimediaController, 1260 &PciMultimediaSubclass::AudioController, 1261 Some(&TestPI::Test), 1262 PciHeaderType::Device, 1263 0xABCD, 1264 0x2468, 1265 0, 1266 ); 1267 1268 cfg.add_pci_bar( 1269 PciBarConfiguration::new( 1270 0, 1271 0x10, 1272 PciBarRegionType::Memory64BitRegion, 1273 PciBarPrefetchable::NotPrefetchable, 1274 ) 1275 .set_address(0x0123_4567_89AB_CDE0), 1276 ) 1277 .expect("add_pci_bar failed"); 1278 1279 assert_eq!( 1280 cfg.get_bar_type(0), 1281 Some(PciBarRegionType::Memory64BitRegion) 1282 ); 1283 assert_eq!(cfg.get_bar_addr(0), 0x0123_4567_89AB_CDE0); 1284 assert_eq!(cfg.writable_bits[BAR0_REG + 1], 0xFFFFFFFF); 1285 assert_eq!(cfg.writable_bits[BAR0_REG + 0], 0xFFFFFFF0); 1286 1287 let mut bar_iter = cfg.get_bars(); 1288 assert_eq!( 1289 bar_iter.next(), 1290 Some(PciBarConfiguration { 1291 addr: 0x0123_4567_89AB_CDE0, 1292 size: 0x10, 1293 bar_idx: 0, 1294 region_type: PciBarRegionType::Memory64BitRegion, 1295 prefetchable: PciBarPrefetchable::NotPrefetchable 1296 }) 1297 ); 1298 assert_eq!(bar_iter.next(), None); 1299 } 1300 1301 #[test] add_pci_bar_mem_32bit()1302 fn add_pci_bar_mem_32bit() { 1303 let mut cfg = PciConfiguration::new( 1304 0x1234, 1305 0x5678, 1306 PciClassCode::MultimediaController, 1307 &PciMultimediaSubclass::AudioController, 1308 Some(&TestPI::Test), 1309 PciHeaderType::Device, 1310 0xABCD, 1311 0x2468, 1312 0, 1313 ); 1314 1315 cfg.add_pci_bar( 1316 PciBarConfiguration::new( 1317 0, 1318 0x10, 1319 PciBarRegionType::Memory32BitRegion, 1320 PciBarPrefetchable::NotPrefetchable, 1321 ) 1322 .set_address(0x12345670), 1323 ) 1324 .expect("add_pci_bar failed"); 1325 1326 assert_eq!( 1327 cfg.get_bar_type(0), 1328 Some(PciBarRegionType::Memory32BitRegion) 1329 ); 1330 assert_eq!(cfg.get_bar_addr(0), 0x12345670); 1331 assert_eq!(cfg.writable_bits[BAR0_REG], 0xFFFFFFF0); 1332 1333 let mut bar_iter = cfg.get_bars(); 1334 assert_eq!( 1335 bar_iter.next(), 1336 Some(PciBarConfiguration { 1337 addr: 0x12345670, 1338 size: 0x10, 1339 bar_idx: 0, 1340 region_type: PciBarRegionType::Memory32BitRegion, 1341 prefetchable: PciBarPrefetchable::NotPrefetchable 1342 }) 1343 ); 1344 assert_eq!(bar_iter.next(), None); 1345 } 1346 1347 #[test] add_pci_bar_io()1348 fn add_pci_bar_io() { 1349 let mut cfg = PciConfiguration::new( 1350 0x1234, 1351 0x5678, 1352 PciClassCode::MultimediaController, 1353 &PciMultimediaSubclass::AudioController, 1354 Some(&TestPI::Test), 1355 PciHeaderType::Device, 1356 0xABCD, 1357 0x2468, 1358 0, 1359 ); 1360 1361 cfg.add_pci_bar( 1362 PciBarConfiguration::new( 1363 0, 1364 0x4, 1365 PciBarRegionType::IoRegion, 1366 PciBarPrefetchable::NotPrefetchable, 1367 ) 1368 .set_address(0x1230), 1369 ) 1370 .expect("add_pci_bar failed"); 1371 1372 assert_eq!(cfg.get_bar_type(0), Some(PciBarRegionType::IoRegion)); 1373 assert_eq!(cfg.get_bar_addr(0), 0x1230); 1374 assert_eq!(cfg.writable_bits[BAR0_REG], 0xFFFFFFFC); 1375 1376 let mut bar_iter = cfg.get_bars(); 1377 assert_eq!( 1378 bar_iter.next(), 1379 Some(PciBarConfiguration { 1380 addr: 0x1230, 1381 size: 0x4, 1382 bar_idx: 0, 1383 region_type: PciBarRegionType::IoRegion, 1384 prefetchable: PciBarPrefetchable::NotPrefetchable 1385 }) 1386 ); 1387 assert_eq!(bar_iter.next(), None); 1388 } 1389 1390 #[test] add_pci_bar_multiple()1391 fn add_pci_bar_multiple() { 1392 let mut cfg = PciConfiguration::new( 1393 0x1234, 1394 0x5678, 1395 PciClassCode::MultimediaController, 1396 &PciMultimediaSubclass::AudioController, 1397 Some(&TestPI::Test), 1398 PciHeaderType::Device, 1399 0xABCD, 1400 0x2468, 1401 0, 1402 ); 1403 1404 // bar_num 0-1: 64-bit memory 1405 cfg.add_pci_bar( 1406 PciBarConfiguration::new( 1407 0, 1408 0x10, 1409 PciBarRegionType::Memory64BitRegion, 1410 PciBarPrefetchable::NotPrefetchable, 1411 ) 1412 .set_address(0x0123_4567_89AB_CDE0), 1413 ) 1414 .expect("add_pci_bar failed"); 1415 1416 // bar 2: 32-bit memory 1417 cfg.add_pci_bar( 1418 PciBarConfiguration::new( 1419 2, 1420 0x10, 1421 PciBarRegionType::Memory32BitRegion, 1422 PciBarPrefetchable::NotPrefetchable, 1423 ) 1424 .set_address(0x12345670), 1425 ) 1426 .expect("add_pci_bar failed"); 1427 1428 // bar 3: I/O 1429 cfg.add_pci_bar( 1430 PciBarConfiguration::new( 1431 3, 1432 0x4, 1433 PciBarRegionType::IoRegion, 1434 PciBarPrefetchable::NotPrefetchable, 1435 ) 1436 .set_address(0x1230), 1437 ) 1438 .expect("add_pci_bar failed"); 1439 1440 // Confirm default memory and I/O region configurations. 1441 let mut bar_iter = cfg.get_bars(); 1442 assert_eq!( 1443 bar_iter.next(), 1444 Some(PciBarConfiguration { 1445 addr: 0x0123_4567_89AB_CDE0, 1446 size: 0x10, 1447 bar_idx: 0, 1448 region_type: PciBarRegionType::Memory64BitRegion, 1449 prefetchable: PciBarPrefetchable::NotPrefetchable 1450 }) 1451 ); 1452 assert_eq!( 1453 bar_iter.next(), 1454 Some(PciBarConfiguration { 1455 addr: 0x12345670, 1456 size: 0x10, 1457 bar_idx: 2, 1458 region_type: PciBarRegionType::Memory32BitRegion, 1459 prefetchable: PciBarPrefetchable::NotPrefetchable 1460 }) 1461 ); 1462 assert_eq!( 1463 bar_iter.next(), 1464 Some(PciBarConfiguration { 1465 addr: 0x1230, 1466 size: 0x4, 1467 bar_idx: 3, 1468 region_type: PciBarRegionType::IoRegion, 1469 prefetchable: PciBarPrefetchable::NotPrefetchable 1470 }) 1471 ); 1472 assert_eq!(bar_iter.next(), None); 1473 1474 // Reassign the address for BAR 0 and verify that get_memory_regions() matches. 1475 cfg.write_reg(4 + 0, 0, &0xBBAA9980u32.to_le_bytes()); 1476 cfg.write_reg(4 + 1, 0, &0xFFEEDDCCu32.to_le_bytes()); 1477 1478 let mut bar_iter = cfg.get_bars(); 1479 assert_eq!( 1480 bar_iter.next(), 1481 Some(PciBarConfiguration { 1482 addr: 0xFFEE_DDCC_BBAA_9980, 1483 size: 0x10, 1484 bar_idx: 0, 1485 region_type: PciBarRegionType::Memory64BitRegion, 1486 prefetchable: PciBarPrefetchable::NotPrefetchable 1487 }) 1488 ); 1489 assert_eq!( 1490 bar_iter.next(), 1491 Some(PciBarConfiguration { 1492 addr: 0x12345670, 1493 size: 0x10, 1494 bar_idx: 2, 1495 region_type: PciBarRegionType::Memory32BitRegion, 1496 prefetchable: PciBarPrefetchable::NotPrefetchable 1497 }) 1498 ); 1499 assert_eq!( 1500 bar_iter.next(), 1501 Some(PciBarConfiguration { 1502 addr: 0x1230, 1503 size: 0x4, 1504 bar_idx: 3, 1505 region_type: PciBarRegionType::IoRegion, 1506 prefetchable: PciBarPrefetchable::NotPrefetchable 1507 }) 1508 ); 1509 assert_eq!(bar_iter.next(), None); 1510 } 1511 1512 #[test] add_pci_bar_invalid_size()1513 fn add_pci_bar_invalid_size() { 1514 let mut cfg = PciConfiguration::new( 1515 0x1234, 1516 0x5678, 1517 PciClassCode::MultimediaController, 1518 &PciMultimediaSubclass::AudioController, 1519 Some(&TestPI::Test), 1520 PciHeaderType::Device, 1521 0xABCD, 1522 0x2468, 1523 0, 1524 ); 1525 1526 // I/O BAR with size 2 (too small) 1527 assert_eq!( 1528 cfg.add_pci_bar( 1529 PciBarConfiguration::new( 1530 0, 1531 0x2, 1532 PciBarRegionType::IoRegion, 1533 PciBarPrefetchable::NotPrefetchable, 1534 ) 1535 .set_address(0x1230), 1536 ), 1537 Err(Error::BarSizeInvalid(0x2)) 1538 ); 1539 1540 // I/O BAR with size 3 (not a power of 2) 1541 assert_eq!( 1542 cfg.add_pci_bar( 1543 PciBarConfiguration::new( 1544 0, 1545 0x3, 1546 PciBarRegionType::IoRegion, 1547 PciBarPrefetchable::NotPrefetchable, 1548 ) 1549 .set_address(0x1230), 1550 ), 1551 Err(Error::BarSizeInvalid(0x3)) 1552 ); 1553 1554 // Memory BAR with size 8 (too small) 1555 assert_eq!( 1556 cfg.add_pci_bar( 1557 PciBarConfiguration::new( 1558 0, 1559 0x8, 1560 PciBarRegionType::Memory32BitRegion, 1561 PciBarPrefetchable::NotPrefetchable, 1562 ) 1563 .set_address(0x12345670), 1564 ), 1565 Err(Error::BarSizeInvalid(0x8)) 1566 ); 1567 } 1568 1569 #[test] add_rom_bar()1570 fn add_rom_bar() { 1571 let mut cfg = PciConfiguration::new( 1572 0x1234, 1573 0x5678, 1574 PciClassCode::MultimediaController, 1575 &PciMultimediaSubclass::AudioController, 1576 Some(&TestPI::Test), 1577 PciHeaderType::Device, 1578 0xABCD, 1579 0x2468, 1580 0, 1581 ); 1582 1583 // Attempt to add a 64-bit memory BAR as the expansion ROM (invalid). 1584 assert_eq!( 1585 cfg.add_pci_bar(PciBarConfiguration::new( 1586 ROM_BAR_IDX, 1587 0x1000, 1588 PciBarRegionType::Memory64BitRegion, 1589 PciBarPrefetchable::NotPrefetchable, 1590 ),), 1591 Err(Error::BarInvalidRomType) 1592 ); 1593 1594 // Attempt to add an I/O BAR as the expansion ROM (invalid). 1595 assert_eq!( 1596 cfg.add_pci_bar(PciBarConfiguration::new( 1597 ROM_BAR_IDX, 1598 0x1000, 1599 PciBarRegionType::IoRegion, 1600 PciBarPrefetchable::NotPrefetchable, 1601 ),), 1602 Err(Error::BarInvalidRomType) 1603 ); 1604 1605 // Attempt to add a 1KB memory region as the expansion ROM (too small). 1606 assert_eq!( 1607 cfg.add_pci_bar(PciBarConfiguration::new( 1608 ROM_BAR_IDX, 1609 1024, 1610 PciBarRegionType::Memory32BitRegion, 1611 PciBarPrefetchable::NotPrefetchable, 1612 ),), 1613 Err(Error::BarSizeInvalid(1024)) 1614 ); 1615 1616 // Add a 32-bit memory BAR as the expansion ROM (valid). 1617 cfg.add_pci_bar( 1618 PciBarConfiguration::new( 1619 ROM_BAR_IDX, 1620 0x800, 1621 PciBarRegionType::Memory32BitRegion, 1622 PciBarPrefetchable::NotPrefetchable, 1623 ) 1624 .set_address(0x12345000), 1625 ) 1626 .expect("add_pci_bar failed"); 1627 1628 assert_eq!( 1629 cfg.get_bar_type(ROM_BAR_IDX), 1630 Some(PciBarRegionType::Memory32BitRegion) 1631 ); 1632 assert_eq!(cfg.get_bar_addr(ROM_BAR_IDX), 0x12345000); 1633 assert_eq!(cfg.read_reg(ROM_BAR_REG), 0x12345000); 1634 assert_eq!(cfg.writable_bits[ROM_BAR_REG], 0xFFFFF801); 1635 } 1636 1637 #[test] pci_configuration_capability_snapshot_restore() -> anyhow::Result<()>1638 fn pci_configuration_capability_snapshot_restore() -> anyhow::Result<()> { 1639 let mut cfg = PciConfiguration::new( 1640 0x1234, 1641 0x5678, 1642 PciClassCode::MultimediaController, 1643 &PciMultimediaSubclass::AudioController, 1644 Some(&TestPI::Test), 1645 PciHeaderType::Device, 1646 0xABCD, 1647 0x2468, 1648 0, 1649 ); 1650 1651 let snap_init = cfg.snapshot().context("failed to snapshot")?; 1652 1653 // Add a capability. 1654 let cap1 = TestCap { 1655 _vndr: 0, 1656 _next: 0, 1657 len: 4, 1658 foo: 0xAA, 1659 }; 1660 cfg.add_capability(&cap1, None).unwrap(); 1661 1662 let snap_mod = cfg.snapshot().context("failed to snapshot mod")?; 1663 cfg.restore(snap_init.clone()) 1664 .context("failed to restore snap_init")?; 1665 let snap_restore_init = cfg.snapshot().context("failed to snapshot restored_init")?; 1666 assert_eq!(snap_init, snap_restore_init); 1667 assert_ne!(snap_init, snap_mod); 1668 cfg.restore(snap_mod.clone()) 1669 .context("failed to restore snap_init")?; 1670 let snap_restore_mod = cfg.snapshot().context("failed to snapshot restored_mod")?; 1671 assert_eq!(snap_mod, snap_restore_mod); 1672 Ok(()) 1673 } 1674 1675 #[test] pci_configuration_pci_bar_snapshot_restore() -> anyhow::Result<()>1676 fn pci_configuration_pci_bar_snapshot_restore() -> anyhow::Result<()> { 1677 let mut cfg = PciConfiguration::new( 1678 0x1234, 1679 0x5678, 1680 PciClassCode::MultimediaController, 1681 &PciMultimediaSubclass::AudioController, 1682 Some(&TestPI::Test), 1683 PciHeaderType::Device, 1684 0xABCD, 1685 0x2468, 1686 0, 1687 ); 1688 1689 let snap_init = cfg.snapshot().context("failed to snapshot")?; 1690 1691 // bar_num 0-1: 64-bit memory 1692 cfg.add_pci_bar( 1693 PciBarConfiguration::new( 1694 0, 1695 0x10, 1696 PciBarRegionType::Memory64BitRegion, 1697 PciBarPrefetchable::NotPrefetchable, 1698 ) 1699 .set_address(0x0123_4567_89AB_CDE0), 1700 ) 1701 .expect("add_pci_bar failed"); 1702 1703 let snap_mod = cfg.snapshot().context("failed to snapshot mod")?; 1704 cfg.restore(snap_init.clone()) 1705 .context("failed to restore snap_init")?; 1706 let snap_restore_init = cfg.snapshot().context("failed to snapshot restored_init")?; 1707 assert_eq!(snap_init, snap_restore_init); 1708 assert_ne!(snap_init, snap_mod); 1709 cfg.restore(snap_mod.clone()) 1710 .context("failed to restore snap_init")?; 1711 let snap_restore_mod = cfg.snapshot().context("failed to snapshot restored_mod")?; 1712 assert_eq!(snap_mod, snap_restore_mod); 1713 Ok(()) 1714 } 1715 1716 #[test] pci_configuration_capability_pci_bar_snapshot_restore() -> anyhow::Result<()>1717 fn pci_configuration_capability_pci_bar_snapshot_restore() -> anyhow::Result<()> { 1718 let mut cfg = PciConfiguration::new( 1719 0x1234, 1720 0x5678, 1721 PciClassCode::MultimediaController, 1722 &PciMultimediaSubclass::AudioController, 1723 Some(&TestPI::Test), 1724 PciHeaderType::Device, 1725 0xABCD, 1726 0x2468, 1727 0, 1728 ); 1729 1730 let snap_init = cfg.snapshot().context("failed to snapshot")?; 1731 1732 // Add a capability. 1733 let cap1 = TestCap { 1734 _vndr: 0, 1735 _next: 0, 1736 len: 4, 1737 foo: 0xAA, 1738 }; 1739 cfg.add_capability(&cap1, None).unwrap(); 1740 1741 // bar_num 0-1: 64-bit memory 1742 cfg.add_pci_bar( 1743 PciBarConfiguration::new( 1744 0, 1745 0x10, 1746 PciBarRegionType::Memory64BitRegion, 1747 PciBarPrefetchable::NotPrefetchable, 1748 ) 1749 .set_address(0x0123_4567_89AB_CDE0), 1750 ) 1751 .expect("add_pci_bar failed"); 1752 1753 let snap_mod = cfg.snapshot().context("failed to snapshot mod")?; 1754 cfg.restore(snap_init.clone()) 1755 .context("failed to restore snap_init")?; 1756 let snap_restore_init = cfg.snapshot().context("failed to snapshot restored_init")?; 1757 assert_eq!(snap_init, snap_restore_init); 1758 assert_ne!(snap_init, snap_mod); 1759 cfg.restore(snap_mod.clone()) 1760 .context("failed to restore snap_init")?; 1761 let snap_restore_mod = cfg.snapshot().context("failed to snapshot restored_mod")?; 1762 assert_eq!(snap_mod, snap_restore_mod); 1763 Ok(()) 1764 } 1765 } 1766