From 74f33c0f44e3991c4fbca42227b9a91d8807ec2e Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Mon, 23 May 2016 09:02:32 +0200 Subject: [PATCH] Use own Itd entry type --- src/interrupts/idt.rs | 92 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 84 insertions(+), 8 deletions(-) diff --git a/src/interrupts/idt.rs b/src/interrupts/idt.rs index b8c68197..93ab6d75 100644 --- a/src/interrupts/idt.rs +++ b/src/interrupts/idt.rs @@ -1,22 +1,24 @@ -use x86::irq::IdtEntry; -pub struct Idt([IdtEntry; 16]); +pub struct Idt([Entry; 16]); impl Idt { pub fn new() -> Idt { - Idt([IdtEntry::missing(); 16]) + Idt([Entry::missing(); 16]) } - pub fn set_handler(&mut self, entry: usize, handler: extern fn()->!) { - let ptr = handler as usize; - self.0[entry] = IdtEntry::interrupt_gate(0x8, ptr as *const _); + pub fn set_handler(&mut self, entry: usize, handler: extern "C" fn() -> !) { + self.0[entry] = Entry::new(EntryType::InterruptGate, 0x8, handler); } - pub unsafe fn load(&self) { + pub fn set_interrupt_stack(&mut self, entry: usize, stack_index: u16) { + self.0[entry].options.set_stack_index(stack_index); + } + + pub unsafe fn load(&'static self) { use x86::dtables::{DescriptorTablePointer, lidt}; use core::mem::size_of; - let ptr = DescriptorTablePointer{ + let ptr = DescriptorTablePointer { base: self as *const _ as u64, limit: (size_of::() - 1) as u16, }; @@ -24,3 +26,77 @@ impl Idt { lidt(&ptr); } } + +use bit_field::BitField; + +#[derive(Debug, Clone, Copy)] +#[repr(C, packed)] +pub struct Entry { + target_low: u16, + gdt_selector: u16, + options: EntryOptions, + target_middle: u16, + target_high: u32, + reserved: u32, +} + +impl Entry { + pub fn missing() -> Entry { + Entry { + gdt_selector: 0, + target_low: 0, + target_middle: 0, + target_high: 0, + options: MISSING, + reserved: 0, + } + } + + pub fn new(ty: EntryType, gdt_selector: u16, handler: extern "C" fn() -> !) -> Entry { + let target = handler as u64; + + Entry { + gdt_selector: gdt_selector, + target_low: target as u16, + target_middle: (target >> 16) as u16, + target_high: (target >> 32) as u32, + options: EntryOptions::new(ty), + reserved: 0, + } + } +} + +const MISSING: EntryOptions = EntryOptions(BitField::new(0)); + +#[derive(Debug, Clone, Copy)] +pub struct EntryOptions(BitField); + +impl EntryOptions { + pub fn new(ty: EntryType) -> Self { + let mut flags = BitField::new(0); + match ty { + EntryType::InterruptGate => flags.set_range(8..12, 0b1110), + EntryType::TrapGate => flags.set_range(8..12, 0b1111), + } + // set present bit + flags.set_bit(15); + + EntryOptions(flags) + } + + pub fn set_privilege(&mut self, dpl: u16) { + assert!(dpl < 4); + self.0.set_range(13..15, dpl); + } + + pub fn set_stack_index(&mut self, index: u16) { + assert!(index < 8); + self.0.set_range(0..3, index); + } +} + +#[allow(dead_code)] +pub enum EntryType { + InterruptGate, + TrapGate, +}