diff --git a/src/arch/x86_64/gdt.rs b/src/arch/x86_64/gdt.rs index 34cac9c1..20d00341 100644 --- a/src/arch/x86_64/gdt.rs +++ b/src/arch/x86_64/gdt.rs @@ -5,7 +5,7 @@ use core::fmt; use core::fmt::Debug; use spin::{Mutex, MutexGuard, Once}; use x86_64::{PrivilegeLevel, VirtAddr}; -use x86_64::structures::gdt::SegmentSelector; +use x86_64::structures::gdt::*; use x86_64::structures::tss::TaskStateSegment; /// Alloc TSS & GDT at kernel heap, then init and load it. @@ -29,10 +29,11 @@ pub fn init() { let tss = Box::into_raw(tss); let gdt = Box::new({ - let mut gdt = Gdt::new(); + let mut gdt = GlobalDescriptorTable::new(); gdt.add_entry(KCODE); gdt.add_entry(UCODE); - gdt.add_entry(KDATA); + // KDATA use segment 0 + // gdt.add_entry(KDATA); gdt.add_entry(UDATA); gdt.add_entry(UCODE32); gdt.add_entry(UDATA32); @@ -60,7 +61,7 @@ static CPUS: [Once>; MAX_CPU_NUM] = [ ]; pub struct Cpu { - gdt: &'static Gdt, + gdt: &'static GlobalDescriptorTable, tss: &'static mut TaskStateSegment, } @@ -92,131 +93,8 @@ const UDATA32: Descriptor = Descriptor::UserSegment(0x00cff200_0000ffff); // EX pub const KCODE_SELECTOR: SegmentSelector = SegmentSelector::new(1, PrivilegeLevel::Ring0); pub const UCODE_SELECTOR: SegmentSelector = SegmentSelector::new(2, PrivilegeLevel::Ring3); -pub const KDATA_SELECTOR: SegmentSelector = SegmentSelector::new(3, PrivilegeLevel::Ring0); -pub const UDATA_SELECTOR: SegmentSelector = SegmentSelector::new(4, PrivilegeLevel::Ring3); -pub const UCODE32_SELECTOR: SegmentSelector = SegmentSelector::new(5, PrivilegeLevel::Ring3); -pub const UDATA32_SELECTOR: SegmentSelector = SegmentSelector::new(6, PrivilegeLevel::Ring3); -pub const TSS_SELECTOR: SegmentSelector = SegmentSelector::new(7, PrivilegeLevel::Ring0); - - -pub struct Gdt { - table: [u64; 10], - next_free: usize, -} - -impl Gdt { - pub fn new() -> Gdt { - Gdt { - table: [0; 10], - next_free: 1, - } - } - - pub fn add_entry(&mut self, entry: Descriptor) -> SegmentSelector { - let index = match entry { - Descriptor::UserSegment(value) => self.push(value), - Descriptor::SystemSegment(value_low, value_high) => { - let index = self.push(value_low); - self.push(value_high); - index - } - }; - SegmentSelector::new(index as u16, PrivilegeLevel::Ring0) - } - - pub fn load(&'static self) { - use x86_64::instructions::tables::{DescriptorTablePointer, lgdt}; - use core::mem::size_of; - - let ptr = DescriptorTablePointer { - base: self.table.as_ptr() as u64, - limit: (self.table.len() * size_of::() - 1) as u16, - }; - - unsafe { lgdt(&ptr) }; - } - - fn push(&mut self, value: u64) -> usize { - if self.next_free < self.table.len() { - let index = self.next_free; - self.table[index] = value; - self.next_free += 1; - index - } else { - panic!("GDT full"); - } - } -} - -pub enum Descriptor { - UserSegment(u64), - SystemSegment(u64, u64), -} - -impl Descriptor { - pub fn tss_segment(tss: &'static TaskStateSegment) -> Descriptor { - use core::mem::size_of; - use bit_field::BitField; - - let ptr = tss as *const _ as u64; - - let mut low = DescriptorFlags::PRESENT.bits(); - // base - low.set_bits(16..40, ptr.get_bits(0..24)); - low.set_bits(56..64, ptr.get_bits(24..32)); - // limit (the `-1` in needed since the bound is inclusive) - low.set_bits(0..16, (size_of::() - 1) as u64); - // type (0b1001 = available 64-bit tss) - low.set_bits(40..44, 0b1001); - - let mut high = 0; - high.set_bits(0..32, ptr.get_bits(32..64)); - - Descriptor::SystemSegment(low, high) - } -} - -bitflags! { - /// Reference: https://wiki.osdev.org/GDT - struct DescriptorFlags: u64 { - const ACCESSED = 1 << 40; - const DATA_WRITABLE = 1 << 41; - const CODE_READABLE = 1 << 41; - const CONFORMING = 1 << 42; - const EXECUTABLE = 1 << 43; - const USER_SEGMENT = 1 << 44; - const USER_MODE = 1 << 45 | 1 << 46; - const PRESENT = 1 << 47; - const LONG_MODE = 1 << 53; - } -} - -impl Debug for Descriptor { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match self { - Descriptor::UserSegment(flags) => - write!(f, "UserSegment( {:?} )", DescriptorFlags{bits: *flags}), - Descriptor::SystemSegment(low, high) => - write!(f, "SystemSegment{:?}", (low, high)), - } - } -} - -pub mod test -{ - pub fn print_flags() { - use super::*; - // The following 4 GDT entries were copied from xv6 x86_64 - let list: [(&str, Descriptor); 4] = [ - ("KCODE", super::KCODE), // Code, DPL=0, R/X - ("UCODE", super::UCODE), // Code, DPL=3, R/X - ("KDATA", super::KDATA), // Data, DPL=0, W - ("UDATA", super::UDATA), // Data, DPL=3, W - ]; - // Let's see what that means - println!("GDT Segments from xv6 x86_64:"); - for (name, desc) in list.iter() { - println!(" {}: {:?}", name, desc); - } - } -} \ No newline at end of file +pub const KDATA_SELECTOR: SegmentSelector = SegmentSelector::new(0, PrivilegeLevel::Ring0); +pub const UDATA_SELECTOR: SegmentSelector = SegmentSelector::new(3, PrivilegeLevel::Ring3); +pub const UCODE32_SELECTOR: SegmentSelector = SegmentSelector::new(4, PrivilegeLevel::Ring3); +pub const UDATA32_SELECTOR: SegmentSelector = SegmentSelector::new(5, PrivilegeLevel::Ring3); +pub const TSS_SELECTOR: SegmentSelector = SegmentSelector::new(6, PrivilegeLevel::Ring0); \ No newline at end of file