Skip to main content

kernel/arch/x86_64/cpu/tables/
gdt.rs

1// SPDX-License-Identifier: GPL-3.0-only
2//! Global Descriptor Table (GDT): owns the kernel segment descriptors and the TSS
3//! selector, and loads them into the CPU.
4//!
5//! Authors: MarioS271
6
7use super::tss::Tss;
8use crate::kinfo;
9use x86_64::instructions::tables::load_tss;
10use x86_64::registers::segmentation::{Segment, CS, DS, ES, SS};
11use x86_64::structures::gdt::{Descriptor, GlobalDescriptorTable, SegmentSelector};
12
13pub struct GdtSetupInfo {
14    pub kernel_code: SegmentSelector,
15    pub kernel_data: SegmentSelector,
16    pub user_code: SegmentSelector,
17    pub user_data: SegmentSelector,
18    pub tss_selector: SegmentSelector
19}
20
21/// Build the GDT and return it and a struct containing it and all its segment selectors
22pub fn gdt_init(tss: &'static Tss) -> (GlobalDescriptorTable, GdtSetupInfo) {
23    let mut gdt = GlobalDescriptorTable::new();
24
25    let kernel_code = gdt.append(Descriptor::kernel_code_segment());
26    let kernel_data = gdt.append(Descriptor::kernel_data_segment());
27    let user_data = gdt.append(Descriptor::user_data_segment());
28    let user_code = gdt.append(Descriptor::user_code_segment());
29    let tss_selector = gdt.append(Descriptor::tss_segment(unsafe { tss.tss() }));
30
31    (gdt, GdtSetupInfo {
32        kernel_code,
33        kernel_data,
34        user_data,
35        user_code,
36        tss_selector
37    })
38}
39
40/// Load the GDT and its selectors
41///
42/// # Safety
43/// The caller must guarantee that the given segment selectors in `gdt_setup_info` are valid
44/// and point to the given `gdt`
45pub unsafe fn gdt_load(gdt: &'static GlobalDescriptorTable, gdt_setup_info: &GdtSetupInfo) {
46    gdt.load();
47
48    unsafe {
49        CS::set_reg(gdt_setup_info.kernel_code);
50        SS::set_reg(gdt_setup_info.kernel_data);
51        DS::set_reg(gdt_setup_info.kernel_data);
52        ES::set_reg(gdt_setup_info.kernel_data);
53        load_tss(gdt_setup_info.tss_selector);
54    }
55
56    kinfo!("Initialized GDT");
57}