diff --git a/arch/x86_64/src/gdt.rs b/arch/x86_64/src/gdt.rs index 00457f9..64220d5 100644 --- a/arch/x86_64/src/gdt.rs +++ b/arch/x86_64/src/gdt.rs @@ -1,6 +1,9 @@ //! Global descriptor table use core::mem; +use x86::dtables::{self, DescriptorTablePointer}; +use x86::segmentation::{self, SegmentSelector}; +use x86::task::{self, TaskStateSegment}; pub const GDT_NULL: usize = 0; pub const GDT_KERNEL_CODE: usize = 1; @@ -9,110 +12,102 @@ pub const GDT_USER_CODE: usize = 3; pub const GDT_USER_DATA: usize = 4; pub const GDT_USER_TLS: usize = 5; pub const GDT_TSS: usize = 6; +pub const GDT_TSS_HIGH: usize = 7; -pub static mut GDTR: GdtDescriptor = GdtDescriptor { - size: 0, - offset: 0 +pub const GDT_A_PRESENT: u8 = 1 << 7; +pub const GDT_A_RING_0: u8 = 0 << 5; +pub const GDT_A_RING_1: u8 = 1 << 5; +pub const GDT_A_RING_2: u8 = 2 << 5; +pub const GDT_A_RING_3: u8 = 3 << 5; +pub const GDT_A_SYSTEM: u8 = 1 << 4; +pub const GDT_A_EXECUTABLE: u8 = 1 << 3; +pub const GDT_A_CONFORMING: u8 = 1 << 2; +pub const GDT_A_PRIVILEGE: u8 = 1 << 1; +pub const GDT_A_DIRTY: u8 = 1; + +pub const GDT_A_TSS_AVAIL: u8 = 0x9; +pub const GDT_A_TSS_BUSY: u8 = 0xB; + +pub const GDT_F_PAGE_SIZE: u8 = 1 << 7; +pub const GDT_F_PROTECTED_MODE: u8 = 1 << 6; +pub const GDT_F_LONG_MODE: u8 = 1 << 5; + +pub static mut GDTR: DescriptorTablePointer = DescriptorTablePointer { + limit: 0, + base: 0 }; -pub static mut GDT: [GdtEntry; 5] = [GdtEntry::new(); 5]; +pub static mut GDT: [GdtEntry; 8] = [ + // Null + GdtEntry::new(0, 0, 0, 0), + // Kernel code + GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE, GDT_F_LONG_MODE), + // Kernel data + GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE), + // User code + GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE, GDT_F_LONG_MODE), + // User data + GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE), + //TODO: User TLS + GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE), + //TODO: TSS + GdtEntry::new(0, 0, 0 , 0), + // TSS must be 16 bytes long, twice the normal size + GdtEntry::new(0, 0, 0, 0), +]; + +pub static mut TSS: TaskStateSegment = TaskStateSegment { + reserved: 0, + rsp: [0; 3], + reserved2: 0, + ist: [0; 7], + reserved3: 0, + reserved4: 0, + iomap_base: 0xFFFF +}; pub unsafe fn init() { - GDT[GDT_KERNEL_CODE].set_access(GDT_PRESENT | GDT_RING_0 | GDT_SYSTEM | GDT_EXECUTABLE | GDT_PRIVILEGE); - GDT[GDT_KERNEL_CODE].set_flags(GDT_LONG_MODE); + GDTR.limit = (GDT.len() * mem::size_of::() - 1) as u16; + GDTR.base = GDT.as_ptr() as u64; - GDT[GDT_KERNEL_DATA].set_access(GDT_PRESENT | GDT_RING_0 | GDT_SYSTEM | GDT_PRIVILEGE); - GDT[GDT_KERNEL_DATA].set_flags(GDT_LONG_MODE); - - GDT[GDT_USER_CODE].set_access(GDT_PRESENT | GDT_RING_3 | GDT_SYSTEM | GDT_EXECUTABLE | GDT_PRIVILEGE); - GDT[GDT_USER_CODE].set_flags(GDT_LONG_MODE); - - GDT[GDT_USER_DATA].set_access(GDT_PRESENT | GDT_RING_3 | GDT_SYSTEM | GDT_PRIVILEGE); - GDT[GDT_USER_DATA].set_flags(GDT_LONG_MODE); - - GDTR.set_slice(&GDT); + GDT[GDT_TSS] = GdtEntry::new(&TSS as *const _ as u32, mem::size_of::() as u32, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_TSS_AVAIL, 0); init_ap(); } pub unsafe fn init_ap() { - GDTR.load(); -} + dtables::lgdt(&GDTR); -bitflags! { - pub flags GdtAccess: u8 { - const GDT_PRESENT = 1 << 7, - const GDT_RING_0 = 0 << 5, - const GDT_RING_1 = 1 << 5, - const GDT_RING_2 = 2 << 5, - const GDT_RING_3 = 3 << 5, - const GDT_SYSTEM = 1 << 4, - const GDT_EXECUTABLE = 1 << 3, - const GDT_CONFORMING = 1 << 2, - const GDT_PRIVILEGE = 1 << 1, - const GDT_DIRTY = 1, - } -} + 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_DATA as u16)); + segmentation::load_gs(SegmentSelector::new(GDT_KERNEL_DATA as u16)); + segmentation::load_ss(SegmentSelector::new(GDT_KERNEL_DATA as u16)); -bitflags! { - pub flags GdtFlags: u8 { - const GDT_PAGE_SIZE = 1 << 7, - const GDT_PROTECTED_MODE = 1 << 6, - const GDT_LONG_MODE = 1 << 5 - } -} - -#[repr(packed)] -pub struct GdtDescriptor { - pub size: u16, - pub offset: u64 -} - -impl GdtDescriptor { - pub fn set_slice(&mut self, slice: &'static [GdtEntry]) { - self.size = (slice.len() * mem::size_of::() - 1) as u16; - self.offset = slice.as_ptr() as u64; - } - - pub unsafe fn load(&self) { - asm!("lgdt [rax]" : : "{rax}"(self as *const _ as usize) : : "intel", "volatile"); - } + //TODO: Seperate TSS for each processor task::load_ltr(SegmentSelector::new(GDT_TSS as u16)); } #[derive(Copy, Clone, Debug)] #[repr(packed)] pub struct GdtEntry { pub limitl: u16, - pub basel: u16, - pub basem: u8, + pub offsetl: u16, + pub offsetm: u8, pub access: u8, pub flags_limith: u8, - pub baseh: u8 + pub offseth: u8 } impl GdtEntry { - pub const fn new() -> Self { + pub const fn new(offset: u32, limit: u32, access: u8, flags: u8) -> Self { GdtEntry { - limitl: 0, - basel: 0, - basem: 0, - access: 0, - flags_limith: 0, - baseh: 0 + limitl: limit as u16, + offsetl: offset as u16, + offsetm: (offset >> 16) as u8, + access: access, + flags_limith: flags & 0xF0 | ((limit >> 16) as u8) & 0x0F, + offseth: (offset >> 24) as u8 } } - - pub fn set_offset(&mut self, offset: usize) { - self.basel = offset as u16; - self.basem = (offset >> 16) as u8; - self.baseh = (offset >> 24) as u8; - } - - pub fn set_access(&mut self, access: GdtAccess) { - self.access = access.bits; - } - - pub fn set_flags(&mut self, flags: GdtFlags) { - self.flags_limith = (self.flags_limith & 0xF) | flags.bits; - } } diff --git a/arch/x86_64/src/lib.rs b/arch/x86_64/src/lib.rs index e360614..27a672d 100644 --- a/arch/x86_64/src/lib.rs +++ b/arch/x86_64/src/lib.rs @@ -95,7 +95,6 @@ macro_rules! interrupt_error { push r11" : : : : "intel", "volatile"); - // Call inner rust function inner(); @@ -148,6 +147,3 @@ pub mod serial; /// Initialization and start function pub mod start; - -/// Task state segment -pub mod tss; diff --git a/arch/x86_64/src/tss.rs b/arch/x86_64/src/tss.rs deleted file mode 100644 index b1034b8..0000000 --- a/arch/x86_64/src/tss.rs +++ /dev/null @@ -1,20 +0,0 @@ -#[repr(packed)] -pub struct Tss { - pub reserved1: u32, - pub sp0: u64, - pub sp1: u64, - pub sp2: u64, - pub reserved2: u32, - pub reserved3: u32, - pub ist1: u64, - pub ist2: u64, - pub ist3: u64, - pub ist4: u64, - pub ist5: u64, - pub ist6: u64, - pub ist7: u64, - pub reserved4: u32, - pub reserved5: u32, - pub reserved6: u16, - pub iomap_base: u16, -}