1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//! This module defines the GDT and its segments.
use crate::arch::gdt::{Descriptor, GlobalDescriptorTable, SegmentSelector};
use crate::arch::DescriptorTablePointer;

#[allow(unused)]
pub enum Segment {
    KernelCode = 1,
    KernelData = 2,
    UserCode = 3,
    UserData = 4,
    TaskState = 5,
}

/// The global descriptor table
pub static mut GDT: GlobalDescriptorTable<3> = GlobalDescriptorTable([
    // First one is usually null
    Descriptor::new(),
    // Kernel code
    Descriptor::segment(0..=u32::MAX, true, false),
    // Kernel data
    Descriptor::segment(0..=u32::MAX, false, false),
    // TODO: A1: Add user code, data and TSS
]);

/// Fat pointer to the GDT, used by the boot asm code.
#[no_mangle]
pub static GDT_PTR: DescriptorTablePointer = unsafe { GDT.pointer() };

/// TODO: A1 - Our task state segment register that saves the kernel stack pointer and segment.

/// Initialize the GDT and TSS
pub fn init() {
    todo!("A1: Initialize and set the TSS");
}

pub fn selector(segment: Segment) -> SegmentSelector {
    let user = matches!(segment, Segment::UserCode | Segment::UserData);
    unsafe { GDT.selector(segment as _, user) }
}