mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-23 17:33:23 +00:00
Fix pci framework bugs
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
739eb30138
commit
df81434088
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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(())
|
||||||
|
@ -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(_) => {}
|
||||||
|
@ -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;
|
||||||
|
Reference in New Issue
Block a user