From b6a75d0a165fc46ab37632622ad9037a20232e35 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 15 Jun 2024 21:54:36 +0200 Subject: [PATCH 1/2] virtio: Support the modern transport on x86 --- pcid/src/driver_interface/irq_helpers.rs | 8 ++-- pcid/src/pci/msi.rs | 4 +- virtio-core/src/arch/x86.rs | 50 ++++++++++++++++++++++-- 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/pcid/src/driver_interface/irq_helpers.rs b/pcid/src/driver_interface/irq_helpers.rs index c5c8d0d7f4..9d7615a285 100644 --- a/pcid/src/driver_interface/irq_helpers.rs +++ b/pcid/src/driver_interface/irq_helpers.rs @@ -178,21 +178,21 @@ pub fn allocate_single_interrupt_vector(cpu_id: usize) -> io::Result (MsiAddrAndData, File) { - use crate::pci::msi::x86_64 as x86_64_msix; + use crate::pci::msi::x86 as x86_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 addr = x86_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); + x86_msix::message_data_edge_triggered(x86_msix::DeliveryMode::Fixed, vector); (MsiAddrAndData::new(addr, msg_data), interrupt_handle) } diff --git a/pcid/src/pci/msi.rs b/pcid/src/pci/msi.rs index a29a12cd96..f477737c3c 100644 --- a/pcid/src/pci/msi.rs +++ b/pcid/src/pci/msi.rs @@ -92,8 +92,8 @@ pub struct MsixTableEntry { pub vec_ctl: Mmio, } -#[cfg(target_arch = "x86_64")] -pub mod x86_64 { +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +pub mod x86 { #[repr(u8)] pub enum TriggerMode { Edge = 0, diff --git a/virtio-core/src/arch/x86.rs b/virtio-core/src/arch/x86.rs index be993050c5..edb85ab942 100644 --- a/virtio-core/src/arch/x86.rs +++ b/virtio-core/src/arch/x86.rs @@ -1,15 +1,57 @@ use crate::{legacy_transport::LegacyTransport, reinit, transport::Error, Device}; -use std::fs::File; + +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 crate::{probe::MappedMsixRegs, MSIX_PRIMARY_VECTOR}; use pcid_interface::*; -pub fn enable_msix(pcid_handle: &mut PcidServerHandle) -> Result { - panic!("virtio-core: x86 doesn't support enable_msix") +pub fn enable_msix(pcid_handle: &mut PciFunctionHandle) -> Result { + let pci_config = pcid_handle.config(); + + // Extended message signaled interrupts. + let msix_info = match pcid_handle.feature_info(PciFeature::MsiX)? { + PciFeatureInfo::MsiX(capability) => capability, + _ => unreachable!(), + }; + msix_info.validate(pci_config.func.bars); + + let bar_address = unsafe { pcid_handle.map_bar(msix_info.table_bar)? } + .ptr + .as_ptr() as usize; + let virt_table_base = (bar_address + msix_info.table_offset as usize) as *mut MsixTableEntry; + + let mut info = MappedMsixRegs { + virt_table_base: NonNull::new(virt_table_base).unwrap(), + info: msix_info, + }; + + // Allocate the primary MSI vector. + // FIXME allow the driver to register multiple MSI-X vectors + // FIXME move this MSI-X registering code into pcid_interface or pcid itself + let interrupt_handle = { + 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 (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 + }; + + pcid_handle.enable_feature(PciFeature::MsiX)?; + + log::info!("virtio: using MSI-X (interrupt_handle={interrupt_handle:?})"); + Ok(interrupt_handle) } pub fn probe_legacy_port_transport( pci_config: &SubdriverArguments, - pcid_handle: &mut PcidServerHandle, + pcid_handle: &mut PciFunctionHandle, ) -> Result { let port = pci_config.func.bars[0].expect_port(); From 359f4482dd0353c5b8a4e2e3fa12966215e3eb5e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 15 Jun 2024 21:56:25 +0200 Subject: [PATCH 2/2] virtio: Merge the x86 and x86_64 platform specific code --- virtio-core/src/arch/x86_64.rs | 81 ---------------------------------- virtio-core/src/lib.rs | 6 +-- 2 files changed, 1 insertion(+), 86 deletions(-) delete mode 100644 virtio-core/src/arch/x86_64.rs diff --git a/virtio-core/src/arch/x86_64.rs b/virtio-core/src/arch/x86_64.rs deleted file mode 100644 index edb85ab942..0000000000 --- a/virtio-core/src/arch/x86_64.rs +++ /dev/null @@ -1,81 +0,0 @@ -use crate::{legacy_transport::LegacyTransport, reinit, transport::Error, Device}; - -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 crate::{probe::MappedMsixRegs, MSIX_PRIMARY_VECTOR}; - -use pcid_interface::*; - -pub fn enable_msix(pcid_handle: &mut PciFunctionHandle) -> Result { - let pci_config = pcid_handle.config(); - - // Extended message signaled interrupts. - let msix_info = match pcid_handle.feature_info(PciFeature::MsiX)? { - PciFeatureInfo::MsiX(capability) => capability, - _ => unreachable!(), - }; - msix_info.validate(pci_config.func.bars); - - let bar_address = unsafe { pcid_handle.map_bar(msix_info.table_bar)? } - .ptr - .as_ptr() as usize; - let virt_table_base = (bar_address + msix_info.table_offset as usize) as *mut MsixTableEntry; - - let mut info = MappedMsixRegs { - virt_table_base: NonNull::new(virt_table_base).unwrap(), - info: msix_info, - }; - - // Allocate the primary MSI vector. - // FIXME allow the driver to register multiple MSI-X vectors - // FIXME move this MSI-X registering code into pcid_interface or pcid itself - let interrupt_handle = { - 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 (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 - }; - - pcid_handle.enable_feature(PciFeature::MsiX)?; - - log::info!("virtio: using MSI-X (interrupt_handle={interrupt_handle:?})"); - Ok(interrupt_handle) -} - -pub fn probe_legacy_port_transport( - pci_config: &SubdriverArguments, - pcid_handle: &mut PciFunctionHandle, -) -> Result { - let port = pci_config.func.bars[0].expect_port(); - - common::acquire_port_io_rights().expect("virtio: failed to set I/O privilege level"); - log::warn!("virtio: using legacy transport"); - - let transport = LegacyTransport::new(port); - - // Setup interrupts. - let all_pci_features = pcid_handle.fetch_all_features()?; - let has_msix = all_pci_features.iter().any(|feature| feature.is_msix()); - - // According to the virtio specification, the device REQUIRED to support MSI-X. - assert!(has_msix, "virtio: device does not support MSI-X"); - let irq_handle = enable_msix(pcid_handle)?; - - let device = Device { - transport, - irq_handle, - device_space: core::ptr::null_mut(), - }; - - device.transport.reset(); - reinit(&device)?; - - Ok(device) -} diff --git a/virtio-core/src/lib.rs b/virtio-core/src/lib.rs index c38a88ac3d..8dfd9a676f 100644 --- a/virtio-core/src/lib.rs +++ b/virtio-core/src/lib.rs @@ -10,14 +10,10 @@ mod probe; #[path="arch/aarch64.rs"] mod arch; -#[cfg(target_arch = "x86")] +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] #[path="arch/x86.rs"] mod arch; -#[cfg(target_arch = "x86_64")] -#[path="arch/x86_64.rs"] -mod arch; - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] mod legacy_transport;