kernel/drivers/virtio/device/
mod.rs1use core::result::Result;
5
6use alloc::{boxed::Box, sync::Arc, vec};
7
8use crate::{device::{manager::{DeviceManager, DriverPriority}, platform::{resource::PlatformDeviceResourceType, PlatformDeviceDriver, PlatformDeviceInfo}, Device}, driver_initcall, drivers::block::virtio_blk::VirtioBlockDevice};
9use super::queue::VirtQueue;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub enum Register {
19 MagicValue = 0x00,
20 Version = 0x04,
21 DeviceId = 0x08,
22 VendorId = 0x0c,
23 DeviceFeatures = 0x10,
24 DeviceFeaturesSel = 0x14,
25 DriverFeatures = 0x20,
26 DriverFeaturesSel = 0x24,
27 GuestPageSize = 0x28,
28 QueueSel = 0x30,
29 QueueNumMax = 0x34,
30 QueueNum = 0x38,
31 QueueAlign = 0x3c,
32 QueuePfn = 0x40,
33 QueueReady = 0x44,
34 QueueNotify = 0x50,
35 InterruptStatus = 0x60,
36 InterruptAck = 0x64,
37 Status = 0x70,
38 QueueDescLow = 0x80,
39 QueueDescHigh = 0x84,
40 DriverDescLow = 0x90,
41 DriverDescHigh = 0x94,
42 DeviceDescLow = 0xa0,
43 DeviceDescHigh = 0xa4,
44 DeviceConfig = 0x100,
45}
46
47impl Register {
48 pub fn offset(&self) -> usize {
49 *self as usize
50 }
51
52 pub fn from_offset(offset: usize) -> Self {
53 match offset {
54 0x00 => Register::MagicValue,
55 0x04 => Register::Version,
56 0x08 => Register::DeviceId,
57 0x0c => Register::VendorId,
58 0x10 => Register::DeviceFeatures,
59 0x14 => Register::DeviceFeaturesSel,
60 0x20 => Register::DriverFeatures,
61 0x24 => Register::DriverFeaturesSel,
62 0x28 => Register::GuestPageSize,
63 0x30 => Register::QueueSel,
64 0x34 => Register::QueueNumMax,
65 0x38 => Register::QueueNum,
66 0x3c => Register::QueueAlign,
67 0x40 => Register::QueuePfn,
68 0x44 => Register::QueueReady,
69 0x50 => Register::QueueNotify,
70 0x60 => Register::InterruptStatus,
71 0x64 => Register::InterruptAck,
72 0x70 => Register::Status,
73 0x80 => Register::QueueDescLow,
74 0x84 => Register::QueueDescHigh,
75 0x90 => Register::DriverDescLow,
76 0x94 => Register::DriverDescHigh,
77 0xa0 => Register::DeviceDescLow,
78 0xa4 => Register::DeviceDescHigh,
79 _ => panic!("Invalid register offset"),
80 }
81 }
82}
83
84#[derive(Debug, Clone, Copy)]
90pub enum DeviceStatus {
91 Reset = 0x00,
92 Acknowledge = 0x01,
93 Driver = 0x02,
94 DriverOK = 0x04,
95 FeaturesOK = 0x08,
96 DeviceNeedReset = 0x40,
97 Failed = 0x80,
98}
99
100impl DeviceStatus {
101 pub fn is_set(&self, status: u32) -> bool {
113 (status & *self as u32) != 0
114 }
115
116 pub fn set(&self, status: &mut u32) {
125 *status |= *self as u32;
126 }
127
128 pub fn clear(&self, status: &mut u32) {
137 *status &= !(*self as u32);
138 }
139
140 pub fn toggle(&self, status: &mut u32) {
149 *status ^= *self as u32;
150 }
151
152 pub fn from_u32(status: u32) -> Self {
165 match status {
166 0x00 => DeviceStatus::Reset,
167 0x01 => DeviceStatus::Acknowledge,
168 0x02 => DeviceStatus::Driver,
169 0x04 => DeviceStatus::DriverOK,
170 0x08 => DeviceStatus::FeaturesOK,
171 0x40 => DeviceStatus::DeviceNeedReset,
172 0x80 => DeviceStatus::Failed,
173 _ => panic!("Invalid device status"),
174 }
175 }
176
177 pub fn to_u32(&self) -> u32 {
186 *self as u32
187 }
188}
189
190pub trait VirtioDevice {
196 fn init(&mut self) -> Result<(), &'static str> {
206 if self.read32_register(Register::MagicValue) != 0x74726976 {
208 self.set_failed();
209 return Err("Invalid Magic Value");
210 }
211
212 let version = self.read32_register(Register::Version);
214 if version != 2 {
215 self.set_failed();
216 return Err("Invalid Version");
217 }
218
219 self.reset();
221
222 self.acknowledge();
224
225 self.driver();
227
228 if !self.negotiate_features() {
230 self.set_failed();
231 return Err("Feature negotiation failed");
232 }
233
234 for i in 0..self.get_virtqueue_count() {
236 if !self.setup_queue(i) {
237 self.set_failed();
238 return Err("Failed to set up virtqueue");
239 }
240 }
241
242 self.driver_ok();
244 Ok(())
245 }
246
247 fn reset(&mut self) {
249 self.write32_register(Register::Status, 0);
250 }
251
252 fn acknowledge(&mut self) {
254 let mut status = self.read32_register(Register::Status);
255 DeviceStatus::Acknowledge.set(&mut status);
256 self.write32_register(Register::Status, status);
257 }
258
259 fn driver(&mut self) {
261 let mut status = self.read32_register(Register::Status);
262 DeviceStatus::Driver.set(&mut status);
263 self.write32_register(Register::Status, status);
264 }
265
266 fn driver_ok(&mut self) {
268 let mut status = self.read32_register(Register::Status);
269 DeviceStatus::DriverOK.set(&mut status);
270 self.write32_register(Register::Status, status);
271 }
272
273 fn set_failed(&mut self) {
275 let mut status = self.read32_register(Register::Status);
276 DeviceStatus::Failed.set(&mut status);
277 self.write32_register(Register::Status, status);
278 }
279
280 fn negotiate_features(&mut self) -> bool {
289 let device_features = self.read32_register(Register::DeviceFeatures);
291 let driver_features = self.get_supported_features(device_features);
293 self.write32_register(Register::DriverFeatures, driver_features);
295
296 let mut status = self.read32_register(Register::Status);
298 DeviceStatus::FeaturesOK.set(&mut status);
299 self.write32_register(Register::Status, status);
300
301 let status = self.read32_register(Register::Status);
303 DeviceStatus::FeaturesOK.is_set(status)
304 }
305
306 fn get_supported_features(&self, device_features: u32) -> u32 {
319 device_features
322 }
323
324 fn setup_queue(&mut self, queue_idx: usize) -> bool {
337 if queue_idx >= self.get_virtqueue_count() {
338 return false;
339 }
340
341 self.write32_register(Register::QueueSel, queue_idx as u32);
343 let ready = self.read32_register(Register::QueueReady);
345 if ready != 0 {
346 return false; }
348
349 let queue_size = self.read32_register(Register::QueueNumMax);
351 if queue_size == 0 {
352 return false; }
354
355 self.write32_register(Register::QueueNum, queue_size);
357
358 let desc_addr = self.get_queue_desc_addr(queue_idx);
360 let driver_addr = self.get_queue_driver_addr(queue_idx);
361 let device_addr = self.get_queue_device_addr(queue_idx);
362
363 if desc_addr.is_none() || driver_addr.is_none() || device_addr.is_none() {
364 return false;
365 }
366
367 let desc_addr = desc_addr.unwrap();
368 let driver_addr = driver_addr.unwrap();
369 let device_addr = device_addr.unwrap();
370
371 let desc_addr_low = (desc_addr & 0xffffffff) as u32;
373 let desc_addr_high = (desc_addr >> 32) as u32;
374 self.write32_register(Register::QueueDescLow, desc_addr_low);
375 self.write32_register(Register::QueueDescHigh, desc_addr_high);
376
377 let driver_addr_low = (driver_addr & 0xffffffff) as u32;
379 let driver_addr_high = (driver_addr >> 32) as u32;
380 self.write32_register(Register::DriverDescLow, driver_addr_low);
381 self.write32_register(Register::DriverDescHigh, driver_addr_high);
382
383 let device_addr_low = (device_addr & 0xffffffff) as u32;
385 let device_addr_high = (device_addr >> 32) as u32;
386 self.write32_register(Register::DeviceDescLow, device_addr_low);
387 self.write32_register(Register::DeviceDescHigh, device_addr_high);
388
389 let status = self.read32_register(Register::Status);
391 if DeviceStatus::Failed.is_set(status) {
392 return false; }
394
395 self.write32_register(Register::QueueReady, 1);
397
398 let status = self.read32_register(Register::Status);
400 if DeviceStatus::Failed.is_set(status) {
401 return false; }
403
404 true
405 }
406
407 fn read_config<T: Sized>(&self, offset: usize) -> T {
419 let addr = self.get_base_addr() + Register::DeviceConfig.offset() + offset;
420 unsafe { core::ptr::read_volatile(addr as *const T) }
421 }
422
423 fn write_config<T: Sized>(&self, offset: usize, value: T) {
432 let addr = self.get_base_addr() + Register::DeviceConfig.offset() + offset;
433 unsafe { core::ptr::write_volatile(addr as *mut T, value) }
434 }
435
436 fn get_device_info(&self) -> (u32, u32) {
442 let device_id = self.read32_register(Register::DeviceId);
443 let vendor_id = self.read32_register(Register::VendorId);
444 (device_id, vendor_id)
445 }
446
447 fn get_interrupt_status(&self) -> u32 {
453 self.read32_register(Register::InterruptStatus)
454 }
455
456 fn process_interrupts(&mut self) -> u32 {
464 let status = self.get_interrupt_status();
465 if status != 0 {
466 self.write32_register(Register::InterruptAck, status & 0x03);
467 }
468 status
469 }
470
471 fn memory_barrier(&self) {
473 core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst);
474 }
475
476 fn notify(&self, virtqueue_idx: usize) {
489 if virtqueue_idx >= self.get_virtqueue_count() {
490 panic!("Invalid virtqueue index");
491 }
492 self.memory_barrier();
494 self.write32_register(Register::QueueNotify, virtqueue_idx as u32);
495 }
496
497 fn read32_register(&self, register: Register) -> u32 {
507 let addr = self.get_base_addr() + register.offset();
508 unsafe { core::ptr::read_volatile(addr as *const u32) }
509 }
510
511 fn write32_register(&self, register: Register, value: u32) {
518 let addr = self.get_base_addr() + register.offset();
519 unsafe { core::ptr::write_volatile(addr as *mut u32, value) }
520 }
521
522 fn read64_register(&self, register: Register) -> u64 {
532 let addr = self.get_base_addr() + register.offset();
533 unsafe { core::ptr::read_volatile(addr as *const u64) }
534 }
535
536 fn write64_register(&self, register: Register, value: u64) {
543 let addr = self.get_base_addr() + register.offset();
544 unsafe { core::ptr::write_volatile(addr as *mut u64, value) }
545 }
546
547 fn get_base_addr(&self) -> usize;
550 fn get_virtqueue_count(&self) -> usize;
551
552 fn get_queue_desc_addr(&self, queue_idx: usize) -> Option<u64>;
554
555 fn get_queue_driver_addr(&self, queue_idx: usize) -> Option<u64>;
557
558 fn get_queue_device_addr(&self, queue_idx: usize) -> Option<u64>;
560}
561
562
563pub enum VirtioDeviceType {
569 Invalid = 0,
570 Net = 1,
571 Block = 2,
572 Console = 3,
573 Rng = 4,
574}
575
576impl VirtioDeviceType {
577 pub fn from_u32(device_type: u32) -> Self {
589 match device_type {
590 0 => VirtioDeviceType::Invalid,
591 1 => VirtioDeviceType::Net,
592 2 => VirtioDeviceType::Block,
593 3 => VirtioDeviceType::Console,
594 4 => VirtioDeviceType::Rng,
595 _ => panic!("Not supported device type"),
596 }
597 }
598}
599
600struct VirtioDeviceCommon {
606 base_addr: usize,
607}
608
609impl VirtioDeviceCommon {
610 pub fn new(base_addr: usize) -> Self {
620 Self { base_addr }
621 }
622}
623
624impl VirtioDevice for VirtioDeviceCommon {
625 fn init(&mut self) -> Result<(), &'static str> {
626 Ok(())
628 }
629
630 fn get_base_addr(&self) -> usize {
631 self.base_addr
632 }
633
634 fn get_virtqueue_count(&self) -> usize {
635 0
637 }
638
639 fn get_queue_desc_addr(&self, _queue_idx: usize) -> Option<u64> {
640 None
642 }
643
644 fn get_queue_driver_addr(&self, _queue_idx: usize) -> Option<u64> {
645 None
647 }
648
649 fn get_queue_device_addr(&self, _queue_idx: usize) -> Option<u64> {
650 None
652 }
653}
654
655fn probe_fn(device: &PlatformDeviceInfo) -> Result<(), &'static str> {
656 let res = device.get_resources();
657 if res.is_empty() {
658 return Err("No resources found");
659 }
660
661 let mem_res = res.iter()
663 .find(|r| r.res_type == PlatformDeviceResourceType::MEM)
664 .ok_or("Memory resource not found")?;
665
666 let base_addr = mem_res.start as usize;
667
668 let virtio_device = VirtioDeviceCommon::new(base_addr);
670 let device_type = VirtioDeviceType::from_u32(virtio_device.get_device_info().0);
672
673 match device_type {
674 VirtioDeviceType::Block => {
675 let dev: Arc<dyn Device> = Arc::new(VirtioBlockDevice::new(base_addr));
676 DeviceManager::get_mut_manager().register_device(dev);
677 }
678 _ => {
679 return Err("Unsupported device type");
681 }
682 }
683
684 Ok(())
685}
686
687fn remove_fn(_device: &PlatformDeviceInfo) -> Result<(), &'static str> {
688 Ok(())
689}
690
691fn register_driver() {
692 let driver = PlatformDeviceDriver::new(
693 "virtio-mmio",
694 probe_fn,
695 remove_fn,
696 vec!["virtio,mmio"],
697 );
698 DeviceManager::get_mut_manager().register_driver(Box::new(driver), DriverPriority::Standard)
700}
701
702driver_initcall!(register_driver);
703
704#[cfg(test)]
705mod tests;