xref: /DragonOS/kernel/src/driver/virtio/sysfs.rs (revision f79998f626801329580c782fd05e36cb2027f474)
1 use alloc::{
2     string::{String, ToString},
3     sync::{Arc, Weak},
4 };
5 use ida::IdAllocator;
6 use intertrait::cast::CastArc;
7 use log::error;
8 use system_error::SystemError;
9 use unified_init::macros::unified_init;
10 
11 use crate::{
12     driver::{
13         base::{
14             device::{
15                 bus::{bus_manager, Bus},
16                 device_manager,
17                 driver::{driver_manager, Driver},
18                 Device,
19             },
20             kobject::KObject,
21             subsys::SubSysPrivate,
22         },
23         virtio::irq::{virtio_irq_manager, DefaultVirtioIrqHandler},
24     },
25     exception::{irqdesc::IrqHandleFlags, manage::irq_manager},
26     filesystem::{
27         sysfs::{
28             file::sysfs_emit_str, Attribute, AttributeGroup, SysFSOpsSupport, SYSFS_ATTR_MODE_RO,
29         },
30         vfs::syscall::ModeType,
31     },
32     init::initcall::INITCALL_CORE,
33 };
34 
35 use super::{VirtIODevice, VirtIODeviceIndex, VirtIODriver};
36 
37 static mut VIRTIO_BUS: Option<Arc<VirtIOBus>> = None;
38 
39 #[inline(always)]
40 pub fn virtio_bus() -> Arc<VirtIOBus> {
41     unsafe { VIRTIO_BUS.as_ref().unwrap().clone() }
42 }
43 
44 #[derive(Debug)]
45 pub struct VirtIOBus {
46     private: SubSysPrivate,
47 }
48 
49 impl VirtIOBus {
50     pub fn new() -> Arc<Self> {
51         let w: Weak<Self> = Weak::new();
52         let private = SubSysPrivate::new("virtio".to_string(), Some(w), None, &[]);
53         let bus = Arc::new(Self { private });
54         bus.subsystem()
55             .set_bus(Some(Arc::downgrade(&(bus.clone() as Arc<dyn Bus>))));
56 
57         return bus;
58     }
59 }
60 
61 impl Bus for VirtIOBus {
62     fn name(&self) -> String {
63         self.private.name()
64     }
65 
66     fn dev_name(&self) -> String {
67         return self.name();
68     }
69 
70     fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] {
71         // todo: VirtIODeviceAttrGroup
72         return &[];
73     }
74 
75     fn subsystem(&self) -> &SubSysPrivate {
76         return &self.private;
77     }
78 
79     fn probe(&self, device: &Arc<dyn Device>) -> Result<(), SystemError> {
80         let drv = device.driver().ok_or(SystemError::EINVAL)?;
81         let virtio_drv = drv.cast::<dyn VirtIODriver>().map_err(|_| {
82             error!(
83                 "VirtIOBus::probe() failed: device.driver() is not a VirtioDriver. Device: '{:?}'",
84                 device.name()
85             );
86             SystemError::EINVAL
87         })?;
88 
89         let virtio_dev = device.clone().cast::<dyn VirtIODevice>().map_err(|_| {
90             error!(
91                 "VirtIOBus::probe() failed: device is not a VirtIODevice. Device: '{:?}'",
92                 device.name()
93             );
94             SystemError::EINVAL
95         })?;
96 
97         return virtio_drv.probe(&virtio_dev);
98     }
99 
100     fn remove(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
101         todo!()
102     }
103 
104     fn sync_state(&self, _device: &Arc<dyn Device>) {
105         todo!()
106     }
107 
108     fn shutdown(&self, _device: &Arc<dyn Device>) {
109         todo!()
110     }
111 
112     fn resume(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
113         todo!()
114     }
115 
116     fn match_device(
117         &self,
118         _device: &Arc<dyn Device>,
119         _driver: &Arc<dyn Driver>,
120     ) -> Result<bool, SystemError> {
121         // todo: https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/virtio/virtio.c#85
122         todo!("VirtIOBus::match_device() is not implemented")
123     }
124 }
125 
126 #[unified_init(INITCALL_CORE)]
127 fn virtio_init() -> Result<(), SystemError> {
128     let bus = VirtIOBus::new();
129     unsafe {
130         VIRTIO_BUS = Some(bus.clone());
131     }
132     bus_manager()
133         .register(bus)
134         .expect("Failed to register virtio bus!");
135     Ok(())
136 }
137 
138 #[inline(always)]
139 pub fn virtio_driver_manager() -> &'static VirtIODriverManager {
140     &VirtIODriverManager
141 }
142 
143 pub struct VirtIODriverManager;
144 
145 impl VirtIODriverManager {
146     pub fn register(&self, driver: Arc<dyn VirtIODriver>) -> Result<(), SystemError> {
147         driver.set_bus(Some(Arc::downgrade(&(virtio_bus() as Arc<dyn Bus>))));
148         return driver_manager().register(driver as Arc<dyn Driver>);
149     }
150 
151     #[allow(dead_code)]
152     pub fn unregister(&self, driver: &Arc<dyn VirtIODriver>) {
153         driver_manager().unregister(&(driver.clone() as Arc<dyn Driver>));
154     }
155 }
156 
157 #[inline(always)]
158 pub fn virtio_device_manager() -> &'static VirtIODeviceManager {
159     &VirtIODeviceManager
160 }
161 
162 pub struct VirtIODeviceManager;
163 
164 impl VirtIODeviceManager {
165     pub fn device_add(&self, dev: Arc<dyn VirtIODevice>) -> Result<(), SystemError> {
166         dev.set_bus(Some(Arc::downgrade(&(virtio_bus() as Arc<dyn Bus>))));
167         device_manager().device_default_initialize(&(dev.clone() as Arc<dyn Device>));
168         let drv = dev.driver().ok_or(SystemError::EINVAL)?;
169 
170         let virtio_drv = drv.cast::<dyn VirtIODriver>().map_err(|_| {
171             error!(
172                 "VirtIODeviceManager::device_add() failed: device.driver() is not a VirtioDriver. Device: '{:?}'",
173                 dev.name()
174             );
175             SystemError::EINVAL
176         })?;
177         let virtio_index = VIRTIO_DEVICE_INDEX_MANAGER.alloc();
178         dev.set_virtio_device_index(virtio_index);
179         dev.set_device_name(format!("virtio{}", virtio_index.data()));
180         virtio_drv.probe(&dev)?;
181 
182         device_manager().add_device(dev.clone() as Arc<dyn Device>)?;
183         let r = device_manager()
184             .add_groups(&(dev.clone() as Arc<dyn Device>), &[&VirtIODeviceAttrGroup]);
185 
186         self.setup_irq(&dev).ok();
187 
188         return r;
189     }
190 
191     /// # setup_irq - 设置中断
192     ///
193     /// 为virtio设备设置中断。
194     fn setup_irq(&self, dev: &Arc<dyn VirtIODevice>) -> Result<(), SystemError> {
195         let irq = dev.irq().ok_or(SystemError::EINVAL)?;
196         if let Err(e) = irq_manager().request_irq(
197             irq,
198             dev.device_name(),
199             &DefaultVirtioIrqHandler,
200             IrqHandleFlags::IRQF_SHARED,
201             Some(dev.dev_id().clone()),
202         ) {
203             error!(
204                 "Failed to request irq for virtio device '{}': irq: {:?}, error {:?}",
205                 dev.device_name(),
206                 irq,
207                 e
208             );
209             return Err(e);
210         }
211 
212         virtio_irq_manager()
213             .register_device(dev.clone())
214             .map_err(|e| {
215                 error!(
216                     "Failed to register virtio device's irq, dev: '{}', irq: {:?}, error {:?}",
217                     dev.device_name(),
218                     irq,
219                     e
220                 );
221                 e
222             })?;
223         return Ok(());
224     }
225 
226     #[allow(dead_code)]
227     pub fn device_remove(&self, dev: &Arc<dyn VirtIODevice>) -> Result<(), SystemError> {
228         device_manager().remove(&(dev.clone() as Arc<dyn Device>));
229         return Ok(());
230     }
231 }
232 
233 static VIRTIO_DEVICE_INDEX_MANAGER: VirtIODeviceIndexManager = VirtIODeviceIndexManager::new();
234 
235 /// VirtIO设备索引管理器
236 ///
237 /// VirtIO设备索引管理器用于分配和管理VirtIO设备的唯一索引。
238 pub struct VirtIODeviceIndexManager {
239     // ID分配器
240     ///
241     /// ID分配器用于分配唯一的索引给VirtIO设备。
242     ida: IdAllocator,
243 }
244 
245 // VirtIO设备索引管理器的新建实例
246 impl VirtIODeviceIndexManager {
247     /// 创建新的VirtIO设备索引管理器实例
248     ///
249     /// 创建一个新的VirtIO设备索引管理器实例,初始时分配器从0开始,直到最大usize值。
250     const fn new() -> Self {
251         Self {
252             ida: IdAllocator::new(0, usize::MAX),
253         }
254     }
255 
256     /// 分配一个新的VirtIO设备索引
257     ///
258     /// 分配一个唯一的索引给VirtIO设备。
259     pub fn alloc(&self) -> VirtIODeviceIndex {
260         VirtIODeviceIndex(self.ida.alloc().unwrap())
261     }
262 
263     // 释放一个VirtIO设备索引
264     ///
265     /// 释放之前分配的VirtIO设备索引,使其可以被重新使用。
266     #[allow(dead_code)]
267     pub fn free(&self, index: VirtIODeviceIndex) {
268         self.ida.free(index.0);
269     }
270 }
271 
272 /// VirtIO设备属性组
273 ///
274 /// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/virtio/virtio.c#64
275 #[derive(Debug)]
276 pub struct VirtIODeviceAttrGroup;
277 
278 impl AttributeGroup for VirtIODeviceAttrGroup {
279     fn name(&self) -> Option<&str> {
280         None
281     }
282 
283     fn attrs(&self) -> &[&'static dyn Attribute] {
284         &[&AttrDevice, &AttrVendor]
285     }
286 }
287 
288 #[derive(Debug)]
289 struct AttrDevice;
290 
291 impl Attribute for AttrDevice {
292     fn name(&self) -> &str {
293         "device"
294     }
295 
296     fn mode(&self) -> ModeType {
297         SYSFS_ATTR_MODE_RO
298     }
299 
300     fn support(&self) -> SysFSOpsSupport {
301         SysFSOpsSupport::ATTR_SHOW
302     }
303 
304     fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
305         let dev = kobj.cast::<dyn VirtIODevice>().map_err(|_| {
306             error!("AttrDevice::show() failed: kobj is not a VirtIODevice");
307             SystemError::EINVAL
308         })?;
309         let device_type_id = dev.device_type_id();
310 
311         return sysfs_emit_str(buf, &format!("0x{:04x}\n", device_type_id));
312     }
313 }
314 
315 #[derive(Debug)]
316 struct AttrVendor;
317 
318 impl Attribute for AttrVendor {
319     fn name(&self) -> &str {
320         "vendor"
321     }
322 
323     fn mode(&self) -> ModeType {
324         SYSFS_ATTR_MODE_RO
325     }
326 
327     fn support(&self) -> SysFSOpsSupport {
328         SysFSOpsSupport::ATTR_SHOW
329     }
330 
331     fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
332         let dev = kobj.cast::<dyn VirtIODevice>().map_err(|_| {
333             error!("AttrVendor::show() failed: kobj is not a VirtIODevice");
334             SystemError::EINVAL
335         })?;
336         let vendor = dev.vendor();
337 
338         return sysfs_emit_str(buf, &format!("0x{:04x}\n", vendor));
339     }
340 }
341