From 67d3015e2efea14b1e1d16d0762003d5869c5f1f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 23 Jan 2024 19:22:32 +0100 Subject: [PATCH] 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. --- ihdad/src/main.rs | 15 ++-------- nvmed/src/main.rs | 37 +++++------------------- pcid/src/driver_interface/irq_helpers.rs | 21 ++++++++++++++ pcid/src/driver_interface/mod.rs | 18 +++--------- pcid/src/main.rs | 22 +++++++------- pcid/src/pci/msi.rs | 33 +++++++++++++++++---- rtl8139d/src/main.rs | 35 +++++----------------- rtl8168d/src/main.rs | 35 +++++----------------- virtio-core/src/arch/x86_64.rs | 29 ++++--------------- xhcid/src/main.rs | 33 +++++---------------- 10 files changed, 104 insertions(+), 174 deletions(-) diff --git a/ihdad/src/main.rs b/ihdad/src/main.rs index 7f87807b40..ba8ae837d8 100755 --- a/ihdad/src/main.rs +++ b/ihdad/src/main.rs @@ -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"); diff --git a/nvmed/src/main.rs b/nvmed/src/main.rs index e38060bc1b..7058e9f6ae 100644 --- a/nvmed/src/main.rs +++ b/nvmed/src/main.rs @@ -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(); diff --git a/pcid/src/driver_interface/irq_helpers.rs b/pcid/src/driver_interface/irq_helpers.rs index e0d63164e5..d7c9b4b5ea 100644 --- a/pcid/src/driver_interface/irq_helpers.rs +++ b/pcid/src/driver_interface/irq_helpers.rs @@ -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 { let mut buffer = [0u8; 8]; @@ -153,3 +155,22 @@ pub fn allocate_single_interrupt_vector(cpu_id: usize) -> io::Result (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) +} diff --git a/pcid/src/driver_interface/mod.rs b/pcid/src/driver_interface/mod.rs index 88b7068915..0595fee914 100644 --- a/pcid/src/driver_interface/mod.rs +++ b/pcid/src/driver_interface/mod.rs @@ -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, - /// 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, - - /// 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, - - /// 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, + /// 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, /// 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. diff --git a/pcid/src/main.rs b/pcid/src/main.rs index bbc46d0794..56f78191bf 100644 --- a/pcid/src/main.rs +++ b/pcid/src/main.rs @@ -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); diff --git a/pcid/src/pci/msi.rs b/pcid/src/pci/msi.rs index 96ab83e915..ce176a1846 100644 --- a/pcid/src/pci/msi.rs +++ b/pcid/src/pci/msi.rs @@ -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 { diff --git a/rtl8139d/src/main.rs b/rtl8139d/src/main.rs index a8400063be..c61e3049ab 100644 --- a/rtl8139d/src/main.rs +++ b/rtl8139d/src/main.rs @@ -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 }; diff --git a/rtl8168d/src/main.rs b/rtl8168d/src/main.rs index 334554d12e..f5452baff9 100644 --- a/rtl8168d/src/main.rs +++ b/rtl8168d/src/main.rs @@ -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 }; diff --git a/virtio-core/src/arch/x86_64.rs b/virtio-core/src/arch/x86_64.rs index 3965e08c39..e67d8ab767 100644 --- a/virtio-core/src/arch/x86_64.rs +++ b/virtio-core/src/arch/x86_64.rs @@ -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 { 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 }; diff --git a/xhcid/src/main.rs b/xhcid/src/main.rs index 2315c2a1dc..bbab755d9a 100644 --- a/xhcid/src/main.rs +++ b/xhcid/src/main.rs @@ -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))) };