strat9_kernel/arch/x86_64/
tss.rs1use core::{
8 mem::MaybeUninit,
9 sync::atomic::{AtomicBool, Ordering},
10};
11use x86_64::{structures::tss::TaskStateSegment, VirtAddr};
12
13pub const DOUBLE_FAULT_IST_INDEX: u16 = 0;
15
16const IST_STACK_SIZE: usize = 4096 * 5;
18
19static mut IST_STACKS: [[u8; IST_STACK_SIZE]; crate::arch::x86_64::percpu::MAX_CPUS] =
21 [[0; IST_STACK_SIZE]; crate::arch::x86_64::percpu::MAX_CPUS];
22
23static mut TSS: [MaybeUninit<TaskStateSegment>; crate::arch::x86_64::percpu::MAX_CPUS] =
25 [const { MaybeUninit::uninit() }; crate::arch::x86_64::percpu::MAX_CPUS];
26
27static TSS_INIT: [AtomicBool; crate::arch::x86_64::percpu::MAX_CPUS] =
28 [const { AtomicBool::new(false) }; crate::arch::x86_64::percpu::MAX_CPUS];
29
30pub fn init() {
34 init_cpu(0);
35}
36
37pub fn init_cpu(cpu_index: usize) {
39 assert!(
41 cpu_index < crate::arch::x86_64::percpu::MAX_CPUS,
42 "TSS init_cpu: cpu_index {} >= MAX_CPUS {}",
43 cpu_index,
44 crate::arch::x86_64::percpu::MAX_CPUS,
45 );
46 unsafe {
48 let stack_ptr = &raw const IST_STACKS[cpu_index] as *const u8;
49 let stack_end = VirtAddr::from_ptr(stack_ptr) + IST_STACK_SIZE as u64;
50 let mut tss = TaskStateSegment::new();
51 tss.interrupt_stack_table[DOUBLE_FAULT_IST_INDEX as usize] = stack_end;
52
53 TSS[cpu_index].write(tss);
54 TSS_INIT[cpu_index].store(true, Ordering::Release);
55
56 let ist_addr = VirtAddr::from_ptr(stack_ptr);
57 log::info!(
58 "TSS[CPU{}] initialized: IST[{}] stack @ {:#x}..{:#x} ({} KB)",
59 cpu_index,
60 DOUBLE_FAULT_IST_INDEX,
61 ist_addr.as_u64(),
62 ist_addr.as_u64() + IST_STACK_SIZE as u64,
63 IST_STACK_SIZE / 1024,
64 );
65 }
66}
67
68pub fn tss_for(cpu_index: usize) -> &'static TaskStateSegment {
70 assert!(
71 cpu_index < crate::arch::x86_64::percpu::MAX_CPUS,
72 "tss_for: cpu_index {} >= MAX_CPUS",
73 cpu_index,
74 );
75 if !TSS_INIT[cpu_index].load(Ordering::Acquire) {
76 panic!("TSS for CPU{} not initialized", cpu_index);
77 }
78 unsafe { &*TSS[cpu_index].as_ptr() }
80}
81
82pub fn set_kernel_stack(stack_top: VirtAddr) {
87 let cpu_index = crate::arch::x86_64::percpu::current_cpu_index();
88 set_kernel_stack_for(cpu_index, stack_top);
89}
90
91pub fn set_kernel_stack_for(cpu_index: usize, stack_top: VirtAddr) {
93 if cpu_index >= crate::arch::x86_64::percpu::MAX_CPUS {
94 log::warn!("set_kernel_stack_for: cpu_index {} out of range", cpu_index);
95 return;
96 }
97 if !TSS_INIT[cpu_index].load(Ordering::Acquire) {
100 return;
101 }
102 unsafe {
103 let tss = &raw mut *TSS[cpu_index].as_mut_ptr();
104 (*tss).privilege_stack_table[0] = stack_top;
105 }
106}