LoGin bd70d2d1f4
chore: 将工具链更新到2024-07-23 (#864)
* chore: 将工具链更新到2024-07-23
2024-07-25 00:55:02 +08:00

78 lines
2.5 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use x86::{current::task::TaskStateSegment, segmentation::SegmentSelector, Ring};
use crate::{
mm::{percpu::PerCpu, VirtAddr},
smp::core::smp_get_processor_id,
};
// === 段选择子在GDT中的索引 ===
/// kernel code segment selector
pub const KERNEL_CS: SegmentSelector = SegmentSelector::new(1, Ring::Ring0);
/// kernel data segment selector
pub const KERNEL_DS: SegmentSelector = SegmentSelector::new(2, Ring::Ring0);
/// user data segment selector
pub const USER_DS: SegmentSelector = SegmentSelector::new(5, Ring::Ring3);
/// user code segment selector
/// 如果改这里记得改syscall_64里面写死的常量
pub const USER_CS: SegmentSelector = SegmentSelector::new(6, Ring::Ring3);
static mut TSS_MANAGER: TSSManager = TSSManager::new();
extern "C" {
static mut GDT_Table: [u64; 512];
}
/// 切换fs和gs段寄存器
///
/// 由于需要return使得它生效所以不能inline
#[inline(never)]
pub unsafe fn switch_fs_and_gs(fs: SegmentSelector, gs: SegmentSelector) {
x86::segmentation::load_fs(fs);
x86::segmentation::load_gs(gs);
}
#[derive(Debug)]
pub struct TSSManager {
tss: [TaskStateSegment; PerCpu::MAX_CPU_NUM as usize],
}
impl TSSManager {
const fn new() -> Self {
return Self {
tss: [TaskStateSegment::new(); PerCpu::MAX_CPU_NUM as usize],
};
}
/// 获取当前CPU的TSS
pub unsafe fn current_tss() -> &'static mut TaskStateSegment {
&mut TSS_MANAGER.tss[smp_get_processor_id().data() as usize]
}
/// 加载当前CPU的TSS
pub unsafe fn load_tr() {
let index = (10 + smp_get_processor_id().data() * 2) as u16;
let selector = SegmentSelector::new(index, Ring::Ring0);
Self::set_tss_descriptor(
index,
VirtAddr::new(Self::current_tss() as *mut TaskStateSegment as usize),
);
x86::task::load_tr(selector);
}
#[allow(static_mut_refs)]
unsafe fn set_tss_descriptor(index: u16, vaddr: VirtAddr) {
const LIMIT: u64 = 103;
let gdt_vaddr = VirtAddr::new(&GDT_Table as *const _ as usize);
let gdt: &mut [u64] = core::slice::from_raw_parts_mut(gdt_vaddr.data() as *mut u64, 512);
let vaddr = vaddr.data() as u64;
gdt[index as usize] = (LIMIT & 0xffff)
| ((vaddr & 0xffff) << 16)
| (((vaddr >> 16) & 0xff) << 32)
| (0x89 << 40)
| (((vaddr >> 24) & 0xff) << 56);
gdt[index as usize + 1] = (vaddr >> 32) & 0xffffffff;
}
}