70 lines
1.9 KiB
Rust
70 lines
1.9 KiB
Rust
use x86_64::{
|
|
VirtAddr,
|
|
instructions::tables::load_tss,
|
|
registers::segmentation::{CS, DS, ES, SS, Segment},
|
|
structures::{
|
|
gdt::{Descriptor, GlobalDescriptorTable, SegmentSelector},
|
|
tss::TaskStateSegment,
|
|
},
|
|
};
|
|
|
|
use spin::Lazy;
|
|
|
|
pub const DOUBLE_FAULT_1ST_INDEX: u16 = 0;
|
|
|
|
static TSS: Lazy<TaskStateSegment> = 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);
|
|
|
|
stack_start + STACK_SIZE.try_into().unwrap()
|
|
};
|
|
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_code_selector,
|
|
_user_data_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);
|
|
}
|
|
}
|