49 lines
1.3 KiB
Rust
49 lines
1.3 KiB
Rust
|
use conquer_once::spin::Lazy;
|
||
|
use x86_64::structures::gdt::{Descriptor, GlobalDescriptorTable, SegmentSelector};
|
||
|
use x86_64::structures::tss::TaskStateSegment;
|
||
|
use x86_64::VirtAddr;
|
||
|
|
||
|
pub const DOUBLE_FAULT_IST_INDEX: u16 = 0;
|
||
|
|
||
|
static TSS: Lazy<TaskStateSegment> = Lazy::new(|| {
|
||
|
let mut tss = TaskStateSegment::new();
|
||
|
tss.interrupt_stack_table[DOUBLE_FAULT_IST_INDEX as usize] = {
|
||
|
const STACK_SIZE: usize = 4096;
|
||
|
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
|
||
|
|
||
|
let stack_start = VirtAddr::from_ptr(unsafe { &STACK });
|
||
|
let stack_end = stack_start + STACK_SIZE;
|
||
|
stack_end
|
||
|
};
|
||
|
tss
|
||
|
});
|
||
|
|
||
|
static GDT: Lazy<(GlobalDescriptorTable, Selectors)> = Lazy::new(|| {
|
||
|
let mut gdt = GlobalDescriptorTable::new();
|
||
|
let code_selector = gdt.add_entry(Descriptor::kernel_code_segment());
|
||
|
let tss_selector = gdt.add_entry(Descriptor::tss_segment(&TSS));
|
||
|
(
|
||
|
gdt,
|
||
|
Selectors {
|
||
|
code_selector,
|
||
|
tss_selector,
|
||
|
},
|
||
|
)
|
||
|
});
|
||
|
|
||
|
struct Selectors {
|
||
|
code_selector: SegmentSelector,
|
||
|
tss_selector: SegmentSelector,
|
||
|
}
|
||
|
|
||
|
pub fn init() {
|
||
|
use x86_64::instructions::segmentation::set_cs;
|
||
|
use x86_64::instructions::tables::load_tss;
|
||
|
|
||
|
GDT.0.load();
|
||
|
unsafe {
|
||
|
set_cs(GDT.1.code_selector);
|
||
|
load_tss(GDT.1.tss_selector);
|
||
|
}
|
||
|
}
|