Add helper for allocating a single MSI/MSI-X interrupt vector
It doesn't actually configure the device to emit it though, but does make this easier to do.
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");
|
||||
|
||||
+7
-30
@@ -127,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)
|
||||
};
|
||||
@@ -166,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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
+28
-5
@@ -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;
|
||||
@@ -352,11 +369,11 @@ pub mod x86_64 {
|
||||
}
|
||||
|
||||
// TODO: should the reserved field be preserved?
|
||||
pub const fn message_address(destination_id: u8, redirect_hint: bool, dest_mode_logical: bool) -> u32 {
|
||||
0xFEE0_0000u32
|
||||
| ((destination_id as u32) << 12)
|
||||
| ((redirect_hint as u32) << 3)
|
||||
| ((dest_mode_logical 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)
|
||||
@@ -408,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 {
|
||||
|
||||
+8
-27
@@ -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;
|
||||
|
||||
@@ -112,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!(),
|
||||
@@ -124,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");
|
||||
@@ -163,8 +154,6 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle) -> File {
|
||||
// Allocate one msi vector.
|
||||
|
||||
let method = {
|
||||
use pcid_interface::msi::x86_64::{DeliveryMode, self as x86_64_msix};
|
||||
|
||||
// primary interrupter
|
||||
let k = 0;
|
||||
|
||||
@@ -172,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
|
||||
};
|
||||
|
||||
+8
-27
@@ -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;
|
||||
|
||||
@@ -110,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!(),
|
||||
@@ -122,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");
|
||||
@@ -161,8 +152,6 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle) -> File {
|
||||
// Allocate one msi vector.
|
||||
|
||||
let method = {
|
||||
use pcid_interface::msi::x86_64::{DeliveryMode, self as x86_64_msix};
|
||||
|
||||
// primary interrupter
|
||||
let k = 0;
|
||||
|
||||
@@ -170,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::*;
|
||||
@@ -36,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
|
||||
};
|
||||
|
||||
+7
-26
@@ -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};
|
||||
@@ -99,8 +99,6 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle, bar0_address: usize) -> (O
|
||||
}
|
||||
|
||||
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!(),
|
||||
@@ -111,17 +109,11 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle, bar0_address: usize) -> (O
|
||||
// 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");
|
||||
@@ -148,8 +140,6 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle, bar0_address: usize) -> (O
|
||||
// Allocate one msi vector.
|
||||
|
||||
let method = {
|
||||
use pcid_interface::msi::x86_64::{DeliveryMode, self as x86_64_msix};
|
||||
|
||||
// primary interrupter
|
||||
let k = 0;
|
||||
|
||||
@@ -157,18 +147,9 @@ fn get_int_method(pcid_handle: &mut PcidServerHandle, bar0_address: usize) -> (O
|
||||
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)))
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user