Fix pci framework bugs

This commit is contained in:
Yuke Peng
2023-08-10 16:13:41 +08:00
committed by Tate, Hongliang Tian
parent 739eb30138
commit df81434088
6 changed files with 77 additions and 43 deletions

View File

@ -9,7 +9,7 @@ pub trait PciDevice: Sync + Send + Debug {
fn device_id(&self) -> PciDeviceId; fn device_id(&self) -> PciDeviceId;
} }
#[derive(Debug)] #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum PciDriverProbeError { pub enum PciDriverProbeError {
DeviceNotMatch, DeviceNotMatch,
ConfigurationSpaceError, ConfigurationSpaceError,
@ -55,7 +55,9 @@ impl PciBus {
continue; continue;
} }
Err((err, common_device)) => { Err((err, common_device)) => {
error!("PCI device construction failed, reason: {:?}", err); if err != PciDriverProbeError::DeviceNotMatch {
error!("PCI device construction failed, reason: {:?}", err);
}
debug_assert!(device_id == *common_device.device_id()); debug_assert!(device_id == *common_device.device_id());
common_device common_device
} }
@ -76,7 +78,9 @@ impl PciBus {
return; return;
} }
Err((err, common_device)) => { Err((err, common_device)) => {
error!("PCI device construction failed, reason: {:?}", err); if err != PciDriverProbeError::DeviceNotMatch {
error!("PCI device construction failed, reason: {:?}", err);
}
debug_assert!(device_id == *common_device.device_id()); debug_assert!(device_id == *common_device.device_id());
common_device common_device
} }

View File

