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