diff --git a/pcid/src/driver_handler.rs b/pcid/src/driver_handler.rs index 77f1729829..8cf114276f 100644 --- a/pcid/src/driver_handler.rs +++ b/pcid/src/driver_handler.rs @@ -5,11 +5,10 @@ use std::sync::Arc; use std::thread; use log::{error, info}; -use pci_types::PciAddress; +use pci_types::{ConfigRegionAccess, PciAddress}; use crate::driver_interface; use crate::pci::cap::Capability as PciCapability; -use crate::pci::PciFunc; use crate::State; pub struct DriverHandler { @@ -101,11 +100,6 @@ impl DriverHandler { use crate::pci::cap::{MsiCapability, MsixCapability}; use driver_interface::*; - let func = PciFunc { - pci: &self.state.pcie, - addr: self.addr, - }; - match request { PcidClientRequest::RequestCapabilities => PcidClientResponse::Capabilities( self.capabilities @@ -135,7 +129,7 @@ impl DriverHandler { // active at the same time. unsafe { msix_capability.set_msix_enabled(false); - msix_capability.write_a(&func); + msix_capability.write_a(self.addr, &self.state.pcie); } } @@ -153,7 +147,7 @@ impl DriverHandler { }; unsafe { capability.set_enabled(true); - capability.write_message_control(&func); + capability.write_message_control(self.addr, &self.state.pcie); } PcidClientResponse::FeatureEnabled(feature) } @@ -167,7 +161,7 @@ impl DriverHandler { // active at the same time. unsafe { msi_capability.set_enabled(false); - msi_capability.write_message_control(&func); + msi_capability.write_message_control(self.addr, &self.state.pcie); } } @@ -185,7 +179,7 @@ impl DriverHandler { }; unsafe { capability.set_msix_enabled(true); - capability.write_a(&func); + capability.write_a(self.addr, &self.state.pcie); } PcidClientResponse::FeatureEnabled(feature) } @@ -273,7 +267,7 @@ impl DriverHandler { info.set_mask_bits(mask_bits); } unsafe { - info.write_all(&func); + info.write_all(self.addr, &self.state.pcie); } PcidClientResponse::SetFeatureInfo(PciFeature::Msi) } else { @@ -291,7 +285,7 @@ impl DriverHandler { if let Some(mask) = function_mask { info.set_function_mask(mask); unsafe { - info.write_a(&func); + info.write_a(self.addr, &self.state.pcie); } } PcidClientResponse::SetFeatureInfo(PciFeature::MsiX) @@ -303,12 +297,12 @@ impl DriverHandler { } }, PcidClientRequest::ReadConfig(offset) => { - let value = unsafe { func.read_u32(offset) }; + let value = unsafe { self.state.pcie.read(self.addr, offset) }; return PcidClientResponse::ReadConfig(value); } PcidClientRequest::WriteConfig(offset, value) => { unsafe { - func.write_u32(offset, value); + self.state.pcie.write(self.addr, offset, value); } return PcidClientResponse::WriteConfig; } diff --git a/pcid/src/main.rs b/pcid/src/main.rs index 648a291a4c..039e0fd2ea 100644 --- a/pcid/src/main.rs +++ b/pcid/src/main.rs @@ -4,6 +4,7 @@ use std::sync::{Arc, Mutex}; use std::thread; use log::{debug, info, trace, warn}; +use pci_types::capability::PciCapabilityAddress; use pci_types::{CommandRegister, PciAddress}; use redox_log::{OutputBuilder, RedoxLogger}; use structopt::StructOpt; @@ -11,7 +12,6 @@ use structopt::StructOpt; use crate::cfg_access::Pcie; use crate::config::Config; use crate::driver_interface::LegacyInterruptLine; -use crate::pci::PciFunc; use crate::pci_header::{PciEndpointHeader, PciHeader, PciHeaderError}; mod cfg_access; @@ -98,11 +98,14 @@ fn handle_parsed_header(state: Arc, config: &Config, header: PciEndpointH }; let capabilities = if endpoint_header.status(&state.pcie).has_capability_list() { - let func = PciFunc { - pci: &state.pcie, - addr: header.address(), - }; - crate::pci::cap::CapabilitiesIter::new(header.cap_pointer(), &func).collect::>() + crate::pci::cap::CapabilitiesIter::new( + PciCapabilityAddress { + address: header.address(), + offset: header.cap_pointer(), + }, + &state.pcie, + ) + .collect::>() } else { Vec::new() }; diff --git a/pcid/src/pci/cap.rs b/pcid/src/pci/cap.rs index 06e1436f5f..47dc68fc55 100644 --- a/pcid/src/pci/cap.rs +++ b/pcid/src/pci/cap.rs @@ -1,40 +1,39 @@ -use super::func::PciFunc; - +use pci_types::capability::PciCapabilityAddress; +use pci_types::ConfigRegionAccess; use serde::{Serialize, Deserialize}; pub struct CapabilitiesIter<'a> { - offset: u8, - func: &'a PciFunc<'a>, + addr: PciCapabilityAddress, + access: &'a dyn ConfigRegionAccess, } impl<'a> CapabilitiesIter<'a> { - pub fn new(offset: u8, func: &'a PciFunc) -> Self { - Self { - offset, - func, - } + pub fn new(addr: PciCapabilityAddress, access: &'a dyn ConfigRegionAccess) -> Self { + Self { addr, access } } } impl<'a> Iterator for CapabilitiesIter<'a> { type Item = Capability; fn next(&mut self) -> Option { - let offset = unsafe { + let addr = unsafe { // mask RsvdP bits - self.offset = self.offset & 0xFC; + self.addr.offset = self.addr.offset & 0xFC; - if self.offset == 0 { return None }; + if self.addr.offset == 0 { + return None; + }; - let first_dword = self.func.read_u32(u16::from(self.offset)); - let next = ((first_dword >> 8) & 0xFF) as u8; + let first_dword = self.access.read(self.addr.address, self.addr.offset); + let next = ((first_dword >> 8) & 0xFF) as u16; - let offset = self.offset; - self.offset = next; + let addr = self.addr; + self.addr.offset = next; - offset + addr }; let cap = unsafe { - Capability::parse(self.func, offset) + Capability::parse(addr, self.access) }; Some(cap) @@ -56,20 +55,20 @@ pub enum CapabilityId { #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] pub enum MsiCapability { _32BitAddress { - cap_offset: u8, + cap_offset: u16, message_control: u32, message_address: u32, message_data: u16, }, _64BitAddress { - cap_offset: u8, + cap_offset: u16, message_control: u32, message_address_lo: u32, message_address_hi: u32, message_data: u16, }, _32BitAddressWithPvm { - cap_offset: u8, + cap_offset: u16, message_control: u32, message_address: u32, message_data: u32, @@ -77,7 +76,7 @@ pub enum MsiCapability { pending_bits: u32, }, _64BitAddressWithPvm { - cap_offset: u8, + cap_offset: u16, message_control: u32, message_address_lo: u32, message_address_hi: u32, @@ -89,7 +88,7 @@ pub enum MsiCapability { #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] pub struct MsixCapability { - pub cap_offset: u8, + pub cap_offset: u16, pub a: u32, pub b: u32, pub c: u32, @@ -133,23 +132,37 @@ impl Capability { _ => None, } } - unsafe fn parse_msi(func: &PciFunc, offset: u8) -> Self { - Self::Msi(MsiCapability::parse(func, offset)) + unsafe fn parse_msi(addr: PciCapabilityAddress, access: &dyn ConfigRegionAccess) -> Self { + Self::Msi(MsiCapability::parse(addr, access)) } - unsafe fn parse_msix(func: &PciFunc, offset: u8) -> Self { + unsafe fn parse_msix(addr: PciCapabilityAddress, access: &dyn ConfigRegionAccess) -> Self { Self::MsiX(MsixCapability { - cap_offset: offset, - a: func.read_u32(u16::from(offset)), - b: func.read_u32(u16::from(offset + 4)), - c: func.read_u32(u16::from(offset + 8)), + cap_offset: addr.offset, + a: access.read(addr.address, addr.offset), + b: access.read(addr.address, addr.offset + 4), + c: access.read(addr.address, addr.offset + 8), }) } - unsafe fn parse_vendor(func: &PciFunc, offset: u8) -> Self { - let next = func.read_u8(u16::from(offset+1)); - let length = func.read_u8(u16::from(offset+2)); - log::info!("Vendor specific offset: {offset:#02x} next: {next:#02x} cap len: {length:#02x}"); + unsafe fn parse_vendor(addr: PciCapabilityAddress, access: &dyn ConfigRegionAccess) -> Self { + let dword = access.read(addr.address, addr.offset); + let next = (dword >> 8) & 0xFF; + let length = ((dword >> 16) & 0xFF) as u16; + log::info!( + "Vendor specific offset: {:#02x} next: {next:#02x} cap len: {length:#02x}", + addr.offset + ); let data = if length > 0 { - let mut raw_data = func.read_range(offset.into(), length.into()); + assert!( + length > 3 && length % 4 == 0, + "invalid range length: {}", + length + ); + let mut raw_data = { + (addr.offset..addr.offset + length) + .step_by(4) + .flat_map(|offset| access.read(addr.address, offset).to_le_bytes()) + .collect::>() + }; raw_data.drain(3..).collect() } else { log::warn!("Vendor specific capability is invalid"); @@ -159,18 +172,22 @@ impl Capability { data }) } - unsafe fn parse(func: &PciFunc, offset: u8) -> Self { - assert_eq!(offset & 0xFC, offset, "capability must be dword aligned"); + unsafe fn parse(addr: PciCapabilityAddress, access: &dyn ConfigRegionAccess) -> Self { + assert_eq!( + addr.offset & 0xFC, + addr.offset, + "capability must be dword aligned" + ); - let dword = func.read_u32(u16::from(offset)); + let dword = access.read(addr.address, addr.offset); let capability_id = (dword & 0xFF) as u8; if capability_id == CapabilityId::Msi as u8 { - Self::parse_msi(func, offset) + Self::parse_msi(addr, access) } else if capability_id == CapabilityId::MsiX as u8 { - Self::parse_msix(func, offset) + Self::parse_msix(addr, access) } else if capability_id == CapabilityId::Vendor as u8 { - Self::parse_vendor(func, offset) + Self::parse_vendor(addr, access) } else { if capability_id != CapabilityId::Pcie as u8 && capability_id != CapabilityId::PwrMgmt as u8 diff --git a/pcid/src/pci/func.rs b/pcid/src/pci/func.rs deleted file mode 100644 index 7caec137a8..0000000000 --- a/pcid/src/pci/func.rs +++ /dev/null @@ -1,33 +0,0 @@ -use pci_types::{ConfigRegionAccess, PciAddress}; - -pub struct PciFunc<'pci> { - pub pci: &'pci dyn ConfigRegionAccess, - pub addr: PciAddress, -} - -impl<'pci> PciFunc<'pci> { - pub unsafe fn read_range(&self, offset: u16, len: u16) -> Vec { - assert!(len > 3 && len % 4 == 0, "invalid range length: {}", len); - (offset..offset + len) - .step_by(4) - .flat_map(|offset| self.read_u32(offset).to_le_bytes()) - .collect::>() - } - - pub unsafe fn read_u8(&self, offset: u16) -> u8 { - let dword_offset = (offset / 4) * 4; - let dword = self.read_u32(dword_offset); - - let shift = (offset % 4) * 8; - ((dword >> shift) & 0xFF) as u8 - } - - pub unsafe fn read_u32(&self, offset: u16) -> u32 { - self.pci.read(self.addr, offset) - } -} -impl<'pci> PciFunc<'pci> { - pub unsafe fn write_u32(&self, offset: u16, value: u32) { - self.pci.write(self.addr, offset, value); - } -} diff --git a/pcid/src/pci/mod.rs b/pcid/src/pci/mod.rs index b8080263f5..2db9368d9b 100644 --- a/pcid/src/pci/mod.rs +++ b/pcid/src/pci/mod.rs @@ -1,10 +1,8 @@ pub use self::bar::PciBar; -pub use self::func::PciFunc; pub use self::id::FullDeviceId; pub use pci_types::PciAddress; mod bar; pub mod cap; -pub mod func; mod id; pub mod msi; diff --git a/pcid/src/pci/msi.rs b/pcid/src/pci/msi.rs index 2af0c43d99..727d36695f 100644 --- a/pcid/src/pci/msi.rs +++ b/pcid/src/pci/msi.rs @@ -2,8 +2,9 @@ use std::fmt; use super::bar::PciBar; pub use super::cap::{MsiCapability, MsixCapability}; -use super::func::PciFunc; +use pci_types::capability::PciCapabilityAddress; +use pci_types::{ConfigRegionAccess, PciAddress}; use serde::{Deserialize, Serialize}; use syscall::{Io, Mmio}; @@ -42,47 +43,47 @@ impl MsiCapability { const MC_MSI_ENABLED_BIT: u16 = 1; - pub(crate) unsafe fn parse(func: &PciFunc, offset: u8) -> Self { - let dword = func.read_u32(u16::from(offset)); + pub(crate) unsafe fn parse(addr: PciCapabilityAddress, access: &dyn ConfigRegionAccess) -> Self { + let dword = access.read(addr.address, addr.offset); let message_control = (dword >> 16) as u16; if message_control & Self::MC_PVT_CAPABLE_BIT != 0 { if message_control & Self::MC_64_BIT_ADDR_BIT != 0 { Self::_64BitAddressWithPvm { - cap_offset: offset, + cap_offset: addr.offset, message_control: dword, - message_address_lo: func.read_u32(u16::from(offset + 4)), - message_address_hi: func.read_u32(u16::from(offset + 8)), - message_data: func.read_u32(u16::from(offset + 12)), - mask_bits: func.read_u32(u16::from(offset + 16)), - pending_bits: func.read_u32(u16::from(offset + 20)), + message_address_lo: access.read(addr.address, addr.offset + 4), + message_address_hi: access.read(addr.address, addr.offset + 8), + message_data: access.read(addr.address, addr.offset + 12), + mask_bits: access.read(addr.address, addr.offset + 16), + pending_bits: access.read(addr.address, addr.offset + 20), } } else { Self::_32BitAddressWithPvm { - cap_offset: offset, + cap_offset: addr.offset, message_control: dword, - message_address: func.read_u32(u16::from(offset + 4)), - message_data: func.read_u32(u16::from(offset + 8)), - mask_bits: func.read_u32(u16::from(offset + 12)), - pending_bits: func.read_u32(u16::from(offset + 16)), + message_address: access.read(addr.address, addr.offset + 4), + message_data: access.read(addr.address, addr.offset + 8), + mask_bits: access.read(addr.address, addr.offset + 12), + pending_bits: access.read(addr.address, addr.offset + 16), } } } else { if message_control & Self::MC_64_BIT_ADDR_BIT != 0 { Self::_64BitAddress { - cap_offset: offset, + cap_offset: addr.offset, message_control: dword, - message_address_lo: func.read_u32(u16::from(offset + 4)), - message_address_hi: func.read_u32(u16::from(offset + 8)), - message_data: func.read_u32(u16::from(offset + 12)) as u16, + message_address_lo: access.read(addr.address, addr.offset + 4), + message_address_hi: access.read(addr.address, addr.offset + 8), + message_data: access.read(addr.address, addr.offset + 12) as u16, } } else { Self::_32BitAddress { - cap_offset: offset, + cap_offset: addr.offset, message_control: dword, - message_address: func.read_u32(u16::from(offset + 4)), - message_data: func.read_u32(u16::from(offset + 8)) as u16, + message_address: access.read(addr.address, addr.offset + 4), + message_data: access.read(addr.address, addr.offset + 8) as u16, } } } @@ -116,8 +117,8 @@ impl MsiCapability { | Self::_64BitAddressWithPvm { ref mut message_control, .. } => *message_control = new_message_control, } } - pub(crate) unsafe fn write_message_control(&self, func: &PciFunc) { - func.write_u32(self.cap_offset(), self.message_control_raw()); + pub(crate) unsafe fn write_message_control(&self, addr: PciAddress, access: &dyn ConfigRegionAccess) { + access.write(addr, self.cap_offset(), self.message_control_raw()); } pub(crate) fn is_pvt_capable(&self) -> bool { self.message_control() & Self::MC_PVT_CAPABLE_BIT != 0 @@ -184,36 +185,36 @@ impl MsiCapability { } Some(()) } - unsafe fn write_message_address(&self, func: &PciFunc) { - func.write_u32(self.cap_offset() + 4, self.message_address()) + unsafe fn write_message_address(&self, addr: PciAddress, access: &dyn ConfigRegionAccess) { + access.write(addr, self.cap_offset() + 4, self.message_address()) } - unsafe fn write_message_upper_address(&self, func: &PciFunc) -> Option<()> { + unsafe fn write_message_upper_address(&self, addr: PciAddress, access: &dyn ConfigRegionAccess) -> Option<()> { let value = self.message_upper_address()?; - func.write_u32(self.cap_offset() + 8, value); + access.write(addr, self.cap_offset() + 8, value); Some(()) } - unsafe fn write_message_data(&self, func: &PciFunc) { + unsafe fn write_message_data(&self, addr: PciAddress, access: &dyn ConfigRegionAccess) { match self { - &Self::_32BitAddress { cap_offset, message_data, .. } => func.write_u32(u16::from(cap_offset + 8), message_data.into()), - &Self::_32BitAddressWithPvm { cap_offset, message_data, .. } => func.write_u32(u16::from(cap_offset + 8), message_data), - &Self::_64BitAddress { cap_offset, message_data, .. } => func.write_u32(u16::from(cap_offset + 12), message_data.into()), - &Self::_64BitAddressWithPvm { cap_offset, message_data, .. } => func.write_u32(u16::from(cap_offset + 12), message_data), + &Self::_32BitAddress { cap_offset, message_data, .. } => access.write(addr, u16::from(cap_offset + 8), message_data.into()), + &Self::_32BitAddressWithPvm { cap_offset, message_data, .. } => access.write(addr, u16::from(cap_offset + 8), message_data), + &Self::_64BitAddress { cap_offset, message_data, .. } => access.write(addr, u16::from(cap_offset + 12), message_data.into()), + &Self::_64BitAddressWithPvm { cap_offset, message_data, .. } => access.write(addr, u16::from(cap_offset + 12), message_data), } } - unsafe fn write_mask_bits(&self, func: &PciFunc) -> Option<()> { + unsafe fn write_mask_bits(&self, addr: PciAddress, access: &dyn ConfigRegionAccess) -> Option<()> { match self { - &Self::_32BitAddressWithPvm { cap_offset, mask_bits, .. } => func.write_u32(u16::from(cap_offset + 12), mask_bits), - &Self::_64BitAddressWithPvm { cap_offset, mask_bits, .. } => func.write_u32(u16::from(cap_offset + 16), mask_bits), + &Self::_32BitAddressWithPvm { cap_offset, mask_bits, .. } => access.write(addr, u16::from(cap_offset + 12), mask_bits), + &Self::_64BitAddressWithPvm { cap_offset, mask_bits, .. } => access.write(addr, u16::from(cap_offset + 16), mask_bits), &Self::_32BitAddress { .. } | &Self::_64BitAddress { .. } => return None, } Some(()) } - pub(crate) unsafe fn write_all(&self, func: &PciFunc) { - self.write_message_control(func); - self.write_message_address(func); - self.write_message_upper_address(func); - self.write_message_data(func); - self.write_mask_bits(func); + pub(crate) unsafe fn write_all(&self, addr: PciAddress, access: &dyn ConfigRegionAccess) { + self.write_message_control(addr, access); + self.write_message_address(addr, access); + self.write_message_upper_address(addr, access); + self.write_message_data(addr, access); + self.write_mask_bits(addr, access); } } @@ -328,8 +329,8 @@ impl MsixCapability { /// Write the first DWORD into configuration space (containing the partially modifiable Message /// Control field). - pub(crate) unsafe fn write_a(&self, func: &PciFunc) { - func.write_u32(u16::from(self.cap_offset), self.a) + pub(crate) unsafe fn write_a(&self, addr: PciAddress, access: &dyn ConfigRegionAccess) { + access.write(addr, u16::from(self.cap_offset), self.a) } } diff --git a/pcid/src/pci_header.rs b/pcid/src/pci_header.rs index 5e450ca26c..4779427aea 100644 --- a/pcid/src/pci_header.rs +++ b/pcid/src/pci_header.rs @@ -23,7 +23,7 @@ pub struct PciEndpointHeader { shared: SharedPciHeader, subsystem_vendor_id: u16, subsystem_id: u16, - cap_pointer: u8, + cap_pointer: u16, } #[derive(Clone, Copy, Debug, PartialEq)] @@ -240,7 +240,7 @@ impl PciEndpointHeader { bars } - pub fn cap_pointer(&self) -> u8 { + pub fn cap_pointer(&self) -> u16 { self.cap_pointer } }