Skip to main content

proka_kernel/interrupts/
gdt.rs

1use lazy_static::lazy_static;
2use x86_64::structures::gdt::{Descriptor, GlobalDescriptorTable, SegmentSelector};
3use x86_64::structures::tss::TaskStateSegment;
4use x86_64::VirtAddr;
5
6pub const DOUBLE_FAULT_IST_INDEX: u16 = 0;
7
8lazy_static! {
9    static ref TSS: TaskStateSegment = {
10        let mut tss = TaskStateSegment::new();
11        tss.interrupt_stack_table[DOUBLE_FAULT_IST_INDEX as usize] = {
12            const STACK_SIZE: usize = 8192 * 5;
13            static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
14
15            let stack_start = VirtAddr::from_ptr(&raw const STACK);
16            stack_start + STACK_SIZE as u64
17        };
18        tss
19    };
20}
21
22lazy_static! {
23    static ref GDT: (GlobalDescriptorTable, Selectors) = {
24        let mut gdt = GlobalDescriptorTable::new();
25        let code_selector = gdt.append(Descriptor::kernel_code_segment());
26        let data_selector = gdt.append(Descriptor::kernel_data_segment());
27        let tss_selector = gdt.append(Descriptor::tss_segment(&TSS));
28        (
29            gdt,
30            Selectors {
31                code_selector,
32                data_selector,
33                tss_selector,
34            },
35        )
36    };
37}
38
39struct Selectors {
40    code_selector: SegmentSelector,
41    data_selector: SegmentSelector,
42    tss_selector: SegmentSelector,
43}
44
45pub fn init() {
46    use x86_64::instructions::segmentation::{Segment, CS, DS, ES, SS};
47    use x86_64::instructions::tables::load_tss;
48
49    GDT.0.load();
50    unsafe {
51        CS::set_reg(GDT.1.code_selector);
52        SS::set_reg(GDT.1.data_selector);
53        DS::set_reg(GDT.1.data_selector);
54        ES::set_reg(GDT.1.data_selector);
55        load_tss(GDT.1.tss_selector);
56    }
57}