Skip to content

Commit

Permalink
Merge pull request #165 from rcore-os/thiserror
Browse files Browse the repository at this point in the history
Use thiserror for error types.
  • Loading branch information
qwandor authored Nov 21, 2024
2 parents e97f718 + 2fa73a2 commit fea238e
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 140 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ log = "0.4.22"
bitflags = "2.6.0"
enumn = "0.1.14"
embedded-io = { version = "0.6.1", optional = true }
thiserror = { version = "2.0.0", default-features = false }
zerocopy = { version = "0.8.7", features = ["derive"] }

[features]
Expand Down
44 changes: 15 additions & 29 deletions src/device/socket/error.rs
Original file line number Diff line number Diff line change
@@ -1,61 +1,47 @@
//! This module contain the error from the VirtIO socket driver.

use core::{fmt, result};
use core::result;
use thiserror::Error;

/// The error type of VirtIO socket driver.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[derive(Copy, Clone, Debug, Eq, Error, PartialEq)]
pub enum SocketError {
/// There is an existing connection.
#[error("There is an existing connection. Please close the current connection before attempting to connect again.")]
ConnectionExists,
/// The device is not connected to any peer.
#[error("The device is not connected to any peer. Please connect it to a peer first.")]
NotConnected,
/// Peer socket is shutdown.
#[error("The peer socket is shutdown.")]
PeerSocketShutdown,
/// The given buffer is shorter than expected.
#[error("The given buffer is shorter than expected")]
BufferTooShort,
/// The given buffer for output is shorter than expected.
#[error("The given output buffer is too short. '{0}' bytes is needed for the output buffer.")]
OutputBufferTooShort(usize),
/// The given buffer has exceeded the maximum buffer size.
#[error("The given buffer length '{0}' has exceeded the maximum allowed buffer length '{1}'")]
BufferTooLong(usize, usize),
/// Unknown operation.
#[error("The operation code '{0}' is unknown")]
UnknownOperation(u16),
/// Invalid operation,
#[error("Invalid operation")]
InvalidOperation,
/// Invalid number.
#[error("Invalid number")]
InvalidNumber,
/// Unexpected data in packet.
#[error("No data is expected in the packet")]
UnexpectedDataInPacket,
/// Peer has insufficient buffer space, try again later.
#[error("Peer has insufficient buffer space, try again later")]
InsufficientBufferSpaceInPeer,
/// Recycled a wrong buffer.
#[error("Recycled a wrong buffer")]
RecycledWrongBuffer,
}

impl fmt::Display for SocketError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::ConnectionExists => write!(
f,
"There is an existing connection. Please close the current connection before attempting to connect again."),
Self::NotConnected => write!(f, "The device is not connected to any peer. Please connect it to a peer first."),
Self::PeerSocketShutdown => write!(f, "The peer socket is shutdown."),
Self::BufferTooShort => write!(f, "The given buffer is shorter than expected"),
Self::BufferTooLong(actual, max) => {
write!(f, "The given buffer length '{actual}' has exceeded the maximum allowed buffer length '{max}'")
}
Self::OutputBufferTooShort(expected) => {
write!(f, "The given output buffer is too short. '{expected}' bytes is needed for the output buffer.")
}
Self::UnknownOperation(op) => {
write!(f, "The operation code '{op}' is unknown")
}
Self::InvalidOperation => write!(f, "Invalid operation"),
Self::InvalidNumber => write!(f, "Invalid number"),
Self::UnexpectedDataInPacket => write!(f, "No data is expected in the packet"),
Self::InsufficientBufferSpaceInPeer => write!(f, "Peer has insufficient buffer space, try again later"),
Self::RecycledWrongBuffer => write!(f, "Recycled a wrong buffer"),
}
}
}

pub type Result<T> = result::Result<T, SocketError>;
61 changes: 18 additions & 43 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,9 @@ mod queue;
pub mod transport;
mod volatile;

use core::{
fmt::{self, Display, Formatter},
ptr::{self, NonNull},
};
use core::ptr::{self, NonNull};
use device::socket::SocketError;
use thiserror::Error;

pub use self::hal::{BufferDirection, Hal, PhysAddr};

Expand All @@ -71,30 +70,41 @@ pub const PAGE_SIZE: usize = 0x1000;
pub type Result<T = ()> = core::result::Result<T, Error>;

