mirror of
https://github.com/phil-opp/blog_os.git
synced 2025-12-16 22:37:49 +00:00
Use own Itd entry type
This commit is contained in:
@@ -1,22 +1,24 @@
|
|||||||
use x86::irq::IdtEntry;
|
|
||||||
|
|
||||||
pub struct Idt([IdtEntry; 16]);
|
pub struct Idt([Entry; 16]);
|
||||||
|
|
||||||
impl Idt {
|
impl Idt {
|
||||||
pub fn new() -> Idt {
|
pub fn new() -> Idt {
|
||||||
Idt([IdtEntry::missing(); 16])
|
Idt([Entry::missing(); 16])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_handler(&mut self, entry: usize, handler: extern fn()->!) {
|
pub fn set_handler(&mut self, entry: usize, handler: extern "C" fn() -> !) {
|
||||||
let ptr = handler as usize;
|
self.0[entry] = Entry::new(EntryType::InterruptGate, 0x8, handler);
|
||||||
self.0[entry] = IdtEntry::interrupt_gate(0x8, ptr as *const _);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 x86::dtables::{DescriptorTablePointer, lidt};
|
||||||
use core::mem::size_of;
|
use core::mem::size_of;
|
||||||
|
|
||||||
let ptr = DescriptorTablePointer{
|
let ptr = DescriptorTablePointer {
|
||||||
base: self as *const _ as u64,
|
base: self as *const _ as u64,
|
||||||
limit: (size_of::<Self>() - 1) as u16,
|
limit: (size_of::<Self>() - 1) as u16,
|
||||||
};
|
};
|
||||||
@@ -24,3 +26,77 @@ impl Idt {
|
|||||||
lidt(&ptr);
|
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<u16>);
|
||||||
|
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user