Merge branch 'pci_interrupts_rework2' into 'master'
Various improvements to the MSI-X support See merge request redox-os/drivers!138
This commit is contained in:
+3
-12
@@ -6,7 +6,6 @@ extern crate spin;
|
||||
extern crate syscall;
|
||||
extern crate event;
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::usize;
|
||||
use std::fs::File;
|
||||
use std::io::{ErrorKind, Read, Write, Result};
|
||||
@@ -17,7 +16,7 @@ use std::sync::Arc;
|
||||
|
||||
use event::EventQueue;
|
||||
use pcid_interface::{MsiSetFeatureInfo, PcidServerHandle, PciFeature, PciFeatureInfo, SetFeatureInfo};
|
||||
use pcid_interface::irq_helpers::{read_bsp_apic_id, allocate_single_interrupt_vector};
|
||||
use pcid_interface::irq_helpers::{read_bsp_apic_id, allocate_single_interrupt_vector_for_msi};
|
||||
use redox_log::{OutputBuilder, RedoxLogger};
|
||||
|
||||
pub mod hda;
|
||||
@@ -91,8 +90,6 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle) -> File {
|
||||
}
|
||||
|
||||
if msi_enabled && !msix_enabled {
|
||||
use pcid_interface::msi::x86_64::{DeliveryMode, self as x86_64_msix};
|
||||
|
||||
let capability = match pcid_handle.feature_info(PciFeature::Msi).expect("ihdad: failed to retrieve the MSI capability structure from pcid") {
|
||||
PciFeatureInfo::Msi(s) => s,
|
||||
PciFeatureInfo::MsiX(_) => panic!(),
|
||||
@@ -103,17 +100,11 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle) -> File {
|
||||
// pcid_interface, so that this can be shared between nvmed, xhcid, ixgebd, etc..
|
||||
|
||||
let destination_id = read_bsp_apic_id().expect("ihdad: failed to read BSP apic id");
|
||||
let lapic_id = u8::try_from(destination_id).expect("CPU id didn't fit inside u8");
|
||||
let msg_addr = x86_64_msix::message_address(lapic_id, false, false);
|
||||
|
||||
let (vector, interrupt_handle) = allocate_single_interrupt_vector(destination_id).expect("ihdad: failed to allocate interrupt vector").expect("ihdad: no interrupt vectors left");
|
||||
let msg_data = x86_64_msix::message_data_edge_triggered(DeliveryMode::Fixed, vector);
|
||||
let (msg_addr_and_data, interrupt_handle) = allocate_single_interrupt_vector_for_msi(destination_id);
|
||||
|
||||
let set_feature_info = MsiSetFeatureInfo {
|
||||
multi_message_enable: Some(0),
|
||||
message_address: Some(msg_addr),
|
||||
message_upper_address: Some(0),
|
||||
message_data: Some(msg_data as u16),
|
||||
message_address_and_data: Some(msg_addr_and_data),
|
||||
mask_bits: None,
|
||||
};
|
||||
pcid_handle.set_feature_info(SetFeatureInfo::Msi(set_feature_info)).expect("ihdad: failed to set feature info");
|
||||
|
||||
+8
-40
@@ -88,6 +88,7 @@ fn get_int_method(
|
||||
PciFeatureInfo::MsiX(msix) => msix,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
capability_struct.validate(function.bars);
|
||||
fn bar_base(
|
||||
allocated_bars: &AllocatedBars,
|
||||
function: &PciFunction,
|
||||
@@ -108,22 +109,13 @@ fn get_int_method(
|
||||
}
|
||||
let table_bar_base: *mut u8 =
|
||||
bar_base(allocated_bars, function, capability_struct.table_bir())?.as_ptr();
|
||||
let pba_bar_base: *mut u8 =
|
||||
bar_base(allocated_bars, function, capability_struct.pba_bir())?.as_ptr();
|
||||
let table_base =
|
||||
unsafe { table_bar_base.offset(capability_struct.table_offset() as isize) };
|
||||
let pba_base = unsafe { pba_bar_base.offset(capability_struct.pba_offset() as isize) };
|
||||
|
||||
let vector_count = capability_struct.table_size();
|
||||
let table_entries: &'static mut [MsixTableEntry] = unsafe {
|
||||
slice::from_raw_parts_mut(table_base as *mut MsixTableEntry, vector_count as usize)
|
||||
};
|
||||
let pba_entries: &'static mut [Mmio<u64>] = unsafe {
|
||||
slice::from_raw_parts_mut(
|
||||
table_base as *mut Mmio<u64>,
|
||||
(vector_count as usize + 63) / 64,
|
||||
)
|
||||
};
|
||||
|
||||
// Mask all interrupts in case some earlier driver/os already unmasked them (according to
|
||||
// the PCI Local Bus spec 3.0, they are masked after system reset).
|
||||
@@ -135,25 +127,14 @@ fn get_int_method(
|
||||
capability_struct.set_msix_enabled(true); // only affects our local mirror of the cap
|
||||
|
||||
let (msix_vector_number, irq_handle) = {
|
||||
use msi_x86_64::DeliveryMode;
|
||||
use pcid_interface::msi::x86_64 as msi_x86_64;
|
||||
|
||||
let entry: &mut MsixTableEntry = &mut table_entries[0];
|
||||
|
||||
let bsp_cpu_id =
|
||||
irq_helpers::read_bsp_apic_id().expect("nvmed: failed to read APIC ID");
|
||||
let bsp_lapic_id = bsp_cpu_id
|
||||
.try_into()
|
||||
.expect("nvmed: BSP local apic ID couldn't fit inside u8");
|
||||
let (vector, irq_handle) = irq_helpers::allocate_single_interrupt_vector(bsp_cpu_id)
|
||||
.expect("nvmed: failed to allocate single MSI-X interrupt vector")
|
||||
.expect("nvmed: no interrupt vectors left on BSP");
|
||||
|
||||
let msg_addr = msi_x86_64::message_address(bsp_lapic_id, false, false);
|
||||
let msg_data = msi_x86_64::message_data_edge_triggered(DeliveryMode::Fixed, vector);
|
||||
|
||||
entry.set_addr_lo(msg_addr);
|
||||
entry.set_msg_data(msg_data);
|
||||
let (msg_addr_and_data, irq_handle) =
|
||||
irq_helpers::allocate_single_interrupt_vector_for_msi(bsp_cpu_id);
|
||||
entry.write_addr_and_data(msg_addr_and_data);
|
||||
entry.unmask();
|
||||
|
||||
(0, irq_handle)
|
||||
};
|
||||
@@ -161,7 +142,6 @@ fn get_int_method(
|
||||
let interrupt_method = InterruptMethod::MsiX(MsixCfg {
|
||||
cap: capability_struct,
|
||||
table: table_entries,
|
||||
pba: pba_entries,
|
||||
});
|
||||
let interrupt_sources =
|
||||
InterruptSources::MsiX(std::iter::once((msix_vector_number, irq_handle)).collect());
|
||||
@@ -175,27 +155,15 @@ fn get_int_method(
|
||||
};
|
||||
|
||||
let (msi_vector_number, irq_handle) = {
|
||||
use msi_x86_64::DeliveryMode;
|
||||
use pcid_interface::msi::x86_64 as msi_x86_64;
|
||||
use pcid_interface::{MsiSetFeatureInfo, SetFeatureInfo};
|
||||
|
||||
let bsp_cpu_id =
|
||||
irq_helpers::read_bsp_apic_id().expect("nvmed: failed to read BSP APIC ID");
|
||||
let bsp_lapic_id = bsp_cpu_id
|
||||
.try_into()
|
||||
.expect("nvmed: BSP local apic ID couldn't fit inside u8");
|
||||
let (vector, irq_handle) = irq_helpers::allocate_single_interrupt_vector(bsp_cpu_id)
|
||||
.expect("nvmed: failed to allocate single MSI interrupt vector")
|
||||
.expect("nvmed: no interrupt vectors left on BSP");
|
||||
|
||||
let msg_addr = msi_x86_64::message_address(bsp_lapic_id, false, false);
|
||||
let msg_data =
|
||||
msi_x86_64::message_data_edge_triggered(DeliveryMode::Fixed, vector) as u16;
|
||||
let (msg_addr_and_data, irq_handle) =
|
||||
irq_helpers::allocate_single_interrupt_vector_for_msi(bsp_cpu_id);
|
||||
|
||||
pcid_handle.set_feature_info(SetFeatureInfo::Msi(MsiSetFeatureInfo {
|
||||
message_address: Some(msg_addr),
|
||||
message_upper_address: Some(0),
|
||||
message_data: Some(msg_data),
|
||||
message_address_and_data: Some(msg_addr_and_data),
|
||||
multi_message_enable: Some(0), // enable 2^0=1 vectors
|
||||
mask_bits: None,
|
||||
})).unwrap();
|
||||
|
||||
@@ -122,7 +122,6 @@ impl InterruptMethod {
|
||||
pub struct MsixCfg {
|
||||
pub cap: MsixCapability,
|
||||
pub table: &'static mut [MsixTableEntry],
|
||||
pub pba: &'static mut [Mmio<u64>],
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
|
||||
@@ -8,6 +8,8 @@ use std::fs::{self, File};
|
||||
use std::io::{self, prelude::*};
|
||||
use std::num::NonZeroU8;
|
||||
|
||||
use crate::pci::msi::MsiAddrAndData;
|
||||
|
||||
/// Read the local APIC ID of the bootstrap processor.
|
||||
pub fn read_bsp_apic_id() -> io::Result<usize> {
|
||||
let mut buffer = [0u8; 8];
|
||||
@@ -153,3 +155,22 @@ pub fn allocate_single_interrupt_vector(cpu_id: usize) -> io::Result<Option<(u8,
|
||||
assert_eq!(files.len(), 1);
|
||||
Ok(Some((base, files.pop().unwrap())))
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
pub fn allocate_single_interrupt_vector_for_msi(cpu_id: usize) -> (MsiAddrAndData, File) {
|
||||
use crate::pci::msi::x86_64 as x86_64_msix;
|
||||
|
||||
// FIXME for cpu_id >255 we need to use the IOMMU to use IRQ remapping
|
||||
let lapic_id = u8::try_from(cpu_id).expect("CPU id couldn't fit inside u8");
|
||||
let rh = false;
|
||||
let dm = false;
|
||||
let addr = x86_64_msix::message_address(lapic_id, rh, dm);
|
||||
|
||||
let (vector, interrupt_handle) = allocate_single_interrupt_vector(cpu_id)
|
||||
.expect("failed to allocate interrupt vector")
|
||||
.expect("no interrupt vectors left");
|
||||
let msg_data =
|
||||
x86_64_msix::message_data_edge_triggered(x86_64_msix::DeliveryMode::Fixed, vector);
|
||||
|
||||
(MsiAddrAndData::new(addr, msg_data), interrupt_handle)
|
||||
}
|
||||
|
||||
@@ -163,22 +163,12 @@ pub struct MsiSetFeatureInfo {
|
||||
/// is the log2 of the interrupt vectors, minus one. Can only be 0b000..=0b101.
|
||||
pub multi_message_enable: Option<u8>,
|
||||
|
||||
/// The system-specific message address, must be DWORD aligned.
|
||||
/// The system-specific message address and data.
|
||||
///
|
||||
/// The message address contains things like the CPU that will be targeted, at least on
|
||||
/// x86_64.
|
||||
pub message_address: Option<u32>,
|
||||
|
||||
/// The upper 32 bits of the 64-bit message address. Not guaranteed to exist, and is
|
||||
/// reserved on x86_64 (currently).
|
||||
pub message_upper_address: Option<u32>,
|
||||
|
||||
/// The message data, containing the actual interrupt vector (lower 8 bits), etc.
|
||||
///
|
||||
/// The spec mentions that the lower N bits can be modified, where N is the multi message
|
||||
/// enable, which means that the vector set here has to be aligned to that number, and that
|
||||
/// all vectors in that range have to be allocated.
|
||||
pub message_data: Option<u16>,
|
||||
/// x86_64. The message data contains the actual interrupt vector (lower 8 bits) and
|
||||
/// the kind of interrupt, at least on x86_64.
|
||||
pub message_address_and_data: Option<msi::MsiAddrAndData>,
|
||||
|
||||
/// A bitmap of the vectors that are masked. This field is not guaranteed (and not likely,
|
||||
/// at least according to the feature flags I got from QEMU), to exist.
|
||||
|
||||
+12
-10
@@ -14,7 +14,7 @@ use redox_log::{OutputBuilder, RedoxLogger};
|
||||
use crate::cfg_access::Pcie;
|
||||
use crate::config::Config;
|
||||
use crate::driver_interface::LegacyInterruptLine;
|
||||
use crate::pci::{PciBar, PciFunc};
|
||||
use crate::pci::PciFunc;
|
||||
use crate::pci::cap::Capability as PciCapability;
|
||||
use crate::pci::func::{ConfigReader, ConfigWriter};
|
||||
use crate::pci_header::{PciEndpointHeader, PciHeader, PciHeaderError};
|
||||
@@ -130,20 +130,22 @@ impl DriverHandler {
|
||||
info.set_multi_message_enable(mme);
|
||||
|
||||
}
|
||||
if let Some(message_addr) = info_to_set.message_address {
|
||||
if let Some(message_addr_and_data) = info_to_set.message_address_and_data {
|
||||
let message_addr = message_addr_and_data.addr;
|
||||
if message_addr & 0b11 != 0 {
|
||||
return PcidClientResponse::Error(PcidServerResponseError::InvalidBitPattern);
|
||||
}
|
||||
info.set_message_address(message_addr);
|
||||
}
|
||||
if let Some(message_addr_upper) = info_to_set.message_upper_address {
|
||||
info.set_message_upper_address(message_addr_upper);
|
||||
}
|
||||
if let Some(message_data) = info_to_set.message_data {
|
||||
if message_data & ((1 << info.multi_message_enable()) - 1) != 0 {
|
||||
info.set_message_address(message_addr as u32);
|
||||
info.set_message_upper_address((message_addr >> 32) as u32);
|
||||
if message_addr_and_data.data & ((1 << info.multi_message_enable()) - 1) != 0 {
|
||||
return PcidClientResponse::Error(PcidServerResponseError::InvalidBitPattern);
|
||||
}
|
||||
info.set_message_data(message_data);
|
||||
info.set_message_data(
|
||||
message_addr_and_data
|
||||
.data
|
||||
.try_into()
|
||||
.expect("pcid: MSI message data too big"),
|
||||
);
|
||||
}
|
||||
if let Some(mask_bits) = info_to_set.mask_bits {
|
||||
info.set_mask_bits(mask_bits);
|
||||
|
||||
+67
-19
@@ -4,8 +4,25 @@ use super::bar::PciBar;
|
||||
pub use super::cap::{MsiCapability, MsixCapability};
|
||||
use super::func::{ConfigReader, ConfigWriter};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use syscall::{Io, Mmio};
|
||||
|
||||
/// The address and data to use for MSI and MSI-X.
|
||||
///
|
||||
/// For MSI using this only works when you need a single interrupt vector.
|
||||
/// For MSI-X you can have a single [MsiEntry] for each interrupt vector.
|
||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||
pub struct MsiAddrAndData {
|
||||
pub(crate) addr: u64,
|
||||
pub(crate) data: u32,
|
||||
}
|
||||
|
||||
impl MsiAddrAndData {
|
||||
pub fn new(addr: u64, data: u32) -> Self {
|
||||
MsiAddrAndData { addr, data }
|
||||
}
|
||||
}
|
||||
|
||||
impl MsiCapability {
|
||||
pub const MC_PVT_CAPABLE_BIT: u16 = 1 << 8;
|
||||
pub const MC_64_BIT_ADDR_BIT: u16 = 1 << 7;
|
||||
@@ -203,6 +220,45 @@ impl MsiCapability {
|
||||
}
|
||||
|
||||
impl MsixCapability {
|
||||
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.pba_bir() > 5 {
|
||||
panic!("MSI-X PBA BIR contained a reserved enum value: {}", self.pba_bir());
|
||||
}
|
||||
|
||||
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_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();
|
||||
|
||||
// Ensure that the table and PBA are within the BAR.
|
||||
|
||||
if !(0..table_bar_size as u64).contains(&(table_offset as u64 + table_min_length as u64)) {
|
||||
panic!(
|
||||
"Table {:#x}:{:#x} outside of BAR with length {:#x}",
|
||||
table_offset,
|
||||
table_offset + table_min_length as usize,
|
||||
table_bar_size
|
||||
);
|
||||
}
|
||||
|
||||
if !(0..pba_bar_size as u64).contains(&(pba_offset as u64 + pba_min_length as u64)) {
|
||||
panic!(
|
||||
"PBA {:#x}:{:#x} outside of BAR with length {:#x}",
|
||||
pba_offset,
|
||||
pba_offset + pba_min_length as usize,
|
||||
pba_bar_size
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const MC_MSIX_ENABLED_BIT: u16 = 1 << 15;
|
||||
const MC_MSIX_ENABLED_SHIFT: u8 = 15;
|
||||
const MC_FUNCTION_MASK_BIT: u16 = 1 << 14;
|
||||
@@ -271,20 +327,6 @@ impl MsixCapability {
|
||||
}
|
||||
|
||||
|
||||
pub fn table_base_pointer(&self, bars: [PciBar; 6]) -> usize {
|
||||
if self.table_bir() > 5 {
|
||||
panic!("MSI-X Table BIR contained a reserved enum value: {}", self.table_bir());
|
||||
}
|
||||
bars[usize::from(self.table_bir())].expect_mem().0 + self.table_offset() as usize
|
||||
}
|
||||
|
||||
pub fn pba_base_pointer(&self, bars: [PciBar; 6]) -> usize {
|
||||
if self.pba_bir() > 5 {
|
||||
panic!("MSI-X PBA BIR contained a reserved enum value: {}", self.pba_bir());
|
||||
}
|
||||
bars[usize::from(self.pba_bir())].expect_mem().0 + self.pba_offset() as usize
|
||||
}
|
||||
|
||||
/// Write the first DWORD into configuration space (containing the partially modifiable Message
|
||||
/// Control field).
|
||||
pub unsafe fn write_a<W: ConfigWriter>(&self, writer: &W, offset: u8) {
|
||||
@@ -327,11 +369,11 @@ pub mod x86_64 {
|
||||
}
|
||||
|
||||
// TODO: should the reserved field be preserved?
|
||||
pub const fn message_address(destination_id: u8, rh: bool, dm: bool) -> u32 {
|
||||
0xFEE0_0000u32
|
||||
| ((destination_id as u32) << 12)
|
||||
| ((rh as u32) << 3)
|
||||
| ((dm as u32) << 2)
|
||||
pub const fn message_address(destination_id: u8, redirect_hint: bool, dest_mode_logical: bool) -> u64 {
|
||||
0x0000_0000_FEE0_0000u64
|
||||
| ((destination_id as u64) << 12)
|
||||
| ((redirect_hint as u64) << 3)
|
||||
| ((dest_mode_logical as u64) << 2)
|
||||
}
|
||||
pub const fn message_data(trigger_mode: TriggerMode, level_trigger_mode: LevelTriggerMode, delivery_mode: DeliveryMode, vector: u8) -> u32 {
|
||||
((trigger_mode as u32) << 15)
|
||||
@@ -383,6 +425,12 @@ impl MsixTableEntry {
|
||||
pub fn unmask(&mut self) {
|
||||
self.set_masked(false);
|
||||
}
|
||||
|
||||
pub fn write_addr_and_data(&mut self, entry: MsiAddrAndData) {
|
||||
self.set_addr_lo(entry.addr as u32);
|
||||
self.set_addr_hi((entry.addr >> 32) as u32);
|
||||
self.set_msg_data(entry.data);
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for MsixTableEntry {
|
||||
|
||||
+12
-62
@@ -5,7 +5,7 @@ extern crate netutils;
|
||||
extern crate syscall;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::convert::TryInto;
|
||||
use std::{env, process};
|
||||
use std::fs::File;
|
||||
use std::io::{ErrorKind, Read, Result, Write};
|
||||
@@ -15,11 +15,10 @@ use std::sync::Arc;
|
||||
|
||||
use event::EventQueue;
|
||||
use pcid_interface::{MsiSetFeatureInfo, PcidServerHandle, PciFeature, PciFeatureInfo, SetFeatureInfo, SubdriverArguments};
|
||||
use pcid_interface::irq_helpers::{read_bsp_apic_id, allocate_single_interrupt_vector};
|
||||
use pcid_interface::irq_helpers::{read_bsp_apic_id, allocate_single_interrupt_vector_for_msi};
|
||||
use pcid_interface::msi::{MsixCapability, MsixTableEntry};
|
||||
use redox_log::{RedoxLogger, OutputBuilder};
|
||||
use syscall::{EventFlags, Packet, SchemeBlockMut};
|
||||
use syscall::io::Io;
|
||||
|
||||
pub mod device;
|
||||
|
||||
@@ -81,7 +80,6 @@ where
|
||||
|
||||
pub struct MsixInfo {
|
||||
pub virt_table_base: NonNull<MsixTableEntry>,
|
||||
pub virt_pba_base: NonNull<u64>,
|
||||
pub capability: MsixCapability,
|
||||
}
|
||||
|
||||
@@ -93,18 +91,6 @@ impl MsixInfo {
|
||||
assert!(k < self.capability.table_size() as usize);
|
||||
unsafe { self.table_entry_pointer_unchecked(k) }
|
||||
}
|
||||
pub unsafe fn pba_pointer_unchecked(&mut self, k: usize) -> &mut u64 {
|
||||
&mut *self.virt_pba_base.as_ptr().offset(k as isize)
|
||||
}
|
||||
pub fn pba_pointer(&mut self, k: usize) -> &mut u64 {
|
||||
assert!(k < self.capability.table_size() as usize);
|
||||
unsafe { self.pba_pointer_unchecked(k) }
|
||||
}
|
||||
pub fn pba(&mut self, k: usize) -> bool {
|
||||
let byte = k / 64;
|
||||
let bit = k % 64;
|
||||
*self.pba_pointer(byte) & (1 << bit) != 0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@@ -125,8 +111,6 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle) -> File {
|
||||
}
|
||||
|
||||
if msi_enabled && !msix_enabled {
|
||||
use pcid_interface::msi::x86_64::{DeliveryMode, self as x86_64_msix};
|
||||
|
||||
let capability = match pcid_handle.feature_info(PciFeature::Msi).expect("rtl8139d: failed to retrieve the MSI capability structure from pcid") {
|
||||
PciFeatureInfo::Msi(s) => s,
|
||||
PciFeatureInfo::MsiX(_) => panic!(),
|
||||
@@ -137,17 +121,11 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle) -> File {
|
||||
// pcid_interface, so that this can be shared between nvmed, xhcid, ixgebd, etc..
|
||||
|
||||
let destination_id = read_bsp_apic_id().expect("rtl8139d: failed to read BSP apic id");
|
||||
let lapic_id = u8::try_from(destination_id).expect("CPU id didn't fit inside u8");
|
||||
let msg_addr = x86_64_msix::message_address(lapic_id, false, false);
|
||||
|
||||
let (vector, interrupt_handle) = allocate_single_interrupt_vector(destination_id).expect("rtl8139d: failed to allocate interrupt vector").expect("rtl8139d: no interrupt vectors left");
|
||||
let msg_data = x86_64_msix::message_data_edge_triggered(DeliveryMode::Fixed, vector);
|
||||
let (msg_addr_and_data, interrupt_handle) = allocate_single_interrupt_vector_for_msi(destination_id);
|
||||
|
||||
let set_feature_info = MsiSetFeatureInfo {
|
||||
multi_message_enable: Some(0),
|
||||
message_address: Some(msg_addr),
|
||||
message_upper_address: Some(0),
|
||||
message_data: Some(msg_data as u16),
|
||||
message_address_and_data: Some(msg_addr_and_data),
|
||||
mask_bits: None,
|
||||
};
|
||||
pcid_handle.set_feature_info(SetFeatureInfo::Msi(set_feature_info)).expect("rtl8139d: failed to set feature info");
|
||||
@@ -161,41 +139,21 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle) -> File {
|
||||
PciFeatureInfo::Msi(_) => panic!(),
|
||||
PciFeatureInfo::MsiX(s) => s,
|
||||
};
|
||||
let table_size = capability.table_size();
|
||||
let table_base = capability.table_base_pointer(pci_config.func.bars);
|
||||
let table_min_length = table_size * 16;
|
||||
let pba_min_length = div_round_up(table_size, 8);
|
||||
capability.validate(pci_config.func.bars);
|
||||
|
||||
let pba_base = capability.pba_base_pointer(pci_config.func.bars);
|
||||
let bar = &pci_config.func.bars[capability.table_bir() as usize];
|
||||
let bar_address = unsafe { bar.physmap_mem("rtl8139d") } as usize;
|
||||
|
||||
let bir = capability.table_bir() as usize;
|
||||
let bar = &pci_config.func.bars[bir];
|
||||
let (bar_ptr, bar_size) = bar.expect_mem();
|
||||
|
||||
let address = unsafe { bar.physmap_mem("rtl8139d") } as usize;
|
||||
|
||||
if !(bar_ptr as u64..bar_ptr as u64 + bar_size as u64).contains(&(table_base as u64 + table_min_length as u64)) {
|
||||
panic!("Table {:#x}{:#x} outside of BAR {:#x}:{:#x}", table_base, table_base + table_min_length as usize, bar_ptr, bar_ptr + bar_size);
|
||||
}
|
||||
|
||||
if !(bar_ptr as u64..bar_ptr as u64 + bar_size as u64).contains(&(pba_base as u64 + pba_min_length as u64)) {
|
||||
panic!("PBA {:#x}{:#x} outside of BAR {:#x}:{:#X}", pba_base, pba_base + pba_min_length as usize, bar_ptr, bar_ptr + bar_size);
|
||||
}
|
||||
|
||||
let virt_table_base = ((table_base - bar_ptr) + address) as *mut MsixTableEntry;
|
||||
let virt_pba_base = ((pba_base - bar_ptr) + address) as *mut u64;
|
||||
let virt_table_base = (bar_address + capability.table_offset() as usize) as *mut MsixTableEntry;
|
||||
|
||||
let mut info = MsixInfo {
|
||||
virt_table_base: NonNull::new(virt_table_base).unwrap(),
|
||||
virt_pba_base: NonNull::new(virt_pba_base).unwrap(),
|
||||
capability,
|
||||
};
|
||||
|
||||
// Allocate one msi vector.
|
||||
|
||||
let method = {
|
||||
use pcid_interface::msi::x86_64::{DeliveryMode, self as x86_64_msix};
|
||||
|
||||
// primary interrupter
|
||||
let k = 0;
|
||||
|
||||
@@ -203,18 +161,10 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle) -> File {
|
||||
let table_entry_pointer = info.table_entry_pointer(k);
|
||||
|
||||
let destination_id = read_bsp_apic_id().expect("rtl8139d: failed to read BSP apic id");
|
||||
let lapic_id = u8::try_from(destination_id).expect("rtl8139d: CPU id couldn't fit inside u8");
|
||||
let rh = false;
|
||||
let dm = false;
|
||||
let addr = x86_64_msix::message_address(lapic_id, rh, dm);
|
||||
|
||||
let (vector, interrupt_handle) = allocate_single_interrupt_vector(destination_id).expect("rtl8139d: failed to allocate interrupt vector").expect("rtl8139d: no interrupt vectors left");
|
||||
let msg_data = x86_64_msix::message_data_edge_triggered(DeliveryMode::Fixed, vector);
|
||||
|
||||
table_entry_pointer.addr_lo.write(addr);
|
||||
table_entry_pointer.addr_hi.write(0);
|
||||
table_entry_pointer.msg_data.write(msg_data);
|
||||
table_entry_pointer.vec_ctl.writef(MsixTableEntry::VEC_CTL_MASK_BIT, false);
|
||||
let (msg_addr_and_data, interrupt_handle) =
|
||||
allocate_single_interrupt_vector_for_msi(destination_id);
|
||||
table_entry_pointer.write_addr_and_data(msg_addr_and_data);
|
||||
table_entry_pointer.unmask();
|
||||
|
||||
interrupt_handle
|
||||
};
|
||||
|
||||
+12
-62
@@ -3,7 +3,7 @@ extern crate netutils;
|
||||
extern crate syscall;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::convert::TryInto;
|
||||
use std::{env, process};
|
||||
use std::fs::File;
|
||||
use std::io::{ErrorKind, Read, Result, Write};
|
||||
@@ -13,11 +13,10 @@ use std::sync::Arc;
|
||||
|
||||
use event::EventQueue;
|
||||
use pcid_interface::{MsiSetFeatureInfo, PcidServerHandle, PciFeature, PciFeatureInfo, SetFeatureInfo, SubdriverArguments};
|
||||
use pcid_interface::irq_helpers::{read_bsp_apic_id, allocate_single_interrupt_vector};
|
||||
use pcid_interface::irq_helpers::{read_bsp_apic_id, allocate_single_interrupt_vector_for_msi};
|
||||
use pcid_interface::msi::{MsixCapability, MsixTableEntry};
|
||||
use redox_log::{RedoxLogger, OutputBuilder};
|
||||
use syscall::{EventFlags, Packet, SchemeBlockMut};
|
||||
use syscall::io::Io;
|
||||
|
||||
pub mod device;
|
||||
|
||||
@@ -79,7 +78,6 @@ where
|
||||
|
||||
pub struct MsixInfo {
|
||||
pub virt_table_base: NonNull<MsixTableEntry>,
|
||||
pub virt_pba_base: NonNull<u64>,
|
||||
pub capability: MsixCapability,
|
||||
}
|
||||
|
||||
@@ -91,18 +89,6 @@ impl MsixInfo {
|
||||
assert!(k < self.capability.table_size() as usize);
|
||||
unsafe { self.table_entry_pointer_unchecked(k) }
|
||||
}
|
||||
pub unsafe fn pba_pointer_unchecked(&mut self, k: usize) -> &mut u64 {
|
||||
&mut *self.virt_pba_base.as_ptr().offset(k as isize)
|
||||
}
|
||||
pub fn pba_pointer(&mut self, k: usize) -> &mut u64 {
|
||||
assert!(k < self.capability.table_size() as usize);
|
||||
unsafe { self.pba_pointer_unchecked(k) }
|
||||
}
|
||||
pub fn pba(&mut self, k: usize) -> bool {
|
||||
let byte = k / 64;
|
||||
let bit = k % 64;
|
||||
*self.pba_pointer(byte) & (1 << bit) != 0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@@ -123,8 +109,6 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle) -> File {
|
||||
}
|
||||
|
||||
if msi_enabled && !msix_enabled {
|
||||
use pcid_interface::msi::x86_64::{DeliveryMode, self as x86_64_msix};
|
||||
|
||||
let capability = match pcid_handle.feature_info(PciFeature::Msi).expect("rtl8168d: failed to retrieve the MSI capability structure from pcid") {
|
||||
PciFeatureInfo::Msi(s) => s,
|
||||
PciFeatureInfo::MsiX(_) => panic!(),
|
||||
@@ -135,17 +119,11 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle) -> File {
|
||||
// pcid_interface, so that this can be shared between nvmed, xhcid, ixgebd, etc..
|
||||
|
||||
let destination_id = read_bsp_apic_id().expect("rtl8168d: failed to read BSP apic id");
|
||||
let lapic_id = u8::try_from(destination_id).expect("CPU id didn't fit inside u8");
|
||||
let msg_addr = x86_64_msix::message_address(lapic_id, false, false);
|
||||
|
||||
let (vector, interrupt_handle) = allocate_single_interrupt_vector(destination_id).expect("rtl8168d: failed to allocate interrupt vector").expect("rtl8168d: no interrupt vectors left");
|
||||
let msg_data = x86_64_msix::message_data_edge_triggered(DeliveryMode::Fixed, vector);
|
||||
let (msg_addr_and_data, interrupt_handle) = allocate_single_interrupt_vector_for_msi(destination_id);
|
||||
|
||||
let set_feature_info = MsiSetFeatureInfo {
|
||||
multi_message_enable: Some(0),
|
||||
message_address: Some(msg_addr),
|
||||
message_upper_address: Some(0),
|
||||
message_data: Some(msg_data as u16),
|
||||
message_address_and_data: Some(msg_addr_and_data),
|
||||
mask_bits: None,
|
||||
};
|
||||
pcid_handle.set_feature_info(SetFeatureInfo::Msi(set_feature_info)).expect("rtl8168d: failed to set feature info");
|
||||
@@ -159,41 +137,21 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle) -> File {
|
||||
PciFeatureInfo::Msi(_) => panic!(),
|
||||
PciFeatureInfo::MsiX(s) => s,
|
||||
};
|
||||
let table_size = capability.table_size();
|
||||
let table_base = capability.table_base_pointer(pci_config.func.bars);
|
||||
let table_min_length = table_size * 16;
|
||||
let pba_min_length = div_round_up(table_size, 8);
|
||||
capability.validate(pci_config.func.bars);
|
||||
|
||||
let pba_base = capability.pba_base_pointer(pci_config.func.bars);
|
||||
let bar = &pci_config.func.bars[capability.table_bir() as usize];
|
||||
let bar_address = unsafe { bar.physmap_mem("rtl8168d") } as usize;
|
||||
|
||||
let bir = capability.table_bir() as usize;
|
||||
let bar = &pci_config.func.bars[bir];
|
||||
let (bar_ptr, bar_size) = bar.expect_mem();
|
||||
|
||||
let address = unsafe { bar.physmap_mem("rtl8168d") } as usize;
|
||||
|
||||
if !(bar_ptr as u64..bar_ptr as u64 + bar_size as u64).contains(&(table_base as u64 + table_min_length as u64)) {
|
||||
panic!("Table {:#x}{:#x} outside of BAR {:#x}:{:#x}", table_base, table_base + table_min_length as usize, bar_ptr, bar_ptr + bar_size);
|
||||
}
|
||||
|
||||
if !(bar_ptr as u64..bar_ptr as u64 + bar_size as u64).contains(&(pba_base as u64 + pba_min_length as u64)) {
|
||||
panic!("PBA {:#x}{:#x} outside of BAR {:#x}:{:#X}", pba_base, pba_base + pba_min_length as usize, bar_ptr, bar_ptr + bar_size);
|
||||
}
|
||||
|
||||
let virt_table_base = ((table_base - bar_ptr) + address) as *mut MsixTableEntry;
|
||||
let virt_pba_base = ((pba_base - bar_ptr) + address) as *mut u64;
|
||||
let virt_table_base = (bar_address + capability.table_offset() as usize) as *mut MsixTableEntry;
|
||||
|
||||
let mut info = MsixInfo {
|
||||
virt_table_base: NonNull::new(virt_table_base).unwrap(),
|
||||
virt_pba_base: NonNull::new(virt_pba_base).unwrap(),
|
||||
capability,
|
||||
};
|
||||
|
||||
// Allocate one msi vector.
|
||||
|
||||
let method = {
|
||||
use pcid_interface::msi::x86_64::{DeliveryMode, self as x86_64_msix};
|
||||
|
||||
// primary interrupter
|
||||
let k = 0;
|
||||
|
||||
@@ -201,18 +159,10 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle) -> File {
|
||||
let table_entry_pointer = info.table_entry_pointer(k);
|
||||
|
||||
let destination_id = read_bsp_apic_id().expect("rtl8168d: failed to read BSP apic id");
|
||||
let lapic_id = u8::try_from(destination_id).expect("rtl8168d: CPU id couldn't fit inside u8");
|
||||
let rh = false;
|
||||
let dm = false;
|
||||
let addr = x86_64_msix::message_address(lapic_id, rh, dm);
|
||||
|
||||
let (vector, interrupt_handle) = allocate_single_interrupt_vector(destination_id).expect("rtl8168d: failed to allocate interrupt vector").expect("rtl8168d: no interrupt vectors left");
|
||||
let msg_data = x86_64_msix::message_data_edge_triggered(DeliveryMode::Fixed, vector);
|
||||
|
||||
table_entry_pointer.addr_lo.write(addr);
|
||||
table_entry_pointer.addr_hi.write(0);
|
||||
table_entry_pointer.msg_data.write(msg_data);
|
||||
table_entry_pointer.vec_ctl.writef(MsixTableEntry::VEC_CTL_MASK_BIT, false);
|
||||
let (msg_addr_and_data, interrupt_handle) =
|
||||
allocate_single_interrupt_vector_for_msi(destination_id);
|
||||
table_entry_pointer.write_addr_and_data(msg_addr_and_data);
|
||||
table_entry_pointer.unmask();
|
||||
|
||||
interrupt_handle
|
||||
};
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
use crate::{legacy_transport::LegacyTransport, reinit, transport::Error, Device};
|
||||
|
||||
use pcid_interface::irq_helpers::{allocate_single_interrupt_vector, read_bsp_apic_id};
|
||||
use pcid_interface::msi::{self, MsixTableEntry};
|
||||
use pcid_interface::irq_helpers::{allocate_single_interrupt_vector_for_msi, read_bsp_apic_id};
|
||||
use pcid_interface::msi::MsixTableEntry;
|
||||
use std::{fs::File, ptr::NonNull};
|
||||
|
||||
use syscall::Io;
|
||||
|
||||
use crate::{probe::MsixInfo, MSIX_PRIMARY_VECTOR};
|
||||
|
||||
use pcid_interface::*;
|
||||
@@ -18,28 +16,11 @@ pub fn enable_msix(pcid_handle: &mut PcidServerHandle) -> Result<File, Error> {
|
||||
PciFeatureInfo::MsiX(capability) => capability,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
capability.validate(pci_config.func.bars);
|
||||
|
||||
let table_size = capability.table_size();
|
||||
let table_base = capability.table_base_pointer(pci_config.func.bars);
|
||||
let table_min_length = table_size * 16;
|
||||
let pba_min_length = table_size.div_ceil(8);
|
||||
|
||||
let pba_base = capability.pba_base_pointer(pci_config.func.bars);
|
||||
|
||||
let bir = capability.table_bir() as usize;
|
||||
let bar = &pci_config.func.bars[bir];
|
||||
let (bar_ptr, bar_size) = bar.expect_mem();
|
||||
|
||||
let address = unsafe { bar.physmap_mem("virtio-core") } as usize;
|
||||
|
||||
// Ensure that the table and PBA are be within the BAR.
|
||||
{
|
||||
let bar_range = bar_ptr as u64..bar_ptr as u64 + bar_size as u64;
|
||||
assert!(bar_range.contains(&(table_base as u64 + table_min_length as u64)));
|
||||
assert!(bar_range.contains(&(pba_base as u64 + pba_min_length as u64)));
|
||||
}
|
||||
|
||||
let virt_table_base = ((table_base - bar_ptr as usize) + address) as *mut MsixTableEntry;
|
||||
let bar = &pci_config.func.bars[capability.table_bir() 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 mut info = MsixInfo {
|
||||
virt_table_base: NonNull::new(virt_table_base).unwrap(),
|
||||
@@ -53,25 +34,10 @@ pub fn enable_msix(pcid_handle: &mut PcidServerHandle) -> Result<File, Error> {
|
||||
let table_entry_pointer = info.table_entry_pointer(MSIX_PRIMARY_VECTOR as usize);
|
||||
|
||||
let destination_id = read_bsp_apic_id().expect("virtio_core: `read_bsp_apic_id()` failed");
|
||||
let lapic_id = u8::try_from(destination_id).unwrap();
|
||||
|
||||
let rh = false;
|
||||
let dm = false;
|
||||
let addr = msi::x86_64::message_address(lapic_id, rh, dm);
|
||||
|
||||
let (vector, interrupt_handle) = allocate_single_interrupt_vector(destination_id)
|
||||
.unwrap()
|
||||
.expect("virtio_core: interrupt vector exhaustion");
|
||||
|
||||
let msg_data =
|
||||
msi::x86_64::message_data_edge_triggered(msi::x86_64::DeliveryMode::Fixed, vector);
|
||||
|
||||
table_entry_pointer.addr_lo.write(addr);
|
||||
table_entry_pointer.addr_hi.write(0);
|
||||
table_entry_pointer.msg_data.write(msg_data);
|
||||
table_entry_pointer
|
||||
.vec_ctl
|
||||
.writef(MsixTableEntry::VEC_CTL_MASK_BIT, false);
|
||||
let (msg_addr_and_data, interrupt_handle) =
|
||||
allocate_single_interrupt_vector_for_msi(destination_id);
|
||||
table_entry_pointer.write_addr_and_data(msg_addr_and_data);
|
||||
table_entry_pointer.unmask();
|
||||
|
||||
interrupt_handle
|
||||
};
|
||||
|
||||
+11
-46
@@ -12,8 +12,8 @@ use std::sync::{Arc, Mutex};
|
||||
use std::env;
|
||||
|
||||
use pcid_interface::{MsiSetFeatureInfo, PcidServerHandle, PciFeature, PciFeatureInfo, SetFeatureInfo};
|
||||
use pcid_interface::irq_helpers::{read_bsp_apic_id, allocate_single_interrupt_vector};
|
||||
use pcid_interface::msi::{MsiCapability, MsixCapability, MsixTableEntry};
|
||||
use pcid_interface::irq_helpers::{read_bsp_apic_id, allocate_single_interrupt_vector_for_msi};
|
||||
use pcid_interface::msi::MsixTableEntry;
|
||||
|
||||
use event::{Event, EventQueue};
|
||||
use redox_log::{RedoxLogger, OutputBuilder};
|
||||
@@ -82,11 +82,9 @@ fn setup_logging(name: &str) -> Option<&'static RedoxLogger> {
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn get_int_method(pcid_handle: &mut PcidServerHandle, address: usize) -> (Option<File>, InterruptMethod) {
|
||||
fn get_int_method(pcid_handle: &mut PcidServerHandle, bar0_address: usize) -> (Option<File>, InterruptMethod) {
|
||||
let pci_config = pcid_handle.fetch_config().expect("xhcid: failed to fetch config");
|
||||
|
||||
let (bar_ptr, bar_size) = pci_config.func.bars[0].expect_mem();
|
||||
|
||||
let all_pci_features = pcid_handle.fetch_all_features().expect("xhcid: failed to fetch pci features");
|
||||
log::debug!("XHCI PCI FEATURES: {:?}", all_pci_features);
|
||||
|
||||
@@ -101,8 +99,6 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle, address: usize) -> (Option
|
||||
}
|
||||
|
||||
if msi_enabled && !msix_enabled {
|
||||
use pcid_interface::msi::x86_64::{DeliveryMode, self as x86_64_msix};
|
||||
|
||||
let mut capability = match pcid_handle.feature_info(PciFeature::Msi).expect("xhcid: failed to retrieve the MSI capability structure from pcid") {
|
||||
PciFeatureInfo::Msi(s) => s,
|
||||
PciFeatureInfo::MsiX(_) => panic!(),
|
||||
@@ -113,17 +109,11 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle, address: usize) -> (Option
|
||||
// pcid_interface, so that this can be shared between nvmed, xhcid, ixgebd, etc..
|
||||
|
||||
let destination_id = read_bsp_apic_id().expect("xhcid: failed to read BSP apic id");
|
||||
let lapic_id = u8::try_from(destination_id).expect("CPU id didn't fit inside u8");
|
||||
let msg_addr = x86_64_msix::message_address(lapic_id, false, false);
|
||||
|
||||
let (vector, interrupt_handle) = allocate_single_interrupt_vector(destination_id).expect("xhcid: failed to allocate interrupt vector").expect("xhcid: no interrupt vectors left");
|
||||
let msg_data = x86_64_msix::message_data_edge_triggered(DeliveryMode::Fixed, vector);
|
||||
let (msg_addr_and_data, interrupt_handle) = allocate_single_interrupt_vector_for_msi(destination_id);
|
||||
|
||||
let set_feature_info = MsiSetFeatureInfo {
|
||||
multi_message_enable: Some(0),
|
||||
message_address: Some(msg_addr),
|
||||
message_upper_address: Some(0),
|
||||
message_data: Some(msg_data as u16),
|
||||
message_address_and_data: Some(msg_addr_and_data),
|
||||
mask_bits: None,
|
||||
};
|
||||
pcid_handle.set_feature_info(SetFeatureInfo::Msi(set_feature_info)).expect("xhcid: failed to set feature info");
|
||||
@@ -137,35 +127,19 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle, address: usize) -> (Option
|
||||
PciFeatureInfo::Msi(_) => panic!(),
|
||||
PciFeatureInfo::MsiX(s) => s,
|
||||
};
|
||||
let table_size = capability.table_size();
|
||||
let table_base = capability.table_base_pointer(pci_config.func.bars);
|
||||
let table_min_length = table_size * 16;
|
||||
let pba_min_length = crate::xhci::scheme::div_round_up(table_size, 8);
|
||||
capability.validate(pci_config.func.bars);
|
||||
|
||||
let pba_base = capability.pba_base_pointer(pci_config.func.bars);
|
||||
|
||||
if !(bar_ptr as u64..bar_ptr as u64 + bar_size as u64).contains(&(table_base as u64 + table_min_length as u64)) {
|
||||
panic!("Table {:#x}{:#x} outside of BAR {:#x}:{:#x}", table_base, table_base + table_min_length as usize, bar_ptr, bar_ptr + bar_size);
|
||||
}
|
||||
|
||||
if !(bar_ptr as u64..bar_ptr as u64 + bar_size as u64).contains(&(pba_base as u64 + pba_min_length as u64)) {
|
||||
panic!("PBA {:#x}{:#x} outside of BAR {:#x}:{:#X}", pba_base, pba_base + pba_min_length as usize, bar_ptr, bar_ptr + bar_size);
|
||||
}
|
||||
|
||||
let virt_table_base = ((table_base - bar_ptr as usize) + address) as *mut MsixTableEntry;
|
||||
let virt_pba_base = ((pba_base - bar_ptr as usize) + address) as *mut u64;
|
||||
assert_eq!(capability.table_bir(), 0);
|
||||
let virt_table_base = (bar0_address + capability.table_offset() as usize) as *mut MsixTableEntry;
|
||||
|
||||
let mut info = xhci::MsixInfo {
|
||||
virt_table_base: NonNull::new(virt_table_base).unwrap(),
|
||||
virt_pba_base: NonNull::new(virt_pba_base).unwrap(),
|
||||
capability,
|
||||
};
|
||||
|
||||
// Allocate one msi vector.
|
||||
|
||||
let method = {
|
||||
use pcid_interface::msi::x86_64::{DeliveryMode, self as x86_64_msix};
|
||||
|
||||
// primary interrupter
|
||||
let k = 0;
|
||||
|
||||
@@ -173,18 +147,9 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle, address: usize) -> (Option
|
||||
let table_entry_pointer = info.table_entry_pointer(k);
|
||||
|
||||
let destination_id = read_bsp_apic_id().expect("xhcid: failed to read BSP apic id");
|
||||
let lapic_id = u8::try_from(destination_id).expect("xhcid: CPU id couldn't fit inside u8");
|
||||
let rh = false;
|
||||
let dm = false;
|
||||
let addr = x86_64_msix::message_address(lapic_id, rh, dm);
|
||||
|
||||
let (vector, interrupt_handle) = allocate_single_interrupt_vector(destination_id).expect("xhcid: failed to allocate interrupt vector").expect("xhcid: no interrupt vectors left");
|
||||
let msg_data = x86_64_msix::message_data_edge_triggered(DeliveryMode::Fixed, vector);
|
||||
|
||||
table_entry_pointer.addr_lo.write(addr);
|
||||
table_entry_pointer.addr_hi.write(0);
|
||||
table_entry_pointer.msg_data.write(msg_data);
|
||||
table_entry_pointer.vec_ctl.writef(MsixTableEntry::VEC_CTL_MASK_BIT, false);
|
||||
let (msg_addr_and_data, interrupt_handle) = allocate_single_interrupt_vector_for_msi(destination_id);
|
||||
table_entry_pointer.write_addr_and_data(msg_addr_and_data);
|
||||
table_entry_pointer.unmask();
|
||||
|
||||
(Some(interrupt_handle), InterruptMethod::MsiX(Mutex::new(info)))
|
||||
};
|
||||
|
||||
@@ -70,7 +70,6 @@ pub enum InterruptMethod {
|
||||
|
||||
pub struct MsixInfo {
|
||||
pub virt_table_base: NonNull<MsixTableEntry>,
|
||||
pub virt_pba_base: NonNull<u64>,
|
||||
pub capability: MsixCapability,
|
||||
}
|
||||
impl MsixInfo {
|
||||
@@ -81,18 +80,6 @@ impl MsixInfo {
|
||||
assert!(k < self.capability.table_size() as usize);
|
||||
unsafe { self.table_entry_pointer_unchecked(k) }
|
||||
}
|
||||
pub unsafe fn pba_pointer_unchecked(&mut self, k: usize) -> &mut u64 {
|
||||
&mut *self.virt_pba_base.as_ptr().offset(k as isize)
|
||||
}
|
||||
pub fn pba_pointer(&mut self, k: usize) -> &mut u64 {
|
||||
assert!(k < self.capability.table_size() as usize);
|
||||
unsafe { self.pba_pointer_unchecked(k) }
|
||||
}
|
||||
pub fn pba(&mut self, k: usize) -> bool {
|
||||
let byte = k / 64;
|
||||
let bit = k % 64;
|
||||
*self.pba_pointer(byte) & (1 << bit) != 0
|
||||
}
|
||||
}
|
||||
|
||||
impl Xhci {
|
||||
|
||||
Reference in New Issue
Block a user