Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a SelectorErrorCode to segment_not_present in IDT #274

Merged
merged 16 commits into from
Jul 17, 2021
67 changes: 67 additions & 0 deletions src/structures/idt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,18 @@ pub type PageFaultHandlerFunc =
#[derive(Copy, Clone, Debug)]
pub struct PageFaultHandlerFunc(());

/// A segment not present handler function that pushes a selector error code.
///
/// This type alias is only usable with the `abi_x86_interrupt` feature enabled.
#[cfg(feature = "abi_x86_interrupt")]
pub type SegmentNotPresentHandlerFunc =
extern "x86-interrupt" fn(InterruptStackFrame, error_code: SelectorErrorCode);

/// This type is not usable without the `abi_x86_interrupt` feature.
#[cfg(not(feature = "abi_x86_interrupt"))]
#[derive(Copy, Clone, Debug)]
pub struct SegmentNotPresentHandlerFunc(());

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove (for now). Also when we add this back, note that the #NP exception isn't the only exception that uses this error code.

#TS, #NP: SelectorErrorCode
#SS, #GP: SelectorErrorCode or zero (depending on context)
#AC, #DF: Error code always 0

#PF, #CP, #VC, #SX: Custom error code

/// A handler function that must not return, e.g. for a machine check exception.
///
/// This type alias is only usable with the `abi_x86_interrupt` feature enabled.
Expand Down Expand Up @@ -733,6 +745,7 @@ macro_rules! impl_set_handler_fn {
impl_set_handler_fn!(HandlerFunc);
impl_set_handler_fn!(HandlerFuncWithErrCode);
impl_set_handler_fn!(PageFaultHandlerFunc);
impl_set_handler_fn!(SegmentNotPresentHandlerFunc);
impl_set_handler_fn!(DivergingHandlerFunc);
impl_set_handler_fn!(DivergingHandlerFuncWithErrCode);

Expand Down Expand Up @@ -918,6 +931,60 @@ bitflags! {
}
}

// https://wiki.osdev.org/Exceptions#Selector_Error_Code
/// Describes a segment selector error code.
budde25 marked this conversation as resolved.
Show resolved Hide resolved
#[derive(Clone, Copy)]
budde25 marked this conversation as resolved.
Show resolved Hide resolved
#[repr(transparent)]
pub struct SelectorErrorCode {
budde25 marked this conversation as resolved.
Show resolved Hide resolved
flags: u64,
}

impl SelectorErrorCode {
budde25 marked this conversation as resolved.
Show resolved Hide resolved
/// If this flag is set, it indicates that the exception originated externally to the processor
budde25 marked this conversation as resolved.
Show resolved Hide resolved
pub fn external(&self) -> bool {
self.flags.get_bit(0)
}

/// The descriptor table where the exception occurred.
budde25 marked this conversation as resolved.
Show resolved Hide resolved
pub fn descriptor_table(&self) -> DescriptorTable {
match self.flags.get_bits(1..3) {
0b00 => DescriptorTable::Gdt,
0b01 => DescriptorTable::Idt,
0b10 => DescriptorTable::Ldt,
0b11 => DescriptorTable::Idt,
_ => unreachable!(),
}
}

/// The index of the descriptor table.
budde25 marked this conversation as resolved.
Show resolved Hide resolved
pub fn index(&self) -> u64 {
self.flags.get_bits(3..16)
}
}
budde25 marked this conversation as resolved.
Show resolved Hide resolved

impl fmt::Debug for SelectorErrorCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut s = f.debug_struct("Selector Error");
s.field("external", &self.external());
s.field("descriptor table", &self.descriptor_table());
s.field("index", &self.index());
s.finish()
}
}

/// The possible descriptor table values.
///
/// Used by the [`SelectorErrorCode`] to represent where the exception occurred.
budde25 marked this conversation as resolved.
Show resolved Hide resolved
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
budde25 marked this conversation as resolved.
Show resolved Hide resolved
pub enum DescriptorTable {
/// Global Descriptor Table.
Gdt,
/// Interrupt Descriptor Table.
Idt,
/// Logical Descriptor Table.
Ldt,
}

#[cfg(test)]
mod test {
use super::*;
Expand Down