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:
bjorn3
2024-01-23 19:22:32 +01:00
parent 9b809312c2
commit 67d3015e2e
10 changed files with 104 additions and 174 deletions
+3 -12
View File
@@ -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
View File
@@ -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();
+21
View File
@@ -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)
}
+4 -14
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
};
+6 -23
View File
@@ -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
View File
@@ -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)))
};