rustubs/arch/x86_64/
gdt.rs1use crate::defs::ExternSyms::{GDT, GDT_80, TSS0, TSS_DESC};
7use crate::defs::P2V;
8use bit_field::BitField;
9use core::mem::size_of;
10use core::{arch::asm, slice::from_raw_parts_mut};
11
12pub unsafe fn init() {
15 let gdtd = unsafe { &mut *(GDT_80 as *mut GDTDescriptor) };
16 debug_assert!(gdtd.table_size == 7 * 8 - 1);
18 gdtd.table_addr = P2V(GDT as u64).unwrap();
19 unsafe { asm!("lgdt [{}]", in (reg) P2V(GDT_80 as u64).unwrap()) }
20 let tssd = from_raw_parts_mut(TSS_DESC as *mut u64, 2);
22 let (low, high) = to_tss_desc(TSS0 as u64);
23 tssd[0] = low;
24 tssd[1] = high;
25 asm!("ltr {0:x}", in(reg) 0x28, options(nostack, preserves_flags));
28}
29
30pub unsafe fn set_tss_ksp(ksp: u64) {
31 let tss = TSS0 as *mut TaskStateSegment;
32 (*tss).privilege_stack_table[0] = ksp;
33}
34
35#[repr(C)]
38#[repr(packed)]
39struct GDTDescriptor {
40 pub table_size: u16,
41 pub table_addr: u64,
42}
43
44fn to_tss_desc(tss_addr: u64) -> (u64, u64) {
47 let mut low: u64 = 1 << 47;
49 low.set_bits(16..40, tss_addr.get_bits(0..24));
51 low.set_bits(56..64, tss_addr.get_bits(24..32));
52 low.set_bits(0..16, (size_of::<TaskStateSegment>() - 1) as u64);
54 low.set_bits(40..44, 0b1001);
56 let mut high: u64 = 0;
57 high.set_bits(0..32, tss_addr.get_bits(32..64));
58 (low, high)
59}
60
61#[derive(Debug, Clone, Copy)]
65#[repr(C, packed(4))]
66pub struct TaskStateSegment {
67 reserved_1: u32,
68 pub privilege_stack_table: [u64; 3],
71 reserved_2: u64,
72 pub interrupt_stack_table: [u64; 7],
75 reserved_3: u64,
76 reserved_4: u16,
77 pub iomap_base: u16,
80}
81
82impl TaskStateSegment {
83 #[inline]
90 pub const fn new() -> TaskStateSegment {
91 TaskStateSegment {
92 privilege_stack_table: [0; 3],
93 interrupt_stack_table: [0; 7],
94 iomap_base: size_of::<TaskStateSegment>() as u16,
95 reserved_1: 0,
96 reserved_2: 0,
97 reserved_3: 0,
98 reserved_4: 0,
99 }
100 }
101}