xref: /cloud-hypervisor/pci/src/lib.rs (revision 8c072946915d9ef7aca6e9b7d406fa11a119d330)
1e8308dd1SSamuel Ortiz // Copyright 2018 The Chromium OS Authors. All rights reserved.
2e8308dd1SSamuel Ortiz // Use of this source code is governed by a BSD-style license that can be
3040ea543SSamuel Ortiz // found in the LICENSE-BSD-3-Clause file.
45e9886bbSRuslan Mstoi //
55e9886bbSRuslan Mstoi // SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
6e8308dd1SSamuel Ortiz 
7e8308dd1SSamuel Ortiz //! Implements pci devices and busses.
8e8308dd1SSamuel Ortiz #[macro_use]
9e8308dd1SSamuel Ortiz extern crate log;
10e8308dd1SSamuel Ortiz 
112bb0b22cSJing Liu mod bus;
12e8308dd1SSamuel Ortiz mod configuration;
13e8308dd1SSamuel Ortiz mod device;
14ee39e465SSebastien Boeuf mod msi;
158df05b72SSebastien Boeuf mod msix;
1653ce5298SSamuel Ortiz mod vfio;
179254b74cSRob Bradford mod vfio_user;
18e8308dd1SSamuel Ortiz 
19*8c072946SArvind Vasudev use std::fmt::{self, Debug, Display};
2088a9f799SRob Bradford use std::num::ParseIntError;
2188a9f799SRob Bradford use std::str::FromStr;
2288a9f799SRob Bradford 
2388a9f799SRob Bradford use serde::de::Visitor;
2488a9f799SRob Bradford 
25833a3d45SRob Bradford pub use self::bus::{PciBus, PciConfigIo, PciConfigMmio, PciRoot, PciRootError};
26e8308dd1SSamuel Ortiz pub use self::configuration::{
27827229d8SRob Bradford     PciBarConfiguration, PciBarPrefetchable, PciBarRegionType, PciCapability, PciCapabilityId,
28e45e3df6SSebastien Boeuf     PciClassCode, PciConfiguration, PciExpressCapabilityId, PciHeaderType, PciMassStorageSubclass,
290b7fb42aSSamuel Ortiz     PciNetworkControllerSubclass, PciProgrammingInterface, PciSerialBusSubClass, PciSubclass,
30eae80438SSebastien Boeuf     PCI_CONFIGURATION_ID,
31e8308dd1SSamuel Ortiz };
322bb0b22cSJing Liu pub use self::device::{
33e91638e6SSebastien Boeuf     BarReprogrammingParams, DeviceRelocation, Error as PciDeviceError, PciDevice,
342bb0b22cSJing Liu };
354bb12a2dSSebastien Boeuf pub use self::msi::{msi_num_enabled_vectors, MsiCap, MsiConfig};
36eae80438SSebastien Boeuf pub use self::msix::{MsixCap, MsixConfig, MsixTableEntry, MSIX_CONFIG_ID, MSIX_TABLE_ENTRY_SIZE};
37045964deSAndrew Carp pub use self::vfio::{MmioRegion, VfioDmaMapping, VfioPciDevice, VfioPciError};
3843365adeSRob Bradford pub use self::vfio_user::{VfioUserDmaMapping, VfioUserPciDevice, VfioUserPciDeviceError};
39e8308dd1SSamuel Ortiz 
40e8308dd1SSamuel Ortiz /// PCI has four interrupt pins A->D.
41e8308dd1SSamuel Ortiz #[derive(Copy, Clone)]
42e8308dd1SSamuel Ortiz pub enum PciInterruptPin {
43e8308dd1SSamuel Ortiz     IntA,
44e8308dd1SSamuel Ortiz     IntB,
45e8308dd1SSamuel Ortiz     IntC,
46e8308dd1SSamuel Ortiz     IntD,
47e8308dd1SSamuel Ortiz }
48e8308dd1SSamuel Ortiz 
49e8308dd1SSamuel Ortiz impl PciInterruptPin {
to_mask(self) -> u3250e8308dd1SSamuel Ortiz     pub fn to_mask(self) -> u32 {
51e8308dd1SSamuel Ortiz         self as u32
52e8308dd1SSamuel Ortiz     }
53e8308dd1SSamuel Ortiz }
540faa7afaSRob Bradford 
550faa7afaSRob Bradford #[cfg(target_arch = "x86_64")]
560faa7afaSRob Bradford pub const PCI_CONFIG_IO_PORT: u64 = 0xcf8;
570faa7afaSRob Bradford #[cfg(target_arch = "x86_64")]
580faa7afaSRob Bradford pub const PCI_CONFIG_IO_PORT_SIZE: u64 = 0x8;
5979e43ac5SRob Bradford 
602716bc33SRob Bradford #[derive(Clone, Copy, PartialEq, Eq, PartialOrd)]
6179e43ac5SRob Bradford pub struct PciBdf(u32);
6279e43ac5SRob Bradford 
6342b5d4a2SSebastien Boeuf struct PciBdfVisitor;
6442b5d4a2SSebastien Boeuf 
650aab960bSRuoqing He impl Visitor<'_> for PciBdfVisitor {
6642b5d4a2SSebastien Boeuf     type Value = PciBdf;
6742b5d4a2SSebastien Boeuf 
expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result6842b5d4a2SSebastien Boeuf     fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
6942b5d4a2SSebastien Boeuf         formatter.write_str("struct PciBdf")
7042b5d4a2SSebastien Boeuf     }
7142b5d4a2SSebastien Boeuf 
visit_str<E>(self, v: &str) -> Result<Self::Value, E> where E: serde::de::Error,7242b5d4a2SSebastien Boeuf     fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
7342b5d4a2SSebastien Boeuf     where
7442b5d4a2SSebastien Boeuf         E: serde::de::Error,
7542b5d4a2SSebastien Boeuf     {
7642b5d4a2SSebastien Boeuf         Ok(v.into())
7742b5d4a2SSebastien Boeuf     }
7842b5d4a2SSebastien Boeuf }
7942b5d4a2SSebastien Boeuf 
8042b5d4a2SSebastien Boeuf impl<'de> serde::Deserialize<'de> for PciBdf {
deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de>,8142b5d4a2SSebastien Boeuf     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
8242b5d4a2SSebastien Boeuf     where
8342b5d4a2SSebastien Boeuf         D: serde::Deserializer<'de>,
8442b5d4a2SSebastien Boeuf     {
8542b5d4a2SSebastien Boeuf         deserializer.deserialize_str(PciBdfVisitor)
8642b5d4a2SSebastien Boeuf     }
8742b5d4a2SSebastien Boeuf }
8842b5d4a2SSebastien Boeuf 
8942b5d4a2SSebastien Boeuf impl serde::Serialize for PciBdf {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer,9042b5d4a2SSebastien Boeuf     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
9142b5d4a2SSebastien Boeuf     where
9242b5d4a2SSebastien Boeuf         S: serde::Serializer,
9342b5d4a2SSebastien Boeuf     {
9442b5d4a2SSebastien Boeuf         serializer.collect_str(&self.to_string())
9542b5d4a2SSebastien Boeuf     }
9642b5d4a2SSebastien Boeuf }
9742b5d4a2SSebastien Boeuf 
9879e43ac5SRob Bradford impl PciBdf {
segment(&self) -> u169979e43ac5SRob Bradford     pub fn segment(&self) -> u16 {
10079e43ac5SRob Bradford         ((self.0 >> 16) & 0xffff) as u16
10179e43ac5SRob Bradford     }
10279e43ac5SRob Bradford 
bus(&self) -> u810379e43ac5SRob Bradford     pub fn bus(&self) -> u8 {
10479e43ac5SRob Bradford         ((self.0 >> 8) & 0xff) as u8
10579e43ac5SRob Bradford     }
10679e43ac5SRob Bradford 
device(&self) -> u810779e43ac5SRob Bradford     pub fn device(&self) -> u8 {
10879e43ac5SRob Bradford         ((self.0 >> 3) & 0x1f) as u8
10979e43ac5SRob Bradford     }
11079e43ac5SRob Bradford 
function(&self) -> u811179e43ac5SRob Bradford     pub fn function(&self) -> u8 {
11279e43ac5SRob Bradford         (self.0 & 0x7) as u8
11379e43ac5SRob Bradford     }
11479e43ac5SRob Bradford 
new(segment: u16, bus: u8, device: u8, function: u8) -> Self11579e43ac5SRob Bradford     pub fn new(segment: u16, bus: u8, device: u8, function: u8) -> Self {
11679e43ac5SRob Bradford         Self(
117b57cc3d7SRob Bradford             ((segment as u32) << 16)
118b57cc3d7SRob Bradford                 | ((bus as u32) << 8)
119b57cc3d7SRob Bradford                 | (((device & 0x1f) as u32) << 3)
12079e43ac5SRob Bradford                 | (function & 0x7) as u32,
12179e43ac5SRob Bradford         )
12279e43ac5SRob Bradford     }
12379e43ac5SRob Bradford }
12479e43ac5SRob Bradford 
12579e43ac5SRob Bradford impl From<u32> for PciBdf {
from(bdf: u32) -> Self12679e43ac5SRob Bradford     fn from(bdf: u32) -> Self {
12779e43ac5SRob Bradford         Self(bdf)
12879e43ac5SRob Bradford     }
12979e43ac5SRob Bradford }
13079e43ac5SRob Bradford 
13179e43ac5SRob Bradford impl From<PciBdf> for u32 {
from(bdf: PciBdf) -> Self13279e43ac5SRob Bradford     fn from(bdf: PciBdf) -> Self {
13379e43ac5SRob Bradford         bdf.0
13479e43ac5SRob Bradford     }
13579e43ac5SRob Bradford }
13679e43ac5SRob Bradford 
13779e43ac5SRob Bradford impl From<&PciBdf> for u32 {
from(bdf: &PciBdf) -> Self13879e43ac5SRob Bradford     fn from(bdf: &PciBdf) -> Self {
13979e43ac5SRob Bradford         bdf.0
14079e43ac5SRob Bradford     }
14179e43ac5SRob Bradford }
14279e43ac5SRob Bradford 
14379e43ac5SRob Bradford impl From<PciBdf> for u16 {
from(bdf: PciBdf) -> Self14479e43ac5SRob Bradford     fn from(bdf: PciBdf) -> Self {
14579e43ac5SRob Bradford         (bdf.0 & 0xffff) as u16
14679e43ac5SRob Bradford     }
14779e43ac5SRob Bradford }
14879e43ac5SRob Bradford 
14979e43ac5SRob Bradford impl From<&PciBdf> for u16 {
from(bdf: &PciBdf) -> Self15079e43ac5SRob Bradford     fn from(bdf: &PciBdf) -> Self {
15179e43ac5SRob Bradford         (bdf.0 & 0xffff) as u16
15279e43ac5SRob Bradford     }
15379e43ac5SRob Bradford }
15479e43ac5SRob Bradford 
155*8c072946SArvind Vasudev impl Debug for PciBdf {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result156*8c072946SArvind Vasudev     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
157*8c072946SArvind Vasudev         write!(
158*8c072946SArvind Vasudev             f,
159*8c072946SArvind Vasudev             "{:04x}:{:02x}:{:02x}.{:01x}",
160*8c072946SArvind Vasudev             self.segment(),
161*8c072946SArvind Vasudev             self.bus(),
162*8c072946SArvind Vasudev             self.device(),
163*8c072946SArvind Vasudev             self.function()
164*8c072946SArvind Vasudev         )
165*8c072946SArvind Vasudev     }
166*8c072946SArvind Vasudev }
167*8c072946SArvind Vasudev 
16879e43ac5SRob Bradford impl Display for PciBdf {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result16979e43ac5SRob Bradford     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17079e43ac5SRob Bradford         write!(
17179e43ac5SRob Bradford             f,
17279e43ac5SRob Bradford             "{:04x}:{:02x}:{:02x}.{:01x}",
17379e43ac5SRob Bradford             self.segment(),
17479e43ac5SRob Bradford             self.bus(),
17579e43ac5SRob Bradford             self.device(),
17679e43ac5SRob Bradford             self.function()
17779e43ac5SRob Bradford         )
17879e43ac5SRob Bradford     }
17979e43ac5SRob Bradford }
18042b5d4a2SSebastien Boeuf 
18142b5d4a2SSebastien Boeuf impl FromStr for PciBdf {
18242b5d4a2SSebastien Boeuf     type Err = ParseIntError;
18342b5d4a2SSebastien Boeuf 
from_str(s: &str) -> Result<Self, Self::Err>18442b5d4a2SSebastien Boeuf     fn from_str(s: &str) -> Result<Self, Self::Err> {
18542b5d4a2SSebastien Boeuf         let items: Vec<&str> = s.split('.').collect();
18642b5d4a2SSebastien Boeuf         assert_eq!(items.len(), 2);
18742b5d4a2SSebastien Boeuf         let function = u8::from_str_radix(items[1], 16)?;
18842b5d4a2SSebastien Boeuf         let items: Vec<&str> = items[0].split(':').collect();
18942b5d4a2SSebastien Boeuf         assert_eq!(items.len(), 3);
19042b5d4a2SSebastien Boeuf         let segment = u16::from_str_radix(items[0], 16)?;
19142b5d4a2SSebastien Boeuf         let bus = u8::from_str_radix(items[1], 16)?;
19242b5d4a2SSebastien Boeuf         let device = u8::from_str_radix(items[2], 16)?;
19342b5d4a2SSebastien Boeuf         Ok(PciBdf::new(segment, bus, device, function))
19442b5d4a2SSebastien Boeuf     }
19542b5d4a2SSebastien Boeuf }
19642b5d4a2SSebastien Boeuf 
19742b5d4a2SSebastien Boeuf impl From<&str> for PciBdf {
from(bdf: &str) -> Self19842b5d4a2SSebastien Boeuf     fn from(bdf: &str) -> Self {
19942b5d4a2SSebastien Boeuf         Self::from_str(bdf).unwrap()
20042b5d4a2SSebastien Boeuf     }
20142b5d4a2SSebastien Boeuf }
202