Ensure GDT and IDT state is sane before attempting to set up paging
This commit is contained in:
@@ -100,16 +100,13 @@ pub unsafe fn set_tss_stack(stack: usize) {
|
||||
TSS.rsp[0] = stack as u64;
|
||||
}
|
||||
|
||||
/// Initialize GDT
|
||||
pub unsafe fn init(tcb_offset: usize, stack_offset: usize) {
|
||||
// Initialize GDT
|
||||
pub unsafe fn init() {
|
||||
// Setup the initial GDT with TLS, so we can setup the TLS GDT (a little confusing)
|
||||
// This means that each CPU will have its own GDT, but we only need to define it once as a thread local
|
||||
INIT_GDTR.limit = (INIT_GDT.len() * mem::size_of::<GdtEntry>() - 1) as u16;
|
||||
INIT_GDTR.base = INIT_GDT.as_ptr() as u64;
|
||||
|
||||
// Set the TLS segment to the offset of the Thread Control Block
|
||||
INIT_GDT[GDT_KERNEL_TLS].set_offset(tcb_offset as u32);
|
||||
|
||||
// Load the initial GDT, before we have access to thread locals
|
||||
dtables::lgdt(&INIT_GDTR);
|
||||
|
||||
@@ -117,9 +114,21 @@ pub unsafe fn init(tcb_offset: usize, stack_offset: usize) {
|
||||
segmentation::load_cs(SegmentSelector::new(GDT_KERNEL_CODE as u16));
|
||||
segmentation::load_ds(SegmentSelector::new(GDT_KERNEL_DATA as u16));
|
||||
segmentation::load_es(SegmentSelector::new(GDT_KERNEL_DATA as u16));
|
||||
segmentation::load_fs(SegmentSelector::new(GDT_KERNEL_TLS as u16));
|
||||
segmentation::load_fs(SegmentSelector::new(GDT_KERNEL_DATA as u16));
|
||||
segmentation::load_gs(SegmentSelector::new(GDT_KERNEL_DATA as u16));
|
||||
segmentation::load_ss(SegmentSelector::new(GDT_KERNEL_DATA as u16));
|
||||
}
|
||||
|
||||
/// Initialize GDT with TLS
|
||||
pub unsafe fn init_paging(tcb_offset: usize, stack_offset: usize) {
|
||||
// Set the TLS segment to the offset of the Thread Control Block
|
||||
INIT_GDT[GDT_KERNEL_TLS].set_offset(tcb_offset as u32);
|
||||
|
||||
// Load the initial GDT, before we have access to thread locals
|
||||
dtables::lgdt(&INIT_GDTR);
|
||||
|
||||
// Load the segment descriptors
|
||||
segmentation::load_fs(SegmentSelector::new(GDT_KERNEL_TLS as u16));
|
||||
|
||||
// Now that we have access to thread locals, setup the AP's individual GDT
|
||||
GDTR.limit = (GDT.len() * mem::size_of::<GdtEntry>() - 1) as u16;
|
||||
|
||||
@@ -3,6 +3,11 @@ use x86::dtables::{self, DescriptorTablePointer};
|
||||
|
||||
use interrupt::*;
|
||||
|
||||
pub static mut INIT_IDTR: DescriptorTablePointer = DescriptorTablePointer {
|
||||
limit: 0,
|
||||
base: 0
|
||||
};
|
||||
|
||||
pub static mut IDTR: DescriptorTablePointer = DescriptorTablePointer {
|
||||
limit: 0,
|
||||
base: 0
|
||||
@@ -11,6 +16,10 @@ pub static mut IDTR: DescriptorTablePointer = DescriptorTablePointer {
|
||||
pub static mut IDT: [IdtEntry; 256] = [IdtEntry::new(); 256];
|
||||
|
||||
pub unsafe fn init() {
|
||||
dtables::lidt(&INIT_IDTR);
|
||||
}
|
||||
|
||||
pub unsafe fn init_paging() {
|
||||
IDTR.limit = (IDT.len() * mem::size_of::<IdtEntry>() - 1) as u16;
|
||||
IDTR.base = IDT.as_ptr() as u64;
|
||||
|
||||
|
||||
@@ -72,17 +72,23 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
|
||||
println!("Stack: {:X}:{:X}", stack_base, stack_base + stack_size);
|
||||
println!("Env: {:X}:{:X}", env_base, env_base + env_size);
|
||||
|
||||
// Set up GDT before paging
|
||||
gdt::init();
|
||||
|
||||
// Set up IDT before paging
|
||||
idt::init();
|
||||
|
||||
// Initialize memory management
|
||||
memory::init(0, kernel_base + ((kernel_size + 4095)/4096) * 4096);
|
||||
|
||||
// Initialize paging
|
||||
let (mut active_table, tcb_offset) = paging::init(0, kernel_base, kernel_base + kernel_size, stack_base, stack_base + stack_size);
|
||||
|
||||
// Set up GDT
|
||||
gdt::init(tcb_offset, stack_base + stack_size);
|
||||
// Set up GDT after paging with TLS
|
||||
gdt::init_paging(tcb_offset, stack_base + stack_size);
|
||||
|
||||
// Set up IDT
|
||||
idt::init();
|
||||
idt::init_paging();
|
||||
|
||||
// Test tdata and tbss
|
||||
{
|
||||
@@ -151,14 +157,20 @@ pub unsafe extern fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! {
|
||||
assert_eq!(BSS_TEST_ZERO, 0);
|
||||
assert_eq!(DATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFF);
|
||||
|
||||
// Set up GDT before paging
|
||||
gdt::init();
|
||||
|
||||
// Set up IDT before paging
|
||||
idt::init();
|
||||
|
||||
// Initialize paging
|
||||
let tcb_offset = paging::init_ap(cpu_id, bsp_table, stack_start, stack_end);
|
||||
|
||||
// Set up GDT for AP
|
||||
gdt::init(tcb_offset, stack_end);
|
||||
// Set up GDT with TLS
|
||||
gdt::init_paging(tcb_offset, stack_end);
|
||||
|
||||
// Set up IDT for AP
|
||||
idt::init();
|
||||
idt::init_paging();
|
||||
|
||||
// Test tdata and tbss
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user