xref: /DragonOS/kernel/src/driver/block/virtio_blk.rs (revision 9fa0e95eeed8630a8a69c874090af2f10e8eee02)
1 use core::{any::Any, fmt::Debug};
2 
3 use alloc::{
4     string::{String, ToString},
5     sync::{Arc, Weak},
6     vec::Vec,
7 };
8 use bitmap::traits::BitMapOps;
9 use log::error;
10 use system_error::SystemError;
11 use unified_init::macros::unified_init;
12 use virtio_drivers::device::blk::{VirtIOBlk, SECTOR_SIZE};
13 
14 use crate::{
15     driver::{
16         base::{
17             block::{
18                 block_device::{BlockDevName, BlockDevice, BlockId, GeneralBlockRange, LBA_SIZE},
19                 disk_info::Partition,
20                 manager::{block_dev_manager, BlockDevMeta},
21             },
22             class::Class,
23             device::{
24                 bus::Bus,
25                 driver::{Driver, DriverCommonData},
26                 Device, DeviceCommonData, DeviceId, DeviceType, IdTable,
27             },
28             kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
29             kset::KSet,
30         },
31         virtio::{
32             sysfs::{virtio_bus, virtio_device_manager, virtio_driver_manager},
33             transport::VirtIOTransport,
34             virtio_impl::HalImpl,
35             VirtIODevice, VirtIODeviceIndex, VirtIODriver, VIRTIO_VENDOR_ID,
36         },
37     },
38     exception::{irqdesc::IrqReturn, IrqNumber},
39     filesystem::{kernfs::KernFSInode, mbr::MbrDiskPartionTable},
40     init::initcall::INITCALL_POSTCORE,
41     libs::{
42         rwlock::{RwLockReadGuard, RwLockWriteGuard},
43         spinlock::{SpinLock, SpinLockGuard},
44     },
45 };
46 
47 const VIRTIO_BLK_BASENAME: &str = "virtio_blk";
48 
49 static mut VIRTIO_BLK_DRIVER: Option<Arc<VirtIOBlkDriver>> = None;
50 
51 #[inline(always)]
52 fn virtio_blk_driver() -> Arc<VirtIOBlkDriver> {
53     unsafe { VIRTIO_BLK_DRIVER.as_ref().unwrap().clone() }
54 }
55 
56 /// Get the first virtio block device
57 #[allow(dead_code)]
58 pub fn virtio_blk_0() -> Option<Arc<VirtIOBlkDevice>> {
59     virtio_blk_driver()
60         .devices()
61         .first()
62         .cloned()
63         .map(|dev| dev.arc_any().downcast().unwrap())
64 }
65 
66 pub fn virtio_blk(transport: VirtIOTransport, dev_id: Arc<DeviceId>) {
67     let device = VirtIOBlkDevice::new(transport, dev_id);
68     if let Some(device) = device {
69         virtio_device_manager()
70             .device_add(device.clone() as Arc<dyn VirtIODevice>)
71             .expect("Add virtio blk failed");
72     }
73 }
74 
75 static mut VIRTIOBLK_MANAGER: Option<VirtIOBlkManager> = None;
76 
77 #[inline]
78 fn virtioblk_manager() -> &'static VirtIOBlkManager {
79     unsafe { VIRTIOBLK_MANAGER.as_ref().unwrap() }
80 }
81 
82 #[unified_init(INITCALL_POSTCORE)]
83 fn virtioblk_manager_init() -> Result<(), SystemError> {
84     unsafe {
85         VIRTIOBLK_MANAGER = Some(VirtIOBlkManager::new());
86     }
87     Ok(())
88 }
89 
90 pub struct VirtIOBlkManager {
91     inner: SpinLock<InnerVirtIOBlkManager>,
92 }
93 
94 struct InnerVirtIOBlkManager {
95     id_bmp: bitmap::StaticBitmap<{ VirtIOBlkManager::MAX_DEVICES }>,
96     devname: [Option<BlockDevName>; VirtIOBlkManager::MAX_DEVICES],
97 }
98 
99 impl VirtIOBlkManager {
100     pub const MAX_DEVICES: usize = 25;
101 
102     pub fn new() -> Self {
103         Self {
104             inner: SpinLock::new(InnerVirtIOBlkManager {
105                 id_bmp: bitmap::StaticBitmap::new(),
106                 devname: [const { None }; Self::MAX_DEVICES],
107             }),
108         }
109     }
110 
111     fn inner(&self) -> SpinLockGuard<InnerVirtIOBlkManager> {
112         self.inner.lock()
113     }
114 
115     pub fn alloc_id(&self) -> Option<BlockDevName> {
116         let mut inner = self.inner();
117         let idx = inner.id_bmp.first_false_index()?;
118         inner.id_bmp.set(idx, true);
119         let name = Self::format_name(idx);
120         inner.devname[idx] = Some(name.clone());
121         Some(name)
122     }
123 
124     /// Generate a new block device name like 'vda', 'vdb', etc.
125     fn format_name(id: usize) -> BlockDevName {
126         let x = (b'a' + id as u8) as char;
127         BlockDevName::new(format!("vd{}", x), id)
128     }
129 
130     pub fn free_id(&self, id: usize) {
131         if id >= Self::MAX_DEVICES {
132             return;
133         }
134         self.inner().id_bmp.set(id, false);
135         self.inner().devname[id] = None;
136     }
137 }
138 
139 /// virtio block device
140 #[derive(Debug)]
141 #[cast_to([sync] VirtIODevice)]
142 #[cast_to([sync] Device)]
143 pub struct VirtIOBlkDevice {
144     blkdev_meta: BlockDevMeta,
145     dev_id: Arc<DeviceId>,
146     inner: SpinLock<InnerVirtIOBlkDevice>,
147     locked_kobj_state: LockedKObjectState,
148     self_ref: Weak<Self>,
149 }
150 
151 unsafe impl Send for VirtIOBlkDevice {}
152 unsafe impl Sync for VirtIOBlkDevice {}
153 
154 impl VirtIOBlkDevice {
155     pub fn new(transport: VirtIOTransport, dev_id: Arc<DeviceId>) -> Option<Arc<Self>> {
156         let devname = virtioblk_manager().alloc_id()?;
157         let irq = transport.irq().map(|irq| IrqNumber::new(irq.data()));
158         let device_inner = VirtIOBlk::<HalImpl, VirtIOTransport>::new(transport);
159         if let Err(e) = device_inner {
160             error!("VirtIOBlkDevice '{dev_id:?}' create failed: {:?}", e);
161             return None;
162         }
163 
164         let mut device_inner: VirtIOBlk<HalImpl, VirtIOTransport> = device_inner.unwrap();
165         device_inner.enable_interrupts();
166         let dev = Arc::new_cyclic(|self_ref| Self {
167             blkdev_meta: BlockDevMeta::new(devname),
168             self_ref: self_ref.clone(),
169             dev_id,
170             locked_kobj_state: LockedKObjectState::default(),
171             inner: SpinLock::new(InnerVirtIOBlkDevice {
172                 device_inner,
173                 name: None,
174                 virtio_index: None,
175                 device_common: DeviceCommonData::default(),
176                 kobject_common: KObjectCommonData::default(),
177                 irq,
178             }),
179         });
180 
181         dev.set_driver(Some(Arc::downgrade(
182             &(virtio_blk_driver() as Arc<dyn Driver>),
183         )));
184 
185         Some(dev)
186     }
187 
188     fn inner(&self) -> SpinLockGuard<InnerVirtIOBlkDevice> {
189         self.inner.lock()
190     }
191 }
192 
193 impl BlockDevice for VirtIOBlkDevice {
194     fn dev_name(&self) -> &BlockDevName {
195         &self.blkdev_meta.devname
196     }
197 
198     fn blkdev_meta(&self) -> &BlockDevMeta {
199         &self.blkdev_meta
200     }
201 
202     fn disk_range(&self) -> GeneralBlockRange {
203         let inner = self.inner();
204         let blocks = inner.device_inner.capacity() as usize * SECTOR_SIZE / LBA_SIZE;
205         drop(inner);
206         log::debug!(
207             "VirtIOBlkDevice '{:?}' disk_range: 0..{}",
208             self.dev_name(),
209             blocks
210         );
211         GeneralBlockRange::new(0, blocks).unwrap()
212     }
213 
214     fn read_at_sync(
215         &self,
216         lba_id_start: BlockId,
217         count: usize,
218         buf: &mut [u8],
219     ) -> Result<usize, SystemError> {
220         let mut inner = self.inner();
221 
222         inner
223             .device_inner
224             .read_blocks(lba_id_start, &mut buf[..count * LBA_SIZE])
225             .map_err(|e| {
226                 error!(
227                     "VirtIOBlkDevice '{:?}' read_at_sync failed: {:?}",
228                     self.dev_id, e
229                 );
230                 SystemError::EIO
231             })?;
232 
233         Ok(count)
234     }
235 
236     fn write_at_sync(
237         &self,
238         lba_id_start: BlockId,
239         count: usize,
240         buf: &[u8],
241     ) -> Result<usize, SystemError> {
242         self.inner()
243             .device_inner
244             .write_blocks(lba_id_start, &buf[..count * LBA_SIZE])
245             .map_err(|_| SystemError::EIO)?;
246         Ok(count)
247     }
248 
249     fn sync(&self) -> Result<(), SystemError> {
250         Ok(())
251     }
252 
253     fn blk_size_log2(&self) -> u8 {
254         9
255     }
256 
257     fn as_any_ref(&self) -> &dyn Any {
258         self
259     }
260 
261     fn device(&self) -> Arc<dyn Device> {
262         self.self_ref.upgrade().unwrap()
263     }
264 
265     fn block_size(&self) -> usize {
266         todo!()
267     }
268 
269     fn partitions(&self) -> Vec<Arc<Partition>> {
270         let device = self.self_ref.upgrade().unwrap() as Arc<dyn BlockDevice>;
271         let mbr_table = MbrDiskPartionTable::from_disk(device.clone())
272             .expect("Failed to get MBR partition table");
273         mbr_table.partitions(Arc::downgrade(&device))
274     }
275 }
276 
277 struct InnerVirtIOBlkDevice {
278     device_inner: VirtIOBlk<HalImpl, VirtIOTransport>,
279     name: Option<String>,
280     virtio_index: Option<VirtIODeviceIndex>,
281     device_common: DeviceCommonData,
282     kobject_common: KObjectCommonData,
283     irq: Option<IrqNumber>,
284 }
285 
286 impl Debug for InnerVirtIOBlkDevice {
287     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
288         f.debug_struct("InnerVirtIOBlkDevice").finish()
289     }
290 }
291 
292 impl VirtIODevice for VirtIOBlkDevice {
293     fn irq(&self) -> Option<IrqNumber> {
294         self.inner().irq
295     }
296 
297     fn handle_irq(
298         &self,
299         _irq: crate::exception::IrqNumber,
300     ) -> Result<IrqReturn, system_error::SystemError> {
301         // todo: handle virtio blk irq
302         Ok(crate::exception::irqdesc::IrqReturn::Handled)
303     }
304 
305     fn dev_id(&self) -> &Arc<DeviceId> {
306         &self.dev_id
307     }
308 
309     fn set_device_name(&self, name: String) {
310         self.inner().name = Some(name);
311     }
312 
313     fn device_name(&self) -> String {
314         self.inner()
315             .name
316             .clone()
317             .unwrap_or_else(|| VIRTIO_BLK_BASENAME.to_string())
318     }
319 
320     fn set_virtio_device_index(&self, index: VirtIODeviceIndex) {
321         self.inner().virtio_index = Some(index);
322     }
323 
324     fn virtio_device_index(&self) -> Option<VirtIODeviceIndex> {
325         self.inner().virtio_index
326     }
327 
328     fn device_type_id(&self) -> u32 {
329         virtio_drivers::transport::DeviceType::Block as u32
330     }
331 
332     fn vendor(&self) -> u32 {
333         VIRTIO_VENDOR_ID.into()
334     }
335 }
336 
337 impl Device for VirtIOBlkDevice {
338     fn dev_type(&self) -> DeviceType {
339         DeviceType::Net
340     }
341 
342     fn id_table(&self) -> IdTable {
343         IdTable::new(VIRTIO_BLK_BASENAME.to_string(), None)
344     }
345 
346     fn bus(&self) -> Option<Weak<dyn Bus>> {
347         self.inner().device_common.bus.clone()
348     }
349 
350     fn set_bus(&self, bus: Option<Weak<dyn Bus>>) {
351         self.inner().device_common.bus = bus;
352     }
353 
354     fn class(&self) -> Option<Arc<dyn Class>> {
355         let mut guard = self.inner();
356         let r = guard.device_common.class.clone()?.upgrade();
357         if r.is_none() {
358             guard.device_common.class = None;
359         }
360 
361         return r;
362     }
363 
364     fn set_class(&self, class: Option<Weak<dyn Class>>) {
365         self.inner().device_common.class = class;
366     }
367 
368     fn driver(&self) -> Option<Arc<dyn Driver>> {
369         let r = self.inner().device_common.driver.clone()?.upgrade();
370         if r.is_none() {
371             self.inner().device_common.driver = None;
372         }
373 
374         return r;
375     }
376 
377     fn set_driver(&self, driver: Option<Weak<dyn Driver>>) {
378         self.inner().device_common.driver = driver;
379     }
380 
381     fn is_dead(&self) -> bool {
382         false
383     }
384 
385     fn can_match(&self) -> bool {
386         self.inner().device_common.can_match
387     }
388 
389     fn set_can_match(&self, can_match: bool) {
390         self.inner().device_common.can_match = can_match;
391     }
392 
393     fn state_synced(&self) -> bool {
394         true
395     }
396 }
397 
398 impl KObject for VirtIOBlkDevice {
399     fn as_any_ref(&self) -> &dyn Any {
400         self
401     }
402 
403     fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
404         self.inner().kobject_common.kern_inode = inode;
405     }
406 
407     fn inode(&self) -> Option<Arc<KernFSInode>> {
408         self.inner().kobject_common.kern_inode.clone()
409     }
410 
411     fn parent(&self) -> Option<Weak<dyn KObject>> {
412         self.inner().kobject_common.parent.clone()
413     }
414 
415     fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
416         self.inner().kobject_common.parent = parent;
417     }
418 
419     fn kset(&self) -> Option<Arc<KSet>> {
420         self.inner().kobject_common.kset.clone()
421     }
422 
423     fn set_kset(&self, kset: Option<Arc<KSet>>) {
424         self.inner().kobject_common.kset = kset;
425     }
426 
427     fn kobj_type(&self) -> Option<&'static dyn KObjType> {
428         self.inner().kobject_common.kobj_type
429     }
430 
431     fn name(&self) -> String {
432         self.device_name()
433     }
434 
435     fn set_name(&self, _name: String) {
436         // do nothing
437     }
438 
439     fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
440         self.locked_kobj_state.read()
441     }
442 
443     fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
444         self.locked_kobj_state.write()
445     }
446 
447     fn set_kobj_state(&self, state: KObjectState) {
448         *self.locked_kobj_state.write() = state;
449     }
450 
451     fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
452         self.inner().kobject_common.kobj_type = ktype;
453     }
454 }
455 
456 #[unified_init(INITCALL_POSTCORE)]
457 fn virtio_blk_driver_init() -> Result<(), SystemError> {
458     let driver = VirtIOBlkDriver::new();
459     virtio_driver_manager()
460         .register(driver.clone() as Arc<dyn VirtIODriver>)
461         .expect("Add virtio net driver failed");
462     unsafe {
463         VIRTIO_BLK_DRIVER = Some(driver);
464     }
465 
466     return Ok(());
467 }
468 
469 #[derive(Debug)]
470 #[cast_to([sync] VirtIODriver)]
471 #[cast_to([sync] Driver)]
472 struct VirtIOBlkDriver {
473     inner: SpinLock<InnerVirtIOBlkDriver>,
474     kobj_state: LockedKObjectState,
475 }
476 
477 impl VirtIOBlkDriver {
478     pub fn new() -> Arc<Self> {
479         let inner = InnerVirtIOBlkDriver {
480             driver_common: DriverCommonData::default(),
481             kobj_common: KObjectCommonData::default(),
482         };
483         Arc::new(VirtIOBlkDriver {
484             inner: SpinLock::new(inner),
485             kobj_state: LockedKObjectState::default(),
486         })
487     }
488 
489     fn inner(&self) -> SpinLockGuard<InnerVirtIOBlkDriver> {
490         return self.inner.lock();
491     }
492 }
493 
494 #[derive(Debug)]
495 struct InnerVirtIOBlkDriver {
496     driver_common: DriverCommonData,
497     kobj_common: KObjectCommonData,
498 }
499 
500 impl VirtIODriver for VirtIOBlkDriver {
501     fn probe(&self, device: &Arc<dyn VirtIODevice>) -> Result<(), SystemError> {
502         let dev = device
503             .clone()
504             .arc_any()
505             .downcast::<VirtIOBlkDevice>()
506             .map_err(|_| {
507                 error!(
508                 "VirtIOBlkDriver::probe() failed: device is not a VirtIO block device. Device: '{:?}'",
509                 device.name()
510             );
511                 SystemError::EINVAL
512             })?;
513 
514         block_dev_manager().register(dev as Arc<dyn BlockDevice>)?;
515         return Ok(());
516     }
517 }
518 
519 impl Driver for VirtIOBlkDriver {
520     fn id_table(&self) -> Option<IdTable> {
521         Some(IdTable::new(VIRTIO_BLK_BASENAME.to_string(), None))
522     }
523 
524     fn add_device(&self, device: Arc<dyn Device>) {
525         let iface = device
526             .arc_any()
527             .downcast::<VirtIOBlkDevice>()
528             .expect("VirtIOBlkDriver::add_device() failed: device is not a VirtIOBlkDevice");
529 
530         self.inner()
531             .driver_common
532             .devices
533             .push(iface as Arc<dyn Device>);
534     }
535 
536     fn delete_device(&self, device: &Arc<dyn Device>) {
537         let _iface = device
538             .clone()
539             .arc_any()
540             .downcast::<VirtIOBlkDevice>()
541             .expect("VirtIOBlkDriver::delete_device() failed: device is not a VirtIOBlkDevice");
542 
543         let mut guard = self.inner();
544         let index = guard
545             .driver_common
546             .devices
547             .iter()
548             .position(|dev| Arc::ptr_eq(device, dev))
549             .expect("VirtIOBlkDriver::delete_device() failed: device not found");
550 
551         guard.driver_common.devices.remove(index);
552     }
553 
554     fn devices(&self) -> Vec<Arc<dyn Device>> {
555         self.inner().driver_common.devices.clone()
556     }
557 
558     fn bus(&self) -> Option<Weak<dyn Bus>> {
559         Some(Arc::downgrade(&virtio_bus()) as Weak<dyn Bus>)
560     }
561 
562     fn set_bus(&self, _bus: Option<Weak<dyn Bus>>) {
563         // do nothing
564     }
565 }
566 
567 impl KObject for VirtIOBlkDriver {
568     fn as_any_ref(&self) -> &dyn Any {
569         self
570     }
571 
572     fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
573         self.inner().kobj_common.kern_inode = inode;
574     }
575 
576     fn inode(&self) -> Option<Arc<KernFSInode>> {
577         self.inner().kobj_common.kern_inode.clone()
578     }
579 
580     fn parent(&self) -> Option<Weak<dyn KObject>> {
581         self.inner().kobj_common.parent.clone()
582     }
583 
584     fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
585         self.inner().kobj_common.parent = parent;
586     }
587 
588     fn kset(&self) -> Option<Arc<KSet>> {
589         self.inner().kobj_common.kset.clone()
590     }
591 
592     fn set_kset(&self, kset: Option<Arc<KSet>>) {
593         self.inner().kobj_common.kset = kset;
594     }
595 
596     fn kobj_type(&self) -> Option<&'static dyn KObjType> {
597         self.inner().kobj_common.kobj_type
598     }
599 
600     fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
601         self.inner().kobj_common.kobj_type = ktype;
602     }
603 
604     fn name(&self) -> String {
605         VIRTIO_BLK_BASENAME.to_string()
606     }
607 
608     fn set_name(&self, _name: String) {
609         // do nothing
610     }
611 
612     fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
613         self.kobj_state.read()
614     }
615 
616     fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
617         self.kobj_state.write()
618     }
619 
620     fn set_kobj_state(&self, state: KObjectState) {
621         *self.kobj_state.write() = state;
622     }
623 }
624