/// The error type of VirtIO drivers.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[derive(Copy, Clone, Debug, Eq, Error, PartialEq)]
pub enum Error {
/// There are not enough descriptors available in the virtqueue, try again later.
#[error("Virtqueue is full")]
QueueFull,
/// The device is not ready.
#[error("Device not ready")]
NotReady,
/// The device used a different descriptor chain to the one we were expecting.
#[error("Device used a different descriptor chain to the one we were expecting")]
WrongToken,
/// The queue is already in use.
#[error("Virtqueue is already in use")]
AlreadyUsed,
/// Invalid parameter.
#[error("Invalid parameter")]
InvalidParam,
/// Failed to alloc DMA memory.
/// Failed to allocate DMA memory.
#[error("Failed to allocate DMA memory")]
DmaError,
/// I/O Error
/// I/O error
#[error("I/O error")]
IoError,
/// The request was not supported by the device.
#[error("Request not supported by device")]
Unsupported,
/// The config space advertised by the device is smaller than the driver expected.
#[error("Config space advertised by the device is smaller than expected")]
ConfigSpaceTooSmall,
/// The device doesn't have any config space, but the driver expects some.
#[error("The device doesn't have any config space, but the driver expects some")]
ConfigSpaceMissing,
/// Error from the socket device.
SocketDeviceError(device::socket::SocketError),
#[error("Error from the socket device: {0}")]
SocketDeviceError(#[from] SocketError),
}

#[cfg(feature = "alloc")]
Expand All @@ -104,41 +114,6 @@ impl From<alloc::string::FromUtf8Error> for Error {
}
}

impl Display for Error {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Self::QueueFull => write!(f, "Virtqueue is full"),
Self::NotReady => write!(f, "Device not ready"),
Self::WrongToken => write!(
f,
"Device used a different descriptor chain to the one we were expecting"
),
Self::AlreadyUsed => write!(f, "Virtqueue is already in use"),
Self::InvalidParam => write!(f, "Invalid parameter"),
Self::DmaError => write!(f, "Failed to allocate DMA memory"),
Self::IoError => write!(f, "I/O Error"),
Self::Unsupported => write!(f, "Request not supported by device"),
Self::ConfigSpaceTooSmall => write!(
f,
"Config space advertised by the device is smaller than expected"
),
Self::ConfigSpaceMissing => {
write!(
f,
"The device doesn't have any config space, but the driver expects some"
)
}
Self::SocketDeviceError(e) => write!(f, "Error from the socket device: {e:?}"),
}
}
}

impl From<device::socket::SocketError> for Error {
fn from(e: device::socket::SocketError) -> Self {
Self::SocketDeviceError(e)
}
}

/// Align `size` up to a page.
fn align_up(size: usize) -> usize {
(size + PAGE_SIZE) & !(PAGE_SIZE - 1)
Expand Down
22 changes: 4 additions & 18 deletions src/transport/mmio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use crate::{
};
use core::{
convert::{TryFrom, TryInto},
fmt::{self, Display, Formatter},
mem::{align_of, size_of},
ptr::NonNull,
};
Expand Down Expand Up @@ -51,32 +50,19 @@ impl From<MmioVersion> for u32 {
}

/// An error encountered initialising a VirtIO MMIO transport.
#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Clone, Debug, Eq, Error, PartialEq)]
pub enum MmioError {
/// The header doesn't start with the expected magic value 0x74726976.
#[error("Invalid magic value {0:#010x} (expected 0x74726976)")]
BadMagic(u32),
/// The header reports a version number that is neither 1 (legacy) nor 2 (modern).
#[error("Unsupported Virtio MMIO version {0}")]
UnsupportedVersion(u32),
/// The header reports a device ID of 0.
#[error("Device ID was zero")]
ZeroDeviceId,
}

impl Display for MmioError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Self::BadMagic(magic) => write!(
f,
"Invalid magic value {:#010x} (expected 0x74726976).",
magic
),
Self::UnsupportedVersion(version) => {
write!(f, "Unsupported Virtio MMIO version {}.", version)
}
Self::ZeroDeviceId => write!(f, "Device ID was zero."),
}
}
}

/// MMIO Device Register Interface, both legacy and modern.
///
/// Ref: 4.2.2 MMIO Device Register Layout and 4.2.4 Legacy interface
Expand Down
54 changes: 13 additions & 41 deletions src/transport/pci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use crate::{
Error,
};
use core::{
fmt::{self, Display, Formatter},
mem::{align_of, size_of},
ptr::{addr_of_mut, NonNull},
};
Expand Down Expand Up @@ -431,75 +430,48 @@ fn get_bar_region_slice<H: Hal, T>(
}

