Skip to content

Commit 84c528f

Browse files
authored
fix(driver/virtio): 修改pci transport中断初始化的位置 (#1018)
* fix(driver/virtio): 修改pci transport中断初始化的位置
1 parent 55e6f0b commit 84c528f

File tree

5 files changed

+83
-31
lines changed

5 files changed

+83
-31
lines changed

kernel/src/driver/block/virtio_blk.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,14 @@ unsafe impl Sync for VirtIOBlkDevice {}
163163

164164
impl VirtIOBlkDevice {
165165
pub fn new(transport: VirtIOTransport, dev_id: Arc<DeviceId>) -> Option<Arc<Self>> {
166+
// 设置中断
167+
if let Err(err) = transport.setup_irq(dev_id.clone()) {
168+
error!("VirtIOBlkDevice '{dev_id:?}' setup_irq failed: {:?}", err);
169+
return None;
170+
}
171+
166172
let devname = virtioblk_manager().alloc_id()?;
167-
let irq = transport.irq().map(|irq| IrqNumber::new(irq.data()));
173+
let irq = Some(transport.irq());
168174
let device_inner = VirtIOBlk::<HalImpl, VirtIOTransport>::new(transport);
169175
if let Err(e) = device_inner {
170176
error!("VirtIOBlkDevice '{dev_id:?}' create failed: {:?}", e);

kernel/src/driver/net/virtio_net.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ impl Debug for InnerVirtIONetDevice {
9191

9292
impl VirtIONetDevice {
9393
pub fn new(transport: VirtIOTransport, dev_id: Arc<DeviceId>) -> Option<Arc<Self>> {
94+
// 设置中断
95+
if let Err(err) = transport.setup_irq(dev_id.clone()) {
96+
error!("VirtIONetDevice '{dev_id:?}' setup_irq failed: {:?}", err);
97+
return None;
98+
}
99+
94100
let driver_net: VirtIONet<HalImpl, VirtIOTransport, 2> =
95101
match VirtIONet::<HalImpl, VirtIOTransport, 2>::new(transport, 4096) {
96102
Ok(net) => net,

kernel/src/driver/virtio/transport.rs

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,57 @@
1-
use virtio_drivers::transport::Transport;
1+
use alloc::{string::ToString, sync::Arc};
22

3-
use crate::exception::HardwareIrqNumber;
3+
use virtio_drivers::transport::Transport;
44

5-
use super::{transport_mmio::VirtIOMmioTransport, transport_pci::PciTransport};
5+
use crate::{
6+
driver::{
7+
base::device::DeviceId,
8+
pci::{
9+
pci::{PciDeviceStructure, PciError},
10+
pci_irq::{IrqCommonMsg, IrqSpecificMsg, PciInterrupt, PciIrqError, PciIrqMsg, IRQ},
11+
},
12+
},
13+
exception::IrqNumber,
14+
};
15+
16+
use super::{
17+
irq::DefaultVirtioIrqHandler, transport_mmio::VirtIOMmioTransport, transport_pci::PciTransport,
18+
};
619

720
pub enum VirtIOTransport {
821
Pci(PciTransport),
922
Mmio(VirtIOMmioTransport),
1023
}
1124

1225
impl VirtIOTransport {
13-
pub fn irq(&self) -> Option<HardwareIrqNumber> {
14-
match self {
15-
VirtIOTransport::Mmio(transport) => Some(transport.irq()),
16-
_ => None,
17-
}
26+
pub fn irq(&self) -> IrqNumber {
27+
match self {
28+
VirtIOTransport::Pci(transport) => transport.irq(),
29+
VirtIOTransport::Mmio(transport) => IrqNumber::new(transport.irq().data()),
30+
}
31+
}
32+
33+
/// 设置中断
34+
pub fn setup_irq(&self, dev_id: Arc<DeviceId>) -> Result<(), PciError> {
35+
if let VirtIOTransport::Pci(transport) = self {
36+
let mut pci_device_guard = transport.pci_device();
37+
let standard_device = pci_device_guard.as_standard_device_mut().unwrap();
38+
standard_device
39+
.irq_init(IRQ::PCI_IRQ_MSIX | IRQ::PCI_IRQ_MSI)
40+
.ok_or(PciError::PciIrqError(PciIrqError::IrqNotInited))?;
41+
// 中断相关信息
42+
let msg = PciIrqMsg {
43+
irq_common_message: IrqCommonMsg::init_from(
44+
0,
45+
"Virtio_IRQ".to_string(),
46+
&DefaultVirtioIrqHandler,
47+
dev_id,
48+
),
49+
irq_specific_message: IrqSpecificMsg::msi_default(),
50+
};
51+
standard_device.irq_install(msg)?;
52+
standard_device.irq_enable(true)?;
53+
}
54+
return Ok(());
1855
}
1956
}
2057

kernel/src/driver/virtio/transport_pci.rs

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,16 @@ use crate::driver::pci::pci::{
66
PciStandardDeviceBar, PCI_CAP_ID_VNDR,
77
};
88

9-
use crate::driver::pci::pci_irq::{IrqCommonMsg, IrqSpecificMsg, PciInterrupt, PciIrqMsg, IRQ};
109
use crate::driver::pci::root::pci_root_0;
1110

1211
use crate::exception::IrqNumber;
1312

13+
use crate::libs::spinlock::{SpinLock, SpinLockGuard};
1414
use crate::libs::volatile::{
1515
volread, volwrite, ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly,
1616
};
1717
use crate::mm::VirtAddr;
1818

19-
use alloc::string::ToString;
2019
use alloc::sync::Arc;
2120
use core::{
2221
fmt::{self, Display, Formatter},
@@ -28,7 +27,6 @@ use virtio_drivers::{
2827
Error, Hal, PhysAddr,
2928
};
3029

31-
use super::irq::DefaultVirtioIrqHandler;
3230
use super::VIRTIO_VENDOR_ID;
3331

3432
/// The offset to add to a VirtIO device ID to get the corresponding PCI device ID.
@@ -104,6 +102,7 @@ pub struct PciTransport {
104102
config_space: Option<NonNull<[u32]>>,
105103
irq: IrqNumber,
106104
dev_id: Arc<DeviceId>,
105+
device: Arc<SpinLock<PciDeviceStructureGeneralDevice>>,
107106
}
108107

109108
impl PciTransport {
@@ -140,21 +139,7 @@ impl PciTransport {
140139
// 目前缺少对PCI设备中断号的统一管理,所以这里需要指定一个中断号。不能与其他中断重复
141140
let irq_vector = standard_device.irq_vector_mut().unwrap();
142141
irq_vector.push(irq);
143-
standard_device
144-
.irq_init(IRQ::PCI_IRQ_MSIX | IRQ::PCI_IRQ_MSI)
145-
.ok_or(VirtioPciError::UnableToInitIrq)?;
146-
// 中断相关信息
147-
let msg = PciIrqMsg {
148-
irq_common_message: IrqCommonMsg::init_from(
149-
0,
150-
"Virtio_IRQ".to_string(),
151-
&DefaultVirtioIrqHandler,
152-
dev_id.clone(),
153-
),
154-
irq_specific_message: IrqSpecificMsg::msi_default(),
155-
};
156-
standard_device.irq_install(msg)?;
157-
standard_device.irq_enable(true)?;
142+
158143
//device_capability为迭代器,遍历其相当于遍历所有的cap空间
159144
for capability in device.capabilities().unwrap() {
160145
if capability.id != PCI_CAP_ID_VNDR {
@@ -236,8 +221,17 @@ impl PciTransport {
236221
config_space,
237222
irq,
238223
dev_id,
224+
device: Arc::new(SpinLock::new(device.clone())),
239225
})
240226
}
227+
228+
pub fn pci_device(&self) -> SpinLockGuard<PciDeviceStructureGeneralDevice> {
229+
self.device.lock()
230+
}
231+
232+
pub fn irq(&self) -> IrqNumber {
233+
self.irq
234+
}
241235
}
242236

243237
impl Transport for PciTransport {
@@ -446,8 +440,6 @@ pub enum VirtioPciError {
446440
/// `VIRTIO_PCI_CAP_NOTIFY_CFG` capability has a `notify_off_multiplier` that is not a multiple
447441
/// of 2.
448442
InvalidNotifyOffMultiplier(u32),
449-
/// Unable to find capability such as MSIX or MSI.
450-
UnableToInitIrq,
451443
/// No valid `VIRTIO_PCI_CAP_ISR_CFG` capability was found.
452444
MissingIsrConfig,
453445
/// An IO BAR was provided rather than a memory BAR.
@@ -477,7 +469,6 @@ impl Display for VirtioPciError {
477469
"PCI device vender ID {:#06x} was not the VirtIO vendor ID {:#06x}.",
478470
vendor_id, VIRTIO_VENDOR_ID
479471
),
480-
Self::UnableToInitIrq => write!(f, "Unable to find capability such as MSIX or MSI."),
481472
Self::MissingCommonConfig => write!(
482473
f,
483474
"No valid `VIRTIO_PCI_CAP_COMMON_CFG` capability was found."

kernel/src/net/net_core.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ use crate::{
77
driver::net::{NetDevice, Operstate},
88
libs::rwlock::RwLockReadGuard,
99
net::{socket::SocketPollMethod, NET_DEVICES},
10-
time::timer::{next_n_ms_timer_jiffies, Timer, TimerFunction},
10+
time::{
11+
sleep::nanosleep,
12+
timer::{next_n_ms_timer_jiffies, Timer, TimerFunction},
13+
PosixTimeSpec,
14+
},
1115
};
1216

1317
use super::{
@@ -118,6 +122,14 @@ fn dhcp_query() -> Result<(), SystemError> {
118122
.remove_default_ipv4_route();
119123
}
120124
}
125+
// 在睡眠前释放锁
126+
drop(binding);
127+
128+
let sleep_time = PosixTimeSpec {
129+
tv_sec: 5,
130+
tv_nsec: 0,
131+
};
132+
let _ = nanosleep(sleep_time)?;
121133
}
122134

123135
return Err(SystemError::ETIMEDOUT);

0 commit comments

Comments
 (0)