@ -73,8 +73,12 @@ impl Capability {
/// 0xFC, the top of the capability position. /// 0xFC, the top of the capability position.
const CAPABILITY_TOP: u16 = 0xFC; const CAPABILITY_TOP: u16 = 0xFC;
pub fn capability_data(&self) -> &CapabilityData {
&self.cap_data
}
/// get the capabilities of one device /// get the capabilities of one device
pub fn device_capabilities(dev: &mut PciCommonDevice) -> Vec<Self> { pub(super) fn device_capabilities(dev: &mut PciCommonDevice) -> Vec<Self> {
if !dev.status().contains(Status::CAPABILITIES_LIST) { if !dev.status().contains(Status::CAPABILITIES_LIST) {
return Vec::new(); return Vec::new();
} }

View File

@ -2,16 +2,17 @@ use alloc::{sync::Arc, vec::Vec};
use crate::{ use crate::{
bus::pci::{ bus::pci::{
cfg_space::{Bar, MemoryBar}, cfg_space::{Bar, Command, MemoryBar},
common_device::PciCommonDevice, common_device::PciCommonDevice,
device_info::PciDeviceLocation, device_info::PciDeviceLocation,
}, },
sync::{SpinLock, SpinLockGuard},
trap::IrqAllocateHandle, trap::IrqAllocateHandle,
vm::VmIo, vm::VmIo,
}; };
/// MSI-X capability. It will set the BAR space it uses to be hidden. /// MSI-X capability. It will set the BAR space it uses to be hidden.
#[derive(Debug, Clone)] #[derive(Debug)]
#[repr(C)] #[repr(C)]
pub struct CapabilityMsixData { pub struct CapabilityMsixData {
loc: PciDeviceLocation, loc: PciDeviceLocation,
@ -22,7 +23,26 @@ pub struct CapabilityMsixData {
table_bar: Arc<MemoryBar>, table_bar: Arc<MemoryBar>,
/// Pending bits table. /// Pending bits table.
pending_table_bar: Arc<MemoryBar>, pending_table_bar: Arc<MemoryBar>,
irq_allocate_handles: Vec<Option<Arc<IrqAllocateHandle>>>, table_offset: usize,
pending_table_offset: usize,
irq_allocate_handles: SpinLock<Vec<Option<IrqAllocateHandle>>>,
}
impl Clone for CapabilityMsixData {
fn clone(&self) -> Self {
let handles = self.irq_allocate_handles.lock();
let new_vec = handles.clone().to_vec();
Self {
loc: self.loc.clone(),
ptr: self.ptr.clone(),
table_size: self.table_size.clone(),
table_bar: self.table_bar.clone(),
pending_table_bar: self.pending_table_bar.clone(),
irq_allocate_handles: SpinLock::new(new_vec),
table_offset: self.table_offset,
pending_table_offset: self.pending_table_offset,
}
}
} }
impl CapabilityMsixData { impl CapabilityMsixData {
@ -60,28 +80,37 @@ impl CapabilityMsixData {
} }
} }
let pba_offset = (pba_info & !(0b111u32)) as usize;
let table_offset = (table_info & !(0b111u32)) as usize;
let table_size = (dev.location().read16(cap_ptr + 2) & 0b11_1111_1111) + 1; let table_size = (dev.location().read16(cap_ptr + 2) & 0b11_1111_1111) + 1;
// TODO: Different architecture seems to have different, so we should set different address here. // TODO: Different architecture seems to have different, so we should set different address here.
let message_address = 0xFEE0_000 as u32; let message_address = 0xFEE0_0000u32;
let message_upper_address = 0 as u32; let message_upper_address = 0u32;
// Set message address 0xFEE0_0000 // Set message address 0xFEE0_0000
for i in 0..table_size { for i in 0..table_size {
// Set message address and disable this msix entry // Set message address and disable this msix entry
table_bar table_bar
.io_mem() .io_mem()
.write_val((16 * i) as usize, &message_address) .write_val((16 * i) as usize + table_offset, &message_address)
.unwrap(); .unwrap();
table_bar table_bar
.io_mem() .io_mem()
.write_val((16 * i + 4) as usize, &message_upper_address) .write_val((16 * i + 4) as usize + table_offset, &message_upper_address)
.unwrap(); .unwrap();
table_bar table_bar
.io_mem() .io_mem()
.write_val((16 * i + 12) as usize, &(1 as u32)) .write_val((16 * i + 12) as usize + table_offset, &(1 as u32))
.unwrap(); .unwrap();
} }
// enable MSI-X, bit15: MSI-X Enable
dev.location()
.write16(cap_ptr + 2, dev.location().read16(cap_ptr + 2) | 0x8000);
// disable INTx, enable Bus master.
dev.set_command(dev.command() | Command::INTERRUPT_DISABLE | Command::BUS_MASTER);
let mut irq_allocate_handles = Vec::with_capacity(table_size as usize); let mut irq_allocate_handles = Vec::with_capacity(table_size as usize);
for i in 0..table_size { for i in 0..table_size {
irq_allocate_handles.push(None); irq_allocate_handles.push(None);
@ -93,7 +122,9 @@ impl CapabilityMsixData {
table_size: (dev.location().read16(cap_ptr + 2) & 0b11_1111_1111) + 1, table_size: (dev.location().read16(cap_ptr + 2) & 0b11_1111_1111) + 1,
table_bar, table_bar,
pending_table_bar: pba_bar, pending_table_bar: pba_bar,
irq_allocate_handles, irq_allocate_handles: SpinLock::new(irq_allocate_handles),
table_offset: table_offset,
pending_table_offset: pba_offset,
} }
} }
@ -102,38 +133,31 @@ impl CapabilityMsixData {
(self.loc.read16(self.ptr + 2) & 0b11_1111_1111) + 1 (self.loc.read16(self.ptr + 2) & 0b11_1111_1111) + 1
} }
pub fn set_msix_enable(&self, enable: bool) { pub fn set_interrupt_vector(&self, handle: IrqAllocateHandle, index: u16) {
// bit15: msix enable
let value = (enable as u16) << 15;
// message control
self.loc.write16(
self.ptr + 2,
set_bit(self.loc.read16(self.ptr + 2), 15, enable),
)
}
pub fn set_interrupt_enable(&self, enable: bool) {
// bit14: msix enable
let value = (enable as u16) << 14;
// message control
self.loc.write16(
self.ptr + 2,
set_bit(self.loc.read16(self.ptr + 2), 14, enable),
)
}
pub fn set_interrupt_vector(&mut self, vector: Arc<IrqAllocateHandle>, index: u16) {
if index >= self.table_size { if index >= self.table_size {
return; return;
} }
let old_handles = self.table_bar
core::mem::replace(&mut self.irq_allocate_handles[index as usize], Some(vector)); .io_mem()
.write_val(
(16 * index + 8) as usize + self.table_offset,
&(handle.num() as u32),
)
.unwrap();
let old_handles = core::mem::replace(
&mut self.irq_allocate_handles.lock()[index as usize],
Some(handle),
);
// Enable this msix vector // Enable this msix vector
self.table_bar self.table_bar
.io_mem() .io_mem()
.write_val((16 * index + 12) as usize, &(0 as u32)) .write_val((16 * index + 12) as usize + self.table_offset, &(0 as u32))
.unwrap(); .unwrap();
} }
pub fn interrupt_handles(&self) -> SpinLockGuard<'_, Vec<Option<IrqAllocateHandle>>> {
self.irq_allocate_handles.lock()
}
} }
fn set_bit(origin_value: u16, offset: usize, set: bool) -> u16 { fn set_bit(origin_value: u16, offset: usize, set: bool) -> u16 {

View File

@ -55,7 +55,7 @@ impl CapabilityVndrData {
#[inline] #[inline]
fn check_range(&self, offset: u16) -> Result<()> { fn check_range(&self, offset: u16) -> Result<()> {
if self.length > offset { if self.length < offset {
return Err(Error::InvalidArgs); return Err(Error::InvalidArgs);
} }
Ok(()) Ok(())

View File

@ -112,15 +112,17 @@ impl BarManager {
while idx < max { while idx < max {
match Bar::new(location, idx) { match Bar::new(location, idx) {
Ok(bar) => { Ok(bar) => {
let mut idx_step = 0;
match &bar { match &bar {
Bar::Memory(memory_bar) => { Bar::Memory(memory_bar) => {
if memory_bar.address_length() == AddrLen::Bits64 { if memory_bar.address_length() == AddrLen::Bits64 {
idx += 1; idx_step = 1;
} }
} }
Bar::Io(_) => {} Bar::Io(_) => {}
} }
bars[idx as usize] = Some((bar, false)); bars[idx as usize] = Some((bar, true));
idx += idx_step;
} }
// ignore for now // ignore for now
Err(_) => {} Err(_) => {}

View File

@ -49,9 +49,9 @@
//! ``` //! ```
pub mod bus; pub mod bus;
mod capability; pub mod capability;
mod cfg_space; pub mod cfg_space;
mod common_device; pub mod common_device;
mod device_info; mod device_info;
use crate::sync::Mutex; use crate::sync::Mutex;