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