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