diff --git a/src/arch/x86_64/gdt.rs b/src/arch/x86_64/gdt.rs index ca846074fefc917d339e1a6845569b86b389eef2..00c9430a5482e0dde51d50efa032ce7a2e45337b 100644 --- a/src/arch/x86_64/gdt.rs +++ b/src/arch/x86_64/gdt.rs @@ -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; diff --git a/src/arch/x86_64/idt.rs b/src/arch/x86_64/idt.rs index f9b9859539f77bc550cb8047a934b4466606c507..59ec6c075db1bd27703e599dd262672364a36790 100644 --- a/src/arch/x86_64/idt.rs +++ b/src/arch/x86_64/idt.rs @@ -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; diff --git a/src/arch/x86_64/start.rs b/src/arch/x86_64/start.rs index afba151a49521a4b4cdced6a749f8d8b2149254a..81b12bb3bff77651943ad50a3c36a227c2851fc6 100644 --- a/src/arch/x86_64/start.rs +++ b/src/arch/x86_64/start.rs @@ -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 {