1use core::fmt;
2
3use lazyinit::LazyInit;
4use x86_64::addr::VirtAddr;
5use x86_64::structures::DescriptorTablePointer;
6use x86_64::structures::idt::{Entry, HandlerFunc, InterruptDescriptorTable};
7
8const NUM_INT: usize = 256;
9
10static IDT: LazyInit<IdtStruct> = LazyInit::new();
11
12#[repr(transparent)]
14pub struct IdtStruct {
15 table: InterruptDescriptorTable,
16}
17
18impl IdtStruct {
19 #[allow(clippy::new_without_default)]
22 pub fn new() -> Self {
23 unsafe extern "C" {
24 #[link_name = "trap_handler_table"]
25 static ENTRIES: [extern "C" fn(); NUM_INT];
26 }
27 let mut idt = Self {
28 table: InterruptDescriptorTable::new(),
29 };
30
31 let entries = unsafe {
32 core::slice::from_raw_parts_mut(
33 &mut idt.table as *mut _ as *mut Entry<HandlerFunc>,
34 NUM_INT,
35 )
36 };
37 for i in 0..NUM_INT {
38 #[allow(clippy::missing_transmute_annotations)]
39 let opt = entries[i].set_handler_fn(unsafe { core::mem::transmute(ENTRIES[i]) });
40 if i == 0x3 || i == 0x80 {
41 opt.set_privilege_level(x86_64::PrivilegeLevel::Ring3);
43 }
44 }
45 idt
46 }
47
48 pub fn pointer(&self) -> DescriptorTablePointer {
51 DescriptorTablePointer {
52 base: VirtAddr::new(&self.table as *const _ as u64),
53 limit: (core::mem::size_of::<InterruptDescriptorTable>() - 1) as u16,
54 }
55 }
56
57 pub unsafe fn load(&'static self) {
64 self.table.load();
65 }
66}
67
68impl fmt::Debug for IdtStruct {
69 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
70 f.debug_struct("IdtStruct")
71 .field("pointer", &self.pointer())
72 .field("table", &self.table)
73 .finish()
74 }
75}
76
77pub fn init_idt() {
79 IDT.call_once(IdtStruct::new);
80 unsafe { IDT.load() };
81}