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 slice and slice_mut methods to IDT #95

Merged
merged 8 commits into from Nov 26, 2019
87 changes: 41 additions & 46 deletions src/structures/idt.rs
Expand Up @@ -14,7 +14,8 @@ use bit_field::BitField;
use bitflags::bitflags;
use core::fmt;
use core::marker::PhantomData;
use core::ops::{Deref, Index, IndexMut};
use core::ops::Bound::{Excluded, Included, Unbounded};
use core::ops::{Deref, Index, IndexMut, RangeBounds};

/// An Interrupt Descriptor Table with 256 entries.
///
Expand Down Expand Up @@ -444,65 +445,59 @@ impl InterruptDescriptorTable {
}
}

impl Index<usize> for InterruptDescriptorTable {
type Output = Entry<HandlerFunc>;
impl<I: RangeBounds<usize>> Index<I> for InterruptDescriptorTable {
type Output = [Entry<HandlerFunc>];

/// Returns the IDT entry with the specified index.
///
/// Panics if index is outside the IDT (i.e. greater than 255) or if the entry is an
/// exception that pushes an error code (use the struct fields for accessing these entries).
fn index(&self, index: usize) -> &Self::Output {
match index {
0 => &self.divide_by_zero,
1 => &self.debug,
2 => &self.non_maskable_interrupt,
3 => &self.breakpoint,
4 => &self.overflow,
5 => &self.bound_range_exceeded,
6 => &self.invalid_opcode,
7 => &self.device_not_available,
9 => &self.coprocessor_segment_overrun,
16 => &self.x87_floating_point,
18 => &self.machine_check,
19 => &self.simd_floating_point,
20 => &self.virtualization,
i @ 32..=255 => &self.interrupts[i - 32],
i @ 15 | i @ 31 | i @ 21..=29 => panic!("entry {} is reserved", i),
i @ 8 | i @ 10..=14 | i @ 17 | i @ 30 => {
panic!("entry {} is an exception with error code", i)
}
i => panic!("no entry with index {}", i),
fn index(&self, index: I) -> &Self::Output {
let lower_idx = match index.start_bound() {
Included(start) => *start,
Excluded(start) => *start + 1,
Unbounded => 32,
Copy link
Member

Choose a reason for hiding this comment

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

I would prefer to error in this case because it would be confusing that ..256 is a smaller range than 0..256.

};
let upper_idx = match index.end_bound() {
Included(end) => *end + 1,
Excluded(end) => *end,
Unbounded => 255,
};

if lower_idx > 255 || upper_idx > 255 {
panic!("Index out of range [{}..{}]", lower_idx, upper_idx);
}
if lower_idx < 32 {
panic!("Cannot return slice from traps, faults, and exception handlers");
}
&self.interrupts[(lower_idx - 32)..(upper_idx - 32)]
}
}

impl IndexMut<usize> for InterruptDescriptorTable {
impl<I: RangeBounds<usize>> IndexMut<I> for InterruptDescriptorTable {
/// Returns a mutable reference to the IDT entry with the specified index.
///
/// Panics if index is outside the IDT (i.e. greater than 255) or if the entry is an
/// exception that pushes an error code (use the struct fields for accessing these entries).
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
match index {
0 => &mut self.divide_by_zero,
1 => &mut self.debug,
2 => &mut self.non_maskable_interrupt,
3 => &mut self.breakpoint,
4 => &mut self.overflow,
5 => &mut self.bound_range_exceeded,
6 => &mut self.invalid_opcode,
7 => &mut self.device_not_available,
9 => &mut self.coprocessor_segment_overrun,
16 => &mut self.x87_floating_point,
18 => &mut self.machine_check,
19 => &mut self.simd_floating_point,
20 => &mut self.virtualization,
i @ 32..=255 => &mut self.interrupts[i - 32],
i @ 15 | i @ 31 | i @ 21..=29 => panic!("entry {} is reserved", i),
i @ 8 | i @ 10..=14 | i @ 17 | i @ 30 => {
panic!("entry {} is an exception with error code", i)
}
i => panic!("no entry with index {}", i),
fn index_mut(&mut self, index: I) -> &mut Self::Output {
let lower_idx = match index.start_bound() {
Included(start) => *start,
Excluded(start) => *start + 1,
Unbounded => 32,
Copy link
Member

Choose a reason for hiding this comment

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

Unbounded should be equivalent to 0 for an usize range so that 0..100 and ..100 have the same effect.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Doh, I had this right, then ended up copying the mistake back in during my multiple refactors.

};
let upper_idx = match index.end_bound() {
Included(end) => *end + 1,
Excluded(end) => *end,
Unbounded => 255,
};

if lower_idx > 255 || upper_idx > 255 {
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't this be 256 since the upper bound is excluded so that 32..256 is a valid range?

panic!("Index out of range [{}..{}]", lower_idx, upper_idx);
}
if lower_idx < 32 {
panic!("Cannot return slice from traps, faults, and exception handlers");
}
&mut self.interrupts[(lower_idx - 32)..(upper_idx - 32)]
}
}

Expand Down