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, ¬ify_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