/// An error encountered initialising a VirtIO PCI transport.
#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Clone, Debug, Eq, Error, PartialEq)]
pub enum VirtioPciError {
/// PCI device vender ID was not the VirtIO vendor ID.
#[error("PCI device vender ID {0:#06x} was not the VirtIO vendor ID {VIRTIO_VENDOR_ID:#06x}.")]
InvalidVendorId(u16),
/// No valid `VIRTIO_PCI_CAP_COMMON_CFG` capability was found.
#[error("No valid `VIRTIO_PCI_CAP_COMMON_CFG` capability was found.")]
MissingCommonConfig,
/// No valid `VIRTIO_PCI_CAP_NOTIFY_CFG` capability was found.
#[error("No valid `VIRTIO_PCI_CAP_NOTIFY_CFG` capability was found.")]
MissingNotifyConfig,
/// `VIRTIO_PCI_CAP_NOTIFY_CFG` capability has a `notify_off_multiplier` that is not a multiple
/// of 2.
#[error("`VIRTIO_PCI_CAP_NOTIFY_CFG` capability has a `notify_off_multiplier` that is not a multiple of 2: {0}")]
InvalidNotifyOffMultiplier(u32),
/// No valid `VIRTIO_PCI_CAP_ISR_CFG` capability was found.
#[error("No valid `VIRTIO_PCI_CAP_ISR_CFG` capability was found.")]
MissingIsrConfig,
/// An IO BAR was provided rather than a memory BAR.
#[error("Unexpected IO BAR (expected memory BAR).")]
UnexpectedIoBar,
/// A BAR which we need was not allocated an address.
#[error("Bar {0} not allocated.")]
BarNotAllocated(u8),
/// The offset for some capability was greater than the length of the BAR.
#[error("Capability offset greater than BAR length.")]
BarOffsetOutOfRange,
/// The virtual address was not aligned as expected.
#[error(
"Virtual address {vaddr:#018?} was not aligned to a {alignment} byte boundary as expected."
)]
Misaligned {
/// The virtual address in question.
vaddr: NonNull<u8>,
/// The expected alignment in bytes.
alignment: usize,
},
/// A generic PCI error,
#[error(transparent)]
Pci(PciError),
}

impl Display for VirtioPciError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Self::InvalidVendorId(vendor_id) => write!(
f,
"PCI device vender ID {:#06x} was not the VirtIO vendor ID {:#06x}.",
vendor_id, VIRTIO_VENDOR_ID
),
Self::MissingCommonConfig => write!(
f,
"No valid `VIRTIO_PCI_CAP_COMMON_CFG` capability was found."
),
Self::MissingNotifyConfig => write!(
f,
"No valid `VIRTIO_PCI_CAP_NOTIFY_CFG` capability was found."
),
Self::InvalidNotifyOffMultiplier(notify_off_multiplier) => {
write!(
f,
"`VIRTIO_PCI_CAP_NOTIFY_CFG` capability has a `notify_off_multiplier` that is not a multiple of 2: {}",
notify_off_multiplier
)
}
Self::MissingIsrConfig => {
write!(f, "No valid `VIRTIO_PCI_CAP_ISR_CFG` capability was found.")
}
Self::UnexpectedIoBar => write!(f, "Unexpected IO BAR (expected memory BAR)."),
Self::BarNotAllocated(bar_index) => write!(f, "Bar {} not allocated.", bar_index),
Self::BarOffsetOutOfRange => write!(f, "Capability offset greater than BAR length."),
Self::Misaligned { vaddr, alignment } => write!(
f,
"Virtual address {:#018?} was not aligned to a {} byte boundary as expected.",
vaddr, alignment
),
Self::Pci(pci_error) => pci_error.fmt(f),
}
}
}

impl From<PciError> for VirtioPciError {
fn from(error: PciError) -> Self {
Self::Pci(error)
Expand Down
12 changes: 3 additions & 9 deletions src/transport/pci/bus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use core::{
fmt::{self, Display, Formatter},
};
use log::warn;
use thiserror::Error;

const INVALID_READ: u32 = 0xffffffff;

Expand Down Expand Up @@ -82,20 +83,13 @@ bitflags! {
}

/// Errors accessing a PCI device.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[derive(Copy, Clone, Debug, Eq, Error, PartialEq)]
pub enum PciError {
/// The device reported an invalid BAR type.
#[error("Invalid PCI BAR type")]
InvalidBarType,
}

impl Display for PciError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Self::InvalidBarType => write!(f, "Invalid PCI BAR type."),
}
}
}

/// The root complex of a PCI bus.
#[derive(Debug)]
pub struct PciRoot {
Expand Down

0 comments on commit fea238e

Please sign in to comment.