Create interrupt module with IDT submodule

This commit is contained in:
Philipp Oppermann
2016-05-28 15:22:18 +02:00
parent 245125cb4a
commit b84c5822df
4 changed files with 110 additions and 2 deletions

103
src/interrupts/idt.rs Normal file
View File

@@ -0,0 +1,103 @@
use x86::segmentation::{self, SegmentSelector};
pub struct Idt([Entry; 16]);
impl Idt {
pub fn new() -> Idt {
Idt([Entry::missing(); 16])
}
pub fn set_handler(&mut self, entry: u8, handler: HandlerFunc) -> &mut EntryOptions {
self.0[entry as usize] = Entry::new(segmentation::cs(), handler);
&mut self.0[entry as usize].options
}
pub fn load(&'static self) {
use x86::dtables::{DescriptorTablePointer, lidt};
use core::mem::size_of;
let ptr = DescriptorTablePointer {
base: self as *const _ as u64,
limit: (size_of::<Self>() - 1) as u16,
};
unsafe { lidt(&ptr) };
}
}
#[derive(Debug, Clone, Copy)]
#[repr(C, packed)]
pub struct Entry {
pointer_low: u16,
gdt_selector: SegmentSelector,
options: EntryOptions,
pointer_middle: u16,
pointer_high: u32,
reserved: u32,
}
type HandlerFunc = extern "C" fn() -> !;
impl Entry {
fn new(gdt_selector: SegmentSelector, handler: HandlerFunc) -> Self {
let pointer = handler as u64;
Entry {
gdt_selector: gdt_selector,
pointer_low: pointer as u16,
pointer_middle: (pointer >> 16) as u16,
pointer_high: (pointer >> 32) as u32,
options: EntryOptions::new(),
reserved: 0,
}
}
fn missing() -> Self {
Entry {
gdt_selector: SegmentSelector::new(0),
pointer_low: 0,
pointer_middle: 0,
pointer_high: 0,
options: EntryOptions::minimal(),
reserved: 0,
}
}
}
use bit_field::BitField;
#[derive(Debug, Clone, Copy)]
pub struct EntryOptions(BitField<u16>);
impl EntryOptions {
fn minimal() -> Self {
let mut options = BitField::new(0);
options.set_range(9..12, 0b111); // 'must-be-one' bits
EntryOptions(options)
}
fn new() -> Self {
let mut options = Self::minimal();
options.set_present(true).disable_interrupts(true);
options
}
fn set_present(&mut self, present: bool) -> &mut Self {
self.0.set_bit(15, present);
self
}
fn disable_interrupts(&mut self, disable: bool) -> &mut Self {
self.0.set_bit(8, !disable);
self
}
fn set_privilege_level(&mut self, dpl: u16) -> &mut Self {
self.0.set_range(13..15, dpl);
self
}
fn set_stack_index(&mut self, index: u16) -> &mut Self {
self.0.set_range(0..3, index);
self
}
}

1
src/interrupts/mod.rs Normal file
View File

@@ -0,0 +1 @@
mod idt;