Files
Elyz/kernel/src/cpu/interrupts.rs
2026-06-28 20:31:23 +03:00

143 lines
3.3 KiB
Rust

use core::arch::global_asm;
use core::arch::asm;
use crate::mem::vmm::KERNEL_SPACE;
use crate::mem::address::VirtAddr;
pub static mut IDT: crate::cpu::idt::InterruptDescriptorTable = crate::cpu::idt::InterruptDescriptorTable::new();
pub const TLB_SHOOTDOWN_VECTOR: u8 = 0xFD;
global_asm!(
".global page_fault_stub",
"page_fault_stub:",
"push rax",
"push rcx",
"push rdx",
"push rbx",
"push rbp",
"push rsi",
"push rdi",
"push r8",
"push r9",
"push r10",
"push r11",
"push r12",
"push r13",
"push r14",
"push r15",
".global tlb_shootdown_stub",
"tlb_shootdown_stub:",
"push rax",
"push rcx",
"push rdx",
"push rbx",
"push rbp",
"push rsi",
"push rdi",
"push r8",
"push r9",
"push r10",
"push r11",
"push r12",
"push r13",
"push r14",
"push r15",
"call rust_tlb_shootdown_handler",
"mov rdi, [rsp + 15*8]",
"call rust_page_fault_handler",
"pop r15",
"pop r14",
"pop r13",
"pop r12",
"pop r11",
"pop r10",
"pop r9",
"pop r8",
"pop rdi",
"pop rsi",
"pop rbp",
"pop rbx",
"pop rdx",
"pop rcx",
"pop rax",
"add rsp, 8",
"iretq"
);
unsafe extern "C" {
fn page_fault_stub();
fn tlb_shootdown_stub();
}
pub fn init_idt() {
unsafe {
let idt_mut_ptr = core::ptr::addr_of_mut!(IDT);
(*idt_mut_ptr).set_handler(14, page_fault_stub as u64);
(*idt_mut_ptr).set_handler(TLB_SHOOTDOWN_VECTOR, tlb_shootdown_stub as u64);
let idt_static_ref: &'static crate::cpu::idt::InterruptDescriptorTable = &*core::ptr::addr_of!(IDT);
idt_static_ref.load();
}
}
pub fn process_deferred_mmu_events() {
let mut vmm_guard = KERNEL_SPACE.lock();
if let Some(space) = vmm_guard.as_mut() {
space.process_pending_revocations();
}
}
#[unsafe(no_mangle)]
pub extern "C" fn rust_page_fault_handler(error_code: u64) {
let fault_addr: u64;
unsafe {
asm!("mov {}, cr2", out(reg) fault_addr, options(nomem, nostack, preserves_flags));
}
let write = (error_code & 0x2) != 0;
let present = (error_code & 0x1) != 0;
let virt_addr = VirtAddr(fault_addr);
process_deferred_mmu_events();
let mut vmm_guard = KERNEL_SPACE.lock();
if let Some(space) = vmm_guard.as_mut() {
match space.handle_fault(virt_addr, write) {
Ok(_) => return,
Err(e) => {
panic!(
"KERNEL PANIC: Unprocessed failure of virtual memory (Page Fault)!\n\
Address: {:#X}\n\
Mode: {}\n\
Presence: {}\n\
Cause VMM: {:?}",
fault_addr,
if write { "WRITE" } else { "READ" },
if present { "YES (Protection Violation)" } else { "NO (Not Present)" },
e
);
}
}
} else {
panic!(
"KERNEL PANIC: Critical Page Fault before alocate global KERNEL_SPACE!\n\
Адрес сбоя: {:#X}",
fault_addr
);
}
}
#[unsafe(no_mangle)]
pub extern "C" fn rust_tlb_shootdown_handler() {
crate::mem::vmm::handle_tlb_shootdown_ipi();
crate::cpu::lapic::send_eoi();
}