xref: /DragonOS/kernel/src/driver/virtio/irq.rs (revision f79998f626801329580c782fd05e36cb2027f474)
1 use alloc::sync::Arc;
2 use hashbrown::HashMap;
3 use log::warn;
4 use system_error::SystemError;
5 use unified_init::macros::unified_init;
6 
7 use crate::{
8     driver::base::device::DeviceId,
9     exception::{
10         irqdata::IrqHandlerData,
11         irqdesc::{IrqHandler, IrqReturn},
12         IrqNumber,
13     },
14     init::initcall::INITCALL_CORE,
15     libs::rwlock::RwLock,
16 };
17 
18 use super::VirtIODevice;
19 
20 static mut VIRTIO_IRQ_MANAGER: Option<VirtIOIrqManager> = None;
21 
22 #[inline(always)]
23 pub fn virtio_irq_manager() -> &'static VirtIOIrqManager {
24     unsafe { VIRTIO_IRQ_MANAGER.as_ref().unwrap() }
25 }
26 
27 pub struct VirtIOIrqManager {
28     map: RwLock<HashMap<Arc<DeviceId>, Arc<dyn VirtIODevice>>>,
29 }
30 
31 impl VirtIOIrqManager {
32     fn new() -> Self {
33         VirtIOIrqManager {
34             map: RwLock::new(HashMap::new()),
35         }
36     }
37 
38     /// 注册一个新的设备到virtio中断请求(IRQ)映射中。
39     ///
40     /// # 参数
41     ///
42     /// - `device` - 实现了 `VirtIODevice` trait 的设备对象,被封装在 `Arc` 智能指针中。
43     ///
44     /// # 返回值
45     ///
46     /// - 如果设备成功注册,返回 `Ok(())`。
47     /// - 如果设备ID已经存在于映射中,返回 `Err(SystemError::EEXIST)`。
48     pub fn register_device(&self, device: Arc<dyn VirtIODevice>) -> Result<(), SystemError> {
49         let mut map = self.map.write_irqsave();
50 
51         if map.contains_key(device.dev_id()) {
52             return Err(SystemError::EEXIST);
53         }
54 
55         map.insert(device.dev_id().clone(), device);
56 
57         return Ok(());
58     }
59 
60     /// 取消注册设备
61     ///
62     /// 这个函数会从内部映射中移除指定的设备。设备是通过设备ID来识别的。
63     ///
64     /// # 参数
65     ///
66     /// - `device` - 需要被取消注册的设备,它是一个实现了 `VirtIODevice` trait 的智能指针。
67     #[allow(dead_code)]
68     pub fn unregister_device(&self, dev_id: &Arc<DeviceId>) {
69         let mut map = self.map.write_irqsave();
70         map.remove(dev_id);
71     }
72 
73     /// 查找并返回指定设备ID的设备。
74     ///
75     /// # 参数
76     /// - `dev_id` - 我们要查找的设备的设备ID。
77     ///
78     /// # 返回
79     /// - 如果找到了设备,返回一个包含设备的`Option<Arc<dyn VirtIODevice>>`。
80     /// - 如果没有找到设备,返回`None`。
81 
82     pub fn lookup_device(&self, dev_id: &Arc<DeviceId>) -> Option<Arc<dyn VirtIODevice>> {
83         let map = self.map.read_irqsave();
84         map.get(dev_id).cloned()
85     }
86 }
87 
88 #[unified_init(INITCALL_CORE)]
89 fn init_virtio_irq_manager() -> Result<(), SystemError> {
90     let manager = VirtIOIrqManager::new();
91     unsafe {
92         VIRTIO_IRQ_MANAGER = Some(manager);
93     }
94     return Ok(());
95 }
96 
97 /// `DefaultVirtioIrqHandler` 是一个默认的virtio设备中断处理程序。
98 ///
99 /// 当虚拟设备产生中断时,该处理程序会被调用。
100 ///
101 /// 它首先检查设备ID是否存在,然后尝试查找与设备ID关联的设备。
102 /// 如果找到设备,它会调用设备的 `handle_irq` 方法来处理中断。
103 /// 如果没有找到设备,它会记录一条警告并返回 `IrqReturn::NotHandled`,表示中断未被处理。
104 #[derive(Debug)]
105 pub(super) struct DefaultVirtioIrqHandler;
106 
107 impl IrqHandler for DefaultVirtioIrqHandler {
108     fn handle(
109         &self,
110         irq: IrqNumber,
111         _static_data: Option<&dyn IrqHandlerData>,
112         dev_id: Option<Arc<dyn IrqHandlerData>>,
113     ) -> Result<IrqReturn, SystemError> {
114         let dev_id = dev_id.ok_or(SystemError::EINVAL)?;
115         let dev_id = dev_id
116             .arc_any()
117             .downcast::<DeviceId>()
118             .map_err(|_| SystemError::EINVAL)?;
119 
120         if let Some(dev) = virtio_irq_manager().lookup_device(&dev_id) {
121             return dev.handle_irq(irq);
122         } else {
123             // 未绑定具体设备,因此无法处理中断
124             warn!("No device found for IRQ: {:?}", irq);
125             return Ok(IrqReturn::NotHandled);
126         }
127     }
128 }
129