kernel/drivers/virtio/device/
mod.rs

1//! Virtio device driver interface module.
2//!
3
4use core::{
5    result::Result,
6    sync::atomic::{AtomicUsize, Ordering},
7};
8
9use alloc::{boxed::Box, format, string::ToString, sync::Arc, vec};
10
11use crate::{
12    arch::io_mb,
13    device::{
14        Device,
15        manager::{DeviceManager, DriverPriority},
16        platform::{
17            PlatformDeviceDriver, PlatformDeviceInfo, resource::PlatformDeviceResourceType,
18        },
19    },
20    driver_initcall,
21    drivers::{
22        block::virtio_blk::VirtioBlockDevice, graphics::virtio_gpu::VirtioGpuDevice,
23        network::virtio_net::VirtioNetDevice, virtio_input::VirtioInputDevice,
24        virtio_rng::VirtioRngDevice,
25    },
26    early_println,
27};
28
29// Static counters for device naming
30static BLOCK_COUNTER: AtomicUsize = AtomicUsize::new(0);
31static NET_COUNTER: AtomicUsize = AtomicUsize::new(0);
32static GPU_COUNTER: AtomicUsize = AtomicUsize::new(0);
33static INPUT_COUNTER: AtomicUsize = AtomicUsize::new(0);
34static RNG_COUNTER: AtomicUsize = AtomicUsize::new(0);
35
36/// Register enum for Virtio devices
37///
38/// This enum represents the registers of the Virtio device.
39/// Each variant corresponds to a specific register offset.
40/// The offsets are defined in the Virtio specification.
41/// The register offsets are used to access the device's configuration and status.
42#[derive(Debug, Clone, Copy, PartialEq, Eq)]
43pub enum Register {
44    MagicValue = 0x00,
45    Version = 0x04,
46    DeviceId = 0x08,
47    VendorId = 0x0c,
48    DeviceFeatures = 0x10,
49    DeviceFeaturesSel = 0x14,
50    DriverFeatures = 0x20,
51    DriverFeaturesSel = 0x24,
52    GuestPageSize = 0x28,
53    QueueSel = 0x30,
54    QueueNumMax = 0x34,
55    QueueNum = 0x38,
56    QueueAlign = 0x3c,
57    QueuePfn = 0x40,
58    QueueReady = 0x44,
59    QueueNotify = 0x50,
60    InterruptStatus = 0x60,
61    InterruptAck = 0x64,
62    Status = 0x70,
63    QueueDescLow = 0x80,
64    QueueDescHigh = 0x84,
65    DriverDescLow = 0x90,
66    DriverDescHigh = 0x94,
67    DeviceDescLow = 0xa0,
68    DeviceDescHigh = 0xa4,
69    DeviceConfig = 0x100,
70}
71
72impl Register {
73    pub fn offset(&self) -> usize {
74        *self as usize
75    }
76
77    pub fn from_offset(offset: usize) -> Self {
78        match offset {
79            0x00 => Register::MagicValue,
80            0x04 => Register::Version,
81            0x08 => Register::DeviceId,
82            0x0c => Register::VendorId,
83            0x10 => Register::DeviceFeatures,
84            0x14 => Register::DeviceFeaturesSel,
85            0x20 => Register::DriverFeatures,
86            0x24 => Register::DriverFeaturesSel,
87            0x28 => Register::GuestPageSize,
88            0x30 => Register::QueueSel,
89            0x34 => Register::QueueNumMax,
90            0x38 => Register::QueueNum,
91            0x3c => Register::QueueAlign,
92            0x40 => Register::QueuePfn,
93            0x44 => Register::QueueReady,
94            0x50 => Register::QueueNotify,
95            0x60 => Register::InterruptStatus,
96            0x64 => Register::InterruptAck,
97            0x70 => Register::Status,
98            0x80 => Register::QueueDescLow,
99            0x84 => Register::QueueDescHigh,
100            0x90 => Register::DriverDescLow,
101            0x94 => Register::DriverDescHigh,
102            0xa0 => Register::DeviceDescLow,
103            0xa4 => Register::DeviceDescHigh,
104            _ => panic!("Invalid register offset"),
105        }
106    }
107}
108
109/// DeviceStatus enum for Virtio devices
110///
111/// This enum represents the status of the Virtio device.
112/// Each variant corresponds to a specific status bit.
113/// The status bits are defined in the Virtio specification.
114#[derive(Debug, Clone, Copy)]
115pub enum DeviceStatus {
116    Reset = 0x00,
117    Acknowledge = 0x01,
118    Driver = 0x02,
119    DriverOK = 0x04,
120    FeaturesOK = 0x08,
121    DeviceNeedReset = 0x40,
122    Failed = 0x80,
123}
124
125impl DeviceStatus {
126    /// Check if the status is set
127    ///
128    /// This method checks if the specified status bit is set in the given status.
129    ///
130    /// # Arguments
131    ///
132    /// * `status` - The status to check.
133    ///
134    /// # Returns
135    ///
136    /// Returns true if the status bit is set, false otherwise.
137    pub fn is_set(&self, status: u32) -> bool {
138        (status & *self as u32) != 0
139    }
140
141    /// Set the status bit
142    ///
143    /// This method sets the specified status bit in the given status.
144    ///
145    /// # Arguments
146    ///
147    /// * `status` - A mutable reference to the status to modify.
148    ///
149    pub fn set(&self, status: &mut u32) {
150        *status |= *self as u32;
151    }
152
153    /// Clear the status bit
154    ///
155    /// This method clears the specified status bit in the given status.
156    ///
157    /// # Arguments
158    ///
159    /// * `status` - A mutable reference to the status to modify.
160    ///
161    pub fn clear(&self, status: &mut u32) {
162        *status &= !(*self as u32);
163    }
164
165    /// Toggle the status bit
166    ///
167    /// This method toggles the specified status bit in the given status.
168    ///
169    /// # Arguments
170    ///
171    /// * `status` - A mutable reference to the status to modify.
172    ///
173    pub fn toggle(&self, status: &mut u32) {
174        *status ^= *self as u32;
175    }
176
177    /// Convert from u32 to DeviceStatus
178    ///
179    /// This method converts a u32 value to the corresponding DeviceStatus variant.
180    ///
181    /// # Arguments
182    ///
183    /// * `status` - The u32 value to convert.
184    ///
185    /// # Returns
186    ///
187    /// Returns the corresponding DeviceStatus variant.
188    ///
189    pub fn from_u32(status: u32) -> Self {
190        match status {
191            0x00 => DeviceStatus::Reset,
192            0x01 => DeviceStatus::Acknowledge,
193            0x02 => DeviceStatus::Driver,
194            0x04 => DeviceStatus::DriverOK,
195            0x08 => DeviceStatus::FeaturesOK,
196            0x40 => DeviceStatus::DeviceNeedReset,
197            0x80 => DeviceStatus::Failed,
198            _ => panic!("Invalid device status"),
199        }
200    }
201
202    /// Convert DeviceStatus to u32
203    ///
204    /// This method converts the DeviceStatus variant to its corresponding u32 value.
205    ///
206    /// # Returns
207    ///
208    /// Returns the u32 value corresponding to the DeviceStatus variant.
209    ///
210    pub fn to_u32(&self) -> u32 {
211        *self as u32
212    }
213}
214
215/// VirtioDevice trait
216///
217/// This trait defines the interface for VirtIO devices.
218/// It provides methods for initializing the device, accessing registers,
219/// and performing device operations according to the VirtIO specification.
220pub trait VirtioDevice {
221    #[cfg(not(debug_assertions))]
222    #[inline(never)]
223    fn write32_register_slowpath(&self, addr: usize, value: u32) {
224        io_mb();
225        unsafe { crate::arch::mmio::write32(addr, value) };
226        io_mb();
227        // Some environments effectively require a read to flush a posted MMIO write.
228        // Do NOT read back the just-written register: many virtio-mmio registers are write-only
229        // (QueueNotify, queue address regs, DriverFeatures, etc.), and QEMU will warn.
230        // Reading STATUS is safe and provides a single well-defined flush point.
231        let status_addr = self.get_base_addr() + Register::Status.offset();
232        unsafe {
233            crate::arch::mmio::read32(status_addr);
234        }
235        io_mb();
236    }
237
238    fn debug_dump_mmio_state(&self, tag: &'static str) {
239        #[cfg(debug_assertions)]
240        {
241            let base = self.get_base_addr();
242            let magic = self.read32_register(Register::MagicValue);
243            let version = self.read32_register(Register::Version);
244            let device_id = self.read32_register(Register::DeviceId);
245            let vendor_id = self.read32_register(Register::VendorId);
246            let status = self.read32_register(Register::Status);
247            let isr = self.read32_register(Register::InterruptStatus);
248
249            crate::early_println!(
250                "[virtio][{}] base={:#x} magic=0x{:08x} ver={} dev_id={} vendor=0x{:08x} status=0x{:02x} isr=0x{:02x}",
251                tag,
252                base,
253                magic,
254                version,
255                device_id,
256                vendor_id,
257                status,
258                isr
259            );
260        }
261
262        #[cfg(not(debug_assertions))]
263        {
264            let _ = tag;
265        }
266    }
267
268    fn debug_log_status_transition(&self, tag: &'static str, old: u32, new: u32, readback: u32) {
269        #[cfg(debug_assertions)]
270        {
271            crate::early_println!(
272                "[virtio][{}] status: old=0x{:02x} -> write=0x{:02x} -> readback=0x{:02x}",
273                tag,
274                old,
275                new,
276                readback
277            );
278        }
279
280        #[cfg(not(debug_assertions))]
281        {
282            let _ = (tag, old, new, readback);
283        }
284    }
285
286    fn wait_for_status_zero(
287        &self,
288        tag: &'static str,
289        max_iters: usize,
290    ) -> Result<(), &'static str> {
291        // Virtio spec: after writing 0 (reset), driver should consider reset complete
292        // when it reads back status == 0.
293        for _ in 0..max_iters {
294            let status = self.read32_register(Register::Status) & 0xff;
295            if status == 0 {
296                return Ok(());
297            }
298        }
299        let final_status = self.read32_register(Register::Status) & 0xff;
300        crate::early_println!(
301            "[virtio][{}] reset wait timeout: status=0x{:02x}",
302            tag,
303            final_status
304        );
305        Err("Virtio device reset did not complete")
306    }
307
308    /// Initialize the device
309    ///
310    /// This method performs the standard VirtIO initialization sequence:
311    /// 1. Reset the device
312    /// 2. Acknowledge the device
313    /// 3. Set driver status
314    /// 4. Negotiate features
315    /// 5. Set up virtqueues
316    /// 6. Set driver OK status
317    ///
318    /// # Returns
319    ///
320    /// Returns Ok(negotiated_features) if initialization was successful,
321    /// Err message otherwise
322    fn init(&mut self) -> Result<u32, &'static str> {
323        self.debug_dump_mmio_state("init:entry");
324
325        // Verify device (Magic Value should be "virt")
326        if self.read32_register(Register::MagicValue) != 0x74726976 {
327            self.set_failed();
328            return Err("Invalid Magic Value");
329        }
330
331        // Check device version
332        let version = self.read32_register(Register::Version);
333        if version != 2 {
334            self.set_failed();
335            return Err("Invalid Version");
336        }
337
338        // Reset device
339        if let Err(e) = self.reset() {
340            self.set_failed();
341            return Err(e);
342        }
343        // self.debug_dump_mmio_state("init:after_reset");
344
345        // Acknowledge device
346        self.acknowledge();
347        self.debug_dump_mmio_state("init:after_ack");
348
349        // Set driver status
350        self.driver();
351        self.debug_dump_mmio_state("init:after_driver");
352
353        // Negotiate features
354        let negotiated_features = match self.negotiate_features() {
355            Ok(features) => features,
356            Err(e) => {
357                self.set_failed();
358                return Err(e);
359            }
360        };
361
362        // Set up virtqueues
363        for i in 0..self.get_virtqueue_count() {
364            if !self.setup_queue(i, self.get_virtqueue_size(i)) {
365                self.set_failed();
366                return Err("Failed to set up virtqueue");
367            }
368        }
369
370        // Mark driver OK
371        self.driver_ok();
372        self.debug_dump_mmio_state("init:after_driver_ok");
373        Ok(negotiated_features)
374    }
375
376    fn is_modern_device(&self) -> bool {
377        self.read32_register(Register::Version) == 2
378    }
379
380    fn supports_feature(&self, feature: u32) -> bool {
381        let selector = feature / 32;
382        let bit = feature % 32;
383        self.write32_register(Register::DeviceFeaturesSel, selector);
384        let device_features = self.read32_register(Register::DeviceFeatures);
385        (device_features & (1u32 << bit)) != 0
386    }
387
388    /// Reset the device by writing 0 to the Status register
389    fn reset(&mut self) -> Result<(), &'static str> {
390        // self.debug_dump_mmio_state("reset:before");
391
392        let _old = self.read32_register(Register::Status);
393        self.write32_register(Register::Status, 0);
394        // Ensure the write is visible to the device before we continue.
395        io_mb();
396
397        // let rb = self.read32_register(Register::Status);
398        // self.debug_log_status_transition("reset", old, 0, rb);
399
400        // Spec: wait until the device reports status==0.
401        // Use a bounded loop so we never hang permanently.
402        if cfg!(debug_assertions) {
403            early_println!("[virtio][reset] waiting for reset completion...");
404        }
405        self.wait_for_status_zero("reset", 100_000)?;
406
407        // self.debug_dump_mmio_state("reset:after");
408        Ok(())
409    }
410
411    /// Set ACKNOWLEDGE status bit
412    fn acknowledge(&mut self) {
413        let old = self.read32_register(Register::Status);
414        let mut status = old;
415        DeviceStatus::Acknowledge.set(&mut status);
416        self.write32_register(Register::Status, status);
417
418        let rb = self.read32_register(Register::Status);
419        self.debug_log_status_transition("ack", old, status, rb);
420    }
421
422    /// Set DRIVER status bit
423    fn driver(&mut self) {
424        let old = self.read32_register(Register::Status);
425        let mut status = old;
426        DeviceStatus::Driver.set(&mut status);
427        self.write32_register(Register::Status, status);
428
429        let rb = self.read32_register(Register::Status);
430        self.debug_log_status_transition("driver", old, status, rb);
431    }
432
433    /// Set DRIVER_OK status bit
434    fn driver_ok(&mut self) {
435        let old = self.read32_register(Register::Status);
436        let mut status = old;
437        DeviceStatus::DriverOK.set(&mut status);
438        self.write32_register(Register::Status, status);
439
440        let rb = self.read32_register(Register::Status);
441        self.debug_log_status_transition("driver_ok", old, status, rb);
442    }
443
444    /// Set FAILED status bit
445    fn set_failed(&mut self) {
446        let old = self.read32_register(Register::Status);
447        let mut status = old;
448        DeviceStatus::Failed.set(&mut status);
449        self.write32_register(Register::Status, status);
450
451        let rb = self.read32_register(Register::Status);
452        self.debug_log_status_transition("failed", old, status, rb);
453    }
454
455    /// Negotiate device features
456    ///
457    /// This method reads device features, selects supported features,
458    /// sets driver features, and verifies features OK status.
459    ///
460    /// # Returns
461    ///
462    /// Returns Ok(negotiated_features) if feature negotiation was successful,
463    /// Err message otherwise
464    fn negotiate_features(&mut self) -> Result<u32, &'static str> {
465        // Read device features
466        let device_features = self.read32_register(Register::DeviceFeatures);
467        // Select supported features
468        let driver_features = self.get_supported_features(device_features);
469        crate::early_println!(
470            "[virtio][feat] device_features=0x{:08x} driver_features=0x{:08x}",
471            device_features,
472            driver_features
473        );
474
475        #[cfg(test)]
476        {
477            use crate::early_println;
478            early_println!(
479                "[virtio] Negotiating features: device=0x{:x}, driver=0x{:x}",
480                device_features,
481                driver_features
482            );
483        }
484
485        // Write driver features
486        self.write32_register(Register::DriverFeatures, driver_features);
487
488        // Set FEATURES_OK status bit
489        let mut status = self.read32_register(Register::Status);
490        DeviceStatus::FeaturesOK.set(&mut status);
491        self.write32_register(Register::Status, status);
492
493        // Verify FEATURES_OK status bit
494        let final_status = self.read32_register(Register::Status);
495        let success = DeviceStatus::FeaturesOK.is_set(final_status);
496
497        #[cfg(test)]
498        {
499            use crate::early_println;
500            early_println!(
501                "[virtio] Feature negotiation result: success={}, status=0x{:x}",
502                success,
503                final_status
504            );
505        }
506
507        if success {
508            Ok(driver_features)
509        } else {
510            Err("Feature negotiation failed")
511        }
512    }
513
514    /// Get device features supported by this driver
515    ///
516    /// This method can be overridden by specific device implementations
517    /// to select which features to support.
518    ///
519    /// # Arguments
520    ///
521    /// * `device_features` - The features offered by the device
522    ///
523    /// # Returns
524    ///
525    /// The features supported by the driver
526    fn get_supported_features(&self, device_features: u32) -> u32 {
527        // By default, accept all device features
528        // Device-specific implementations should override this
529        device_features
530    }
531
532    fn allow_ring_features(&self) -> bool {
533        self.is_modern_device()
534            && self.supports_feature(crate::drivers::virtio::features::VIRTIO_F_VERSION_1)
535    }
536
537    /// Set up a virtqueue
538    ///
539    /// This method configures a virtqueue by setting the queue selection,
540    /// size, alignment, and ready status.
541    ///
542    /// # Arguments
543    ///
544    /// * `queue_idx` - The index of the queue to set up
545    ///
546    /// # Returns
547    ///
548    /// Returns true if queue setup was successful, false otherwise
549    fn setup_queue(&mut self, queue_idx: usize, queue_size: usize) -> bool {
550        if queue_idx >= self.get_virtqueue_count() {
551            return false;
552        }
553
554        // Select the queue
555        self.write32_register(Register::QueueSel, queue_idx as u32);
556        // Check if the queue is ready
557        let ready = self.read32_register(Register::QueueReady);
558        if ready != 0 {
559            return false; // Queue already set up
560        }
561
562        // Get maximum queue size
563        let queue_size_max = self.read32_register(Register::QueueNumMax);
564        if queue_size > queue_size_max as usize {
565            return false; // Requested size exceeds maximum
566        }
567
568        // Set queue size
569        self.write32_register(Register::QueueNum, queue_size as u32);
570
571        // Get queue addresses directly - safer than closures
572        let desc_addr = self.get_queue_desc_addr(queue_idx);
573        let driver_addr = self.get_queue_driver_addr(queue_idx);
574        let device_addr = self.get_queue_device_addr(queue_idx);
575
576        if desc_addr.is_none() || driver_addr.is_none() || device_addr.is_none() {
577            return false;
578        }
579
580        let desc_addr = desc_addr.unwrap();
581        let driver_addr = driver_addr.unwrap();
582        let device_addr = device_addr.unwrap();
583
584        // Set the queue descriptor address
585        let desc_addr_low = (desc_addr & 0xffffffff) as u32;
586        let desc_addr_high = (desc_addr >> 32) as u32;
587        self.write32_register(Register::QueueDescLow, desc_addr_low);
588        self.write32_register(Register::QueueDescHigh, desc_addr_high);
589
590        // Set the driver area (available ring) address
591        let driver_addr_low = (driver_addr & 0xffffffff) as u32;
592        let driver_addr_high = (driver_addr >> 32) as u32;
593        self.write32_register(Register::DriverDescLow, driver_addr_low);
594        self.write32_register(Register::DriverDescHigh, driver_addr_high);
595
596        // Set the device area (used ring) address
597        let device_addr_low = (device_addr & 0xffffffff) as u32;
598        let device_addr_high = (device_addr >> 32) as u32;
599        self.write32_register(Register::DeviceDescLow, device_addr_low);
600        self.write32_register(Register::DeviceDescHigh, device_addr_high);
601
602        // Check the status of the queue
603        let status = self.read32_register(Register::Status);
604        if DeviceStatus::Failed.is_set(status) {
605            return false; // Queue setup failed
606        }
607
608        // Mark queue as ready
609        self.write32_register(Register::QueueReady, 1);
610
611        // Check the status of the queue
612        let status = self.read32_register(Register::Status);
613        if DeviceStatus::Failed.is_set(status) {
614            return false; // Queue setup failed
615        }
616
617        true
618    }
619
620    /// Read device-specific configuration
621    ///
622    /// This method reads configuration data from the device-specific configuration space.
623    ///
624    /// # Arguments
625    ///
626    /// * `offset` - The offset within the configuration space
627    ///
628    /// # Returns
629    ///
630    /// The configuration value of type T
631    fn read_config<T: Sized>(&self, offset: usize) -> T {
632        let addr = self.get_base_addr() + Register::DeviceConfig.offset() + offset;
633        // Prefer single-instruction sized accesses for MMIO on AArch64/HVF.
634        // Fall back to byte-wise access for unusual sizes.
635        unsafe {
636            match core::mem::size_of::<T>() {
637                1 => {
638                    let v = crate::arch::mmio::read8(addr);
639                    core::mem::transmute_copy::<u8, T>(&v)
640                }
641                2 => {
642                    let v = crate::arch::mmio::read16(addr);
643                    core::mem::transmute_copy::<u16, T>(&v)
644                }
645                4 => {
646                    let v = crate::arch::mmio::read32(addr);
647                    core::mem::transmute_copy::<u32, T>(&v)
648                }
649                8 => {
650                    let v = crate::arch::mmio::read64(addr);
651                    core::mem::transmute_copy::<u64, T>(&v)
652                }
653                _ => {
654                    let mut out = core::mem::MaybeUninit::<T>::uninit();
655                    let dst = out.as_mut_ptr() as *mut u8;
656                    for i in 0..core::mem::size_of::<T>() {
657                        let b = crate::arch::mmio::read8(addr + i);
658                        core::ptr::write(dst.add(i), b);
659                    }
660                    out.assume_init()
661                }
662            }
663        }
664    }
665
666    /// Write device-specific configuration
667    ///
668    /// This method writes configuration data to the device-specific configuration space.
669    ///
670    /// # Arguments
671    ///
672    /// * `offset` - The offset within the configuration space
673    /// * `value` - The value to write
674    fn write_config<T: Sized>(&self, offset: usize, value: T) {
675        let addr = self.get_base_addr() + Register::DeviceConfig.offset() + offset;
676        // Prefer single-instruction sized accesses for MMIO on AArch64/HVF.
677        // Fall back to byte-wise access for unusual sizes.
678        unsafe {
679            match core::mem::size_of::<T>() {
680                1 => {
681                    let v = core::mem::transmute_copy::<T, u8>(&value);
682                    crate::arch::mmio::write8(addr, v);
683                }
684                2 => {
685                    let v = core::mem::transmute_copy::<T, u16>(&value);
686                    crate::arch::mmio::write16(addr, v);
687                }
688                4 => {
689                    let v = core::mem::transmute_copy::<T, u32>(&value);
690                    crate::arch::mmio::write32(addr, v);
691                }
692                8 => {
693                    let v = core::mem::transmute_copy::<T, u64>(&value);
694                    crate::arch::mmio::write64(addr, v);
695                }
696                _ => {
697                    let src = &value as *const T as *const u8;
698                    for i in 0..core::mem::size_of::<T>() {
699                        let b = core::ptr::read(src.add(i));
700                        crate::arch::mmio::write8(addr + i, b);
701                    }
702                }
703            }
704        }
705    }
706
707    /// Get device and vendor IDs
708    ///
709    /// # Returns
710    ///
711    /// A tuple containing (device_id, vendor_id)
712    fn get_device_info(&self) -> (u32, u32) {
713        let device_id = self.read32_register(Register::DeviceId);
714        let vendor_id = self.read32_register(Register::VendorId);
715        (device_id, vendor_id)
716    }
717
718    /// Get interrupt status
719    ///
720    /// # Returns
721    ///
722    /// The interrupt status register value
723    fn get_interrupt_status(&self) -> u32 {
724        self.read32_register(Register::InterruptStatus)
725    }
726
727    /// Process interrupts (polling method)
728    ///
729    /// This method checks for interrupts and acknowledges them.
730    ///
731    /// # Returns
732    ///
733    /// The interrupt status before acknowledgment
734    fn process_interrupts(&mut self) -> u32 {
735        let status = self.get_interrupt_status();
736        if status != 0 {
737            self.write32_register(Register::InterruptAck, status & 0x03);
738        }
739        status
740    }
741
742    /// Memory barrier for ensuring memory operations ordering
743    fn memory_barrier(&self) {
744        // Virtio requires ordering of normal memory (descriptor writes) vs MMIO doorbells.
745        // On RISC-V, a plain atomic fence may not order memory vs device I/O; use an I/O fence.
746        crate::arch::io_mb();
747    }
748
749    /// Notify the device about new buffers in a specified virtqueue
750    ///
751    /// This method notifies the device that new buffers are available in the specified virtqueue.
752    /// It selects the queue using the QueueSel register and then writes to the QueueNotify register.
753    ///
754    /// # Arguments
755    ///
756    /// * `virtqueue_idx` - The index of the virtqueue to notify
757    ///
758    /// # Panics
759    ///
760    /// Panics if the virtqueue index is invalid
761    fn notify(&self, virtqueue_idx: usize) {
762        if virtqueue_idx >= self.get_virtqueue_count() {
763            panic!("Invalid virtqueue index");
764        }
765        // Insert memory barrier before notification
766        io_mb();
767        self.write32_register(Register::QueueNotify, virtqueue_idx as u32);
768        io_mb();
769    }
770
771    /// Read a 32-bit value from a device register
772    ///
773    /// # Arguments
774    ///
775    /// * `register` - The register to read from
776    ///
777    /// # Returns
778    ///
779    /// The 32-bit value read from the register
780    fn read32_register(&self, register: Register) -> u32 {
781        let addr = self.get_base_addr() + register.offset();
782        io_mb();
783        let val = unsafe { crate::arch::mmio::read32(addr) };
784        io_mb();
785        val
786    }
787
788    /// Write a 32-bit value to a device register
789    ///
790    /// # Arguments
791    ///
792    /// * `register` - The register to write to
793    /// * `value` - The 32-bit value to write
794    fn write32_register(&self, register: Register, value: u32) {
795        let addr = self.get_base_addr() + register.offset();
796        // NOTE: Release builds on some environments have shown sensitivity to MMIO
797        // sequencing/posted writes. Use a non-inlined slowpath with a readback flush
798        // to reduce optimization/timing variance.
799        #[cfg(not(debug_assertions))]
800        {
801            self.write32_register_slowpath(addr, value);
802        }
803
804        #[cfg(debug_assertions)]
805        {
806            io_mb();
807            unsafe { crate::arch::mmio::write32(addr, value) };
808            io_mb();
809        }
810
811        if register == Register::Status && (value & !0xff) != 0 {
812            crate::early_println!(
813                "[virtio][WARN] writing non-8bit value to Status: 0x{:08x} (base={:#x})",
814                value,
815                self.get_base_addr()
816            );
817        }
818    }
819
820    /// Read a 64-bit value from a device register
821    ///
822    /// # Arguments
823    ///
824    /// * `register` - The register to read from
825    ///
826    /// # Returns
827    ///
828    /// The 64-bit value read from the register
829    fn read64_register(&self, register: Register) -> u64 {
830        let addr = self.get_base_addr() + register.offset();
831        io_mb();
832        let val = unsafe { crate::arch::mmio::read64(addr) };
833        io_mb();
834        val
835    }
836
837    /// Write a 64-bit value to a device register
838    ///
839    /// # Arguments
840    ///
841    /// * `register` - The register to write to
842    /// * `value` - The 64-bit value to write
843    fn write64_register(&self, register: Register, value: u64) {
844        let addr = self.get_base_addr() + register.offset();
845        io_mb();
846        unsafe { crate::arch::mmio::write64(addr, value) };
847        io_mb();
848    }
849
850    // Required methods to be implemented by specific device types
851
852    fn get_base_addr(&self) -> usize;
853    fn get_virtqueue_count(&self) -> usize;
854    fn get_virtqueue_size(&self, queue_idx: usize) -> usize;
855
856    /// Get the descriptor address for a virtqueue
857    fn get_queue_desc_addr(&self, queue_idx: usize) -> Option<u64>;
858
859    /// Get the driver area address for a virtqueue
860    fn get_queue_driver_addr(&self, queue_idx: usize) -> Option<u64>;
861
862    /// Get the device area address for a virtqueue
863    fn get_queue_device_addr(&self, queue_idx: usize) -> Option<u64>;
864}
865
866/// Device type enum for Virtio devices
867///
868/// This enum represents the different types of Virtio devices.
869/// Each variant corresponds to a specific device type.
870/// The types are defined in the Virtio specification.
871pub enum VirtioDeviceType {
872    Invalid = 0,
873    Net = 1,
874    Block = 2,
875    Console = 3,
876    Rng = 4,
877    GPU = 16,
878    Input = 18,
879}
880
881impl VirtioDeviceType {
882    /// Convert from u32 to VirtioDeviceType
883    ///
884    /// This method converts a u32 value to the corresponding VirtioDeviceType variant.
885    ///
886    /// # Arguments
887    ///
888    /// * `device_type` - The u32 value to convert.
889    ///
890    /// # Returns
891    ///
892    /// Returns the corresponding VirtioDeviceType variant.
893    pub fn from_u32(device_type: u32) -> Self {
894        match device_type {
895            0 => VirtioDeviceType::Invalid,
896            1 => VirtioDeviceType::Net,
897            2 => VirtioDeviceType::Block,
898            3 => VirtioDeviceType::Console,
899            4 => VirtioDeviceType::Rng,
900            16 => VirtioDeviceType::GPU,
901            18 => VirtioDeviceType::Input,
902            _ => panic!("Not supported device type"),
903        }
904    }
905}
906
907/// Virtio Common Device
908///
909/// Only use this struct for checking the device info.
910/// It should not be used for actual device operations.
911///
912struct VirtioDeviceCommon {
913    base_addr: usize,
914}
915
916impl VirtioDeviceCommon {
917    /// Create a new Virtio device
918    ///
919    /// # Arguments
920    ///
921    /// * `base_addr` - The base address of the device
922    ///
923    /// # Returns
924    ///
925    /// A new instance of `VirtioDeviceCommon`
926    pub fn new(base_addr: usize) -> Self {
927        Self { base_addr }
928    }
929}
930
931impl VirtioDevice for VirtioDeviceCommon {
932    fn init(&mut self) -> Result<u32, &'static str> {
933        // Initialization is not required for the common device
934        Ok(0)
935    }
936
937    fn get_base_addr(&self) -> usize {
938        self.base_addr
939    }
940
941    fn get_virtqueue_count(&self) -> usize {
942        // This should be overridden by specific device implementations
943        0
944    }
945
946    fn get_virtqueue_size(&self, _queue_idx: usize) -> usize {
947        // This should be overridden by specific device implementations
948        0
949    }
950
951    fn get_queue_desc_addr(&self, _queue_idx: usize) -> Option<u64> {
952        // This should be overridden by specific device implementations
953        None
954    }
955
956    fn get_queue_driver_addr(&self, _queue_idx: usize) -> Option<u64> {
957        // This should be overridden by specific device implementations
958        None
959    }
960
961    fn get_queue_device_addr(&self, _queue_idx: usize) -> Option<u64> {
962        // This should be overridden by specific device implementations
963        None
964    }
965}
966
967fn probe_fn(device: &PlatformDeviceInfo) -> Result<(), &'static str> {
968    let res = device.get_resources();
969    if res.is_empty() {
970        return Err("No resources found");
971    }
972
973    // Get memory region resource (res_type == PlatformDeviceResourceType::MEM)
974    let mem_res = res
975        .iter()
976        .find(|r| r.res_type == PlatformDeviceResourceType::MEM)
977        .ok_or("Memory resource not found")?;
978
979    let base_addr = mem_res.start as usize;
980
981    // Create a new Virtio device
982    let virtio_device = VirtioDeviceCommon::new(base_addr);
983    // Check device type
984    let device_type = VirtioDeviceType::from_u32(virtio_device.get_device_info().0);
985
986    match device_type {
987        VirtioDeviceType::Block => {
988            let id = BLOCK_COUNTER.fetch_add(1, Ordering::SeqCst);
989            let name = format!("vblk{}", id);
990            crate::early_println!(
991                "[Virtio] Detected Virtio Block Device at {:#x}, registering as {}",
992                base_addr,
993                name
994            );
995            let dev: Arc<dyn Device> = Arc::new(VirtioBlockDevice::new(base_addr));
996            DeviceManager::get_manager().register_device_with_name(name, dev);
997        }
998        VirtioDeviceType::Net => {
999            let id = NET_COUNTER.fetch_add(1, Ordering::SeqCst);
1000            let name = format!("veth{}", id);
1001            crate::early_println!(
1002                "[Virtio] Detected Virtio Network Device at {:#x}, registering as {}",
1003                base_addr,
1004                name
1005            );
1006            let dev = Arc::new(VirtioNetDevice::new(base_addr));
1007            dev.register_interface(&name);
1008
1009            // Register interrupt handler if IRQ resource is available
1010            if let Some(irq_resource) = device
1011                .get_resources()
1012                .iter()
1013                .find(|r| r.res_type == PlatformDeviceResourceType::IRQ)
1014            {
1015                let interrupt_id = irq_resource.start as u32;
1016                crate::early_println!("[Virtio] Net device interrupt ID: {}", interrupt_id);
1017
1018                if let Err(e) = dev.enable_interrupts(interrupt_id) {
1019                    crate::early_println!("[Virtio] Failed to enable net interrupts: {}", e);
1020                } else if let Err(e) = crate::interrupt::InterruptManager::with_manager(|mgr| {
1021                    mgr.register_interrupt_device(interrupt_id, dev.clone())
1022                }) {
1023                    crate::early_println!(
1024                        "[Virtio] Failed to register net interrupt device: {}",
1025                        e
1026                    );
1027                } else {
1028                    crate::early_println!("[Virtio] Net interrupt device registered");
1029                }
1030            } else {
1031                crate::early_println!("[Virtio] No interrupt resource found for net device");
1032            }
1033
1034            DeviceManager::get_manager().register_device_with_name(name, dev);
1035        }
1036        VirtioDeviceType::GPU => {
1037            let id = GPU_COUNTER.fetch_add(1, Ordering::SeqCst);
1038            let name = format!("vfb{}", id);
1039            crate::early_println!(
1040                "[Virtio] Detected Virtio GPU Device at {:#x}, registering as {}",
1041                base_addr,
1042                name
1043            );
1044            let dev: Arc<dyn Device> = Arc::new(VirtioGpuDevice::new(base_addr));
1045            DeviceManager::get_manager().register_device_with_name(name, dev);
1046        }
1047        VirtioDeviceType::Input => {
1048            crate::early_println!("[Virtio] Detected Virtio Input Device at {:#x}", base_addr);
1049            // Create VirtIO Input device
1050            let dev = Arc::new(VirtioInputDevice::new(base_addr));
1051
1052            // Register interrupt handler if IRQ resource is available
1053            if let Some(irq_resource) = device
1054                .get_resources()
1055                .iter()
1056                .find(|r| r.res_type == PlatformDeviceResourceType::IRQ)
1057            {
1058                let interrupt_id = irq_resource.start as u32;
1059                crate::early_println!("[Virtio] Input device interrupt ID: {}", interrupt_id);
1060
1061                // Enable interrupts
1062                if let Err(e) = dev.enable_interrupts(interrupt_id) {
1063                    crate::early_println!("[Virtio] Failed to enable input interrupts: {}", e);
1064                } else {
1065                    crate::early_println!(
1066                        "[Virtio] Input interrupts enabled (ID: {})",
1067                        interrupt_id
1068                    );
1069
1070                    // Register interrupt handler
1071                    if let Err(e) = crate::interrupt::InterruptManager::with_manager(|mgr| {
1072                        mgr.register_interrupt_device(interrupt_id, dev.clone())
1073                    }) {
1074                        crate::early_println!(
1075                            "[Virtio] Failed to register input interrupt device: {}",
1076                            e
1077                        );
1078                    } else {
1079                        crate::early_println!("[Virtio] Input interrupt device registered");
1080                    }
1081                }
1082            } else {
1083                crate::early_println!("[Virtio] No interrupt resource found for input device");
1084            }
1085
1086            // Keep device alive by registering with DeviceManager
1087            DeviceManager::get_manager().register_device(dev);
1088        }
1089        VirtioDeviceType::Rng => {
1090            let id = RNG_COUNTER.fetch_add(1, Ordering::SeqCst);
1091            crate::early_println!("[Virtio] Detected Virtio RNG Device at {:#x}", base_addr);
1092
1093            // Create and register the VirtIO RNG device as an entropy source
1094            let rng_device = Arc::new(VirtioRngDevice::new(base_addr));
1095            crate::random::RandomManager::register_entropy_source(rng_device);
1096
1097            // Register the RandomCharDevice as /dev/random (only for the first RNG device)
1098            if id == 0 {
1099                let random_char_dev: Arc<dyn Device> =
1100                    Arc::new(crate::random::RandomCharDevice::new());
1101                DeviceManager::get_manager()
1102                    .register_device_with_name("random".to_string(), random_char_dev);
1103                crate::early_println!("[Virtio] Registered /dev/random character device");
1104            }
1105        }
1106        _ => {
1107            // Unsupported device type
1108            return Err("Unsupported device type");
1109        }
1110    }
1111
1112    Ok(())
1113}
1114
1115fn remove_fn(_device: &PlatformDeviceInfo) -> Result<(), &'static str> {
1116    Ok(())
1117}
1118
1119fn register_driver() {
1120    let driver = PlatformDeviceDriver::new("virtio-mmio", probe_fn, remove_fn, vec!["virtio,mmio"]);
1121    // Register the driver with the kernel
1122    DeviceManager::get_manager().register_driver(Box::new(driver), DriverPriority::Standard)
1123}
1124
1125driver_initcall!(register_driver);
1126
1127#[cfg(test)]
1128mod tests;