From 23a569e6f279329828b6d80def4bd0225e772608 Mon Sep 17 00:00:00 2001 From: Ethan Budd Date: Tue, 13 Jul 2021 20:32:04 -0500 Subject: [PATCH 01/15] add a SelectorErrorCode --- src/structures/idt.rs | 66 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/src/structures/idt.rs b/src/structures/idt.rs index 0e318ead3..4b2b5bd6d 100644 --- a/src/structures/idt.rs +++ b/src/structures/idt.rs @@ -236,7 +236,7 @@ pub struct InterruptDescriptorTable { /// that loaded the segment selector resulting in the `#NP`. /// /// The vector number of the `#NP` exception is 11. - pub segment_not_present: Entry, + pub segment_not_present: Entry, /// An stack segment exception (`#SS`) can occur in the following situations: /// @@ -634,6 +634,18 @@ pub type PageFaultHandlerFunc = #[derive(Copy, Clone, Debug)] pub struct PageFaultHandlerFunc(()); +/// A Page fault 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(()); + /// 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. @@ -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); @@ -918,6 +931,57 @@ bitflags! { } } +// https://wiki.osdev.org/Exceptions#Selector_Error_Code +/// Describes a segment selector error code. +#[repr(transparent)] +pub struct SelectorErrorCode { + flags: u64, +} + +impl SelectorErrorCode { + /// When set, the exception originated externally to the processor + fn external(&self) -> bool { + self.flags.get_bit(0) + } + + /// The descriptor table where the exception occurred. + 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. + fn index(&self) -> u64 { + self.flags.get_bits(3..16) + } +} + +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 descriptor tables. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum DescriptorTable { + /// Global Descriptor Table. + Gdt, + /// Interrupt Descriptor Table. + Idt, + /// Logical Descriptor Table. + Ldt, +} + #[cfg(test)] mod test { use super::*; From 76bff62059dfb9b068991b5aa3d94de46326ccc6 Mon Sep 17 00:00:00 2001 From: Ethan Budd Date: Tue, 13 Jul 2021 22:06:31 -0500 Subject: [PATCH 02/15] remove the breaking change --- src/structures/idt.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/structures/idt.rs b/src/structures/idt.rs index 4b2b5bd6d..af36810d4 100644 --- a/src/structures/idt.rs +++ b/src/structures/idt.rs @@ -236,7 +236,7 @@ pub struct InterruptDescriptorTable { /// that loaded the segment selector resulting in the `#NP`. /// /// The vector number of the `#NP` exception is 11. - pub segment_not_present: Entry, + pub segment_not_present: Entry, /// An stack segment exception (`#SS`) can occur in the following situations: /// @@ -634,7 +634,7 @@ pub type PageFaultHandlerFunc = #[derive(Copy, Clone, Debug)] pub struct PageFaultHandlerFunc(()); -/// A Page fault handler function that pushes a selector error code. +/// 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")] From 115c419ef4eec2729c0c6fdf5a07366a57ceb64e Mon Sep 17 00:00:00 2001 From: Ethan Budd Date: Tue, 13 Jul 2021 22:08:00 -0500 Subject: [PATCH 03/15] make SelectorErrorCode methods pub --- src/structures/idt.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/structures/idt.rs b/src/structures/idt.rs index af36810d4..4bb0eac36 100644 --- a/src/structures/idt.rs +++ b/src/structures/idt.rs @@ -940,12 +940,12 @@ pub struct SelectorErrorCode { impl SelectorErrorCode { /// When set, the exception originated externally to the processor - fn external(&self) -> bool { + pub fn external(&self) -> bool { self.flags.get_bit(0) } /// The descriptor table where the exception occurred. - fn descriptor_table(&self) -> DescriptorTable { + pub fn descriptor_table(&self) -> DescriptorTable { match self.flags.get_bits(1..3) { 0b00 => DescriptorTable::Gdt, 0b01 => DescriptorTable::Idt, @@ -956,7 +956,7 @@ impl SelectorErrorCode { } /// The index of the descriptor table. - fn index(&self) -> u64 { + pub fn index(&self) -> u64 { self.flags.get_bits(3..16) } } From e52760436a85e5a1ee61137bf465a29ee7f5b1e5 Mon Sep 17 00:00:00 2001 From: Ethan Budd Date: Tue, 13 Jul 2021 22:09:31 -0500 Subject: [PATCH 04/15] Derive clone and copy for SelectorErrorCode --- src/structures/idt.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/structures/idt.rs b/src/structures/idt.rs index 4bb0eac36..54b8a0384 100644 --- a/src/structures/idt.rs +++ b/src/structures/idt.rs @@ -933,6 +933,7 @@ bitflags! { // https://wiki.osdev.org/Exceptions#Selector_Error_Code /// Describes a segment selector error code. +#[derive(Clone, Copy)] #[repr(transparent)] pub struct SelectorErrorCode { flags: u64, From 08e34168ddb1cb8724bb1f82397f08549d0e767b Mon Sep 17 00:00:00 2001 From: Ethan Budd Date: Tue, 13 Jul 2021 22:16:16 -0500 Subject: [PATCH 05/15] Make Descriptor table public say where it is used --- src/structures/idt.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/structures/idt.rs b/src/structures/idt.rs index 54b8a0384..aa8639212 100644 --- a/src/structures/idt.rs +++ b/src/structures/idt.rs @@ -972,9 +972,11 @@ impl fmt::Debug for SelectorErrorCode { } } -/// The descriptor tables. +/// The possible descriptor table values. +/// +/// Used by the [`SelectorErrorCode`] to represent where the exception occurred. #[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum DescriptorTable { +pub enum DescriptorTable { /// Global Descriptor Table. Gdt, /// Interrupt Descriptor Table. From cdc354553570be9f7acc660152047e1045c0b774 Mon Sep 17 00:00:00 2001 From: Ethan Budd Date: Tue, 13 Jul 2021 22:16:56 -0500 Subject: [PATCH 06/15] update doc comment --- src/structures/idt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/idt.rs b/src/structures/idt.rs index aa8639212..ba3b69346 100644 --- a/src/structures/idt.rs +++ b/src/structures/idt.rs @@ -940,7 +940,7 @@ pub struct SelectorErrorCode { } impl SelectorErrorCode { - /// When set, the exception originated externally to the processor + /// If this flag is set, it indicates that the exception originated externally to the processor pub fn external(&self) -> bool { self.flags.get_bit(0) } From e760408176343db3e999f5aa24d4662b76b37938 Mon Sep 17 00:00:00 2001 From: Ethan Budd Date: Fri, 16 Jul 2021 14:25:08 -0500 Subject: [PATCH 07/15] added a new to SelectorErrorCode --- src/structures/idt.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/structures/idt.rs b/src/structures/idt.rs index ba3b69346..56d01a519 100644 --- a/src/structures/idt.rs +++ b/src/structures/idt.rs @@ -940,6 +940,22 @@ pub struct SelectorErrorCode { } impl SelectorErrorCode { + /// Create a SelectorErrorCode. Returns None is any of the reserved bits (16-64) are set. + pub const fn new(value: u64) -> Option { + if value > u16::MAX as u64 { + None + } else { + Some(Self { flags: value }) + } + } + + /// Create a new SelectorErrorCode dropping any reserved bits (16-64). + pub const fn new_truncate(value: u64) -> Self { + Self { + flags: (value as u16) as u64, + } + } + /// If this flag is set, it indicates that the exception originated externally to the processor pub fn external(&self) -> bool { self.flags.get_bit(0) From fc81eabbf76532e6aa700d5fcfee05fd143cec1b Mon Sep 17 00:00:00 2001 From: Ethan Budd Date: Fri, 16 Jul 2021 14:27:02 -0500 Subject: [PATCH 08/15] Derive more --- src/structures/idt.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/structures/idt.rs b/src/structures/idt.rs index 56d01a519..85aa15ac3 100644 --- a/src/structures/idt.rs +++ b/src/structures/idt.rs @@ -933,7 +933,7 @@ bitflags! { // https://wiki.osdev.org/Exceptions#Selector_Error_Code /// Describes a segment selector error code. -#[derive(Clone, Copy)] +#[derive(Clone, Copy, PartialEq, Eq, Hash)] #[repr(transparent)] pub struct SelectorErrorCode { flags: u64, @@ -991,7 +991,7 @@ impl fmt::Debug for SelectorErrorCode { /// The possible descriptor table values. /// /// Used by the [`SelectorErrorCode`] to represent where the exception occurred. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum DescriptorTable { /// Global Descriptor Table. Gdt, From e145206869e304b7e491beeb57aa39c58d9ad2bf Mon Sep 17 00:00:00 2001 From: Ethan Budd Date: Fri, 16 Jul 2021 14:27:32 -0500 Subject: [PATCH 09/15] Update src/structures/idt.rs Co-authored-by: Joseph Richey --- src/structures/idt.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/structures/idt.rs b/src/structures/idt.rs index 85aa15ac3..f799827aa 100644 --- a/src/structures/idt.rs +++ b/src/structures/idt.rs @@ -931,8 +931,7 @@ bitflags! { } } -// https://wiki.osdev.org/Exceptions#Selector_Error_Code -/// Describes a segment selector error code. +/// Describes an error code referencing a segment selector. #[derive(Clone, Copy, PartialEq, Eq, Hash)] #[repr(transparent)] pub struct SelectorErrorCode { From 10e9f985e66f1f468311c599860baa36cccf8e03 Mon Sep 17 00:00:00 2001 From: Ethan Budd Date: Fri, 16 Jul 2021 14:27:42 -0500 Subject: [PATCH 10/15] Update src/structures/idt.rs Co-authored-by: Joseph Richey --- src/structures/idt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/idt.rs b/src/structures/idt.rs index f799827aa..8df90c63f 100644 --- a/src/structures/idt.rs +++ b/src/structures/idt.rs @@ -989,7 +989,7 @@ impl fmt::Debug for SelectorErrorCode { /// The possible descriptor table values. /// -/// Used by the [`SelectorErrorCode`] to represent where the exception occurred. +/// Used by the [`SelectorErrorCode`] to indicate which table caused the error. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum DescriptorTable { /// Global Descriptor Table. From 9f732fc1f26993ee5eb326937a3c4aae20225c16 Mon Sep 17 00:00:00 2001 From: Ethan Budd Date: Fri, 16 Jul 2021 14:27:58 -0500 Subject: [PATCH 11/15] Update src/structures/idt.rs Co-authored-by: Joseph Richey --- src/structures/idt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/idt.rs b/src/structures/idt.rs index 8df90c63f..c1ae2ebea 100644 --- a/src/structures/idt.rs +++ b/src/structures/idt.rs @@ -971,7 +971,7 @@ impl SelectorErrorCode { } } - /// The index of the descriptor table. + /// The index of the selector which caused the error. pub fn index(&self) -> u64 { self.flags.get_bits(3..16) } From e19310f9f2da657e8e5a00db07d50f99f4cb4757 Mon Sep 17 00:00:00 2001 From: Ethan Budd Date: Fri, 16 Jul 2021 14:28:46 -0500 Subject: [PATCH 12/15] Update src/structures/idt.rs Co-authored-by: Joseph Richey --- src/structures/idt.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/structures/idt.rs b/src/structures/idt.rs index c1ae2ebea..1a43dcc90 100644 --- a/src/structures/idt.rs +++ b/src/structures/idt.rs @@ -955,7 +955,8 @@ impl SelectorErrorCode { } } - /// If this flag is set, it indicates that the exception originated externally to the processor + /// If true, indicates that the exception occurred during delivery of an event + /// external to the program, such as an interrupt or an earlier exception. pub fn external(&self) -> bool { self.flags.get_bit(0) } From 8b80bad6fdbb9fcda8275eb12f362551d3cf4731 Mon Sep 17 00:00:00 2001 From: Ethan Budd Date: Fri, 16 Jul 2021 14:28:56 -0500 Subject: [PATCH 13/15] Update src/structures/idt.rs Co-authored-by: Joseph Richey --- src/structures/idt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/idt.rs b/src/structures/idt.rs index 1a43dcc90..233f30539 100644 --- a/src/structures/idt.rs +++ b/src/structures/idt.rs @@ -961,7 +961,7 @@ impl SelectorErrorCode { self.flags.get_bit(0) } - /// The descriptor table where the exception occurred. + /// The descriptor table this error code refers to. pub fn descriptor_table(&self) -> DescriptorTable { match self.flags.get_bits(1..3) { 0b00 => DescriptorTable::Gdt, From 5852d446c23a07f85f4d837c685d1bdab39ff319 Mon Sep 17 00:00:00 2001 From: Ethan Budd Date: Fri, 16 Jul 2021 14:32:09 -0500 Subject: [PATCH 14/15] remove the handler func until new release --- src/structures/idt.rs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/structures/idt.rs b/src/structures/idt.rs index 85aa15ac3..b27de884d 100644 --- a/src/structures/idt.rs +++ b/src/structures/idt.rs @@ -634,18 +634,6 @@ 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(()); - /// 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. @@ -745,7 +733,6 @@ 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); From d1552d8102674dbf06e29df3e05f377d07d7ed73 Mon Sep 17 00:00:00 2001 From: Ethan Budd Date: Fri, 16 Jul 2021 14:43:28 -0500 Subject: [PATCH 15/15] add is_null() --- src/structures/idt.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/structures/idt.rs b/src/structures/idt.rs index 93bc00178..5931f738c 100644 --- a/src/structures/idt.rs +++ b/src/structures/idt.rs @@ -963,6 +963,11 @@ impl SelectorErrorCode { pub fn index(&self) -> u64 { self.flags.get_bits(3..16) } + + /// If true, the #SS or #GP has returned zero as opposed to a SelectorErrorCode. + pub fn is_null(&self) -> bool { + self.flags == 0 + } } impl fmt::Debug for SelectorErrorCode {