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