From 1a3495bf07be31e7b6767d4b86d05ff755e012d3 Mon Sep 17 00:00:00 2001 From: German Date: Mon, 21 Oct 2024 01:26:48 +0300 Subject: [PATCH] TryFrom implementation for ExceptionVector --- src/structures/idt.rs | 81 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/src/structures/idt.rs b/src/structures/idt.rs index 4a92bacf..7d0431e4 100644 --- a/src/structures/idt.rs +++ b/src/structures/idt.rs @@ -24,7 +24,9 @@ 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::fmt::Formatter; use core::marker::PhantomData; use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ops::{ @@ -1328,6 +1330,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 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 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 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 { + 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",