Merge branch 'x86_virtio_modern_transport' into 'master'

Support the modern virtio transport on x86

See merge request redox-os/drivers!173
This commit is contained in:
Jeremy Soller
2024-06-15 21:37:44 +00:00
5 changed files with 53 additions and 96 deletions
+4 -4
View File
@@ -178,21 +178,21 @@ pub fn allocate_single_interrupt_vector(cpu_id: usize) -> io::Result<Option<(u8,
Ok(Some((base, files.pop().unwrap())))
}
#[cfg(target_arch = "x86_64")]
#[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;
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)
}
+2 -2
View File
@@ -92,8 +92,8 @@ pub struct MsixTableEntry {
pub vec_ctl: Mmio<u32>,
}
#[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,
+46 -4
View File
@@ -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<File, Error> {
panic!("virtio-core: x86 doesn't support enable_msix")
pub fn enable_msix(pcid_handle: &mut PciFunctionHandle) -> Result<File, Error> {
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<Device, Error> {
let port = pci_config.func.bars[0].expect_port();
-81
View File
@@ -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<File, Error> {
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<Device, Error> {
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)
}
+1 -5
View File
@@ -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;