Skip to content

Commit 1a0b149

Browse files
budde25josephlr
andauthored
Add a SelectorErrorCode to segment_not_present in IDT (#274)
* add a SelectorErrorCode * remove the breaking change * make SelectorErrorCode methods pub * Derive clone and copy for SelectorErrorCode * Make Descriptor table public say where it is used * update doc comment * added a new to SelectorErrorCode * Derive more * Update src/structures/idt.rs Co-authored-by: Joseph Richey <[email protected]>
1 parent 7ce4d16 commit 1a0b149

File tree

1 file changed

+75
-0
lines changed

1 file changed

+75
-0
lines changed

src/structures/idt.rs

+75
Original file line numberDiff line numberDiff line change
@@ -918,6 +918,81 @@ bitflags! {
918918
}
919919
}
920920

921+
/// Describes an error code referencing a segment selector.
922+
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
923+
#[repr(transparent)]
924+
pub struct SelectorErrorCode {
925+
flags: u64,
926+
}
927+
928+
impl SelectorErrorCode {
929+
/// Create a SelectorErrorCode. Returns None is any of the reserved bits (16-64) are set.
930+
pub const fn new(value: u64) -> Option<Self> {
931+
if value > u16::MAX as u64 {
932+
None
933+
} else {
934+
Some(Self { flags: value })
935+
}
936+
}
937+
938+
/// Create a new SelectorErrorCode dropping any reserved bits (16-64).
939+
pub const fn new_truncate(value: u64) -> Self {
940+
Self {
941+
flags: (value as u16) as u64,
942+
}
943+
}
944+
945+
/// If true, indicates that the exception occurred during delivery of an event
946+
/// external to the program, such as an interrupt or an earlier exception.
947+
pub fn external(&self) -> bool {
948+
self.flags.get_bit(0)
949+
}
950+
951+
/// The descriptor table this error code refers to.
952+
pub fn descriptor_table(&self) -> DescriptorTable {
953+
match self.flags.get_bits(1..3) {
954+
0b00 => DescriptorTable::Gdt,
955+
0b01 => DescriptorTable::Idt,
956+
0b10 => DescriptorTable::Ldt,
957+
0b11 => DescriptorTable::Idt,
958+
_ => unreachable!(),
959+
}
960+
}
961+
962+
/// The index of the selector which caused the error.
963+
pub fn index(&self) -> u64 {
964+
self.flags.get_bits(3..16)
965+
}
966+
967+
/// If true, the #SS or #GP has returned zero as opposed to a SelectorErrorCode.
968+
pub fn is_null(&self) -> bool {
969+
self.flags == 0
970+
}
971+
}
972+
973+
impl fmt::Debug for SelectorErrorCode {
974+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
975+
let mut s = f.debug_struct("Selector Error");
976+
s.field("external", &self.external());
977+
s.field("descriptor table", &self.descriptor_table());
978+
s.field("index", &self.index());
979+
s.finish()
980+
}
981+
}
982+
983+
/// The possible descriptor table values.
984+
///
985+
/// Used by the [`SelectorErrorCode`] to indicate which table caused the error.
986+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
987+
pub enum DescriptorTable {
988+
/// Global Descriptor Table.
989+
Gdt,
990+
/// Interrupt Descriptor Table.
991+
Idt,
992+
/// Logical Descriptor Table.
993+
Ldt,
994+
}
995+
921996
#[cfg(test)]
922997
mod test {
923998
use super::*;

0 commit comments

Comments
 (0)