xref: /DragonOS/kernel/src/driver/virtio/transport_pci.rs (revision 471d65cf158c9bf741c21f5d0ab92efe7bf1c3d4)
1 //! PCI transport for VirtIO.
2 
3 use crate::driver::base::device::DeviceId;
4 use crate::driver::pci::pci::{
5     BusDeviceFunction, PciDeviceStructure, PciDeviceStructureGeneralDevice, PciError,
6     PciStandardDeviceBar, PCI_CAP_ID_VNDR,
7 };
8 
9 use crate::driver::pci::pci_irq::{IrqCommonMsg, IrqSpecificMsg, PciInterrupt, PciIrqMsg, IRQ};
10 use crate::driver::pci::root::pci_root_0;
11 use crate::driver::virtio::irq::virtio_irq_manager;
12 use crate::exception::irqdata::IrqHandlerData;
13 use crate::exception::irqdesc::{IrqHandler, IrqReturn};
14 
15 use crate::exception::IrqNumber;
16 
17 use crate::libs::volatile::{
18     volread, volwrite, ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly,
19 };
20 use crate::mm::VirtAddr;
21 
22 use alloc::string::ToString;
23 use alloc::sync::Arc;
24 use core::{
25     fmt::{self, Display, Formatter},
26     mem::{align_of, size_of},
27     ptr::{self, addr_of_mut, NonNull},
28 };
29 use system_error::SystemError;
30 use virtio_drivers::{
31     transport::{DeviceStatus, DeviceType, Transport},
32     Error, Hal, PhysAddr,
33 };
34 
35 use super::VIRTIO_VENDOR_ID;
36 
37 /// The offset to add to a VirtIO device ID to get the corresponding PCI device ID.
38 /// PCI Virtio设备的DEVICE_ID 的offset
39 const PCI_DEVICE_ID_OFFSET: u16 = 0x1040;
40 /// PCI Virtio 设备的DEVICE_ID及其对应的设备类型
41 const TRANSITIONAL_NETWORK: u16 = 0x1000;
42 const TRANSITIONAL_BLOCK: u16 = 0x1001;
43 const TRANSITIONAL_MEMORY_BALLOONING: u16 = 0x1002;
44 const TRANSITIONAL_CONSOLE: u16 = 0x1003;
45 const TRANSITIONAL_SCSI_HOST: u16 = 0x1004;
46 const TRANSITIONAL_ENTROPY_SOURCE: u16 = 0x1005;
47 const TRANSITIONAL_9P_TRANSPORT: u16 = 0x1009;
48 
49 /// The offset of the bar field within `virtio_pci_cap`.
50 const CAP_BAR_OFFSET: u8 = 4;
51 /// The offset of the offset field with `virtio_pci_cap`.
52 const CAP_BAR_OFFSET_OFFSET: u8 = 8;
53 /// The offset of the `length` field within `virtio_pci_cap`.
54 const CAP_LENGTH_OFFSET: u8 = 12;
55 /// The offset of the`notify_off_multiplier` field within `virtio_pci_notify_cap`.
56 const CAP_NOTIFY_OFF_MULTIPLIER_OFFSET: u8 = 16;
57 
58 /// Common configuration.
59 const VIRTIO_PCI_CAP_COMMON_CFG: u8 = 1;
60 /// Notifications.
61 const VIRTIO_PCI_CAP_NOTIFY_CFG: u8 = 2;
62 /// ISR Status.
63 const VIRTIO_PCI_CAP_ISR_CFG: u8 = 3;
64 /// Device specific configuration.
65 const VIRTIO_PCI_CAP_DEVICE_CFG: u8 = 4;
66 
67 /// Virtio设备接收中断的设备号
68 const VIRTIO_RECV_VECTOR: IrqNumber = IrqNumber::new(56);
69 /// Virtio设备接收中断的设备号的表项号
70 const VIRTIO_RECV_VECTOR_INDEX: u16 = 0;
71 // 接收的queue号
72 const QUEUE_RECEIVE: u16 = 0;
73 ///@brief device id 转换为设备类型
74 ///@param pci_device_id,device_id
75 ///@return DeviceType 对应的设备类型
76 fn device_type(pci_device_id: u16) -> DeviceType {
77     match pci_device_id {
78         TRANSITIONAL_NETWORK => DeviceType::Network,
79         TRANSITIONAL_BLOCK => DeviceType::Block,
80         TRANSITIONAL_MEMORY_BALLOONING => DeviceType::MemoryBalloon,
81         TRANSITIONAL_CONSOLE => DeviceType::Console,
82         TRANSITIONAL_SCSI_HOST => DeviceType::ScsiHost,
83         TRANSITIONAL_ENTROPY_SOURCE => DeviceType::EntropySource,
84         TRANSITIONAL_9P_TRANSPORT => DeviceType::_9P,
85         id if id >= PCI_DEVICE_ID_OFFSET => DeviceType::from(id - PCI_DEVICE_ID_OFFSET),
86         _ => DeviceType::Invalid,
87     }
88 }
89 
90 /// PCI transport for VirtIO.
91 ///
92 /// Ref: 4.1 Virtio Over PCI Bus
93 #[allow(dead_code)]
94 #[derive(Debug, Clone)]
95 pub struct PciTransport {
96     device_type: DeviceType,
97     /// The bus, device and function identifier for the VirtIO device.
98     _bus_device_function: BusDeviceFunction,
99     /// The common configuration structure within some BAR.
100     common_cfg: NonNull<CommonCfg>,
101     /// The start of the queue notification region within some BAR.
102     notify_region: NonNull<[WriteOnly<u16>]>,
103     notify_off_multiplier: u32,
104     /// The ISR status register within some BAR.
105     isr_status: NonNull<Volatile<u8>>,
106     /// The VirtIO device-specific configuration within some BAR.
107     config_space: Option<NonNull<[u32]>>,
108     irq: IrqNumber,
109     dev_id: Arc<DeviceId>,
110 }
111 
112 impl PciTransport {
113     /// Construct a new PCI VirtIO device driver for the given device function on the given PCI
114     /// root controller.
115     ///
116     /// ## 参数
117     ///
118     /// - `device` - The PCI device structure for the VirtIO device.
119     /// - `irq_handler` - An optional handler for the device's interrupt. If `None`, a default
120     ///     handler `DefaultVirtioIrqHandler` will be used.
121     #[allow(clippy::extra_unused_type_parameters)]
122     pub fn new<H: Hal>(
123         device: &mut PciDeviceStructureGeneralDevice,
124         dev_id: Arc<DeviceId>,
125     ) -> Result<Self, VirtioPciError> {
126         let irq = VIRTIO_RECV_VECTOR;
127         let header = &device.common_header;
128         let bus_device_function = header.bus_device_function;
129         if header.vendor_id != VIRTIO_VENDOR_ID {
130             return Err(VirtioPciError::InvalidVendorId(header.vendor_id));
131         }
132         let device_type = device_type(header.device_id);
133         // Find the PCI capabilities we need.
134         let mut common_cfg: Option<VirtioCapabilityInfo> = None;
135         let mut notify_cfg: Option<VirtioCapabilityInfo> = None;
136         let mut notify_off_multiplier = 0;
137         let mut isr_cfg = None;
138         let mut device_cfg = None;
139         device.bar_ioremap().unwrap()?;
140         device.enable_master();
141         let standard_device = device.as_standard_device_mut().unwrap();
142         // 目前缺少对PCI设备中断号的统一管理,所以这里需要指定一个中断号。不能与其他中断重复
143         let irq_vector = standard_device.irq_vector_mut().unwrap();
144         irq_vector.push(irq);
145         standard_device
146             .irq_init(IRQ::PCI_IRQ_MSIX)
147             .expect("IRQ init failed");
148         // 中断相关信息
149         let msg = PciIrqMsg {
150             irq_common_message: IrqCommonMsg::init_from(
151                 0,
152                 "Virtio_IRQ".to_string(),
153                 &DefaultVirtioIrqHandler,
154                 dev_id.clone(),
155             ),
156             irq_specific_message: IrqSpecificMsg::msi_default(),
157         };
158         standard_device.irq_install(msg)?;
159         standard_device.irq_enable(true)?;
160         //device_capability为迭代器,遍历其相当于遍历所有的cap空间
161         for capability in device.capabilities().unwrap() {
162             if capability.id != PCI_CAP_ID_VNDR {
163                 continue;
164             }
165             let cap_len = capability.private_header as u8;
166             let cfg_type = (capability.private_header >> 8) as u8;
167             if cap_len < 16 {
168                 continue;
169             }
170             let struct_info = VirtioCapabilityInfo {
171                 bar: pci_root_0().read_config(
172                     bus_device_function,
173                     (capability.offset + CAP_BAR_OFFSET).into(),
174                 ) as u8,
175                 offset: pci_root_0().read_config(
176                     bus_device_function,
177                     (capability.offset + CAP_BAR_OFFSET_OFFSET).into(),
178                 ),
179                 length: pci_root_0().read_config(
180                     bus_device_function,
181                     (capability.offset + CAP_LENGTH_OFFSET).into(),
182                 ),
183             };
184 
185             match cfg_type {
186                 VIRTIO_PCI_CAP_COMMON_CFG if common_cfg.is_none() => {
187                     common_cfg = Some(struct_info);
188                 }
189                 VIRTIO_PCI_CAP_NOTIFY_CFG if cap_len >= 20 && notify_cfg.is_none() => {
190                     notify_cfg = Some(struct_info);
191                     notify_off_multiplier = pci_root_0().read_config(
192                         bus_device_function,
193                         (capability.offset + CAP_NOTIFY_OFF_MULTIPLIER_OFFSET).into(),
194                     );
195                 }
196                 VIRTIO_PCI_CAP_ISR_CFG if isr_cfg.is_none() => {
197                     isr_cfg = Some(struct_info);
198                 }
199                 VIRTIO_PCI_CAP_DEVICE_CFG if device_cfg.is_none() => {
200                     device_cfg = Some(struct_info);
201                 }
202                 _ => {}
203             }
204         }
205 
206         let common_cfg = get_bar_region::<_>(
207             &device.standard_device_bar,
208             &common_cfg.ok_or(VirtioPciError::MissingCommonConfig)?,
209         )?;
210 
211         let notify_cfg = notify_cfg.ok_or(VirtioPciError::MissingNotifyConfig)?;
212         if notify_off_multiplier % 2 != 0 {
213             return Err(VirtioPciError::InvalidNotifyOffMultiplier(
214                 notify_off_multiplier,
215             ));
216         }
217         //kdebug!("notify.offset={},notify.length={}",notify_cfg.offset,notify_cfg.length);
218         let notify_region = get_bar_region_slice::<_>(&device.standard_device_bar, &notify_cfg)?;
219         let isr_status = get_bar_region::<_>(
220             &device.standard_device_bar,
221             &isr_cfg.ok_or(VirtioPciError::MissingIsrConfig)?,
222         )?;
223         let config_space = if let Some(device_cfg) = device_cfg {
224             Some(get_bar_region_slice::<_>(
225                 &device.standard_device_bar,
226                 &device_cfg,
227             )?)
228         } else {
229             None
230         };
231         Ok(Self {
232             device_type,
233             _bus_device_function: bus_device_function,
234             common_cfg,
235             notify_region,
236             notify_off_multiplier,
237             isr_status,
238             config_space,
239             irq,
240             dev_id,
241         })
242     }
243 }
244 
245 impl Transport for PciTransport {
246     fn device_type(&self) -> DeviceType {
247         self.device_type
248     }
249 
250     fn read_device_features(&mut self) -> u64 {
251         // Safe because the common config pointer is valid and we checked in get_bar_region that it
252         // was aligned.
253         unsafe {
254             volwrite!(self.common_cfg, device_feature_select, 0);
255             let mut device_features_bits = volread!(self.common_cfg, device_feature) as u64;
256             volwrite!(self.common_cfg, device_feature_select, 1);
257             device_features_bits |= (volread!(self.common_cfg, device_feature) as u64) << 32;
258             device_features_bits
259         }
260     }
261 
262     fn write_driver_features(&mut self, driver_features: u64) {
263         // Safe because the common config pointer is valid and we checked in get_bar_region that it
264         // was aligned.
265         unsafe {
266             volwrite!(self.common_cfg, driver_feature_select, 0);
267             volwrite!(self.common_cfg, driver_feature, driver_features as u32);
268             volwrite!(self.common_cfg, driver_feature_select, 1);
269             volwrite!(
270                 self.common_cfg,
271                 driver_feature,
272                 (driver_features >> 32) as u32
273             );
274         }
275     }
276 
277     fn max_queue_size(&mut self, queue: u16) -> u32 {
278         unsafe {
279             volwrite!(self.common_cfg, queue_select, queue);
280             volread!(self.common_cfg, queue_size).into()
281         }
282     }
283 
284     fn notify(&mut self, queue: u16) {
285         // Safe because the common config and notify region pointers are valid and we checked in
286         // get_bar_region that they were aligned.
287         unsafe {
288             volwrite!(self.common_cfg, queue_select, queue);
289             // TODO: Consider caching this somewhere (per queue).
290             let queue_notify_off = volread!(self.common_cfg, queue_notify_off);
291 
292             let offset_bytes = usize::from(queue_notify_off) * self.notify_off_multiplier as usize;
293             let index = offset_bytes / size_of::<u16>();
294             addr_of_mut!((*self.notify_region.as_ptr())[index]).vwrite(queue);
295         }
296     }
297 
298     fn set_status(&mut self, status: DeviceStatus) {
299         // Safe because the common config pointer is valid and we checked in get_bar_region that it
300         // was aligned.
301         unsafe {
302             volwrite!(self.common_cfg, device_status, status.bits() as u8);
303         }
304     }
305 
306     fn get_status(&self) -> DeviceStatus {
307         // Safe because the common config pointer is valid and we checked in get_bar_region that it
308         // was aligned.
309         unsafe { DeviceStatus::from_bits_truncate(volread!(self.common_cfg, device_status).into()) }
310     }
311 
312     fn set_guest_page_size(&mut self, _guest_page_size: u32) {
313         // No-op, the PCI transport doesn't care.
314     }
315     fn requires_legacy_layout(&self) -> bool {
316         false
317     }
318     fn queue_set(
319         &mut self,
320         queue: u16,
321         size: u32,
322         descriptors: PhysAddr,
323         driver_area: PhysAddr,
324         device_area: PhysAddr,
325     ) {
326         // Safe because the common config pointer is valid and we checked in get_bar_region that it
327         // was aligned.
328         unsafe {
329             volwrite!(self.common_cfg, queue_select, queue);
330             volwrite!(self.common_cfg, queue_size, size as u16);
331             volwrite!(self.common_cfg, queue_desc, descriptors as u64);
332             volwrite!(self.common_cfg, queue_driver, driver_area as u64);
333             volwrite!(self.common_cfg, queue_device, device_area as u64);
334             // 这里设置队列中断对应的中断项
335             if queue == QUEUE_RECEIVE {
336                 volwrite!(self.common_cfg, queue_msix_vector, VIRTIO_RECV_VECTOR_INDEX);
337                 let vector = volread!(self.common_cfg, queue_msix_vector);
338                 if vector != VIRTIO_RECV_VECTOR_INDEX {
339                     panic!("Vector set failed");
340                 }
341             }
342             volwrite!(self.common_cfg, queue_enable, 1);
343         }
344     }
345 
346     fn queue_unset(&mut self, queue: u16) {
347         // Safe because the common config pointer is valid and we checked in get_bar_region that it
348         // was aligned.
349         unsafe {
350             volwrite!(self.common_cfg, queue_select, queue);
351             volwrite!(self.common_cfg, queue_size, 0);
352             volwrite!(self.common_cfg, queue_desc, 0);
353             volwrite!(self.common_cfg, queue_driver, 0);
354             volwrite!(self.common_cfg, queue_device, 0);
355         }
356     }
357 
358     fn queue_used(&mut self, queue: u16) -> bool {
359         // Safe because the common config pointer is valid and we checked in get_bar_region that it
360         // was aligned.
361         unsafe {
362             volwrite!(self.common_cfg, queue_select, queue);
363             volread!(self.common_cfg, queue_enable) == 1
364         }
365     }
366 
367     fn ack_interrupt(&mut self) -> bool {
368         // Safe because the common config pointer is valid and we checked in get_bar_region that it
369         // was aligned.
370         // Reading the ISR status resets it to 0 and causes the device to de-assert the interrupt.
371         let isr_status = unsafe { self.isr_status.as_ptr().vread() };
372         // TODO: Distinguish between queue interrupt and device configuration interrupt.
373         isr_status & 0x3 != 0
374     }
375 
376     fn config_space<T>(&self) -> Result<NonNull<T>, Error> {
377         if let Some(config_space) = self.config_space {
378             if size_of::<T>() > config_space.len() * size_of::<u32>() {
379                 Err(Error::ConfigSpaceTooSmall)
380             } else if align_of::<T>() > 4 {
381                 // Panic as this should only happen if the driver is written incorrectly.
382                 panic!(
383                     "Driver expected config space alignment of {} bytes, but VirtIO only guarantees 4 byte alignment.",
384                     align_of::<T>()
385                 );
386             } else {
387                 // TODO: Use NonNull::as_non_null_ptr once it is stable.
388                 let config_space_ptr = NonNull::new(config_space.as_ptr() as *mut u32).unwrap();
389                 Ok(config_space_ptr.cast())
390             }
391         } else {
392             Err(Error::ConfigSpaceMissing)
393         }
394     }
395 }
396 
397 impl Drop for PciTransport {
398     fn drop(&mut self) {
399         // Reset the device when the transport is dropped.
400         self.set_status(DeviceStatus::empty());
401 
402         // todo: 调用pci的中断释放函数,并且在virtio_irq_manager里面删除对应的设备的中断
403     }
404 }
405 
406 #[repr(C)]
407 struct CommonCfg {
408     device_feature_select: Volatile<u32>,
409     device_feature: ReadOnly<u32>,
410     driver_feature_select: Volatile<u32>,
411     driver_feature: Volatile<u32>,
412     msix_config: Volatile<u16>,
413     num_queues: ReadOnly<u16>,
414     device_status: Volatile<u8>,
415     config_generation: ReadOnly<u8>,
416     queue_select: Volatile<u16>,
417     queue_size: Volatile<u16>,
418     queue_msix_vector: Volatile<u16>,
419     queue_enable: Volatile<u16>,
420     queue_notify_off: Volatile<u16>,
421     queue_desc: Volatile<u64>,
422     queue_driver: Volatile<u64>,
423     queue_device: Volatile<u64>,
424 }
425 
426 /// Information about a VirtIO structure within some BAR, as provided by a `virtio_pci_cap`.
427 /// cfg空间在哪个bar的多少偏移处,长度多少
428 #[derive(Clone, Debug, Eq, PartialEq)]
429 struct VirtioCapabilityInfo {
430     /// The bar in which the structure can be found.
431     bar: u8,
432     /// The offset within the bar.
433     offset: u32,
434     /// The length in bytes of the structure within the bar.
435     length: u32,
436 }
437 
438 /// An error encountered initialising a VirtIO PCI transport.
439 /// VirtIO PCI transport 初始化时的错误
440 #[derive(Clone, Debug, Eq, PartialEq)]
441 pub enum VirtioPciError {
442     /// PCI device vender ID was not the VirtIO vendor ID.
443     InvalidVendorId(u16),
444     /// No valid `VIRTIO_PCI_CAP_COMMON_CFG` capability was found.
445     MissingCommonConfig,
446     /// No valid `VIRTIO_PCI_CAP_NOTIFY_CFG` capability was found.
447     MissingNotifyConfig,
448     /// `VIRTIO_PCI_CAP_NOTIFY_CFG` capability has a `notify_off_multiplier` that is not a multiple
449     /// of 2.
450     InvalidNotifyOffMultiplier(u32),
451     /// No valid `VIRTIO_PCI_CAP_ISR_CFG` capability was found.
452     MissingIsrConfig,
453     /// An IO BAR was provided rather than a memory BAR.
454     UnexpectedBarType,
455     /// A BAR which we need was not allocated an address.
456     BarNotAllocated(u8),
457     /// The offset for some capability was greater than the length of the BAR.
458     BarOffsetOutOfRange,
459     /// The virtual address was not aligned as expected.
460     Misaligned {
461         /// The virtual address in question.
462         vaddr: VirtAddr,
463         /// The expected alignment in bytes.
464         alignment: usize,
465     },
466     ///获取虚拟地址失败
467     BarGetVaddrFailed,
468     /// A generic PCI error,
469     Pci(PciError),
470 }
471 
472 impl Display for VirtioPciError {
473     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
474         match self {
475             Self::InvalidVendorId(vendor_id) => write!(
476                 f,
477                 "PCI device vender ID {:#06x} was not the VirtIO vendor ID {:#06x}.",
478                 vendor_id, VIRTIO_VENDOR_ID
479             ),
480             Self::MissingCommonConfig => write!(
481                 f,
482                 "No valid `VIRTIO_PCI_CAP_COMMON_CFG` capability was found."
483             ),
484             Self::MissingNotifyConfig => write!(
485                 f,
486                 "No valid `VIRTIO_PCI_CAP_NOTIFY_CFG` capability was found."
487             ),
488             Self::InvalidNotifyOffMultiplier(notify_off_multiplier) => {
489                 write!(
490                     f,
491                     "`VIRTIO_PCI_CAP_NOTIFY_CFG` capability has a `notify_off_multiplier` that is not a multiple of 2: {}",
492                     notify_off_multiplier
493                 )
494             }
495             Self::MissingIsrConfig => {
496                 write!(f, "No valid `VIRTIO_PCI_CAP_ISR_CFG` capability was found.")
497             }
498             Self::UnexpectedBarType => write!(f, "Unexpected BAR (expected memory BAR)."),
499             Self::BarNotAllocated(bar_index) => write!(f, "Bar {} not allocated.", bar_index),
500             Self::BarOffsetOutOfRange => write!(f, "Capability offset greater than BAR length."),
501             Self::Misaligned { vaddr, alignment } => write!(
502                 f,
503                 "Virtual address {:?} was not aligned to a {} byte boundary as expected.",
504                 vaddr, alignment
505             ),
506             Self::BarGetVaddrFailed => write!(f, "Get bar virtaddress failed"),
507             Self::Pci(pci_error) => pci_error.fmt(f),
508         }
509     }
510 }
511 
512 /// PCI error到VirtioPciError的转换,层层上报
513 impl From<PciError> for VirtioPciError {
514     fn from(error: PciError) -> Self {
515         Self::Pci(error)
516     }
517 }
518 
519 /// @brief 获取虚拟地址并将其转化为对应类型的指针
520 /// @param device_bar 存储bar信息的结构体 struct_info 存储cfg空间的位置信息
521 /// @return Result<NonNull<T>, VirtioPciError> 成功则返回对应类型的指针,失败则返回Error
522 fn get_bar_region<T>(
523     device_bar: &PciStandardDeviceBar,
524     struct_info: &VirtioCapabilityInfo,
525 ) -> Result<NonNull<T>, VirtioPciError> {
526     let bar_info = device_bar.get_bar(struct_info.bar)?;
527     let (bar_address, bar_size) = bar_info
528         .memory_address_size()
529         .ok_or(VirtioPciError::UnexpectedBarType)?;
530     if bar_address == 0 {
531         return Err(VirtioPciError::BarNotAllocated(struct_info.bar));
532     }
533     if struct_info.offset + struct_info.length > bar_size
534         || size_of::<T>() > struct_info.length as usize
535     {
536         return Err(VirtioPciError::BarOffsetOutOfRange);
537     }
538     //kdebug!("Chossed bar ={},used={}",struct_info.bar,struct_info.offset + struct_info.length);
539     let vaddr = (bar_info
540         .virtual_address()
541         .ok_or(VirtioPciError::BarGetVaddrFailed)?)
542         + struct_info.offset as usize;
543     if vaddr.data() % align_of::<T>() != 0 {
544         return Err(VirtioPciError::Misaligned {
545             vaddr,
546             alignment: align_of::<T>(),
547         });
548     }
549     let vaddr = NonNull::new(vaddr.data() as *mut u8).unwrap();
550     Ok(vaddr.cast())
551 }
552 
553 /// @brief 获取虚拟地址并将其转化为对应类型的切片的指针
554 /// @param device_bar 存储bar信息的结构体 struct_info 存储cfg空间的位置信息切片的指针
555 /// @return Result<NonNull<[T]>, VirtioPciError> 成功则返回对应类型的指针切片,失败则返回Error
556 fn get_bar_region_slice<T>(
557     device_bar: &PciStandardDeviceBar,
558     struct_info: &VirtioCapabilityInfo,
559 ) -> Result<NonNull<[T]>, VirtioPciError> {
560     let ptr = get_bar_region::<T>(device_bar, struct_info)?;
561     // let raw_slice =
562     //     ptr::slice_from_raw_parts_mut(ptr.as_ptr(), struct_info.length as usize / size_of::<T>());
563     Ok(nonnull_slice_from_raw_parts(
564         ptr,
565         struct_info.length as usize / size_of::<T>(),
566     ))
567 }
568 
569 fn nonnull_slice_from_raw_parts<T>(data: NonNull<T>, len: usize) -> NonNull<[T]> {
570     NonNull::new(ptr::slice_from_raw_parts_mut(data.as_ptr(), len)).unwrap()
571 }
572 
573 /// `DefaultVirtioIrqHandler` 是一个默认的virtio设备中断处理程序。
574 ///
575 /// 当虚拟设备产生中断时,该处理程序会被调用。
576 ///
577 /// 它首先检查设备ID是否存在,然后尝试查找与设备ID关联的设备。
578 /// 如果找到设备,它会调用设备的 `handle_irq` 方法来处理中断。
579 /// 如果没有找到设备,它会记录一条警告并返回 `IrqReturn::NotHandled`,表示中断未被处理。
580 #[derive(Debug)]
581 struct DefaultVirtioIrqHandler;
582 
583 impl IrqHandler for DefaultVirtioIrqHandler {
584     fn handle(
585         &self,
586         irq: IrqNumber,
587         _static_data: Option<&dyn IrqHandlerData>,
588         dev_id: Option<Arc<dyn IrqHandlerData>>,
589     ) -> Result<IrqReturn, SystemError> {
590         let dev_id = dev_id.ok_or(SystemError::EINVAL)?;
591         let dev_id = dev_id
592             .arc_any()
593             .downcast::<DeviceId>()
594             .map_err(|_| SystemError::EINVAL)?;
595 
596         if let Some(dev) = virtio_irq_manager().lookup_device(&dev_id) {
597             return dev.handle_irq(irq);
598         } else {
599             // 未绑定具体设备,因此无法处理中断
600 
601             return Ok(IrqReturn::NotHandled);
602         }
603     }
604 }
605