xref: /cloud-hypervisor/pci/src/configuration.rs (revision b440cb7d2330770cd415b63544a371d4caa2db3a)
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(&reg_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(&reg_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