pcid: Store decoded MsixInfo instead of full capability in PciFeatureInfo

This commit is contained in:
bjorn3
2024-06-10 21:00:07 +02:00
parent 7c112c34dd
commit df66633111
11 changed files with 89 additions and 72 deletions
+11 -11
View File
@@ -13,7 +13,7 @@ use event::{user_data, EventQueue};
#[cfg(target_arch = "x86_64")]
use pcid_interface::irq_helpers::allocate_single_interrupt_vector_for_msi;
use pcid_interface::irq_helpers::read_bsp_apic_id;
use pcid_interface::msi::{MsixCapability, MsixTableEntry};
use pcid_interface::msi::{MsixInfo, MsixTableEntry};
use pcid_interface::{
MsiSetFeatureInfo, PciFeature, PciFeatureInfo, PcidServerHandle, SetFeatureInfo,
SubdriverArguments,
@@ -79,17 +79,17 @@ where
}
}
pub struct MsixInfo {
pub struct MappedMsixRegs {
pub virt_table_base: NonNull<MsixTableEntry>,
pub capability: MsixCapability,
pub info: MsixInfo,
}
impl MsixInfo {
impl MappedMsixRegs {
pub unsafe fn table_entry_pointer_unchecked(&mut self, k: usize) -> &mut MsixTableEntry {
&mut *self.virt_table_base.as_ptr().offset(k as isize)
}
pub fn table_entry_pointer(&mut self, k: usize) -> &mut MsixTableEntry {
assert!(k < self.capability.table_size() as usize);
assert!(k < self.info.table_size as usize);
unsafe { self.table_entry_pointer_unchecked(k) }
}
}
@@ -129,20 +129,20 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle) -> File {
interrupt_handle
} else if has_msix {
let capability = match pcid_handle.feature_info(PciFeature::MsiX).expect("rtl8139d: failed to retrieve the MSI-X capability structure from pcid") {
let msix_info = match pcid_handle.feature_info(PciFeature::MsiX).expect("rtl8139d: failed to retrieve the MSI-X capability structure from pcid") {
PciFeatureInfo::Msi(_) => panic!(),
PciFeatureInfo::MsiX(s) => s,
};
capability.validate(pci_config.func.bars);
msix_info.validate(pci_config.func.bars);
let bar = &pci_config.func.bars[capability.table_bir() as usize];
let bar = &pci_config.func.bars[msix_info.table_bar as usize];
let bar_address = unsafe { bar.physmap_mem("rtl8139d") } as usize;
let virt_table_base = (bar_address + capability.table_offset() as usize) as *mut MsixTableEntry;
let virt_table_base = (bar_address + msix_info.table_offset as usize) as *mut MsixTableEntry;
let mut info = MsixInfo {
let mut info = MappedMsixRegs {
virt_table_base: NonNull::new(virt_table_base).unwrap(),
capability,
info: msix_info,
};
// Allocate one msi vector.
+11 -11
View File
@@ -12,7 +12,7 @@ use pcid_interface::{MsiSetFeatureInfo, PcidServerHandle, PciFeature, PciFeature
#[cfg(target_arch = "x86_64")]
use pcid_interface::irq_helpers::allocate_single_interrupt_vector_for_msi;
use pcid_interface::irq_helpers::read_bsp_apic_id;
use pcid_interface::msi::{MsixCapability, MsixTableEntry};
use pcid_interface::msi::{MsixInfo, MsixTableEntry};
use redox_log::{RedoxLogger, OutputBuilder};
use syscall::EventFlags;
@@ -74,17 +74,17 @@ where
}
}
pub struct MsixInfo {
pub struct MappedMsixRegs {
pub virt_table_base: NonNull<MsixTableEntry>,
pub capability: MsixCapability,
pub info: MsixInfo,
}
impl MsixInfo {
impl MappedMsixRegs {
pub unsafe fn table_entry_pointer_unchecked(&mut self, k: usize) -> &mut MsixTableEntry {
&mut *self.virt_table_base.as_ptr().offset(k as isize)
}
pub fn table_entry_pointer(&mut self, k: usize) -> &mut MsixTableEntry {
assert!(k < self.capability.table_size() as usize);
assert!(k < self.info.table_size as usize);
unsafe { self.table_entry_pointer_unchecked(k) }
}
}
@@ -124,20 +124,20 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle) -> File {
interrupt_handle
} else if has_msix {
let capability = match pcid_handle.feature_info(PciFeature::MsiX).expect("rtl8168d: failed to retrieve the MSI-X capability structure from pcid") {
let msix_info = match pcid_handle.feature_info(PciFeature::MsiX).expect("rtl8168d: failed to retrieve the MSI-X capability structure from pcid") {
PciFeatureInfo::Msi(_) => panic!(),
PciFeatureInfo::MsiX(s) => s,
};
capability.validate(pci_config.func.bars);
msix_info.validate(pci_config.func.bars);
let bar = &pci_config.func.bars[capability.table_bir() as usize];
let bar = &pci_config.func.bars[msix_info.table_bar as usize];
let bar_address = unsafe { bar.physmap_mem("rtl8168d") } as usize;
let virt_table_base = (bar_address + capability.table_offset() as usize) as *mut MsixTableEntry;
let virt_table_base = (bar_address + msix_info.table_offset as usize) as *mut MsixTableEntry;
let mut info = MsixInfo {
let mut info = MappedMsixRegs {
virt_table_base: NonNull::new(virt_table_base).unwrap(),
capability,
info: msix_info,
};
// Allocate one msi vector.
+7 -1
View File
@@ -212,7 +212,13 @@ impl DriverHandler {
.iter()
.find_map(|capability| capability.as_msix())
{
PciFeatureInfo::MsiX(*info)
PciFeatureInfo::MsiX(msi::MsixInfo {
table_bar: info.table_bir(),
table_offset: info.table_offset(),
table_size: info.table_size(),
pba_bar: info.pba_bir(),
pba_offset: info.pba_offset(),
})
} else {
return PcidClientResponse::Error(
PcidServerResponseError::NonexistentFeature(feature),
+1 -1
View File
@@ -133,7 +133,7 @@ impl PciFeature {
#[derive(Debug, Serialize, Deserialize)]
pub enum PciFeatureInfo {
Msi(msi::MsiCapability),
MsiX(msi::MsixCapability),
MsiX(msi::MsixInfo),
}
#[derive(Debug, Error)]
+21 -10
View File
@@ -231,24 +231,33 @@ impl MsiCapability {
}
}
impl MsixCapability {
#[derive(Debug, Serialize, Deserialize)]
pub struct MsixInfo {
pub table_bar: u8,
pub table_offset: u32,
pub table_size: u16,
pub pba_bar: u8,
pub pba_offset: u32,
}
impl MsixInfo {
pub fn validate(&self, bars: [PciBar; 6]) {
if self.table_bir() > 5 {
panic!("MSI-X Table BIR contained a reserved enum value: {}", self.table_bir());
if self.table_bar > 5 {
panic!("MSI-X Table BIR contained a reserved enum value: {}", self.table_bar);
}
if self.pba_bir() > 5 {
panic!("MSI-X PBA BIR contained a reserved enum value: {}", self.pba_bir());
if self.pba_bar > 5 {
panic!("MSI-X PBA BIR contained a reserved enum value: {}", self.pba_bar);
}
let table_size = self.table_size();
let table_offset = self.table_offset() as usize;
let table_size = self.table_size;
let table_offset = self.table_offset as usize;
let table_min_length = table_size * 16;
let pba_offset = self.pba_offset() as usize;
let pba_offset = self.pba_offset as usize;
let pba_min_length = table_size.div_ceil(8);
let (_, table_bar_size) = bars[self.table_bir() as usize].expect_mem();
let (_, pba_bar_size) = bars[self.pba_bir() as usize].expect_mem();
let (_, table_bar_size) = bars[self.table_bar as usize].expect_mem();
let (_, pba_bar_size) = bars[self.pba_bar as usize].expect_mem();
// Ensure that the table and PBA are within the BAR.
@@ -270,7 +279,9 @@ impl MsixCapability {
);
}
}
}
impl MsixCapability {
const MC_MSIX_ENABLED_BIT: u16 = 1 << 15;
const MC_MSIX_ENABLED_SHIFT: u8 = 15;
const MC_FUNCTION_MASK_BIT: u16 = 1 << 14;
+8 -8
View File
@@ -82,14 +82,14 @@ fn get_int_method(
// TODO: Allocate more than one vector when possible and useful.
if has_msix {
// Extended message signaled interrupts.
use self::nvme::MsixCfg;
use self::nvme::MappedMsixRegs;
use pcid_interface::msi::MsixTableEntry;
let mut capability_struct = match pcid_handle.feature_info(PciFeature::MsiX).unwrap() {
let msix_info = match pcid_handle.feature_info(PciFeature::MsiX).unwrap() {
PciFeatureInfo::MsiX(msix) => msix,
_ => unreachable!(),
};
capability_struct.validate(function.bars);
msix_info.validate(function.bars);
fn bar_base(
allocated_bars: &AllocatedBars,
function: &PciFunction,
@@ -109,11 +109,11 @@ fn get_int_method(
}
}
let table_bar_base: *mut u8 =
bar_base(allocated_bars, function, capability_struct.table_bir())?.as_ptr();
bar_base(allocated_bars, function, msix_info.table_bar)?.as_ptr();
let table_base =
unsafe { table_bar_base.offset(capability_struct.table_offset() as isize) };
unsafe { table_bar_base.offset(msix_info.table_offset as isize) };
let vector_count = capability_struct.table_size();
let vector_count = msix_info.table_size;
let table_entries: &'static mut [MsixTableEntry] = unsafe {
slice::from_raw_parts_mut(table_base as *mut MsixTableEntry, vector_count as usize)
};
@@ -139,8 +139,8 @@ fn get_int_method(
(0, irq_handle)
};
let interrupt_method = InterruptMethod::MsiX(MsixCfg {
cap: capability_struct,
let interrupt_method = InterruptMethod::MsiX(MappedMsixRegs {
info: msix_info,
table: table_entries,
});
let interrupt_sources =
+4 -4
View File
@@ -22,7 +22,7 @@ pub mod queues;
use self::cq_reactor::NotifReq;
pub use self::queues::{NvmeCmd, NvmeCmdQueue, NvmeComp, NvmeCompQueue};
use pcid_interface::msi::{MsiCapability, MsixCapability, MsixTableEntry};
use pcid_interface::msi::{MsiCapability, MsixInfo, MsixTableEntry};
use pcid_interface::PcidServerHandle;
#[cfg(target_arch = "aarch64")]
@@ -93,7 +93,7 @@ pub enum InterruptMethod {
/// Message signaled interrupts
Msi(MsiCapability),
/// Extended message signaled interrupts
MsiX(MsixCfg),
MsiX(MappedMsixRegs),
}
impl InterruptMethod {
fn is_intx(&self) -> bool {
@@ -119,8 +119,8 @@ impl InterruptMethod {
}
}
pub struct MsixCfg {
pub cap: MsixCapability,
pub struct MappedMsixRegs {
pub info: MsixInfo,
pub table: &'static mut [MsixTableEntry],
}
+7 -7
View File
@@ -4,7 +4,7 @@ use pcid_interface::irq_helpers::{allocate_single_interrupt_vector_for_msi, read
use pcid_interface::msi::MsixTableEntry;
use std::{fs::File, ptr::NonNull};
use crate::{probe::MsixInfo, MSIX_PRIMARY_VECTOR};
use crate::{probe::MappedMsixRegs, MSIX_PRIMARY_VECTOR};
use pcid_interface::*;
@@ -12,19 +12,19 @@ pub fn enable_msix(pcid_handle: &mut PcidServerHandle) -> Result<File, Error> {
let pci_config = pcid_handle.fetch_config()?;
// Extended message signaled interrupts.
let capability = match pcid_handle.feature_info(PciFeature::MsiX)? {
let msix_info = match pcid_handle.feature_info(PciFeature::MsiX)? {
PciFeatureInfo::MsiX(capability) => capability,
_ => unreachable!(),
};
capability.validate(pci_config.func.bars);
msix_info.validate(pci_config.func.bars);
let bar = &pci_config.func.bars[capability.table_bir() as usize];
let bar = &pci_config.func.bars[msix_info.table_bar as usize];
let bar_address = unsafe { bar.physmap_mem("virtio-core") } as usize;
let virt_table_base = (bar_address + capability.table_offset() as usize) as *mut MsixTableEntry;
let virt_table_base = (bar_address + msix_info.table_offset as usize) as *mut MsixTableEntry;
let mut info = MsixInfo {
let mut info = MappedMsixRegs {
virt_table_base: NonNull::new(virt_table_base).unwrap(),
capability,
info: msix_info,
};
// Allocate the primary MSI vector.
+5 -5
View File
@@ -2,7 +2,7 @@ use std::fs::File;
use std::ptr::NonNull;
use std::sync::Arc;
use pcid_interface::msi::{MsixCapability, MsixTableEntry};
use pcid_interface::msi::{MsixInfo, MsixTableEntry};
use pcid_interface::*;
use crate::spec::*;
@@ -20,18 +20,18 @@ pub struct Device {
unsafe impl Send for Device {}
unsafe impl Sync for Device {}
pub struct MsixInfo {
pub struct MappedMsixRegs {
pub virt_table_base: NonNull<MsixTableEntry>,
pub capability: MsixCapability,
pub info: MsixInfo,
}
impl MsixInfo {
impl MappedMsixRegs {
pub unsafe fn table_entry_pointer_unchecked(&mut self, k: usize) -> &mut MsixTableEntry {
&mut *self.virt_table_base.as_ptr().add(k)
}
pub fn table_entry_pointer(&mut self, k: usize) -> &mut MsixTableEntry {
assert!(k < self.capability.table_size() as usize);
assert!(k < self.info.table_size as usize);
unsafe { self.table_entry_pointer_unchecked(k) }
}
}
+6 -6
View File
@@ -119,18 +119,18 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle, bar0_address: usize) -> (O
(Some(interrupt_handle), InterruptMethod::Msi)
} else if has_msix {
let capability = match pcid_handle.feature_info(PciFeature::MsiX).expect("xhcid: failed to retrieve the MSI-X capability structure from pcid") {
let msix_info = match pcid_handle.feature_info(PciFeature::MsiX).expect("xhcid: failed to retrieve the MSI-X capability structure from pcid") {
PciFeatureInfo::Msi(_) => panic!(),
PciFeatureInfo::MsiX(s) => s,
};
capability.validate(pci_config.func.bars);
msix_info.validate(pci_config.func.bars);
assert_eq!(capability.table_bir(), 0);
let virt_table_base = (bar0_address + capability.table_offset() as usize) as *mut MsixTableEntry;
assert_eq!(msix_info.table_bar, 0);
let virt_table_base = (bar0_address + msix_info.table_offset as usize) as *mut MsixTableEntry;
let mut info = xhci::MsixInfo {
let mut info = xhci::MappedMsixRegs {
virt_table_base: NonNull::new(virt_table_base).unwrap(),
capability,
info: msix_info,
};
// Allocate one msi vector.
+8 -8
View File
@@ -21,7 +21,7 @@ use serde::Deserialize;
use crate::usb;
use pcid_interface::msi::{MsixTableEntry, MsixCapability};
use pcid_interface::msi::{MsixInfo, MsixTableEntry};
use pcid_interface::{PcidServerHandle, PciFeature};
mod capability;
@@ -64,19 +64,19 @@ pub enum InterruptMethod {
Msi,
/// Extended message signaled interrupts.
MsiX(Mutex<MsixInfo>),
MsiX(Mutex<MappedMsixRegs>),
}
pub struct MsixInfo {
pub struct MappedMsixRegs {
pub virt_table_base: NonNull<MsixTableEntry>,
pub capability: MsixCapability,
pub info: MsixInfo,
}
impl MsixInfo {
impl MappedMsixRegs {
pub unsafe fn table_entry_pointer_unchecked(&mut self, k: usize) -> &mut MsixTableEntry {
&mut *self.virt_table_base.as_ptr().offset(k as isize)
}
pub fn table_entry_pointer(&mut self, k: usize) -> &mut MsixTableEntry {
assert!(k < self.capability.table_size() as usize);
assert!(k < self.info.table_size as usize);
unsafe { self.table_entry_pointer_unchecked(k) }
}
}
@@ -774,13 +774,13 @@ impl Xhci {
if let InterruptMethod::MsiX(_) = self.interrupt_method { true } else { false }
}
// TODO: Perhaps use an rwlock?
pub fn msix_info(&self) -> Option<MutexGuard<'_, MsixInfo>> {
pub fn msix_info(&self) -> Option<MutexGuard<'_, MappedMsixRegs>> {
match self.interrupt_method {
InterruptMethod::MsiX(ref info) => Some(info.lock().unwrap()),
_ => None,
}
}
pub fn msix_info_mut(&self) -> Option<MutexGuard<'_, MsixInfo>> {
pub fn msix_info_mut(&self) -> Option<MutexGuard<'_, MappedMsixRegs>> {
match self.interrupt_method {
InterruptMethod::MsiX(ref info) => Some(info.lock().unwrap()),
_ => None,