Now have a so-called mapper

This commit is contained in:
Artemis Tosini 2024-07-19 23:54:39 +00:00
parent 697c4bfdc2
commit e9c540b777
Signed by: artemist
SSH key fingerprint: SHA256:EsuWCwx6fjxxExxf65rX+ocQJJAdw4R1KarpFue6Uwc
4 changed files with 138 additions and 16 deletions

56
Cargo.lock generated
View file

@ -2,6 +2,12 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "accessor"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd8b2abd55bf1f9cffbf00fd594566c51a9d31402553284920c1309ca8351086"
[[package]]
name = "aho-corasick"
version = "1.1.3"
@ -66,6 +72,12 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
name = "bit_field"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
[[package]]
name = "clap"
version = "4.5.9"
@ -97,7 +109,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
"syn 2.0.71",
]
[[package]]
@ -196,6 +208,18 @@ dependencies = [
"eyre",
"log",
"pci-driver",
"xhci",
]
[[package]]
name = "num-derive"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
@ -213,6 +237,12 @@ version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "pci-driver"
version = "0.1.4"
@ -276,6 +306,17 @@ version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.71"
@ -371,3 +412,16 @@ name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "xhci"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09f3f0483969259f2adb6524054400d94ac352e59fa37da6c6ca3b9b3d83ff83"
dependencies = [
"accessor",
"bit_field",
"num-derive",
"num-traits",
"paste",
]

View file

@ -9,3 +9,4 @@ env_logger = "0.11.3"
eyre = "0.6.12"
log = "0.4.22"
pci-driver = "0.1.4"
xhci = "0.9.2"

View file

@ -1,3 +1,7 @@
mod pci;
use std::sync::Arc;
use clap::Parser;
use pci_driver::{backends::vfio::VfioPciDevice, device::PciDevice};
@ -16,28 +20,17 @@ fn main() -> eyre::Result<()> {
env_logger::init();
let args = Args::parse();
let device = VfioPciDevice::open(&args.device)?;
let device = Arc::new(VfioPciDevice::open(&args.device)?);
if args.reset {
device.reset()?;
}
let config = device.config();
// This library got the order backwards...
let class = (
config.class_code().programming_interface().read()?,
config.class_code().sub_class_code().read()?,
config.class_code().base_class_code().read()?,
);
println!("{:?}", class);
if class != (0x0c, 0x03, 0x30) {
eyre::bail!("Device is not xHCI controller!");
}
let registers = crate::pci::load_registers(device)?;
log::info!(
"Found PCIe device {:04x}:{:04x}",
config.vendor_id().read()?,
config.device_id().read()?
"xHCI version: {:04x}",
registers.capability.hciversion.read_volatile().get()
);
Ok(())

74
src/pci.rs Normal file
View file

@ -0,0 +1,74 @@
use std::{num::NonZeroUsize, sync::Arc};
use eyre::OptionExt;
use pci_driver::{
backends::vfio::VfioPciDevice,
device::PciDevice,
regions::{MappedOwningPciRegion, PciRegion},
};
use xhci::Registers;
#[derive(Clone)]
pub struct PciMapper {
pub device: Arc<VfioPciDevice>,
pub mapped_region: Arc<MappedOwningPciRegion>,
pub phys_base: usize,
}
impl xhci::accessor::Mapper for PciMapper {
unsafe fn map(&mut self, phys_start: usize, bytes: usize) -> std::num::NonZeroUsize {
log::trace!("Map {:#018x}: {:#x} bytes", phys_start, bytes);
if phys_start < self.phys_base
|| phys_start - self.phys_base + bytes > self.mapped_region.len()
{
panic!("Tried to access invalid address");
}
NonZeroUsize::try_from(
(self.mapped_region.as_ptr() as usize) + (phys_start - self.phys_base),
)
.unwrap()
}
fn unmap(&mut self, virt_start: usize, bytes: usize) {
log::trace!("Unmap {:#018x}: {:#x} bytes", virt_start, bytes);
// no-op, we mapped the entire BAR 0 anyway
}
}
pub fn load_registers(device: Arc<VfioPciDevice>) -> eyre::Result<Registers<PciMapper>> {
let config = device.config();
let class = config.read_le_u32(0x08)? >> 8;
if class != 0x0c_03_30 {
eyre::bail!("Device is not xHCI controller!");
}
log::info!(
"Found xHCI controller device {:04x}:{:04x}",
config.vendor_id().read()?,
config.device_id().read()?
);
let mut bar = [0u8; 8];
device.config().read_bytes(0x10, &mut bar)?;
let phys_base = u64::from_le_bytes(bar) & 0xffff_fff8;
log::debug!("BAR physical base: {:#018x}", phys_base);
let region = device.bar(0).ok_or_eyre("Device does not have BAR 0")?;
let mapped_region =
Arc::new(region.map(0..region.len(), pci_driver::regions::Permissions::ReadWrite)?);
log::debug!(
"BAR virtual base: {:#018x}",
mapped_region.as_ptr() as usize
);
let mapper = PciMapper {
device,
mapped_region,
phys_base: phys_base.try_into()?,
};
unsafe { Ok(Registers::new(phys_base as usize, mapper)) }
}