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