Skip to content

Commit

Permalink
Merge pull request #1239 from hermit-os/interrupt-status
Browse files Browse the repository at this point in the history
refactor(virtio/mmio): migrate `IsrStatusRaw` to `virtio-spec`
  • Loading branch information
mkroening authored May 30, 2024
2 parents 6d8c840 + 0472c8b commit 1fe0476
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 41 deletions.
52 changes: 22 additions & 30 deletions src/drivers/virtio/transport/mmio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
//! The module contains ...
#![allow(dead_code)]

use core::ptr::{read_volatile, write_volatile};
use core::mem;
use core::sync::atomic::{fence, Ordering};

use virtio_spec::mmio::{
DeviceRegisterVolatileFieldAccess, DeviceRegisterVolatileWideFieldAccess, DeviceRegisters,
InterruptStatus,
};
use virtio_spec::DeviceStatus;
use volatile::VolatileRef;
Expand Down Expand Up @@ -380,56 +381,47 @@ impl NotifCtrl {
}
}

/// Wraps a [IsrStatusRaw] in order to preserve
/// Wraps a [`DeviceRegisters`] in order to preserve
/// the original structure and allow interaction with the device via
/// the structure.
///
/// Provides a safe API for Raw structure and allows interaction with the device via
/// the structure.
pub struct IsrStatus {
raw: &'static mut IsrStatusRaw,
// FIXME: integrate into device register struct
raw: VolatileRef<'static, DeviceRegisters>,
}

impl IsrStatus {
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 }
pub fn new(registers: VolatileRef<'_, DeviceRegisters>) -> Self {
let raw =
unsafe { mem::transmute::<VolatileRef<'_, _>, VolatileRef<'static, _>>(registers) };
Self { raw }
}

pub fn is_interrupt(&self) -> bool {
unsafe {
let status = read_volatile(&self.raw.interrupt_status);
status & 0x1 == 0x1
}
self.raw
.as_ptr()
.interrupt_status()
.read()
.contains(InterruptStatus::USED_BUFFER_NOTIFICATION)
}

pub fn is_cfg_change(&self) -> bool {
unsafe {
let status = read_volatile(&self.raw.interrupt_status);
status & 0x2 == 0x2
}
self.raw
.as_ptr()
.interrupt_status()
.read()
.contains(InterruptStatus::CONFIGURATION_CHANGE_NOTIFICATION)
}

pub fn acknowledge(&mut self) {
unsafe {
let status = read_volatile(&self.raw.interrupt_status);
write_volatile(&mut self.raw.interrupt_ack, status);
}
let ptr = self.raw.as_mut_ptr();
let status = ptr.interrupt_status().read();
ptr.interrupt_ack().write(status);
}
}

#[repr(C)]
struct IsrStatusRaw {
interrupt_status: u32,
interrupt_ack: u32,
}

pub(crate) enum VirtioDriver {
#[cfg(any(feature = "tcp", feature = "udp"))]
Network(VirtioNetDriver),
Expand Down
28 changes: 17 additions & 11 deletions virtio-spec/src/mmio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,19 +272,10 @@ device_register_impl! {
///
/// Reading from this register returns a bit mask of events that
/// caused the device interrupt to be asserted.
/// The following events are possible:
///
/// - Used Buffer Notification
/// - bit 0 - the interrupt was asserted
/// because the device has used a buffer
/// in at least one of the active virtual queues.
/// - Configuration Change Notification
/// - bit 1 - the interrupt was
/// asserted because the configuration of the device has changed.
#[doc(alias = "InterruptStatus")]
#[offset(0x060)]
#[access(ReadOnly)]
interrupt_status: le32,
interrupt_status: InterruptStatus,

/// Interrupt acknowledge
///
Expand All @@ -294,7 +285,7 @@ device_register_impl! {
#[doc(alias = "InterruptACK")]
#[offset(0x064)]
#[access(WriteOnly)]
interrupt_ack: le32,
interrupt_ack: InterruptStatus,

/// Device status
///
Expand Down Expand Up @@ -528,3 +519,18 @@ impl_wide_field_access! {
shm_base: shm_base_low, shm_base_high;
}
}

virtio_bitflags! {
/// Interrupt Status
pub struct InterruptStatus: u8 {
/// Used Buffer Notification
///
/// The interrupt was asserted because the device has used a buffer in at least one of the active virtual queues.
const USED_BUFFER_NOTIFICATION = 1 << 0;

/// Configuration Change Notification
///
/// The interrupt was asserted because the configuration of the device has changed.
const CONFIGURATION_CHANGE_NOTIFICATION = 1 << 1;
}
}
13 changes: 13 additions & 0 deletions virtio-spec/src/volatile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use core::marker::PhantomData;
use volatile::access::{Readable, Writable};
use volatile::VolatilePtr;

use crate::mmio::InterruptStatus;
use crate::{be32, be64, le16, le32, le64, DeviceStatus};

/// A wide volatile pointer for 64-bit fields.
Expand Down Expand Up @@ -272,7 +273,18 @@ impl OveralignedField<le32> for DeviceStatus {
}
}

impl OveralignedField<le32> for InterruptStatus {
fn from_field(field: le32) -> Self {
Self::from_bits_retain(u8::from_field(field))
}

fn into_field(self) -> le32 {
self.bits().into_field()
}
}

mod private {
use crate::mmio::InterruptStatus;
use crate::{le16, le32, DeviceStatus};

pub trait Sealed<T> {}
Expand All @@ -281,4 +293,5 @@ mod private {
impl Sealed<le32> for u8 {}
impl Sealed<le32> for le16 {}
impl Sealed<le32> for DeviceStatus {}
impl Sealed<le32> for InterruptStatus {}
}

0 comments on commit 1fe0476

Please sign in to comment.