xref: /cloud-hypervisor/pci/src/configuration.rs (revision f67b3f79ea19c9a66e04074cbbf5d292f6529e43)
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(&reg_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(&reg_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                 info!(
798                     "Detected BAR reprogramming: (BAR {}) 0x{:x}->0x{:x}",
799                     reg_idx, 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                 info!(
824                     "Detected BAR reprogramming: (BAR {}) 0x{:x}->0x{:x}",
825                     reg_idx, 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             info!(
854                 "Detected ROM BAR reprogramming: (BAR {}) 0x{:x}->0x{:x}",
855                 reg_idx, 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