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