xref: /DragonOS/kernel/src/arch/x86_64/process/table.rs (revision c75089286e9d49cef8d039446bf570c1bd4d2550)
1 use x86::{current::task::TaskStateSegment, segmentation::SegmentSelector, Ring};
2 
3 use crate::{
4     mm::{percpu::PerCpu, VirtAddr},
5     smp::core::smp_get_processor_id,
6 };
7 
8 // === 段选择子在GDT中的索引 ===
9 /// kernel code segment selector
10 pub const KERNEL_CS: SegmentSelector = SegmentSelector::new(1, Ring::Ring0);
11 /// kernel data segment selector
12 pub const KERNEL_DS: SegmentSelector = SegmentSelector::new(2, Ring::Ring0);
13 /// user data segment selector
14 pub const USER_DS: SegmentSelector = SegmentSelector::new(5, Ring::Ring3);
15 /// user code segment selector
16 /// 如果改这里,记得改syscall_64里面写死的常量
17 pub const USER_CS: SegmentSelector = SegmentSelector::new(6, Ring::Ring3);
18 
19 static mut TSS_MANAGER: TSSManager = TSSManager::new();
20 
21 extern "C" {
22     static mut GDT_Table: [u64; 512];
23 }
24 /// 切换fs和gs段寄存器
25 ///
26 /// 由于需要return使得它生效,所以不能inline
27 #[inline(never)]
28 pub unsafe fn switch_fs_and_gs(fs: SegmentSelector, gs: SegmentSelector) {
29     x86::segmentation::load_fs(fs);
30     x86::segmentation::load_gs(gs);
31 }
32 
33 #[derive(Debug)]
34 pub struct TSSManager {
35     tss: [TaskStateSegment; PerCpu::MAX_CPU_NUM],
36 }
37 
38 impl TSSManager {
39     const fn new() -> Self {
40         return Self {
41             tss: [TaskStateSegment::new(); PerCpu::MAX_CPU_NUM],
42         };
43     }
44 
45     /// 获取当前CPU的TSS
46     pub unsafe fn current_tss() -> &'static mut TaskStateSegment {
47         &mut TSS_MANAGER.tss[smp_get_processor_id() as usize]
48     }
49 
50     /// 加载当前CPU的TSS
51     pub unsafe fn load_tr() {
52         let index = (10 + smp_get_processor_id() * 2) as u16;
53         let selector = SegmentSelector::new(index, Ring::Ring0);
54 
55         Self::set_tss_descriptor(
56             index,
57             VirtAddr::new(Self::current_tss() as *mut TaskStateSegment as usize),
58         );
59         x86::task::load_tr(selector);
60     }
61 
62     unsafe fn set_tss_descriptor(index: u16, vaddr: VirtAddr) {
63         const LIMIT: u64 = 103;
64         let gdt_vaddr = VirtAddr::new(&GDT_Table as *const _ as usize);
65 
66         let gdt: &mut [u64] = core::slice::from_raw_parts_mut(gdt_vaddr.data() as *mut u64, 512);
67 
68         let vaddr = vaddr.data() as u64;
69         gdt[index as usize] = (LIMIT & 0xffff)
70             | ((vaddr & 0xffff) << 16)
71             | (((vaddr >> 16) & 0xff) << 32)
72             | (0x89 << 40)
73             | (((vaddr >> 24) & 0xff) << 56);
74         gdt[index as usize + 1] = ((vaddr >> 32) & 0xffffffff) | 0;
75     }
76 }
77