2019-04-18 09:59:12 +00:00
|
|
|
// Copyright 2018 The Chromium OS Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
2019-05-08 10:22:53 +00:00
|
|
|
// found in the LICENSE-BSD-3-Clause file.
|
2019-04-18 09:59:12 +00:00
|
|
|
|
|
|
|
//! Implements pci devices and busses.
|
|
|
|
#[macro_use]
|
|
|
|
extern crate log;
|
|
|
|
|
2019-06-04 06:51:00 +00:00
|
|
|
mod bus;
|
2019-04-18 09:59:12 +00:00
|
|
|
mod configuration;
|
|
|
|
mod device;
|
2019-07-17 05:01:32 +00:00
|
|
|
mod msi;
|
2019-05-29 23:33:29 +00:00
|
|
|
mod msix;
|
2019-11-08 14:50:39 +00:00
|
|
|
mod vfio;
|
2021-06-09 13:43:04 +00:00
|
|
|
mod vfio_user;
|
2019-04-18 09:59:12 +00:00
|
|
|
|
2019-09-30 14:23:57 +00:00
|
|
|
pub use self::bus::{PciBus, PciConfigIo, PciConfigMmio, PciRoot, PciRootError};
|
2019-04-18 09:59:12 +00:00
|
|
|
pub use self::configuration::{
|
2021-03-25 17:01:21 +00:00
|
|
|
PciBarConfiguration, PciBarPrefetchable, PciBarRegionType, PciCapability, PciCapabilityId,
|
2019-07-02 15:08:51 +00:00
|
|
|
PciClassCode, PciConfiguration, PciHeaderType, PciMassStorageSubclass,
|
|
|
|
PciNetworkControllerSubclass, PciProgrammingInterface, PciSerialBusSubClass, PciSubclass,
|
2019-04-18 09:59:12 +00:00
|
|
|
};
|
2019-06-04 06:51:00 +00:00
|
|
|
pub use self::device::{
|
2020-01-20 15:41:25 +00:00
|
|
|
BarReprogrammingParams, DeviceRelocation, Error as PciDeviceError, PciDevice,
|
2019-06-04 06:51:00 +00:00
|
|
|
};
|
2020-01-14 22:47:41 +00:00
|
|
|
pub use self::msi::{msi_num_enabled_vectors, MsiCap, MsiConfig};
|
2019-07-17 00:19:21 +00:00
|
|
|
pub use self::msix::{MsixCap, MsixConfig, MsixTableEntry, MSIX_TABLE_ENTRY_SIZE};
|
2019-11-08 14:50:39 +00:00
|
|
|
pub use self::vfio::{VfioPciDevice, VfioPciError};
|
2021-08-11 10:53:21 +00:00
|
|
|
pub use self::vfio_user::{VfioUserDmaMapping, VfioUserPciDevice, VfioUserPciDeviceError};
|
2022-02-16 08:55:26 +00:00
|
|
|
use serde::de::Visitor;
|
|
|
|
use std::fmt::{self, Display};
|
|
|
|
use std::num::ParseIntError;
|
|
|
|
use std::str::FromStr;
|
2019-04-18 09:59:12 +00:00
|
|
|
|
|
|
|
/// PCI has four interrupt pins A->D.
|
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
pub enum PciInterruptPin {
|
|
|
|
IntA,
|
|
|
|
IntB,
|
|
|
|
IntC,
|
|
|
|
IntD,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PciInterruptPin {
|
|
|
|
pub fn to_mask(self) -> u32 {
|
|
|
|
self as u32
|
|
|
|
}
|
|
|
|
}
|
2021-09-17 08:59:30 +00:00
|
|
|
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
|
pub const PCI_CONFIG_IO_PORT: u64 = 0xcf8;
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
|
pub const PCI_CONFIG_IO_PORT_SIZE: u64 = 0x8;
|
2021-10-18 15:31:50 +00:00
|
|
|
|
|
|
|
#[derive(Clone, Copy, PartialEq, PartialOrd)]
|
|
|
|
pub struct PciBdf(u32);
|
|
|
|
|
2022-02-16 08:55:26 +00:00
|
|
|
struct PciBdfVisitor;
|
|
|
|
|
|
|
|
impl<'de> Visitor<'de> for PciBdfVisitor {
|
|
|
|
type Value = PciBdf;
|
|
|
|
|
|
|
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
formatter.write_str("struct PciBdf")
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: serde::de::Error,
|
|
|
|
{
|
|
|
|
Ok(v.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'de> serde::Deserialize<'de> for PciBdf {
|
|
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
|
|
where
|
|
|
|
D: serde::Deserializer<'de>,
|
|
|
|
{
|
|
|
|
deserializer.deserialize_str(PciBdfVisitor)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl serde::Serialize for PciBdf {
|
|
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
|
|
where
|
|
|
|
S: serde::Serializer,
|
|
|
|
{
|
|
|
|
serializer.collect_str(&self.to_string())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-18 15:31:50 +00:00
|
|
|
impl PciBdf {
|
|
|
|
pub fn segment(&self) -> u16 {
|
|
|
|
((self.0 >> 16) & 0xffff) as u16
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn bus(&self) -> u8 {
|
|
|
|
((self.0 >> 8) & 0xff) as u8
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn device(&self) -> u8 {
|
|
|
|
((self.0 >> 3) & 0x1f) as u8
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn function(&self) -> u8 {
|
|
|
|
(self.0 & 0x7) as u8
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn new(segment: u16, bus: u8, device: u8, function: u8) -> Self {
|
|
|
|
Self(
|
|
|
|
(segment as u32) << 16
|
|
|
|
| (bus as u32) << 8
|
|
|
|
| ((device & 0x1f) as u32) << 3
|
|
|
|
| (function & 0x7) as u32,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<u32> for PciBdf {
|
|
|
|
fn from(bdf: u32) -> Self {
|
|
|
|
Self(bdf)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<PciBdf> for u32 {
|
|
|
|
fn from(bdf: PciBdf) -> Self {
|
|
|
|
bdf.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<&PciBdf> for u32 {
|
|
|
|
fn from(bdf: &PciBdf) -> Self {
|
|
|
|
bdf.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<PciBdf> for u16 {
|
|
|
|
fn from(bdf: PciBdf) -> Self {
|
|
|
|
(bdf.0 & 0xffff) as u16
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<&PciBdf> for u16 {
|
|
|
|
fn from(bdf: &PciBdf) -> Self {
|
|
|
|
(bdf.0 & 0xffff) as u16
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Display for PciBdf {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
write!(
|
|
|
|
f,
|
|
|
|
"{:04x}:{:02x}:{:02x}.{:01x}",
|
|
|
|
self.segment(),
|
|
|
|
self.bus(),
|
|
|
|
self.device(),
|
|
|
|
self.function()
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
2022-02-16 08:55:26 +00:00
|
|
|
|
|
|
|
impl FromStr for PciBdf {
|
|
|
|
type Err = ParseIntError;
|
|
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
|
let items: Vec<&str> = s.split('.').collect();
|
|
|
|
assert_eq!(items.len(), 2);
|
|
|
|
let function = u8::from_str_radix(items[1], 16)?;
|
|
|
|
let items: Vec<&str> = items[0].split(':').collect();
|
|
|
|
assert_eq!(items.len(), 3);
|
|
|
|
let segment = u16::from_str_radix(items[0], 16)?;
|
|
|
|
let bus = u8::from_str_radix(items[1], 16)?;
|
|
|
|
let device = u8::from_str_radix(items[2], 16)?;
|
|
|
|
Ok(PciBdf::new(segment, bus, device, function))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<&str> for PciBdf {
|
|
|
|
fn from(bdf: &str) -> Self {
|
|
|
|
Self::from_str(bdf).unwrap()
|
|
|
|
}
|
|
|
|
}
|