Set some more registers

This commit is contained in:
Artemis Tosini 2024-07-20 01:33:49 +00:00
parent e9c540b777
commit 8b0aabaf10
Signed by: artemist
SSH key fingerprint: SHA256:EsuWCwx6fjxxExxf65rX+ocQJJAdw4R1KarpFue6Uwc
2 changed files with 67 additions and 7 deletions

17
src/buffers.rs Normal file
View file

@ -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])
}
}

View file

@ -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()?;
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>(),
&dcbaa as *const DCBAA as *const u8,
pci_driver::regions::Permissions::Read,
)?;
}
registers
.operational
.dcbaap
.update_volatile(|reg| reg.set(dcbaa_physaddr));
Ok(())
}