From 84c528f53d91118bfc79e6d706b5b2de31e89915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E9=93=AD=E6=B6=9B?= <114841534+1037827920@users.noreply.github.com> Date: Tue, 29 Oct 2024 00:26:16 +0800 Subject: [PATCH] =?UTF-8?q?fix(driver/virtio):=20=E4=BF=AE=E6=94=B9pci=20t?= =?UTF-8?q?ransport=E4=B8=AD=E6=96=AD=E5=88=9D=E5=A7=8B=E5=8C=96=E7=9A=84?= =?UTF-8?q?=E4=BD=8D=E7=BD=AE=20(#1018)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(driver/virtio): 修改pci transport中断初始化的位置 --- kernel/src/driver/block/virtio_blk.rs | 8 +++- kernel/src/driver/net/virtio_net.rs | 6 +++ kernel/src/driver/virtio/transport.rs | 47 ++++++++++++++++++++--- kernel/src/driver/virtio/transport_pci.rs | 33 ++++++---------- kernel/src/net/net_core.rs | 14 ++++++- 5 files changed, 80 insertions(+), 28 deletions(-) diff --git a/kernel/src/driver/block/virtio_blk.rs b/kernel/src/driver/block/virtio_blk.rs index 13654424..6240263b 100644 --- a/kernel/src/driver/block/virtio_blk.rs +++ b/kernel/src/driver/block/virtio_blk.rs @@ -163,8 +163,14 @@ unsafe impl Sync for VirtIOBlkDevice {} impl VirtIOBlkDevice { pub fn new(transport: VirtIOTransport, dev_id: Arc) -> Option> { + // 设置中断 + if let Err(err) = transport.setup_irq(dev_id.clone()) { + error!("VirtIOBlkDevice '{dev_id:?}' setup_irq failed: {:?}", err); + return None; + } + let devname = virtioblk_manager().alloc_id()?; - let irq = transport.irq().map(|irq| IrqNumber::new(irq.data())); + let irq = Some(transport.irq()); let device_inner = VirtIOBlk::::new(transport); if let Err(e) = device_inner { error!("VirtIOBlkDevice '{dev_id:?}' create failed: {:?}", e); diff --git a/kernel/src/driver/net/virtio_net.rs b/kernel/src/driver/net/virtio_net.rs index 0bf2e3bf..521f2752 100644 --- a/kernel/src/driver/net/virtio_net.rs +++ b/kernel/src/driver/net/virtio_net.rs @@ -91,6 +91,12 @@ impl Debug for InnerVirtIONetDevice { impl VirtIONetDevice { pub fn new(transport: VirtIOTransport, dev_id: Arc) -> Option> { + // 设置中断 + if let Err(err) = transport.setup_irq(dev_id.clone()) { + error!("VirtIONetDevice '{dev_id:?}' setup_irq failed: {:?}", err); + return None; + } + let driver_net: VirtIONet = match VirtIONet::::new(transport, 4096) { Ok(net) => net, diff --git a/kernel/src/driver/virtio/transport.rs b/kernel/src/driver/virtio/transport.rs index b1819403..9dab0479 100644 --- a/kernel/src/driver/virtio/transport.rs +++ b/kernel/src/driver/virtio/transport.rs @@ -1,8 +1,21 @@ +use alloc::{string::ToString, sync::Arc}; + use virtio_drivers::transport::Transport; -use crate::exception::HardwareIrqNumber; +use crate::{ + driver::{ + base::device::DeviceId, + pci::{ + pci::{PciDeviceStructure, PciError}, + pci_irq::{IrqCommonMsg, IrqSpecificMsg, PciInterrupt, PciIrqError, PciIrqMsg, IRQ}, + }, + }, + exception::IrqNumber, +}; -use super::{transport_mmio::VirtIOMmioTransport, transport_pci::PciTransport}; +use super::{ + irq::DefaultVirtioIrqHandler, transport_mmio::VirtIOMmioTransport, transport_pci::PciTransport, +}; pub enum VirtIOTransport { Pci(PciTransport), @@ -10,12 +23,36 @@ pub enum VirtIOTransport { } impl VirtIOTransport { - pub fn irq(&self) -> Option { + pub fn irq(&self) -> IrqNumber { match self { - VirtIOTransport::Mmio(transport) => Some(transport.irq()), - _ => None, + VirtIOTransport::Pci(transport) => transport.irq(), + VirtIOTransport::Mmio(transport) => IrqNumber::new(transport.irq().data()), } } + + /// 设置中断 + pub fn setup_irq(&self, dev_id: Arc) -> Result<(), PciError> { + if let VirtIOTransport::Pci(transport) = self { + let mut pci_device_guard = transport.pci_device(); + let standard_device = pci_device_guard.as_standard_device_mut().unwrap(); + standard_device + .irq_init(IRQ::PCI_IRQ_MSIX | IRQ::PCI_IRQ_MSI) + .ok_or(PciError::PciIrqError(PciIrqError::IrqNotInited))?; + // 中断相关信息 + let msg = PciIrqMsg { + irq_common_message: IrqCommonMsg::init_from( + 0, + "Virtio_IRQ".to_string(), + &DefaultVirtioIrqHandler, + dev_id, + ), + irq_specific_message: IrqSpecificMsg::msi_default(), + }; + standard_device.irq_install(msg)?; + standard_device.irq_enable(true)?; + } + return Ok(()); + } } impl core::fmt::Debug for VirtIOTransport { diff --git a/kernel/src/driver/virtio/transport_pci.rs b/kernel/src/driver/virtio/transport_pci.rs index 07b687ba..5ecdfed2 100644 --- a/kernel/src/driver/virtio/transport_pci.rs +++ b/kernel/src/driver/virtio/transport_pci.rs @@ -6,17 +6,16 @@ use crate::driver::pci::pci::{ PciStandardDeviceBar, PCI_CAP_ID_VNDR, }; -use crate::driver::pci::pci_irq::{IrqCommonMsg, IrqSpecificMsg, PciInterrupt, PciIrqMsg, IRQ}; use crate::driver::pci::root::pci_root_0; use crate::exception::IrqNumber; +use crate::libs::spinlock::{SpinLock, SpinLockGuard}; use crate::libs::volatile::{ volread, volwrite, ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly, }; use crate::mm::VirtAddr; -use alloc::string::ToString; use alloc::sync::Arc; use core::{ fmt::{self, Display, Formatter}, @@ -28,7 +27,6 @@ use virtio_drivers::{ Error, Hal, PhysAddr, }; -use super::irq::DefaultVirtioIrqHandler; use super::VIRTIO_VENDOR_ID; /// The offset to add to a VirtIO device ID to get the corresponding PCI device ID. @@ -104,6 +102,7 @@ pub struct PciTransport { config_space: Option>, irq: IrqNumber, dev_id: Arc, + device: Arc>, } impl PciTransport { @@ -140,21 +139,7 @@ impl PciTransport { // 目前缺少对PCI设备中断号的统一管理,所以这里需要指定一个中断号。不能与其他中断重复 let irq_vector = standard_device.irq_vector_mut().unwrap(); irq_vector.push(irq); - standard_device - .irq_init(IRQ::PCI_IRQ_MSIX | IRQ::PCI_IRQ_MSI) - .ok_or(VirtioPciError::UnableToInitIrq)?; - // 中断相关信息 - let msg = PciIrqMsg { - irq_common_message: IrqCommonMsg::init_from( - 0, - "Virtio_IRQ".to_string(), - &DefaultVirtioIrqHandler, - dev_id.clone(), - ), - irq_specific_message: IrqSpecificMsg::msi_default(), - }; - standard_device.irq_install(msg)?; - standard_device.irq_enable(true)?; + //device_capability为迭代器,遍历其相当于遍历所有的cap空间 for capability in device.capabilities().unwrap() { if capability.id != PCI_CAP_ID_VNDR { @@ -236,8 +221,17 @@ impl PciTransport { config_space, irq, dev_id, + device: Arc::new(SpinLock::new(device.clone())), }) } + + pub fn pci_device(&self) -> SpinLockGuard { + self.device.lock() + } + + pub fn irq(&self) -> IrqNumber { + self.irq + } } impl Transport for PciTransport { @@ -446,8 +440,6 @@ pub enum VirtioPciError { /// `VIRTIO_PCI_CAP_NOTIFY_CFG` capability has a `notify_off_multiplier` that is not a multiple /// of 2. InvalidNotifyOffMultiplier(u32), - /// Unable to find capability such as MSIX or MSI. - UnableToInitIrq, /// No valid `VIRTIO_PCI_CAP_ISR_CFG` capability was found. MissingIsrConfig, /// An IO BAR was provided rather than a memory BAR. @@ -477,7 +469,6 @@ impl Display for VirtioPciError { "PCI device vender ID {:#06x} was not the VirtIO vendor ID {:#06x}.", vendor_id, VIRTIO_VENDOR_ID ), - Self::UnableToInitIrq => write!(f, "Unable to find capability such as MSIX or MSI."), Self::MissingCommonConfig => write!( f, "No valid `VIRTIO_PCI_CAP_COMMON_CFG` capability was found." diff --git a/kernel/src/net/net_core.rs b/kernel/src/net/net_core.rs index 9de8054e..b90a35aa 100644 --- a/kernel/src/net/net_core.rs +++ b/kernel/src/net/net_core.rs @@ -7,7 +7,11 @@ use crate::{ driver::net::{NetDevice, Operstate}, libs::rwlock::RwLockReadGuard, net::{socket::SocketPollMethod, NET_DEVICES}, - time::timer::{next_n_ms_timer_jiffies, Timer, TimerFunction}, + time::{ + sleep::nanosleep, + timer::{next_n_ms_timer_jiffies, Timer, TimerFunction}, + PosixTimeSpec, + }, }; use super::{ @@ -118,6 +122,14 @@ fn dhcp_query() -> Result<(), SystemError> { .remove_default_ipv4_route(); } } + // 在睡眠前释放锁 + drop(binding); + + let sleep_time = PosixTimeSpec { + tv_sec: 5, + tv_nsec: 0, + }; + let _ = nanosleep(sleep_time)?; } return Err(SystemError::ETIMEDOUT);