2016-08-14 02:58:31 +02:00
|
|
|
use core::mem;
|
|
|
|
|
2016-08-17 02:04:15 +02:00
|
|
|
use interrupt::halt;
|
|
|
|
|
2016-08-14 02:58:31 +02:00
|
|
|
pub static mut IDTR: IdtDescriptor = IdtDescriptor {
|
|
|
|
size: 0,
|
|
|
|
offset: 0
|
|
|
|
};
|
|
|
|
|
|
|
|
pub static mut IDT: [IdtEntry; 256] = [IdtEntry::new(); 256];
|
|
|
|
|
2016-08-16 02:37:58 +02:00
|
|
|
pub unsafe fn init() {
|
|
|
|
for entry in IDT[0..32].iter_mut() {
|
2016-08-15 19:29:53 +02:00
|
|
|
entry.set_flags(IDT_PRESENT | IDT_RING_0 | IDT_INTERRUPT);
|
2016-08-16 02:37:58 +02:00
|
|
|
entry.set_offset(8, exception as usize);
|
|
|
|
}
|
2016-08-17 02:04:15 +02:00
|
|
|
IDT[13].set_offset(8, protection_fault as usize);
|
|
|
|
IDT[14].set_offset(8, page_fault as usize);
|
2016-08-16 02:37:58 +02:00
|
|
|
for entry in IDT[32..].iter_mut() {
|
|
|
|
entry.set_flags(IDT_PRESENT | IDT_RING_0 | IDT_INTERRUPT);
|
|
|
|
entry.set_offset(8, blank as usize);
|
2016-08-15 19:29:53 +02:00
|
|
|
}
|
|
|
|
IDTR.set_slice(&IDT);
|
|
|
|
IDTR.load();
|
|
|
|
}
|
|
|
|
|
2016-08-16 02:37:58 +02:00
|
|
|
interrupt!(blank, {
|
|
|
|
asm!("xchg bx, bx" : : : : "intel", "volatile");
|
|
|
|
println!("INTERRUPT");
|
|
|
|
});
|
|
|
|
|
|
|
|
interrupt!(exception, {
|
2016-08-17 02:04:15 +02:00
|
|
|
println!("EXCEPTION");
|
|
|
|
loop {
|
|
|
|
halt();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
interrupt_error!(protection_fault, {
|
|
|
|
println!("PROTECTION FAULT");
|
|
|
|
loop {
|
|
|
|
halt();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
interrupt_error!(page_fault, {
|
|
|
|
println!("PAGE FAULT");
|
|
|
|
loop {
|
|
|
|
halt();
|
|
|
|
}
|
2016-08-16 02:37:58 +02:00
|
|
|
});
|
|
|
|
|
2016-08-14 17:31:35 +02:00
|
|
|
bitflags! {
|
|
|
|
pub flags IdtFlags: u8 {
|
|
|
|
const IDT_PRESENT = 1 << 7,
|
|
|
|
const IDT_RING_0 = 0 << 5,
|
|
|
|
const IDT_RING_1 = 1 << 5,
|
|
|
|
const IDT_RING_2 = 2 << 5,
|
|
|
|
const IDT_RING_3 = 3 << 5,
|
|
|
|
const IDT_SS = 1 << 4,
|
|
|
|
const IDT_INTERRUPT = 0xE,
|
|
|
|
const IDT_TRAP = 0xF,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-14 02:58:31 +02:00
|
|
|
#[repr(packed)]
|
|
|
|
pub struct IdtDescriptor {
|
2016-08-14 17:31:35 +02:00
|
|
|
size: u16,
|
|
|
|
offset: u64
|
2016-08-14 02:58:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl IdtDescriptor {
|
|
|
|
pub fn set_slice(&mut self, slice: &'static [IdtEntry]) {
|
|
|
|
self.size = (slice.len() * mem::size_of::<IdtEntry>() - 1) as u16;
|
|
|
|
self.offset = slice.as_ptr() as u64;
|
|
|
|
}
|
2016-08-14 17:31:35 +02:00
|
|
|
|
|
|
|
pub unsafe fn load(&self) {
|
|
|
|
asm!("lidt [rax]" : : "{rax}"(self as *const _ as usize) : : "intel", "volatile");
|
|
|
|
}
|
2016-08-14 02:58:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
|
|
#[repr(packed)]
|
|
|
|
pub struct IdtEntry {
|
2016-08-14 17:31:35 +02:00
|
|
|
offsetl: u16,
|
|
|
|
selector: u16,
|
|
|
|
zero: u8,
|
|
|
|
attribute: u8,
|
|
|
|
offsetm: u16,
|
|
|
|
offseth: u32,
|
|
|
|
zero2: u32
|
2016-08-14 02:58:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl IdtEntry {
|
|
|
|
pub const fn new() -> IdtEntry {
|
|
|
|
IdtEntry {
|
|
|
|
offsetl: 0,
|
|
|
|
selector: 0,
|
|
|
|
zero: 0,
|
|
|
|
attribute: 0,
|
|
|
|
offsetm: 0,
|
|
|
|
offseth: 0,
|
|
|
|
zero2: 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-14 17:31:35 +02:00
|
|
|
pub fn set_flags(&mut self, flags: IdtFlags) {
|
|
|
|
self.attribute = flags.bits;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_offset(&mut self, selector: u16, base: usize) {
|
|
|
|
self.selector = selector;
|
2016-08-14 02:58:31 +02:00
|
|
|
self.offsetl = base as u16;
|
|
|
|
self.offsetm = (base >> 16) as u16;
|
|
|
|
self.offseth = (base >> 32) as u32;
|
|
|
|
}
|
|
|
|
}
|