From 8b0aabaf10316020f3a000218d9f89fd5ee8a9cf Mon Sep 17 00:00:00 2001 From: Artemis Tosini Date: Sat, 20 Jul 2024 01:33:49 +0000 Subject: [PATCH] Set some more registers --- src/buffers.rs | 17 +++++++++++++++ src/main.rs | 57 +++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 67 insertions(+), 7 deletions(-) create mode 100644 src/buffers.rs diff --git a/src/buffers.rs b/src/buffers.rs new file mode 100644 index 0000000..34c1af1 --- /dev/null +++ b/src/buffers.rs @@ -0,0 +1,17 @@ +#[repr(transparent)] +#[derive(Debug, Copy, Clone, Default)] +pub struct PhysicalAddress(u64); + +/// Device Context Base Address Array +/// TODO: make more page size independent +/// Align to a page because it shouldn't cross a page and needs to be +/// 64-byte aligned anyway +#[repr(C, align(4096))] +#[derive(Debug)] +pub struct DCBAA([PhysicalAddress; 256]); + +impl Default for DCBAA { + fn default() -> Self { + Self([PhysicalAddress::default(); 256]) + } +} diff --git a/src/main.rs b/src/main.rs index a3979b5..fa445e6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,9 @@ +mod buffers; mod pci; use std::sync::Arc; +use buffers::DCBAA; use clap::Parser; use pci_driver::{backends::vfio::VfioPciDevice, device::PciDevice}; @@ -10,10 +12,6 @@ struct Args { /// Path of the PCIe device, e.g. /sys/bus/pci/devices/0000:02:00.0 #[arg(short = 'd', long)] device: std::path::PathBuf, - - /// Attempt to reset the device with sysfs - #[arg(short = 'r', long)] - reset: bool, } fn main() -> eyre::Result<()> { @@ -22,16 +20,61 @@ fn main() -> eyre::Result<()> { let device = Arc::new(VfioPciDevice::open(&args.device)?); - if args.reset { - device.reset()?; + device.reset()?; + + if device.iommu().alignment() != 4096 { + todo!("Support non-4K page size") } - let registers = crate::pci::load_registers(device)?; + let mut registers = crate::pci::load_registers(device.clone())?; log::info!( "xHCI version: {:04x}", registers.capability.hciversion.read_volatile().get() ); + while registers + .operational + .usbsts + .read_volatile() + .controller_not_ready() + { + std::thread::sleep(std::time::Duration::from_millis(1)); + } + + let device_slots = registers + .capability + .hcsparams1 + .read_volatile() + .number_of_device_slots(); + log::debug!("Controller supports {} device slots", device_slots); + registers.operational.config.update_volatile(|reg| { + reg.set_max_device_slots_enabled(device_slots); + }); + + let dcbaa = DCBAA::default(); + + log::trace!( + "valid_iova_ranges: {:#x?}", + device.iommu().valid_iova_ranges() + ); + log::trace!("max_num_mappings: {}", device.iommu().max_num_mappings()); + + let dcbaa_physaddr = 0x1000u64; + // TODO: Actually deal with valid iova ranges + unsafe { + device.iommu().map( + dcbaa_physaddr, + std::mem::size_of::(), + &dcbaa as *const DCBAA as *const u8, + pci_driver::regions::Permissions::Read, + )?; + } + + registers + .operational + .dcbaap + .update_volatile(|reg| reg.set(dcbaa_physaddr)); + Ok(()) }