Skip to content

Commit

Permalink
add memory barriers to check virtio features
Browse files Browse the repository at this point in the history
  • Loading branch information
stlankes committed Jun 3, 2023
1 parent 5b7b6c2 commit ae66622
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/arch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,26 @@ pub use crate::arch::x86_64::kernel::{
#[cfg(target_arch = "x86_64")]
pub use crate::arch::x86_64::*;

/// Force strict CPU ordering, serializes load and store operations.
#[cfg(target_arch = "aarch64")]
#[inline(always)]
pub(crate) fn memory_barrier() {
use core::arch::asm;
unsafe {
asm!("dmb ish", options(nostack, preserves_flags),);
}
}

/// Force strict CPU ordering, serializes load and store operations.
#[cfg(target_arch = "x86_64")]
#[inline(always)]
pub(crate) fn memory_barrier() {
use core::arch::asm;
unsafe {
asm!("mfence", options(nostack, preserves_flags),);
}
}

pub fn init_drivers() {
// Initialize PCI Drivers for x86_64
#[cfg(feature = "pci")]
Expand Down
16 changes: 16 additions & 0 deletions src/drivers/virtio/transport/pci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use core::mem;
use core::result::Result;

use crate::arch::kernel::interrupts::*;
use crate::arch::memory_barrier;
use crate::arch::mm::PhysAddr;
use crate::arch::pci::PciConfigRegion;
use crate::drivers::error::DriverError;
Expand Down Expand Up @@ -463,32 +464,37 @@ impl ComCfg {

/// Resets the device status field to zero.
pub fn reset_dev(&mut self) {
memory_barrier();
self.com_cfg.device_status = 0;
}

/// 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) {
memory_barrier();
self.com_cfg.device_status = u8::from(device::Status::FAILED);
}

/// Sets the ACKNOWLEDGE bit in the device status field. This indicates, the
/// OS has notived the device
pub fn ack_dev(&mut self) {
memory_barrier();
self.com_cfg.device_status |= u8::from(device::Status::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) {
memory_barrier();
self.com_cfg.device_status |= u8::from(device::Status::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) {
memory_barrier();
self.com_cfg.device_status |= u8::from(device::Status::FEATURES_OK);
}

Expand All @@ -499,6 +505,7 @@ 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 {
memory_barrier();
self.com_cfg.device_status & u8::from(device::Status::FEATURES_OK)
== u8::from(device::Status::FEATURES_OK)
}
Expand All @@ -507,21 +514,27 @@ impl ComCfg {
///
/// After this call, the device is "live"!
pub fn drv_ok(&mut self) {
memory_barrier();
self.com_cfg.device_status |= u8::from(device::Status::DRIVER_OK);
}

/// Returns the features offered by the device. Coded in a 64bit value.
pub fn dev_features(&mut self) -> u64 {
use core::arch::asm;

// Indicate device to show high 32 bits in device_feature field.
// See Virtio specification v1.1. - 4.1.4.3
memory_barrier();
self.com_cfg.device_feature_select = 1;
memory_barrier();

// read high 32 bits of device features
let mut dev_feat = u64::from(self.com_cfg.device_feature) << 32;

// Indicate device to show low 32 bits in device_feature field.
// See Virtio specification v1.1. - 4.1.4.3
self.com_cfg.device_feature_select = 0;
memory_barrier();

// read low 32 bits of device features
dev_feat |= u64::from(self.com_cfg.device_feature);
Expand All @@ -536,14 +549,17 @@ impl ComCfg {

// Indicate to device that driver_features field shows low 32 bits.
// See Virtio specification v1.1. - 4.1.4.3
memory_barrier();
self.com_cfg.driver_feature_select = 0;
memory_barrier();

// write low 32 bits of device features
self.com_cfg.driver_feature = low;

// Indicate to device that driver_features field shows high 32 bits.
// See Virtio specification v1.1. - 4.1.4.3
self.com_cfg.driver_feature_select = 1;
memory_barrier();

// write high 32 bits of device features
self.com_cfg.driver_feature = high;
Expand Down

0 comments on commit ae66622

Please sign in to comment.