1 // Copyright 2018 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE-BSD-3-Clause file. 4 5 use crate::device::BarReprogrammingParams; 6 use crate::{MsixConfig, PciInterruptPin}; 7 use byteorder::{ByteOrder, LittleEndian}; 8 use std::fmt::{self, Display}; 9 use std::sync::{Arc, Mutex}; 10 use versionize::{VersionMap, Versionize, VersionizeError, VersionizeResult}; 11 use versionize_derive::Versionize; 12 use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable, VersionMapped}; 13 14 // The number of 32bit registers in the config space, 4096 bytes. 15 const NUM_CONFIGURATION_REGISTERS: usize = 1024; 16 17 const STATUS_REG: usize = 1; 18 const STATUS_REG_CAPABILITIES_USED_MASK: u32 = 0x0010_0000; 19 const BAR0_REG: usize = 4; 20 const ROM_BAR_REG: usize = 12; 21 const BAR_IO_ADDR_MASK: u32 = 0xffff_fffc; 22 const BAR_MEM_ADDR_MASK: u32 = 0xffff_fff0; 23 const ROM_BAR_ADDR_MASK: u32 = 0xffff_f800; 24 const MSI_CAPABILITY_REGISTER_MASK: u32 = 0x0071_0000; 25 const MSIX_CAPABILITY_REGISTER_MASK: u32 = 0xc000_0000; 26 const NUM_BAR_REGS: usize = 6; 27 const CAPABILITY_LIST_HEAD_OFFSET: usize = 0x34; 28 const FIRST_CAPABILITY_OFFSET: usize = 0x40; 29 const CAPABILITY_MAX_OFFSET: usize = 192; 30 31 const INTERRUPT_LINE_PIN_REG: usize = 15; 32 33 /// Represents the types of PCI headers allowed in the configuration registers. 34 #[derive(Copy, Clone)] 35 pub enum PciHeaderType { 36 Device, 37 Bridge, 38 } 39 40 /// Classes of PCI nodes. 41 #[allow(dead_code)] 42 #[derive(Copy, Clone)] 43 pub enum PciClassCode { 44 TooOld, 45 MassStorage, 46 NetworkController, 47 DisplayController, 48 MultimediaController, 49 MemoryController, 50 BridgeDevice, 51 SimpleCommunicationController, 52 BaseSystemPeripheral, 53 InputDevice, 54 DockingStation, 55 Processor, 56 SerialBusController, 57 WirelessController, 58 IntelligentIoController, 59 EncryptionController, 60 DataAcquisitionSignalProcessing, 61 Other = 0xff, 62 } 63 64 impl PciClassCode { 65 pub fn get_register_value(self) -> u8 { 66 self as u8 67 } 68 } 69 70 /// A PCI subclass. Each class in `PciClassCode` can specify a unique set of subclasses. This trait 71 /// is implemented by each subclass. It allows use of a trait object to generate configurations. 72 pub trait PciSubclass { 73 /// Convert this subclass to the value used in the PCI specification. 74 fn get_register_value(&self) -> u8; 75 } 76 77 /// Subclasses of the MultimediaController class. 78 #[allow(dead_code)] 79 #[derive(Copy, Clone)] 80 pub enum PciMultimediaSubclass { 81 VideoController = 0x00, 82 AudioController = 0x01, 83 TelephonyDevice = 0x02, 84 AudioDevice = 0x03, 85 Other = 0x80, 86 } 87 88 impl PciSubclass for PciMultimediaSubclass { 89 fn get_register_value(&self) -> u8 { 90 *self as u8 91 } 92 } 93 94 /// Subclasses of the BridgeDevice 95 #[allow(dead_code)] 96 #[derive(Copy, Clone)] 97 pub enum PciBridgeSubclass { 98 HostBridge = 0x00, 99 IsaBridge = 0x01, 100 EisaBridge = 0x02, 101 McaBridge = 0x03, 102 PciToPciBridge = 0x04, 103 PcmciaBridge = 0x05, 104 NuBusBridge = 0x06, 105 CardBusBridge = 0x07, 106 RacEwayBridge = 0x08, 107 PciToPciSemiTransparentBridge = 0x09, 108 InfiniBrandToPciHostBridge = 0x0a, 109 OtherBridgeDevice = 0x80, 110 } 111 112 impl PciSubclass for PciBridgeSubclass { 113 fn get_register_value(&self) -> u8 { 114 *self as u8 115 } 116 } 117 118 /// Subclass of the SerialBus 119 #[allow(dead_code)] 120 #[derive(Copy, Clone)] 121 pub enum PciSerialBusSubClass { 122 Firewire = 0x00, 123 Accessbus = 0x01, 124 Ssa = 0x02, 125 Usb = 0x03, 126 } 127 128 impl PciSubclass for PciSerialBusSubClass { 129 fn get_register_value(&self) -> u8 { 130 *self as u8 131 } 132 } 133 134 /// Mass Storage Sub Classes 135 #[allow(dead_code)] 136 #[derive(Copy, Clone)] 137 pub enum PciMassStorageSubclass { 138 ScsiStorage = 0x00, 139 IdeInterface = 0x01, 140 FloppyController = 0x02, 141 IpiController = 0x03, 142 RaidController = 0x04, 143 AtaController = 0x05, 144 SataController = 0x06, 145 SerialScsiController = 0x07, 146 NvmController = 0x08, 147 MassStorage = 0x80, 148 } 149 150 impl PciSubclass for PciMassStorageSubclass { 151 fn get_register_value(&self) -> u8 { 152 *self as u8 153 } 154 } 155 156 /// Network Controller Sub Classes 157 #[allow(dead_code)] 158 #[derive(Copy, Clone)] 159 pub enum PciNetworkControllerSubclass { 160 EthernetController = 0x00, 161 TokenRingController = 0x01, 162 FddiController = 0x02, 163 AtmController = 0x03, 164 IsdnController = 0x04, 165 WorldFipController = 0x05, 166 PicmgController = 0x06, 167 InfinibandController = 0x07, 168 FabricController = 0x08, 169 NetworkController = 0x80, 170 } 171 172 impl PciSubclass for PciNetworkControllerSubclass { 173 fn get_register_value(&self) -> u8 { 174 *self as u8 175 } 176 } 177 178 /// A PCI class programming interface. Each combination of `PciClassCode` and 179 /// `PciSubclass` can specify a set of register-level programming interfaces. 180 /// This trait is implemented by each programming interface. 181 /// It allows use of a trait object to generate configurations. 182 pub trait PciProgrammingInterface { 183 /// Convert this programming interface to the value used in the PCI specification. 184 fn get_register_value(&self) -> u8; 185 } 186 187 /// Types of PCI capabilities. 188 #[derive(PartialEq, Copy, Clone)] 189 #[allow(dead_code)] 190 #[allow(non_camel_case_types)] 191 #[repr(C)] 192 pub enum PciCapabilityId { 193 ListId = 0, 194 PowerManagement = 0x01, 195 AcceleratedGraphicsPort = 0x02, 196 VitalProductData = 0x03, 197 SlotIdentification = 0x04, 198 MessageSignalledInterrupts = 0x05, 199 CompactPciHotSwap = 0x06, 200 PciX = 0x07, 201 HyperTransport = 0x08, 202 VendorSpecific = 0x09, 203 Debugport = 0x0A, 204 CompactPciCentralResourceControl = 0x0B, 205 PciStandardHotPlugController = 0x0C, 206 BridgeSubsystemVendorDeviceId = 0x0D, 207 AgpTargetPciPcibridge = 0x0E, 208 SecureDevice = 0x0F, 209 PciExpress = 0x10, 210 MsiX = 0x11, 211 SataDataIndexConf = 0x12, 212 PciAdvancedFeatures = 0x13, 213 PciEnhancedAllocation = 0x14, 214 } 215 216 impl From<u8> for PciCapabilityId { 217 fn from(c: u8) -> Self { 218 match c { 219 0 => PciCapabilityId::ListId, 220 0x01 => PciCapabilityId::PowerManagement, 221 0x02 => PciCapabilityId::AcceleratedGraphicsPort, 222 0x03 => PciCapabilityId::VitalProductData, 223 0x04 => PciCapabilityId::SlotIdentification, 224 0x05 => PciCapabilityId::MessageSignalledInterrupts, 225 0x06 => PciCapabilityId::CompactPciHotSwap, 226 0x07 => PciCapabilityId::PciX, 227 0x08 => PciCapabilityId::HyperTransport, 228 0x09 => PciCapabilityId::VendorSpecific, 229 0x0A => PciCapabilityId::Debugport, 230 0x0B => PciCapabilityId::CompactPciCentralResourceControl, 231 0x0C => PciCapabilityId::PciStandardHotPlugController, 232 0x0D => PciCapabilityId::BridgeSubsystemVendorDeviceId, 233 0x0E => PciCapabilityId::AgpTargetPciPcibridge, 234 0x0F => PciCapabilityId::SecureDevice, 235 0x10 => PciCapabilityId::PciExpress, 236 0x11 => PciCapabilityId::MsiX, 237 0x12 => PciCapabilityId::SataDataIndexConf, 238 0x13 => PciCapabilityId::PciAdvancedFeatures, 239 0x14 => PciCapabilityId::PciEnhancedAllocation, 240 _ => PciCapabilityId::ListId, 241 } 242 } 243 } 244 245 /// A PCI capability list. Devices can optionally specify capabilities in their configuration space. 246 pub trait PciCapability { 247 fn bytes(&self) -> &[u8]; 248 fn id(&self) -> PciCapabilityId; 249 } 250 251 fn encode_32_bits_bar_size(bar_size: u32) -> Option<u32> { 252 if bar_size > 0 { 253 return Some(!(bar_size - 1)); 254 } 255 None 256 } 257 258 fn decode_32_bits_bar_size(bar_size: u32) -> Option<u32> { 259 if bar_size > 0 { 260 return Some(!bar_size + 1); 261 } 262 None 263 } 264 265 fn encode_64_bits_bar_size(bar_size: u64) -> Option<(u32, u32)> { 266 if bar_size > 0 { 267 let result = !(bar_size - 1); 268 let result_hi = (result >> 32) as u32; 269 let result_lo = (result & 0xffff_ffff) as u32; 270 return Some((result_hi, result_lo)); 271 } 272 None 273 } 274 275 fn decode_64_bits_bar_size(bar_size_hi: u32, bar_size_lo: u32) -> Option<u64> { 276 let bar_size: u64 = ((bar_size_hi as u64) << 32) | (bar_size_lo as u64); 277 if bar_size > 0 { 278 return Some(!bar_size + 1); 279 } 280 None 281 } 282 283 #[derive(Default, Clone, Copy, Versionize)] 284 struct PciBar { 285 addr: u32, 286 size: u32, 287 used: bool, 288 r#type: Option<PciBarRegionType>, 289 } 290 291 #[derive(Versionize)] 292 struct PciConfigurationState { 293 registers: Vec<u32>, 294 writable_bits: Vec<u32>, 295 bars: Vec<PciBar>, 296 rom_bar_addr: u32, 297 rom_bar_size: u32, 298 rom_bar_used: bool, 299 last_capability: Option<(usize, usize)>, 300 msix_cap_reg_idx: Option<usize>, 301 } 302 303 impl VersionMapped for PciConfigurationState {} 304 305 /// Contains the configuration space of a PCI node. 306 /// See the [specification](https://en.wikipedia.org/wiki/PCI_configuration_space). 307 /// The configuration space is accessed with DWORD reads and writes from the guest. 308 pub struct PciConfiguration { 309 registers: [u32; NUM_CONFIGURATION_REGISTERS], 310 writable_bits: [u32; NUM_CONFIGURATION_REGISTERS], // writable bits for each register. 311 bars: [PciBar; NUM_BAR_REGS], 312 rom_bar_addr: u32, 313 rom_bar_size: u32, 314 rom_bar_used: bool, 315 // Contains the byte offset and size of the last capability. 316 last_capability: Option<(usize, usize)>, 317 msix_cap_reg_idx: Option<usize>, 318 msix_config: Option<Arc<Mutex<MsixConfig>>>, 319 } 320 321 /// See pci_regs.h in kernel 322 #[derive(Copy, Clone, PartialEq, Versionize, Debug)] 323 pub enum PciBarRegionType { 324 Memory32BitRegion = 0, 325 IoRegion = 0x01, 326 Memory64BitRegion = 0x04, 327 } 328 329 #[derive(Copy, Clone)] 330 pub enum PciBarPrefetchable { 331 NotPrefetchable = 0, 332 Prefetchable = 0x08, 333 } 334 335 #[derive(Copy, Clone)] 336 pub struct PciBarConfiguration { 337 addr: u64, 338 size: u64, 339 reg_idx: usize, 340 region_type: PciBarRegionType, 341 prefetchable: PciBarPrefetchable, 342 } 343 344 #[derive(Debug)] 345 pub enum Error { 346 BarAddressInvalid(u64, u64), 347 BarInUse(usize), 348 BarInUse64(usize), 349 BarInvalid(usize), 350 BarInvalid64(usize), 351 BarSizeInvalid(u64), 352 CapabilityEmpty, 353 CapabilityLengthInvalid(usize), 354 CapabilitySpaceFull(usize), 355 Decode32BarSize, 356 Decode64BarSize, 357 Encode32BarSize, 358 Encode64BarSize, 359 RomBarAddressInvalid(u64, u64), 360 RomBarInUse(usize), 361 RomBarInvalid(usize), 362 RomBarSizeInvalid(u64), 363 } 364 pub type Result<T> = std::result::Result<T, Error>; 365 366 impl std::error::Error for Error {} 367 368 impl Display for Error { 369 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 370 use self::Error::*; 371 match self { 372 BarAddressInvalid(a, s) => write!(f, "address {} size {} too big", a, s), 373 BarInUse(b) => write!(f, "bar {} already used", b), 374 BarInUse64(b) => write!(f, "64bit bar {} already used(requires two regs)", b), 375 BarInvalid(b) => write!(f, "bar {} invalid, max {}", b, NUM_BAR_REGS - 1), 376 BarInvalid64(b) => write!( 377 f, 378 "64bitbar {} invalid, requires two regs, max {}", 379 b, 380 NUM_BAR_REGS - 1 381 ), 382 BarSizeInvalid(s) => write!(f, "bar address {} not a power of two", s), 383 CapabilityEmpty => write!(f, "empty capabilities are invalid"), 384 CapabilityLengthInvalid(l) => write!(f, "Invalid capability length {}", l), 385 CapabilitySpaceFull(s) => write!(f, "capability of size {} doesn't fit", s), 386 Decode32BarSize => write!(f, "failed to decode 32 bits BAR size"), 387 Decode64BarSize => write!(f, "failed to decode 64 bits BAR size"), 388 Encode32BarSize => write!(f, "failed to encode 32 bits BAR size"), 389 Encode64BarSize => write!(f, "failed to encode 64 bits BAR size"), 390 RomBarAddressInvalid(a, s) => write!(f, "address {} size {} too big", a, s), 391 RomBarInUse(b) => write!(f, "rom bar {} already used", b), 392 RomBarInvalid(b) => write!(f, "rom bar {} invalid, max {}", b, NUM_BAR_REGS - 1), 393 RomBarSizeInvalid(s) => write!(f, "rom bar address {} not a power of two", s), 394 } 395 } 396 } 397 398 impl PciConfiguration { 399 #[allow(clippy::too_many_arguments)] 400 pub fn new( 401 vendor_id: u16, 402 device_id: u16, 403 revision_id: u8, 404 class_code: PciClassCode, 405 subclass: &dyn PciSubclass, 406 programming_interface: Option<&dyn PciProgrammingInterface>, 407 header_type: PciHeaderType, 408 subsystem_vendor_id: u16, 409 subsystem_id: u16, 410 msix_config: Option<Arc<Mutex<MsixConfig>>>, 411 ) -> Self { 412 let mut registers = [0u32; NUM_CONFIGURATION_REGISTERS]; 413 let mut writable_bits = [0u32; NUM_CONFIGURATION_REGISTERS]; 414 registers[0] = u32::from(device_id) << 16 | u32::from(vendor_id); 415 // TODO(dverkamp): Status should be write-1-to-clear 416 writable_bits[1] = 0x0000_ffff; // Status (r/o), command (r/w) 417 let pi = if let Some(pi) = programming_interface { 418 pi.get_register_value() 419 } else { 420 0 421 }; 422 registers[2] = u32::from(class_code.get_register_value()) << 24 423 | u32::from(subclass.get_register_value()) << 16 424 | u32::from(pi) << 8 425 | u32::from(revision_id); 426 writable_bits[3] = 0x0000_00ff; // Cacheline size (r/w) 427 match header_type { 428 PciHeaderType::Device => { 429 registers[3] = 0x0000_0000; // Header type 0 (device) 430 writable_bits[15] = 0x0000_00ff; // Interrupt line (r/w) 431 } 432 PciHeaderType::Bridge => { 433 registers[3] = 0x0001_0000; // Header type 1 (bridge) 434 writable_bits[9] = 0xfff0_fff0; // Memory base and limit 435 writable_bits[15] = 0xffff_00ff; // Bridge control (r/w), interrupt line (r/w) 436 } 437 }; 438 registers[11] = u32::from(subsystem_id) << 16 | u32::from(subsystem_vendor_id); 439 440 let bars = [PciBar::default(); NUM_BAR_REGS]; 441 442 PciConfiguration { 443 registers, 444 writable_bits, 445 bars, 446 rom_bar_addr: 0, 447 rom_bar_size: 0, 448 rom_bar_used: false, 449 last_capability: None, 450 msix_cap_reg_idx: None, 451 msix_config, 452 } 453 } 454 455 fn state(&self) -> PciConfigurationState { 456 PciConfigurationState { 457 registers: self.registers.to_vec(), 458 writable_bits: self.writable_bits.to_vec(), 459 bars: self.bars.to_vec(), 460 rom_bar_addr: self.rom_bar_addr, 461 rom_bar_size: self.rom_bar_size, 462 rom_bar_used: self.rom_bar_used, 463 last_capability: self.last_capability, 464 msix_cap_reg_idx: self.msix_cap_reg_idx, 465 } 466 } 467 468 fn set_state(&mut self, state: &PciConfigurationState) { 469 self.registers.clone_from_slice(state.registers.as_slice()); 470 self.writable_bits 471 .clone_from_slice(state.writable_bits.as_slice()); 472 self.bars.clone_from_slice(state.bars.as_slice()); 473 self.rom_bar_addr = state.rom_bar_addr; 474 self.rom_bar_size = state.rom_bar_size; 475 self.rom_bar_used = state.rom_bar_used; 476 self.last_capability = state.last_capability; 477 self.msix_cap_reg_idx = state.msix_cap_reg_idx; 478 } 479 480 /// Reads a 32bit register from `reg_idx` in the register map. 481 pub fn read_reg(&self, reg_idx: usize) -> u32 { 482 *(self.registers.get(reg_idx).unwrap_or(&0xffff_ffff)) 483 } 484 485 /// Writes a 32bit register to `reg_idx` in the register map. 486 pub fn write_reg(&mut self, reg_idx: usize, value: u32) { 487 let mut mask = self.writable_bits[reg_idx]; 488 489 if (BAR0_REG..BAR0_REG + NUM_BAR_REGS).contains(®_idx) { 490 // Handle very specific case where the BAR is being written with 491 // all 1's to retrieve the BAR size during next BAR reading. 492 if value == 0xffff_ffff { 493 mask &= self.bars[reg_idx - 4].size; 494 } 495 } else if reg_idx == ROM_BAR_REG { 496 // Handle very specific case where the BAR is being written with 497 // all 1's on bits 31-11 to retrieve the BAR size during next BAR 498 // reading. 499 if value & ROM_BAR_ADDR_MASK == ROM_BAR_ADDR_MASK { 500 mask &= self.rom_bar_size; 501 } 502 } 503 504 if let Some(r) = self.registers.get_mut(reg_idx) { 505 *r = (*r & !self.writable_bits[reg_idx]) | (value & mask); 506 } else { 507 warn!("bad PCI register write {}", reg_idx); 508 } 509 } 510 511 /// Writes a 16bit word to `offset`. `offset` must be 16bit aligned. 512 pub fn write_word(&mut self, offset: usize, value: u16) { 513 let shift = match offset % 4 { 514 0 => 0, 515 2 => 16, 516 _ => { 517 warn!("bad PCI config write offset {}", offset); 518 return; 519 } 520 }; 521 let reg_idx = offset / 4; 522 523 if let Some(r) = self.registers.get_mut(reg_idx) { 524 let writable_mask = self.writable_bits[reg_idx]; 525 let mask = (0xffffu32 << shift) & writable_mask; 526 let shifted_value = (u32::from(value) << shift) & writable_mask; 527 *r = *r & !mask | shifted_value; 528 } else { 529 warn!("bad PCI config write offset {}", offset); 530 } 531 } 532 533 /// Writes a byte to `offset`. 534 pub fn write_byte(&mut self, offset: usize, value: u8) { 535 self.write_byte_internal(offset, value, true); 536 } 537 538 /// Writes a byte to `offset`, optionally enforcing read-only bits. 539 fn write_byte_internal(&mut self, offset: usize, value: u8, apply_writable_mask: bool) { 540 let shift = (offset % 4) * 8; 541 let reg_idx = offset / 4; 542 543 if let Some(r) = self.registers.get_mut(reg_idx) { 544 let writable_mask = if apply_writable_mask { 545 self.writable_bits[reg_idx] 546 } else { 547 0xffff_ffff 548 }; 549 let mask = (0xffu32 << shift) & writable_mask; 550 let shifted_value = (u32::from(value) << shift) & writable_mask; 551 *r = *r & !mask | shifted_value; 552 } else { 553 warn!("bad PCI config write offset {}", offset); 554 } 555 } 556 557 /// Adds a region specified by `config`. Configures the specified BAR(s) to 558 /// report this region and size to the guest kernel. Enforces a few constraints 559 /// (i.e, region size must be power of two, register not already used). Returns 'None' on 560 /// failure all, `Some(BarIndex)` on success. 561 pub fn add_pci_bar(&mut self, config: &PciBarConfiguration) -> Result<usize> { 562 if self.bars[config.reg_idx].used { 563 return Err(Error::BarInUse(config.reg_idx)); 564 } 565 566 if config.size.count_ones() != 1 { 567 return Err(Error::BarSizeInvalid(config.size)); 568 } 569 570 if config.reg_idx >= NUM_BAR_REGS { 571 return Err(Error::BarInvalid(config.reg_idx)); 572 } 573 574 let bar_idx = BAR0_REG + config.reg_idx; 575 let end_addr = config 576 .addr 577 .checked_add(config.size - 1) 578 .ok_or(Error::BarAddressInvalid(config.addr, config.size))?; 579 match config.region_type { 580 PciBarRegionType::Memory32BitRegion | PciBarRegionType::IoRegion => { 581 if end_addr > u64::from(u32::max_value()) { 582 return Err(Error::BarAddressInvalid(config.addr, config.size)); 583 } 584 585 // Encode the BAR size as expected by the software running in 586 // the guest. 587 self.bars[config.reg_idx].size = 588 encode_32_bits_bar_size(config.size as u32).ok_or(Error::Encode32BarSize)?; 589 } 590 PciBarRegionType::Memory64BitRegion => { 591 if config.reg_idx + 1 >= NUM_BAR_REGS { 592 return Err(Error::BarInvalid64(config.reg_idx)); 593 } 594 595 if end_addr > u64::max_value() { 596 return Err(Error::BarAddressInvalid(config.addr, config.size)); 597 } 598 599 if self.bars[config.reg_idx + 1].used { 600 return Err(Error::BarInUse64(config.reg_idx)); 601 } 602 603 // Encode the BAR size as expected by the software running in 604 // the guest. 605 let (bar_size_hi, bar_size_lo) = 606 encode_64_bits_bar_size(config.size).ok_or(Error::Encode64BarSize)?; 607 608 self.registers[bar_idx + 1] = (config.addr >> 32) as u32; 609 self.writable_bits[bar_idx + 1] = 0xffff_ffff; 610 self.bars[config.reg_idx + 1].addr = self.registers[bar_idx + 1]; 611 self.bars[config.reg_idx].size = bar_size_lo; 612 self.bars[config.reg_idx + 1].size = bar_size_hi; 613 self.bars[config.reg_idx + 1].used = true; 614 } 615 } 616 617 let (mask, lower_bits) = match config.region_type { 618 PciBarRegionType::Memory32BitRegion | PciBarRegionType::Memory64BitRegion => ( 619 BAR_MEM_ADDR_MASK, 620 config.prefetchable as u32 | config.region_type as u32, 621 ), 622 PciBarRegionType::IoRegion => (BAR_IO_ADDR_MASK, config.region_type as u32), 623 }; 624 625 self.registers[bar_idx] = ((config.addr as u32) & mask) | lower_bits; 626 self.writable_bits[bar_idx] = mask; 627 self.bars[config.reg_idx].addr = self.registers[bar_idx]; 628 self.bars[config.reg_idx].used = true; 629 self.bars[config.reg_idx].r#type = Some(config.region_type); 630 Ok(config.reg_idx) 631 } 632 633 /// Adds rom expansion BAR. 634 pub fn add_pci_rom_bar(&mut self, config: &PciBarConfiguration, active: u32) -> Result<usize> { 635 if self.rom_bar_used { 636 return Err(Error::RomBarInUse(config.reg_idx)); 637 } 638 639 if config.size.count_ones() != 1 { 640 return Err(Error::RomBarSizeInvalid(config.size)); 641 } 642 643 if config.reg_idx != ROM_BAR_REG { 644 return Err(Error::RomBarInvalid(config.reg_idx)); 645 } 646 647 let end_addr = config 648 .addr 649 .checked_add(config.size - 1) 650 .ok_or(Error::RomBarAddressInvalid(config.addr, config.size))?; 651 652 if end_addr > u64::from(u32::max_value()) { 653 return Err(Error::RomBarAddressInvalid(config.addr, config.size)); 654 } 655 656 self.registers[config.reg_idx] = (config.addr as u32) | active; 657 self.writable_bits[config.reg_idx] = ROM_BAR_ADDR_MASK; 658 self.rom_bar_addr = self.registers[config.reg_idx]; 659 self.rom_bar_size = 660 encode_32_bits_bar_size(config.size as u32).ok_or(Error::Encode32BarSize)?; 661 self.rom_bar_used = true; 662 Ok(config.reg_idx) 663 } 664 665 /// Returns the address of the given BAR region. 666 pub fn get_bar_addr(&self, bar_num: usize) -> u64 { 667 let bar_idx = BAR0_REG + bar_num; 668 669 let mut addr = u64::from(self.bars[bar_num].addr & self.writable_bits[bar_idx]); 670 671 if let Some(bar_type) = self.bars[bar_num].r#type { 672 if bar_type == PciBarRegionType::Memory64BitRegion { 673 addr |= u64::from(self.bars[bar_num + 1].addr) << 32; 674 } 675 } 676 677 addr 678 } 679 680 /// Configures the IRQ line and pin used by this device. 681 pub fn set_irq(&mut self, line: u8, pin: PciInterruptPin) { 682 // `pin` is 1-based in the pci config space. 683 let pin_idx = (pin as u32) + 1; 684 self.registers[INTERRUPT_LINE_PIN_REG] = (self.registers[INTERRUPT_LINE_PIN_REG] 685 & 0xffff_0000) 686 | (pin_idx << 8) 687 | u32::from(line); 688 } 689 690 /// Adds the capability `cap_data` to the list of capabilities. 691 /// `cap_data` should include the two-byte PCI capability header (type, next), 692 /// but not populate it. Correct values will be generated automatically based 693 /// on `cap_data.id()`. 694 pub fn add_capability(&mut self, cap_data: &dyn PciCapability) -> Result<usize> { 695 let total_len = cap_data.bytes().len(); 696 // Check that the length is valid. 697 if cap_data.bytes().is_empty() { 698 return Err(Error::CapabilityEmpty); 699 } 700 let (cap_offset, tail_offset) = match self.last_capability { 701 Some((offset, len)) => (Self::next_dword(offset, len), offset + 1), 702 None => (FIRST_CAPABILITY_OFFSET, CAPABILITY_LIST_HEAD_OFFSET), 703 }; 704 let end_offset = cap_offset 705 .checked_add(total_len) 706 .ok_or(Error::CapabilitySpaceFull(total_len))?; 707 if end_offset > CAPABILITY_MAX_OFFSET { 708 return Err(Error::CapabilitySpaceFull(total_len)); 709 } 710 self.registers[STATUS_REG] |= STATUS_REG_CAPABILITIES_USED_MASK; 711 self.write_byte_internal(tail_offset, cap_offset as u8, false); 712 self.write_byte_internal(cap_offset, cap_data.id() as u8, false); 713 self.write_byte_internal(cap_offset + 1, 0, false); // Next pointer. 714 for (i, byte) in cap_data.bytes().iter().enumerate() { 715 self.write_byte_internal(cap_offset + i + 2, *byte, false); 716 } 717 self.last_capability = Some((cap_offset, total_len)); 718 719 match cap_data.id() { 720 PciCapabilityId::MessageSignalledInterrupts => { 721 self.writable_bits[cap_offset / 4] = MSI_CAPABILITY_REGISTER_MASK; 722 } 723 PciCapabilityId::MsiX => { 724 self.msix_cap_reg_idx = Some(cap_offset / 4); 725 self.writable_bits[self.msix_cap_reg_idx.unwrap()] = MSIX_CAPABILITY_REGISTER_MASK; 726 } 727 _ => {} 728 } 729 730 Ok(cap_offset) 731 } 732 733 // Find the next aligned offset after the one given. 734 fn next_dword(offset: usize, len: usize) -> usize { 735 let next = offset + len; 736 (next + 3) & !3 737 } 738 739 pub fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]) { 740 if offset as usize + data.len() > 4 { 741 return; 742 } 743 744 // Handle potential write to MSI-X message control register 745 if let Some(msix_cap_reg_idx) = self.msix_cap_reg_idx { 746 if let Some(msix_config) = &self.msix_config { 747 if msix_cap_reg_idx == reg_idx && offset == 2 && data.len() == 2 { 748 msix_config 749 .lock() 750 .unwrap() 751 .set_msg_ctl(LittleEndian::read_u16(data)); 752 } else if msix_cap_reg_idx == reg_idx && offset == 0 && data.len() == 4 { 753 msix_config 754 .lock() 755 .unwrap() 756 .set_msg_ctl((LittleEndian::read_u32(data) >> 16) as u16); 757 } 758 } 759 } 760 761 match data.len() { 762 1 => self.write_byte(reg_idx * 4 + offset as usize, data[0]), 763 2 => self.write_word( 764 reg_idx * 4 + offset as usize, 765 u16::from(data[0]) | u16::from(data[1]) << 8, 766 ), 767 4 => self.write_reg(reg_idx, LittleEndian::read_u32(data)), 768 _ => (), 769 } 770 } 771 772 pub fn read_config_register(&self, reg_idx: usize) -> u32 { 773 self.read_reg(reg_idx) 774 } 775 776 pub fn detect_bar_reprogramming( 777 &mut self, 778 reg_idx: usize, 779 data: &[u8], 780 ) -> Option<BarReprogrammingParams> { 781 if data.len() != 4 { 782 return None; 783 } 784 785 let value = LittleEndian::read_u32(data); 786 787 let mask = self.writable_bits[reg_idx]; 788 if (BAR0_REG..BAR0_REG + NUM_BAR_REGS).contains(®_idx) { 789 // Ignore the case where the BAR size is being asked for. 790 if value == 0xffff_ffff { 791 return None; 792 } 793 794 let bar_idx = reg_idx - 4; 795 // Handle special case where the address being written is 796 // different from the address initially provided. This is a 797 // BAR reprogramming case which needs to be properly caught. 798 if let Some(bar_type) = self.bars[bar_idx].r#type { 799 // In case of 64 bits memory BAR, we don't do anything until 800 // the upper BAR is modified, otherwise we would be moving the 801 // BAR to a wrong location in memory. 802 if bar_type == PciBarRegionType::Memory64BitRegion { 803 return None; 804 } 805 806 // Ignore the case where the value is unchanged. 807 if (value & mask) == (self.bars[bar_idx].addr & mask) { 808 return None; 809 } 810 811 info!( 812 "Detected BAR reprogramming: (BAR {}) 0x{:x}->0x{:x}", 813 reg_idx, self.registers[reg_idx], value 814 ); 815 let old_base = u64::from(self.bars[bar_idx].addr & mask); 816 let new_base = u64::from(value & mask); 817 let len = u64::from( 818 decode_32_bits_bar_size(self.bars[bar_idx].size) 819 .ok_or(Error::Decode32BarSize) 820 .unwrap(), 821 ); 822 let region_type = bar_type; 823 824 self.bars[bar_idx].addr = value; 825 826 return Some(BarReprogrammingParams { 827 old_base, 828 new_base, 829 len, 830 region_type, 831 }); 832 } else if (reg_idx > BAR0_REG) 833 && ((self.registers[reg_idx - 1] & self.writable_bits[reg_idx - 1]) 834 != (self.bars[bar_idx - 1].addr & self.writable_bits[reg_idx - 1]) 835 || (value & mask) != (self.bars[bar_idx].addr & mask)) 836 { 837 info!( 838 "Detected BAR reprogramming: (BAR {}) 0x{:x}->0x{:x}", 839 reg_idx, self.registers[reg_idx], value 840 ); 841 let old_base = u64::from(self.bars[bar_idx].addr & mask) << 32 842 | u64::from(self.bars[bar_idx - 1].addr & self.writable_bits[reg_idx - 1]); 843 let new_base = u64::from(value & mask) << 32 844 | u64::from(self.registers[reg_idx - 1] & self.writable_bits[reg_idx - 1]); 845 let len = 846 decode_64_bits_bar_size(self.bars[bar_idx].size, self.bars[bar_idx - 1].size) 847 .ok_or(Error::Decode64BarSize) 848 .unwrap(); 849 let region_type = PciBarRegionType::Memory64BitRegion; 850 851 self.bars[bar_idx].addr = value; 852 self.bars[bar_idx - 1].addr = self.registers[reg_idx - 1]; 853 854 return Some(BarReprogrammingParams { 855 old_base, 856 new_base, 857 len, 858 region_type, 859 }); 860 } 861 } else if reg_idx == ROM_BAR_REG && (value & mask) != (self.rom_bar_addr & mask) { 862 // Ignore the case where the BAR size is being asked for. 863 if value & ROM_BAR_ADDR_MASK == ROM_BAR_ADDR_MASK { 864 return None; 865 } 866 867 info!( 868 "Detected ROM BAR reprogramming: (BAR {}) 0x{:x}->0x{:x}", 869 reg_idx, self.registers[reg_idx], value 870 ); 871 let old_base = u64::from(self.rom_bar_addr & mask); 872 let new_base = u64::from(value & mask); 873 let len = u64::from( 874 decode_32_bits_bar_size(self.rom_bar_size) 875 .ok_or(Error::Decode32BarSize) 876 .unwrap(), 877 ); 878 let region_type = PciBarRegionType::Memory32BitRegion; 879 880 self.rom_bar_addr = value; 881 882 return Some(BarReprogrammingParams { 883 old_base, 884 new_base, 885 len, 886 region_type, 887 }); 888 } 889 890 None 891 } 892 } 893 894 impl Pausable for PciConfiguration {} 895 896 impl Snapshottable for PciConfiguration { 897 fn id(&self) -> String { 898 String::from("pci_configuration") 899 } 900 901 fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> { 902 Snapshot::new_from_versioned_state(&self.id(), &self.state()) 903 } 904 905 fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> { 906 self.set_state(&snapshot.to_versioned_state(&self.id())?); 907 Ok(()) 908 } 909 } 910 911 impl Default for PciBarConfiguration { 912 fn default() -> Self { 913 PciBarConfiguration { 914 reg_idx: 0, 915 addr: 0, 916 size: 0, 917 region_type: PciBarRegionType::Memory64BitRegion, 918 prefetchable: PciBarPrefetchable::NotPrefetchable, 919 } 920 } 921 } 922 923 impl PciBarConfiguration { 924 pub fn new( 925 reg_idx: usize, 926 size: u64, 927 region_type: PciBarRegionType, 928 prefetchable: PciBarPrefetchable, 929 ) -> Self { 930 PciBarConfiguration { 931 reg_idx, 932 addr: 0, 933 size, 934 region_type, 935 prefetchable, 936 } 937 } 938 939 #[must_use] 940 pub fn set_register_index(mut self, reg_idx: usize) -> Self { 941 self.reg_idx = reg_idx; 942 self 943 } 944 945 #[must_use] 946 pub fn set_address(mut self, addr: u64) -> Self { 947 self.addr = addr; 948 self 949 } 950 951 #[must_use] 952 pub fn set_size(mut self, size: u64) -> Self { 953 self.size = size; 954 self 955 } 956 957 pub fn get_size(&self) -> u64 { 958 self.size 959 } 960 961 #[must_use] 962 pub fn set_region_type(mut self, region_type: PciBarRegionType) -> Self { 963 self.region_type = region_type; 964 self 965 } 966 } 967 968 #[cfg(test)] 969 mod tests { 970 use vm_memory::ByteValued; 971 972 use super::*; 973 974 #[repr(packed)] 975 #[derive(Clone, Copy, Default)] 976 #[allow(dead_code)] 977 struct TestCap { 978 len: u8, 979 foo: u8, 980 } 981 982 // SAFETY: All members are simple numbers and any value is valid. 983 unsafe impl ByteValued for TestCap {} 984 985 impl PciCapability for TestCap { 986 fn bytes(&self) -> &[u8] { 987 self.as_slice() 988 } 989 990 fn id(&self) -> PciCapabilityId { 991 PciCapabilityId::VendorSpecific 992 } 993 } 994 995 #[test] 996 fn add_capability() { 997 let mut cfg = PciConfiguration::new( 998 0x1234, 999 0x5678, 1000 0x1, 1001 PciClassCode::MultimediaController, 1002 &PciMultimediaSubclass::AudioController, 1003 None, 1004 PciHeaderType::Device, 1005 0xABCD, 1006 0x2468, 1007 None, 1008 ); 1009 1010 // Add two capabilities with different contents. 1011 let cap1 = TestCap { len: 4, foo: 0xAA }; 1012 let cap1_offset = cfg.add_capability(&cap1).unwrap(); 1013 assert_eq!(cap1_offset % 4, 0); 1014 1015 let cap2 = TestCap { 1016 len: 0x04, 1017 foo: 0x55, 1018 }; 1019 let cap2_offset = cfg.add_capability(&cap2).unwrap(); 1020 assert_eq!(cap2_offset % 4, 0); 1021 1022 // The capability list head should be pointing to cap1. 1023 let cap_ptr = cfg.read_reg(CAPABILITY_LIST_HEAD_OFFSET / 4) & 0xFF; 1024 assert_eq!(cap1_offset, cap_ptr as usize); 1025 1026 // Verify the contents of the capabilities. 1027 let cap1_data = cfg.read_reg(cap1_offset / 4); 1028 assert_eq!(cap1_data & 0xFF, 0x09); // capability ID 1029 assert_eq!((cap1_data >> 8) & 0xFF, cap2_offset as u32); // next capability pointer 1030 assert_eq!((cap1_data >> 16) & 0xFF, 0x04); // cap1.len 1031 assert_eq!((cap1_data >> 24) & 0xFF, 0xAA); // cap1.foo 1032 1033 let cap2_data = cfg.read_reg(cap2_offset / 4); 1034 assert_eq!(cap2_data & 0xFF, 0x09); // capability ID 1035 assert_eq!((cap2_data >> 8) & 0xFF, 0x00); // next capability pointer 1036 assert_eq!((cap2_data >> 16) & 0xFF, 0x04); // cap2.len 1037 assert_eq!((cap2_data >> 24) & 0xFF, 0x55); // cap2.foo 1038 } 1039 1040 #[derive(Copy, Clone)] 1041 enum TestPi { 1042 Test = 0x5a, 1043 } 1044 1045 impl PciProgrammingInterface for TestPi { 1046 fn get_register_value(&self) -> u8 { 1047 *self as u8 1048 } 1049 } 1050 1051 #[test] 1052 fn class_code() { 1053 let cfg = PciConfiguration::new( 1054 0x1234, 1055 0x5678, 1056 0x1, 1057 PciClassCode::MultimediaController, 1058 &PciMultimediaSubclass::AudioController, 1059 Some(&TestPi::Test), 1060 PciHeaderType::Device, 1061 0xABCD, 1062 0x2468, 1063 None, 1064 ); 1065 1066 let class_reg = cfg.read_reg(2); 1067 let class_code = (class_reg >> 24) & 0xFF; 1068 let subclass = (class_reg >> 16) & 0xFF; 1069 let prog_if = (class_reg >> 8) & 0xFF; 1070 assert_eq!(class_code, 0x04); 1071 assert_eq!(subclass, 0x01); 1072 assert_eq!(prog_if, 0x5a); 1073 } 1074 } 1075