feat: initial scalable x86_64 microkernel skeleton with Limine, Rust, C HAL, and C++20 IPC
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
//! Global Descriptor Table (GDT) and Task State Segment (TSS) for x86_64
|
||||
|
||||
use core::mem::size_of;
|
||||
|
||||
#[repr(C, packed)]
|
||||
pub struct TaskStateSegment {
|
||||
_reserved1: u32,
|
||||
pub rsp0: u64,
|
||||
pub rsp1: u64,
|
||||
pub rsp2: u64,
|
||||
_reserved2: u64,
|
||||
pub ist: [u64; 7],
|
||||
_reserved3: u64,
|
||||
_reserved4: u16,
|
||||
pub iomap_base: u16,
|
||||
}
|
||||
|
||||
impl TaskStateSegment {
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
_reserved1: 0,
|
||||
rsp0: 0,
|
||||
rsp1: 0,
|
||||
rsp2: 0,
|
||||
_reserved2: 0,
|
||||
ist: [0; 7],
|
||||
_reserved3: 0,
|
||||
_reserved4: 0,
|
||||
iomap_base: size_of::<TaskStateSegment>() as u16,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C, packed)]
|
||||
struct GdtDescriptor {
|
||||
limit: u16,
|
||||
base: u64,
|
||||
}
|
||||
|
||||
pub static mut TSS: TaskStateSegment = TaskStateSegment::new();
|
||||
|
||||
// 8 entries: Null, KCode, KData, UData, UCode, TSS Low, TSS High, Null
|
||||
static mut GDT: [u64; 8] = [
|
||||
0x0000000000000000, // 0x00: Null
|
||||
0x00af9a000000ffff, // 0x08: Kernel Code 64 (Ring 0)
|
||||
0x00cf92000000ffff, // 0x10: Kernel Data 64 (Ring 0)
|
||||
0x00cff2000000ffff, // 0x18: User Data 64 (Ring 3)
|
||||
0x00affa000000ffff, // 0x20: User Code 64 (Ring 3)
|
||||
0x0000000000000000, // 0x28: TSS Low (populated at init)
|
||||
0x0000000000000000, // 0x30: TSS High (populated at init)
|
||||
0x0000000000000000, // 0x38: Alignment / padding
|
||||
];
|
||||
|
||||
pub unsafe fn init() {
|
||||
let tss_addr = core::ptr::addr_of!(TSS) as u64;
|
||||
let tss_size = (size_of::<TaskStateSegment>() - 1) as u64;
|
||||
|
||||
// Build 64-bit TSS descriptor
|
||||
let tss_low = (tss_size & 0xffff)
|
||||
| ((tss_addr & 0xffff) << 16)
|
||||
| (((tss_addr >> 16) & 0xff) << 32)
|
||||
| (0x89u64 << 40) // Present, 64-bit TSS (Available)
|
||||
| (((tss_size >> 16) & 0xf) << 48)
|
||||
| (((tss_addr >> 24) & 0xff) << 56);
|
||||
let tss_high = tss_addr >> 32;
|
||||
|
||||
let gdt_ptr = core::ptr::addr_of_mut!(GDT) as *mut u64;
|
||||
*gdt_ptr.add(5) = tss_low;
|
||||
*gdt_ptr.add(6) = tss_high;
|
||||
|
||||
let descriptor = GdtDescriptor {
|
||||
limit: (size_of::<[u64; 8]>() - 1) as u16,
|
||||
base: gdt_ptr as u64,
|
||||
};
|
||||
|
||||
core::arch::asm!(
|
||||
"lgdt [{0}]",
|
||||
"push 0x08",
|
||||
"lea {tmp}, [2f + rip]",
|
||||
"push {tmp}",
|
||||
"retfq",
|
||||
"2:",
|
||||
"mov ax, 0x10",
|
||||
"mov ds, ax",
|
||||
"mov es, ax",
|
||||
"mov ss, ax",
|
||||
"mov fs, ax",
|
||||
"mov gs, ax",
|
||||
"ltr {tss_sel:x}",
|
||||
in(reg) &descriptor,
|
||||
tmp = out(reg) _,
|
||||
tss_sel = in(reg) (0x28u16),
|
||||
options(preserves_flags)
|
||||
);
|
||||
}
|
||||
|
||||
pub fn set_kernel_stack(stack_top: u64) {
|
||||
unsafe {
|
||||
let tss_ptr = core::ptr::addr_of_mut!(TSS);
|
||||
(*tss_ptr).rsp0 = stack_top;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user