From edbf1dfb21fe76407e5c1c88a117a1a961dea899 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Tue, 28 May 2024 19:18:49 +0200 Subject: [PATCH] refactor(virtio/mmio): migrate `MmioRegisterLayout` to `virtio-spec` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/arch/riscv64/kernel/devicetree.rs | 20 +- src/arch/x86_64/kernel/mmio.rs | 21 +- src/drivers/net/virtio_mmio.rs | 24 +- src/drivers/virtio/transport/mmio.rs | 306 +++++++++----------------- 4 files changed, 148 insertions(+), 223 deletions(-) diff --git a/src/arch/riscv64/kernel/devicetree.rs b/src/arch/riscv64/kernel/devicetree.rs index 6e51c66f05..71b00378a6 100644 --- a/src/arch/riscv64/kernel/devicetree.rs +++ b/src/arch/riscv64/kernel/devicetree.rs @@ -1,4 +1,11 @@ +#[cfg(all(feature = "tcp", not(feature = "pci")))] +use core::ptr::NonNull; + use fdt::Fdt; +#[cfg(all(feature = "tcp", not(feature = "pci")))] +use virtio_spec::mmio::{DeviceRegisterVolatileFieldAccess, DeviceRegisters}; +#[cfg(all(feature = "tcp", not(feature = "pci")))] +use volatile::VolatileRef; #[cfg(feature = "gem-net")] use crate::arch::mm::VirtAddr; @@ -9,11 +16,11 @@ use crate::arch::riscv64::kernel::mmio::MmioDriver; use crate::arch::riscv64::mm::{paging, PhysAddr}; #[cfg(feature = "gem-net")] use crate::drivers::net::gem; +#[cfg(all(feature = "tcp", not(feature = "pci")))] +use crate::drivers::virtio::transport::mmio::DevId; #[cfg(all(feature = "tcp", not(feature = "pci"), not(feature = "gem-net")))] use crate::drivers::virtio::transport::mmio::{self as mmio_virtio, VirtioDriver}; #[cfg(all(feature = "tcp", not(feature = "pci")))] -use crate::drivers::virtio::transport::mmio::{DevId, MmioRegisterLayout}; -#[cfg(all(feature = "tcp", not(feature = "pci")))] use crate::kernel::mmio::register_driver; static mut PLATFORM_MODEL: Model = Model::Unknown; @@ -184,10 +191,11 @@ pub fn init_drivers() { ); // Verify the first register value to find out if this is really an MMIO magic-value. - let mmio = &mut *(virtio_region.starting_address as *mut MmioRegisterLayout); + let ptr = virtio_region.starting_address as *mut DeviceRegisters; + let mmio = VolatileRef::new(NonNull::new(ptr).unwrap()); - let magic = mmio.get_magic_value(); - let version = mmio.get_version(); + let magic = mmio.as_ptr().magic_value().read().to_ne(); + let version = mmio.as_ptr().version().read().to_ne(); const MMIO_MAGIC_VALUE: u32 = 0x74726976; if magic != MMIO_MAGIC_VALUE { @@ -201,7 +209,7 @@ pub fn init_drivers() { trace!("Found a MMIO-device at {mmio:p}"); // Verify the device-ID to find the network card - let id = mmio.get_device_id(); + let id = DevId::from(mmio.as_ptr().device_id().read().to_ne()); if id != DevId::VIRTIO_DEV_ID_NET { debug!("It's not a network card at {mmio:p}"); diff --git a/src/arch/x86_64/kernel/mmio.rs b/src/arch/x86_64/kernel/mmio.rs index c9a721339c..95329b6177 100644 --- a/src/arch/x86_64/kernel/mmio.rs +++ b/src/arch/x86_64/kernel/mmio.rs @@ -1,9 +1,12 @@ use alloc::string::String; use alloc::vec::Vec; +use core::ptr::NonNull; use core::{ptr, str}; use align_address::Align; use hermit_sync::{without_interrupts, InterruptTicketMutex}; +use virtio_spec::mmio::{DeviceRegisterVolatileFieldAccess, DeviceRegisters}; +use volatile::VolatileRef; use crate::arch::x86_64::mm::paging::{ BasePageSize, PageSize, PageTableEntryFlags, PageTableEntryFlagsExt, @@ -11,7 +14,7 @@ use crate::arch::x86_64::mm::paging::{ use crate::arch::x86_64::mm::{paging, PhysAddr}; use crate::drivers::net::virtio_net::VirtioNetDriver; use crate::drivers::virtio::transport::mmio as mmio_virtio; -use crate::drivers::virtio::transport::mmio::{DevId, MmioRegisterLayout, VirtioDriver}; +use crate::drivers::virtio::transport::mmio::{DevId, VirtioDriver}; use crate::env; pub const MAGIC_VALUE: u32 = 0x74726976; @@ -36,12 +39,12 @@ impl MmioDriver { } } -unsafe fn check_ptr(ptr: *mut u8) -> Option<&'static mut MmioRegisterLayout> { +unsafe fn check_ptr(ptr: *mut u8) -> Option> { // Verify the first register value to find out if this is really an MMIO magic-value. - let mmio = unsafe { ptr.cast::().as_mut().unwrap() }; + let mmio = unsafe { VolatileRef::new(NonNull::new(ptr.cast::()).unwrap()) }; - let magic = mmio.get_magic_value(); - let version = mmio.get_version(); + let magic = mmio.as_ptr().magic_value().read().to_ne(); + let version = mmio.as_ptr().version().read().to_ne(); if magic != MAGIC_VALUE { trace!("It's not a MMIO-device at {mmio:p}"); @@ -57,7 +60,7 @@ unsafe fn check_ptr(ptr: *mut u8) -> Option<&'static mut MmioRegisterLayout> { trace!("Found a MMIO-device at {mmio:p}"); // Verify the device-ID to find the network card - let id = mmio.get_device_id(); + let id = DevId::from(mmio.as_ptr().device_id().read().to_ne()); if id != DevId::VIRTIO_DEV_ID_NET { trace!("It's not a network card at {mmio:p}"); @@ -69,7 +72,7 @@ unsafe fn check_ptr(ptr: *mut u8) -> Option<&'static mut MmioRegisterLayout> { fn check_linux_args( linux_mmio: &'static [String], -) -> Result<(&'static mut MmioRegisterLayout, u8), &'static str> { +) -> Result<(VolatileRef<'static, DeviceRegisters>, u8), &'static str> { let virtual_address = crate::arch::mm::virtualmem::allocate(BasePageSize::SIZE as usize).unwrap(); @@ -123,7 +126,7 @@ fn check_linux_args( Err("Network card not found!") } -fn guess_device() -> Result<(&'static mut MmioRegisterLayout, u8), &'static str> { +fn guess_device() -> Result<(VolatileRef<'static, DeviceRegisters>, u8), &'static str> { // Trigger page mapping in the first iteration! let mut current_page = 0; let virtual_address = @@ -175,7 +178,7 @@ fn guess_device() -> Result<(&'static mut MmioRegisterLayout, u8), &'static str> /// Tries to find the network device within the specified address range. /// Returns a reference to it within the Ok() if successful or an Err() on failure. -fn detect_network() -> Result<(&'static mut MmioRegisterLayout, u8), &'static str> { +fn detect_network() -> Result<(VolatileRef<'static, DeviceRegisters>, u8), &'static str> { let linux_mmio = env::mmio(); if !linux_mmio.is_empty() { diff --git a/src/drivers/net/virtio_mmio.rs b/src/drivers/net/virtio_mmio.rs index f99e33a7dd..674e434372 100644 --- a/src/drivers/net/virtio_mmio.rs +++ b/src/drivers/net/virtio_mmio.rs @@ -4,17 +4,18 @@ use alloc::rc::Rc; use alloc::vec::Vec; -use core::ptr; use core::ptr::read_volatile; use core::str::FromStr; use core::sync::atomic::{fence, Ordering}; use smoltcp::phy::ChecksumCapabilities; +use virtio_spec::mmio::{DeviceRegisterVolatileFieldAccess, DeviceRegisters}; +use volatile::VolatileRef; use crate::drivers::net::virtio_net::constants::Status; use crate::drivers::net::virtio_net::{CtrlQueue, NetDevCfg, RxQueues, TxQueues, VirtioNetDriver}; use crate::drivers::virtio::error::{VirtioError, VirtioNetError}; -use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, MmioRegisterLayout, NotifCfg}; +use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, NotifCfg}; use crate::drivers::virtio::virtqueue::Virtq; /// Virtio's network device configuration structure. @@ -110,18 +111,25 @@ impl NetDevCfgRaw { impl VirtioNetDriver { pub fn new( dev_id: u16, - registers: &'static mut MmioRegisterLayout, + mut registers: VolatileRef<'static, DeviceRegisters>, irq: u8, ) -> Result { - let dev_cfg_raw: &'static NetDevCfgRaw = - unsafe { &*(ptr::with_exposed_provenance(ptr::from_ref(registers).addr() + 0xFC)) }; + let dev_cfg_raw: &'static NetDevCfgRaw = unsafe { + &*registers + .borrow_mut() + .as_mut_ptr() + .config_generation() + .as_raw_ptr() + .cast::() + .as_ptr() + }; let dev_cfg = NetDevCfg { raw: dev_cfg_raw, dev_id, features: virtio_spec::net::F::empty(), }; - let isr_stat = IsrStatus::new(registers); - let notif_cfg = NotifCfg::new(registers); + let isr_stat = IsrStatus::new(registers.borrow_mut()); + let notif_cfg = NotifCfg::new(registers.borrow_mut()); let mtu = if let Some(my_mtu) = hermit_var!("HERMIT_MTU") { u16::from_str(&my_mtu).unwrap() @@ -159,7 +167,7 @@ impl VirtioNetDriver { /// [VirtioNetDriver](structs.virtionetdriver.html) or an [VirtioError](enums.virtioerror.html). pub fn init( dev_id: u16, - registers: &'static mut MmioRegisterLayout, + registers: VolatileRef<'static, DeviceRegisters>, irq_no: u8, ) -> Result { if let Ok(mut drv) = VirtioNetDriver::new(dev_id, registers, irq_no) { diff --git a/src/drivers/virtio/transport/mmio.rs b/src/drivers/virtio/transport/mmio.rs index 1706c904d7..9a75eeb8ad 100644 --- a/src/drivers/virtio/transport/mmio.rs +++ b/src/drivers/virtio/transport/mmio.rs @@ -3,11 +3,14 @@ //! The module contains ... #![allow(dead_code)] -use core::ptr; use core::ptr::{read_volatile, write_volatile}; use core::sync::atomic::{fence, Ordering}; +use virtio_spec::mmio::{ + DeviceRegisterVolatileFieldAccess, DeviceRegisterVolatileWideFieldAccess, DeviceRegisters, +}; use virtio_spec::DeviceStatus; +use volatile::VolatileRef; #[cfg(any(feature = "tcp", feature = "udp"))] use crate::arch::kernel::interrupts::*; @@ -60,15 +63,16 @@ impl From for DevId { pub struct VqCfgHandler<'a> { vq_index: u16, - raw: &'a mut MmioRegisterLayout, + raw: VolatileRef<'a, DeviceRegisters>, } impl<'a> VqCfgHandler<'a> { // TODO: Create type for queue selected invariant to get rid of `self.select_queue()` everywhere. fn select_queue(&mut self) { - unsafe { - write_volatile(&mut self.raw.queue_sel, self.vq_index.into()); - } + self.raw + .as_mut_ptr() + .queue_sel() + .write(self.vq_index.into()) } /// Sets the size of a given virtqueue. In case the provided size exceeds the maximum allowed @@ -77,46 +81,30 @@ impl<'a> VqCfgHandler<'a> { /// Returns the set size in form of a `u16`. pub fn set_vq_size(&mut self, size: u16) -> u16 { self.select_queue(); + let ptr = self.raw.as_mut_ptr(); - unsafe { - let num_max = u16::try_from(read_volatile(&self.raw.queue_num_max)).unwrap(); - let size = size.min(num_max); - write_volatile(&mut self.raw.queue_num, size.into()); - size - } + let num_max = ptr.queue_num_max().read().to_ne(); + let size = size.min(num_max); + ptr.queue_num().write(size.into()); + size } pub fn set_ring_addr(&mut self, addr: PhysAddr) { self.select_queue(); - unsafe { - write_volatile(&mut self.raw.queue_desc_low, addr.as_u64() as u32); - write_volatile(&mut self.raw.queue_desc_high, (addr.as_u64() >> 32) as u32); - } + self.raw.as_mut_ptr().queue_desc().write(addr.0.into()); } pub fn set_drv_ctrl_addr(&mut self, addr: PhysAddr) { self.select_queue(); - unsafe { - write_volatile(&mut self.raw.queue_driver_low, addr.as_u64() as u32); - write_volatile( - &mut self.raw.queue_driver_high, - (addr.as_u64() >> 32) as u32, - ); - } + self.raw.as_mut_ptr().queue_driver().write(addr.0.into()); } pub fn set_dev_ctrl_addr(&mut self, addr: PhysAddr) { self.select_queue(); - unsafe { - write_volatile(&mut self.raw.queue_device_low, addr.as_u64() as u32); - write_volatile( - &mut self.raw.queue_device_high, - (addr.as_u64() >> 32) as u32, - ); - } + self.raw.as_mut_ptr().queue_device().write(addr.0.into()); } pub fn notif_off(&mut self) -> u16 { @@ -127,9 +115,7 @@ impl<'a> VqCfgHandler<'a> { pub fn enable_queue(&mut self) { self.select_queue(); - unsafe { - write_volatile(&mut self.raw.queue_ready, 1u32); - } + self.raw.as_mut_ptr().queue_ready().write(true); } } @@ -139,9 +125,8 @@ impl<'a> VqCfgHandler<'a> { /// Provides a safe API for the raw structure and allows interaction with the device via /// the structure. pub struct ComCfg { - // References the raw structure in PCI memory space. Is static as - // long as the device is present, which is mandatory in order to let this code work. - com_cfg: &'static mut MmioRegisterLayout, + // FIXME: remove 'static lifetime + com_cfg: VolatileRef<'static, DeviceRegisters>, /// Preferences of the device for this config. From 1 (highest) to 2^7-1 (lowest) rank: u8, @@ -149,7 +134,7 @@ pub struct ComCfg { // Public Interface of ComCfg impl ComCfg { - pub fn new(raw: &'static mut MmioRegisterLayout, rank: u8) -> Self { + pub fn new(raw: VolatileRef<'static, DeviceRegisters>, rank: u8) -> Self { ComCfg { com_cfg: raw, rank } } @@ -163,89 +148,72 @@ impl ComCfg { } else { Some(VqCfgHandler { vq_index: index, - raw: self.com_cfg, + raw: self.com_cfg.borrow_mut(), }) } } pub fn get_max_queue_size(&mut self, sel: u16) -> u16 { - unsafe { - write_volatile(&mut self.com_cfg.queue_sel, u32::from(sel)); - read_volatile(&self.com_cfg.queue_num_max) - .try_into() - .unwrap() - } + let ptr = self.com_cfg.as_mut_ptr(); + ptr.queue_sel().write(sel.into()); + ptr.queue_num_max().read().to_ne() } - pub fn get_queue_ready(&mut self, sel: u32) -> bool { - unsafe { - write_volatile(&mut self.com_cfg.queue_sel, sel); - read_volatile(&self.com_cfg.queue_ready) != 0 - } + pub fn get_queue_ready(&mut self, sel: u16) -> bool { + let ptr = self.com_cfg.as_mut_ptr(); + ptr.queue_sel().write(sel.into()); + ptr.queue_ready().read() } /// Returns the device status field. pub fn dev_status(&self) -> u8 { - unsafe { read_volatile(&self.com_cfg.status).try_into().unwrap() } + self.com_cfg.as_ptr().status().read().bits() } /// Resets the device status field to zero. pub fn reset_dev(&mut self) { - unsafe { - write_volatile( - &mut self.com_cfg.status, - DeviceStatus::empty().bits().into(), - ); - } + self.com_cfg + .as_mut_ptr() + .status() + .write(DeviceStatus::empty()); } /// Sets the device status field to FAILED. /// A driver MUST NOT initialize and use the device any further after this. /// A driver MAY use the device again after a proper reset of the device. pub fn set_failed(&mut self) { - unsafe { - write_volatile(&mut self.com_cfg.status, DeviceStatus::FAILED.bits().into()); - } + self.com_cfg + .as_mut_ptr() + .status() + .write(DeviceStatus::FAILED); } /// Sets the ACKNOWLEDGE bit in the device status field. This indicates, the /// OS has notived the device pub fn ack_dev(&mut self) { - unsafe { - let status = - DeviceStatus::from_bits(read_volatile(&self.com_cfg.status) as u8).unwrap(); - write_volatile( - &mut self.com_cfg.status, - (status | DeviceStatus::ACKNOWLEDGE).bits().into(), - ); - } + self.com_cfg + .as_mut_ptr() + .status() + .update(|status| status | DeviceStatus::ACKNOWLEDGE); } /// Sets the DRIVER bit in the device status field. This indicates, the OS /// know how to run this device. pub fn set_drv(&mut self) { - unsafe { - let status = - DeviceStatus::from_bits(read_volatile(&self.com_cfg.status) as u8).unwrap(); - write_volatile( - &mut self.com_cfg.status, - (status | DeviceStatus::DRIVER).bits().into(), - ); - } + self.com_cfg + .as_mut_ptr() + .status() + .update(|status| status | DeviceStatus::DRIVER); } /// Sets the FEATURES_OK bit in the device status field. /// /// Drivers MUST NOT accept new features after this step. pub fn features_ok(&mut self) { - unsafe { - let status = - DeviceStatus::from_bits(read_volatile(&self.com_cfg.status) as u8).unwrap(); - write_volatile( - &mut self.com_cfg.status, - (status | DeviceStatus::FEATURES_OK).bits().into(), - ); - } + self.com_cfg + .as_mut_ptr() + .status() + .update(|status| status | DeviceStatus::FEATURES_OK); } /// In order to correctly check feature negotiaten, this function @@ -255,88 +223,79 @@ impl ComCfg { /// Re-reads device status to ensure the FEATURES_OK bit is still set: /// otherwise, the device does not support our subset of features and the device is unusable. pub fn check_features(&self) -> bool { - unsafe { - let status = - DeviceStatus::from_bits(read_volatile(&self.com_cfg.status) as u8).unwrap(); - status.contains(DeviceStatus::FEATURES_OK) - } + self.com_cfg + .as_ptr() + .status() + .read() + .contains(DeviceStatus::FEATURES_OK) } /// Sets the DRIVER_OK bit in the device status field. /// /// After this call, the device is "live"! pub fn drv_ok(&mut self) { - unsafe { - let status = - DeviceStatus::from_bits(read_volatile(&self.com_cfg.status) as u8).unwrap(); - write_volatile( - &mut self.com_cfg.status, - (status | DeviceStatus::DRIVER_OK).bits().into(), - ); - } + self.com_cfg + .as_mut_ptr() + .status() + .update(|status| status | DeviceStatus::DRIVER_OK); } /// Returns the features offered by the device. pub fn dev_features(&mut self) -> virtio_spec::F { + let ptr = self.com_cfg.as_mut_ptr(); + // Indicate device to show high 32 bits in device_feature field. // See Virtio specification v1.1. - 4.1.4.3 - unsafe { - write_volatile(&mut self.com_cfg.device_features_sel, 1u32); + ptr.device_features_sel().write(1.into()); - // read high 32 bits of device features - let mut device_features = u64::from(read_volatile(&self.com_cfg.device_features)) << 32; + // read high 32 bits of device features + let mut device_features = u64::from(ptr.device_features().read().to_ne()) << 32; - // Indicate device to show low 32 bits in device_feature field. - // See Virtio specification v1.1. - 4.1.4.3 - write_volatile(&mut self.com_cfg.device_features_sel, 0u32); + // Indicate device to show low 32 bits in device_feature field. + // See Virtio specification v1.1. - 4.1.4.3 + ptr.device_features_sel().write(0.into()); - // read low 32 bits of device features - device_features |= u64::from(read_volatile(&self.com_cfg.device_features)); + // read low 32 bits of device features + device_features |= u64::from(ptr.device_features().read().to_ne()); - virtio_spec::F::from_bits_retain(u128::from(device_features).into()) - } + virtio_spec::F::from_bits_retain(u128::from(device_features).into()) } /// Write selected features into driver_select field. pub fn set_drv_features(&mut self, features: virtio_spec::F) { + let ptr = self.com_cfg.as_mut_ptr(); + let features = features.bits().to_ne() as u64; let high: u32 = (features >> 32) as u32; let low: u32 = features as u32; - unsafe { - // Indicate to device that driver_features field shows low 32 bits. - // See Virtio specification v1.1. - 4.1.4.3 - write_volatile(&mut self.com_cfg.driver_features_sel, 0u32); + // Indicate to device that driver_features field shows low 32 bits. + // See Virtio specification v1.1. - 4.1.4.3 + ptr.driver_features_sel().write(0.into()); - // write low 32 bits of device features - write_volatile(&mut self.com_cfg.driver_features, low); + // write low 32 bits of device features + ptr.driver_features().write(low.into()); - // Indicate to device that driver_features field shows high 32 bits. - // See Virtio specification v1.1. - 4.1.4.3 - write_volatile(&mut self.com_cfg.driver_features_sel, 1u32); + // Indicate to device that driver_features field shows high 32 bits. + // See Virtio specification v1.1. - 4.1.4.3 + ptr.driver_features_sel().write(1.into()); - // write high 32 bits of device features - write_volatile(&mut self.com_cfg.driver_features, high); - } + // write high 32 bits of device features + ptr.driver_features().write(high.into()); } pub fn print_information(&mut self) { + let ptr = self.com_cfg.as_ptr(); + infoheader!(" MMIO RREGISTER LAYOUT INFORMATION "); - infoentry!("Device version", "{:#X}", self.com_cfg.get_version()); - infoentry!("Device ID", "{:?}", unsafe { - read_volatile(&self.com_cfg.device_id) - }); - infoentry!("Vendor ID", "{:#X}", unsafe { - read_volatile(&self.com_cfg.vendor_id) - }); + infoentry!("Device version", "{:#X}", ptr.version().read()); + infoentry!("Device ID", "{:?}", ptr.device_id().read()); + infoentry!("Vendor ID", "{:#X}", ptr.vendor_id().read()); infoentry!("Device Features", "{:#X}", self.dev_features()); - infoentry!("Interrupt status", "{:#X}", unsafe { - read_volatile(&self.com_cfg.interrupt_status) - }); - infoentry!("Device status", "{:#X}", unsafe { - read_volatile(&self.com_cfg.status) - }); + let ptr = self.com_cfg.as_ptr(); + infoentry!("Interrupt status", "{:#X}", ptr.interrupt_status().read()); + infoentry!("Device status", "{:#X}", ptr.status().read()); infofooter!(); } @@ -350,8 +309,13 @@ pub struct NotifCfg { } impl NotifCfg { - pub fn new(registers: &mut MmioRegisterLayout) -> Self { - let raw = ptr::from_mut(&mut registers.queue_notify); + pub fn new(mut registers: VolatileRef<'_, DeviceRegisters>) -> Self { + let raw = registers + .as_mut_ptr() + .queue_notify() + .as_raw_ptr() + .as_ptr() + .cast(); NotifCfg { queue_notify: raw } } @@ -427,8 +391,12 @@ pub struct IsrStatus { } impl IsrStatus { - pub fn new(registers: &mut MmioRegisterLayout) -> Self { - let ptr = ptr::from_mut(&mut registers.interrupt_status); + pub fn new(mut registers: VolatileRef<'_, DeviceRegisters>) -> Self { + let ptr = registers + .as_mut_ptr() + .interrupt_status() + .as_raw_ptr() + .as_ptr(); let raw: &'static mut IsrStatusRaw = unsafe { &mut *(ptr as *mut IsrStatusRaw) }; IsrStatus { raw } @@ -469,12 +437,12 @@ pub(crate) enum VirtioDriver { #[allow(unused_variables)] pub(crate) fn init_device( - registers: &'static mut MmioRegisterLayout, + registers: VolatileRef<'static, DeviceRegisters>, irq_no: u8, ) -> Result { let dev_id: u16 = 0; - if registers.version == 0x1 { + if registers.as_ptr().version().read().to_ne() == 0x1 { error!("Legacy interface isn't supported!"); return Err(DriverError::InitVirtioDevFail( VirtioError::DevNotSupported(dev_id), @@ -482,7 +450,7 @@ pub(crate) fn init_device( } // Verify the device-ID to find the network card - match registers.device_id { + match registers.as_ptr().device_id().read().to_ne().into() { #[cfg(any(feature = "tcp", feature = "udp"))] DevId::VIRTIO_DEV_ID_NET => { match VirtioNetDriver::init(dev_id, registers, irq_no) { @@ -510,65 +478,3 @@ pub(crate) fn init_device( } } } - -/// The Layout of MMIO Device -#[repr(C, align(4))] -pub struct MmioRegisterLayout { - magic_value: u32, - version: u32, - device_id: DevId, - vendor_id: u32, - - device_features: u32, - device_features_sel: u32, - _reserved0: [u32; 2], - driver_features: u32, - driver_features_sel: u32, - - guest_page_size: u32, // legacy only - _reserved1: u32, - - queue_sel: u32, - queue_num_max: u32, - queue_num: u32, - queue_align: u32, // legacy only - queue_pfn: u32, // legacy only - queue_ready: u32, // non-legacy only - _reserved2: [u32; 2], - queue_notify: u32, - _reserved3: [u32; 3], - - interrupt_status: u32, - interrupt_ack: u32, - _reserved4: [u32; 2], - - status: u32, - _reserved5: [u32; 3], - - queue_desc_low: u32, // non-legacy only - queue_desc_high: u32, // non-legacy only - _reserved6: [u32; 2], - queue_driver_low: u32, // non-legacy only - queue_driver_high: u32, // non-legacy only - _reserved7: [u32; 2], - queue_device_low: u32, // non-legacy only - queue_device_high: u32, // non-legacy only - _reserved8: [u32; 21], - - config_generation: u32, // non-legacy only - config: [u32; 3], -} - -impl MmioRegisterLayout { - pub fn get_magic_value(&self) -> u32 { - unsafe { read_volatile(&self.magic_value) } - } - - pub fn get_version(&self) -> u32 { - unsafe { read_volatile(&self.version) } - } - - pub fn get_device_id(&self) -> DevId { - unsafe { read_volatile(&self.device_id) } - } -}