1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- use core::arch::asm;
- use crate::task::TSS;
- #[repr(transparent)]
- #[derive(Debug, Clone, Copy)]
- pub struct GDTEntry(u64);
- pub struct GDT([GDTEntry; GDT::LEN]);
- impl GDTEntry {
- const NULL: Self = Self(0);
- const KERNEL_CODE64: Self = Self::new(0, 0, 0x9a, 0x2);
- const KERNEL_DATA64: Self = Self::new(0, 0, 0x92, 0x0);
- const USER_CODE64: Self = Self::new(0, 0, 0xfa, 0x2);
- const USER_DATA64: Self = Self::new(0, 0, 0xf2, 0x0);
- const USER_CODE32: Self = Self::new(0, 0xfffff, 0xfa, 0xc);
- const USER_DATA32: Self = Self::new(0, 0xfffff, 0xf2, 0xc);
- pub const fn new(base: u32, limit: u32, access: u8, flags: u8) -> Self {
- let mut entry = 0u64;
- entry |= (limit & 0x0000_ffff) as u64;
- entry |= ((limit & 0x000f_0000) as u64) << 32;
- entry |= ((base & 0x00ff_ffff) as u64) << 16;
- entry |= ((base & 0xff00_0000) as u64) << 32;
- entry |= (access as u64) << 40;
- entry |= (flags as u64) << 52;
- GDTEntry(entry)
- }
- pub const fn new_ldt(base: u64, limit: u32) -> [Self; 2] {
- let first = Self::new(base as u32, limit, 0x82, 0x0);
- let second = Self(base >> 32);
- [first, second]
- }
- pub const fn new_tss(base: u64, limit: u32) -> [Self; 2] {
- let first = Self::new(base as u32, limit, 0x89, 0x0);
- let second = Self(base >> 32);
- [first, second]
- }
- }
- impl GDT {
- const LEN: usize = 10;
- const TLS32_INDEX: usize = 7;
- const TSS_INDEX: usize = 8;
- pub fn new() -> Self {
- Self([
- GDTEntry::NULL,
- GDTEntry::KERNEL_CODE64,
- GDTEntry::KERNEL_DATA64,
- GDTEntry::USER_CODE64,
- GDTEntry::USER_DATA64,
- GDTEntry::USER_CODE32,
- GDTEntry::USER_DATA32,
- GDTEntry::NULL, // User TLS 32bit
- GDTEntry::NULL, // TSS Descriptor Low
- GDTEntry::NULL, // TSS Descriptor High
- ])
- }
- pub fn set_tss(&mut self, base: u64) {
- let tss = GDTEntry::new_tss(base, size_of::<TSS>() as u32 - 1);
- self.0[Self::TSS_INDEX] = tss[0];
- self.0[Self::TSS_INDEX + 1] = tss[1];
- }
- pub fn set_tls32(&mut self, desc: GDTEntry) {
- self.0[7] = desc;
- }
- pub unsafe fn load(&self) {
- let len = Self::LEN * 8 - 1;
- let descriptor: [u64; 2] = [(len as u64) << 48, self.0.as_ptr() as u64];
- assert!(len < 0x10000, "GDT too large");
- let descriptor_address = &descriptor as *const _ as usize + 6;
- asm!(
- "lgdt ({})",
- "ltr %ax",
- in(reg) descriptor_address,
- in("ax") Self::TSS_INDEX as u16 * 8,
- options(att_syntax)
- );
- }
- }
|