1
0
Fork 0
ableos/kernel/src/arch/x86_64/gdt.rs

77 lines
2.2 KiB
Rust

use spin::Lazy;
use x86_64::{
structures::{
gdt::{Descriptor, GlobalDescriptorTable, SegmentSelector},
tss::TaskStateSegment,
},
VirtAddr,
};
pub const DOUBLE_FAULT_IX: u16 = 0;
pub unsafe fn init() {
use x86_64::instructions::segmentation::{Segment, CS, DS, ES, SS};
use x86_64::instructions::tables::load_tss;
log::info!("Initialising GDT");
GDT.0.load();
CS::set_reg(GDT.1.kcode);
DS::set_reg(GDT.1.kdata);
ES::set_reg(GDT.1.kdata);
SS::set_reg(GDT.1.kdata);
load_tss(GDT.1.tss);
init_syscalls(&GDT.1);
}
struct Selectors {
kcode: SegmentSelector,
kdata: SegmentSelector,
tss: SegmentSelector,
udata: SegmentSelector,
ucode: SegmentSelector,
}
static TSS: Lazy<TaskStateSegment> = Lazy::new(|| {
let mut tss = TaskStateSegment::new();
tss.interrupt_stack_table[usize::from(DOUBLE_FAULT_IX)] = {
const SIZE: usize = 5 * 1024;
let stack = unsafe {
alloc::alloc::alloc_zeroed(
alloc::alloc::Layout::from_size_align(SIZE, 1).expect("stack pointer"),
)
};
VirtAddr::from_ptr(stack) + SIZE
};
tss
});
static GDT: Lazy<(GlobalDescriptorTable, Selectors)> = Lazy::new(|| {
let mut gdt = GlobalDescriptorTable::new();
let sels = Selectors {
kcode: gdt.add_entry(Descriptor::kernel_code_segment()),
kdata: gdt.add_entry(Descriptor::kernel_data_segment()),
tss: gdt.add_entry(Descriptor::tss_segment(&TSS)),
udata: gdt.add_entry(Descriptor::user_data_segment()),
ucode: gdt.add_entry(Descriptor::user_code_segment()),
};
(gdt, sels)
});
/// Initialize syscalls
unsafe fn init_syscalls(sls: &Selectors) {
use x86_64::registers::{
model_specific::{Efer, EferFlags, LStar, SFMask, Star},
rflags::RFlags,
};
Star::write(sls.ucode, sls.udata, sls.kcode, sls.kdata);
SFMask::write(RFlags::from_bits(0x200).expect("Invalid RFlags for SFMask"));
LStar::write(VirtAddr::from_ptr(handle_syscall as *const ()));
Efer::update(|x| *x |= EferFlags::SYSTEM_CALL_EXTENSIONS);
}
extern "C" fn handle_syscall(a: u64) -> ! {
log::info!("called syscall {a}");
todo!("Return from syscall");
}