Skip to content

Commit

Permalink
TryFrom implementation for ExceptionVector
Browse files Browse the repository at this point in the history
  • Loading branch information
mrjbom committed Oct 21, 2024
1 parent 323d46c commit 587b2fa
Showing 1 changed file with 80 additions and 0 deletions.
80 changes: 80 additions & 0 deletions src/structures/idt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use crate::registers::rflags::RFlags;
use crate::{PrivilegeLevel, VirtAddr};
use bit_field::BitField;
use bitflags::bitflags;
use core::convert::TryFrom;
use core::fmt;
use core::marker::PhantomData;
use core::ops::Bound::{Excluded, Included, Unbounded};
Expand Down Expand Up @@ -1328,6 +1329,85 @@ pub enum ExceptionVector {
Security = 0x1E,
}

/// Exception vector number is invalid
///
/// Explains the reason an exception vector number is considered invalid
#[derive(Debug)]
pub enum InvalidExceptionVectorNumber {
/// Coprocessor Segment Overrun exception is handled as part of the General Protection Fault
IsCoprocessorSegmentOverrun(u8),
/// Reserved
Reserved(u8),
/// Only the first 32 numbers can be exception numbers
NotException(u8),
}

impl fmt::Display for InvalidExceptionVectorNumber {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
InvalidExceptionVectorNumber::IsCoprocessorSegmentOverrun(exception_vector_number) => {
write!(f, "{exception_vector_number} cannot be a valid exception vector number because the Coprocessor Segment Overrun exception is handled as part of the General Protection Fault")
}
InvalidExceptionVectorNumber::Reserved(exception_vector_number) => {
write!(f, "{exception_vector_number} cannot be a valid exception vector number because it is reserved")
}
InvalidExceptionVectorNumber::NotException(exception_vector_number) => {
write!(f, "{exception_vector_number} cannot be a valid exception vector number because only the first 32 numbers can be exception numbers")
}
}
}
}

impl TryFrom<u8> for ExceptionVector {
type Error = InvalidExceptionVectorNumber;

/// Tries to convert the exception vector number to [`ExceptionVector`]
///
/// Fails if exception vector number is Coprocessor Segment Overrun, reserved or not exception vector number
fn try_from(exception_vector_number: u8) -> Result<Self, Self::Error> {
match exception_vector_number {
0x00 => Ok(Self::Division),
0x01 => Ok(Self::Debug),
0x02 => Ok(Self::NonMaskableInterrupt),
0x03 => Ok(Self::Breakpoint),
0x04 => Ok(Self::Overflow),
0x05 => Ok(Self::BoundRange),
0x06 => Ok(Self::InvalidOpcode),
0x07 => Ok(Self::DeviceNotAvailable),
0x08 => Ok(Self::Double),
0x09 => Err(InvalidExceptionVectorNumber::IsCoprocessorSegmentOverrun(
exception_vector_number,
)),
0x0A => Ok(Self::InvalidTss),
0x0B => Ok(Self::SegmentNotPresent),
0x0C => Ok(Self::Stack),
0x0D => Ok(Self::GeneralProtection),
0x0E => Ok(Self::Page),
0x0F => Err(InvalidExceptionVectorNumber::Reserved(
exception_vector_number,
)),
0x10 => Ok(Self::X87FloatingPoint),
0x11 => Ok(Self::AlignmentCheck),
0x12 => Ok(Self::MachineCheck),
0x13 => Ok(Self::SimdFloatingPoint),
0x14 => Ok(Self::Virtualization),
0x15 => Ok(Self::ControlProtection),
0x16..=0x1B => Err(InvalidExceptionVectorNumber::Reserved(
exception_vector_number,
)),
0x1C => Ok(Self::HypervisorInjection),
0x1D => Ok(Self::VmmCommunication),
0x1E => Ok(Self::Security),
0x1F => Err(InvalidExceptionVectorNumber::Reserved(
exception_vector_number,
)),
0x20..=u8::MAX => Err(InvalidExceptionVectorNumber::NotException(
exception_vector_number,
)),
}
}
}

#[cfg(all(
feature = "instructions",
feature = "abi_x86_interrupt",
Expand Down

0 comments on commit 587b2fa

Please sign in to comment.