use x86_64::{ instructions::tables::load_tss, registers::segmentation::{Segment, CS, DS, ES, SS}, structures::{ gdt::{Descriptor, GlobalDescriptorTable, SegmentSelector}, tss::TaskStateSegment, }, VirtAddr, }; use spin::Lazy; pub const DOUBLE_FAULT_1ST_INDEX: u16 = 0; static TSS: Lazy = Lazy::new(|| { let mut tss = TaskStateSegment::new(); tss.interrupt_stack_table[DOUBLE_FAULT_1ST_INDEX as usize] = { const STACK_SIZE: usize = 4096 * 8; static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE]; let stack_start = VirtAddr::from_ptr(&raw const STACK); let stack_end = stack_start + STACK_SIZE.try_into().unwrap(); stack_end }; tss }); static GDT: Lazy<(GlobalDescriptorTable, Selectors)> = Lazy::new(|| { let mut gdt = GlobalDescriptorTable::new(); let code_selector = gdt.append(Descriptor::kernel_code_segment()); let data_selector = gdt.append(Descriptor::kernel_data_segment()); let user_code_selector = gdt.append(Descriptor::user_code_segment()); let user_data_selector = gdt.append(Descriptor::user_data_segment()); let tss_selector = gdt.append(Descriptor::tss_segment(&TSS)); ( gdt, Selectors { code_selector, data_selector, user_code_selector, user_data_selector, tss_selector, }, ) }); struct Selectors { code_selector: SegmentSelector, data_selector: SegmentSelector, user_code_selector: SegmentSelector, user_data_selector: SegmentSelector, tss_selector: SegmentSelector, } pub fn init() { GDT.0.load(); unsafe { CS::set_reg(GDT.1.code_selector); load_tss(GDT.1.tss_selector); DS::set_reg(self::GDT.1.data_selector); ES::set_reg(self::GDT.1.data_selector); SS::set_reg(self::GDT.1.data_selector); } }