xref: /cloud-hypervisor/pci/src/lib.rs (revision 6f8bd27cf7629733582d930519e98d19e90afb16)
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 //! Implements pci devices and busses.
6 #[macro_use]
7 extern crate log;
8 
9 mod bus;
10 mod configuration;
11 mod device;
12 mod msi;
13 mod msix;
14 mod vfio;
15 mod vfio_user;
16 
17 pub use self::bus::{PciBus, PciConfigIo, PciConfigMmio, PciRoot, PciRootError};
18 pub use self::configuration::{
19     PciBarConfiguration, PciBarPrefetchable, PciBarRegionType, PciCapability, PciCapabilityId,
20     PciClassCode, PciConfiguration, PciExpressCapabilityId, PciHeaderType, PciMassStorageSubclass,
21     PciNetworkControllerSubclass, PciProgrammingInterface, PciSerialBusSubClass, PciSubclass,
22     PCI_CONFIGURATION_ID,
23 };
24 pub use self::device::{
25     BarReprogrammingParams, DeviceRelocation, Error as PciDeviceError, PciDevice,
26 };
27 pub use self::msi::{msi_num_enabled_vectors, MsiCap, MsiConfig};
28 pub use self::msix::{MsixCap, MsixConfig, MsixTableEntry, MSIX_CONFIG_ID, MSIX_TABLE_ENTRY_SIZE};
29 pub use self::vfio::{VfioPciDevice, VfioPciError};
30 pub use self::vfio_user::{VfioUserDmaMapping, VfioUserPciDevice, VfioUserPciDeviceError};
31 use serde::de::Visitor;
32 use std::fmt::{self, Display};
33 use std::num::ParseIntError;
34 use std::str::FromStr;
35 
36 /// PCI has four interrupt pins A->D.
37 #[derive(Copy, Clone)]
38 pub enum PciInterruptPin {
39     IntA,
40     IntB,
41     IntC,
42     IntD,
43 }
44 
45 impl PciInterruptPin {
46     pub fn to_mask(self) -> u32 {
47         self as u32
48     }
49 }
50 
51 #[cfg(target_arch = "x86_64")]
52 pub const PCI_CONFIG_IO_PORT: u64 = 0xcf8;
53 #[cfg(target_arch = "x86_64")]
54 pub const PCI_CONFIG_IO_PORT_SIZE: u64 = 0x8;
55 
56 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd)]
57 pub struct PciBdf(u32);
58 
59 struct PciBdfVisitor;
60 
61 impl<'de> Visitor<'de> for PciBdfVisitor {
62     type Value = PciBdf;
63 
64     fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
65         formatter.write_str("struct PciBdf")
66     }
67 
68     fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
69     where
70         E: serde::de::Error,
71     {
72         Ok(v.into())
73     }
74 }
75 
76 impl<'de> serde::Deserialize<'de> for PciBdf {
77     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
78     where
79         D: serde::Deserializer<'de>,
80     {
81         deserializer.deserialize_str(PciBdfVisitor)
82     }
83 }
84 
85 impl serde::Serialize for PciBdf {
86     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
87     where
88         S: serde::Serializer,
89     {
90         serializer.collect_str(&self.to_string())
91     }
92 }
93 
94 impl PciBdf {
95     pub fn segment(&self) -> u16 {
96         ((self.0 >> 16) & 0xffff) as u16
97     }
98 
99     pub fn bus(&self) -> u8 {
100         ((self.0 >> 8) & 0xff) as u8
101     }
102 
103     pub fn device(&self) -> u8 {
104         ((self.0 >> 3) & 0x1f) as u8
105     }
106 
107     pub fn function(&self) -> u8 {
108         (self.0 & 0x7) as u8
109     }
110 
111     pub fn new(segment: u16, bus: u8, device: u8, function: u8) -> Self {
112         Self(
113             (segment as u32) << 16
114                 | (bus as u32) << 8
115                 | ((device & 0x1f) as u32) << 3
116                 | (function & 0x7) as u32,
117         )
118     }
119 }
120 
121 impl From<u32> for PciBdf {
122     fn from(bdf: u32) -> Self {
123         Self(bdf)
124     }
125 }
126 
127 impl From<PciBdf> for u32 {
128     fn from(bdf: PciBdf) -> Self {
129         bdf.0
130     }
131 }
132 
133 impl From<&PciBdf> for u32 {
134     fn from(bdf: &PciBdf) -> Self {
135         bdf.0
136     }
137 }
138 
139 impl From<PciBdf> for u16 {
140     fn from(bdf: PciBdf) -> Self {
141         (bdf.0 & 0xffff) as u16
142     }
143 }
144 
145 impl From<&PciBdf> for u16 {
146     fn from(bdf: &PciBdf) -> Self {
147         (bdf.0 & 0xffff) as u16
148     }
149 }
150 
151 impl Display for PciBdf {
152     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
153         write!(
154             f,
155             "{:04x}:{:02x}:{:02x}.{:01x}",
156             self.segment(),
157             self.bus(),
158             self.device(),
159             self.function()
160         )
161     }
162 }
163 
164 impl FromStr for PciBdf {
165     type Err = ParseIntError;
166 
167     fn from_str(s: &str) -> Result<Self, Self::Err> {
168         let items: Vec<&str> = s.split('.').collect();
169         assert_eq!(items.len(), 2);
170         let function = u8::from_str_radix(items[1], 16)?;
171         let items: Vec<&str> = items[0].split(':').collect();
172         assert_eq!(items.len(), 3);
173         let segment = u16::from_str_radix(items[0], 16)?;
174         let bus = u8::from_str_radix(items[1], 16)?;
175         let device = u8::from_str_radix(items[2], 16)?;
176         Ok(PciBdf::new(segment, bus, device, function))
177     }
178 }
179 
180 impl From<&str> for PciBdf {
181     fn from(bdf: &str) -> Self {
182         Self::from_str(bdf).unwrap()
183     }
184 }
185