virtio: add check_device_feature and ack_driver_feature for

`StandardTransport`.

Signed-off-by: Anhad Singh <andypython@protonmail.com>
This commit is contained in:
Anhad Singh
2023-06-19 16:33:00 +10:00
parent 12551d450f
commit 100ff9abd4
3 changed files with 53 additions and 15 deletions
+9 -9
View File
@@ -3,6 +3,8 @@
use core::cell::UnsafeCell;
use static_assertions::const_assert_eq;
pub mod transport;
#[derive(Debug, Copy, Clone)]
#[repr(u8)]
pub enum CfgType {
@@ -116,16 +118,14 @@ pub struct Descriptor {
const_assert_eq!(core::mem::size_of::<Descriptor>(), 16);
/// This indicates compliance with the version 1 VirtIO specification.
///
/// See `6.1 Driver Requirements: Reserved Feature Bits` section of the VirtIO
/// specification for more information.
pub const VIRTIO_F_VERSION_1: u32 = 32;
pub struct VirtQueue {}
pub struct StandardTransport {}
impl StandardTransport {
pub fn new() -> Self {
Self {}
}
}
#[derive(Debug)]
#[repr(transparent)]
pub struct VolatileCell<T> {
@@ -141,7 +141,7 @@ impl<T: Copy> VolatileCell<T> {
/// Sets the contained value.
#[inline]
pub fn set(&self, value: T) {
pub fn set(&mut self, value: T) {
unsafe { core::ptr::write_volatile(self.value.get(), value) }
}
}
+16 -6
View File
@@ -2,6 +2,8 @@ use core::ptr::NonNull;
use static_assertions::const_assert_eq;
use thiserror::Error;
use virtiod::transport::StandardTransport;
use virtiod::*;
use pcid_interface::irq_helpers::{allocate_single_interrupt_vector, read_bsp_apic_id};
@@ -14,11 +16,14 @@ use syscall::{Io, PHYSMAP_NO_CACHE, PHYSMAP_WRITE};
// TODO(andypython):
//
// cc 3.1.1 Driver Requirements: Device Initialization
// Reset the device.
// Set the ACKNOWLEDGE status bit: the guest OS has noticed the device. [done]
// Set the DRIVER status bit: the guest OS knows how to drive the device. [done]
// setup interrupts [done]
// cc 3.1.1 Driver Requirements: Device Initialization
//
// ================ Generic =================
// * Reset the device. [done]
// * Set the ACKNOWLEDGE status bit: the guest OS has noticed the device. [done]
// * Set the DRIVER status bit: the guest OS knows how to drive the device. [done]
// * setup interrupts [done]
// =============== Driver Specific===============
// Read device feature bits, and write the subset of feature bits understood by the OS and driver to the device. During this step the driver MAY read (but MUST NOT write) the device-specific configuration fields to check that it can support the device before accepting it.
// Set the FEATURES_OK status bit. The driver MUST NOT accept new feature bits after this step.
// Re-read 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.
@@ -313,7 +318,12 @@ fn deamon(_deamon: redox_daemon::Daemon) -> anyhow::Result<()> {
log::info!("virtio: using standard PCI transport");
let _transport = StandardTransport::new();
let mut transport = StandardTransport::new(pci_header, common);
// Check VirtIO version 1 compliance.
assert!(transport.check_device_feature(VIRTIO_F_VERSION_1));
transport.ack_driver_feature(VIRTIO_F_VERSION_1);
loop {}
}
+28
View File
@@ -0,0 +1,28 @@
use pcid_interface::PciHeader;
use crate::CommonCfg;
pub struct StandardTransport<'a> {
header: PciHeader,
common: &'a mut CommonCfg,
}
impl<'a> StandardTransport<'a> {
pub fn new(header: PciHeader, common: &'a mut CommonCfg) -> Self {
Self { header, common }
}
pub fn check_device_feature(&mut self, feature: u32) -> bool {
self.common.device_feature_select.set(feature >> 5);
(self.common.device_feature.get() & (1 << (feature & 31))) != 0
}
pub fn ack_driver_feature(&mut self, feature: u32) {
self.common.driver_feature_select.set(feature >> 5);
let current = self.common.driver_feature.get();
self.common
.driver_feature
.set(current | (1 << (feature & 31)));
}
}