4.3 KiB
4.3 KiB
Прерывания
IDT (Interrupt Descriptor Table)
Файл: src/cpu/idt.rs
IdtEntry — #[repr(C, packed)]
Структура записи IDT (x86-64):
struct IdtEntry {
offset_low: u16, // адрес обработчика [15:0]
selector: u16, // селектор кода (0x28 — kernel CS)
ist: u8, // Interrupt Stack Table index
type_attr: u8, // тип шлюза, DPL, Present
offset_mid: u16, // адрес обработчика [31:16]
offset_high: u32, // адрес обработчика [63:32]
ignore: u32, // резерв (0)
}
new()— все поля нулиset_handler(handler: u64, selector: u16, flags: u8)— устанавливает адрес и флаги. Принудительно ставит Present (0x80) в flags.
IdtPtr — #[repr(C, packed)]
struct IdtPtr {
limit: u16, // размер IDT - 1
base: u64, // адрес IDT
}
Загружается инструкцией lidt.
InterruptDescriptorTable
struct InterruptDescriptorTable {
entries: [IdtEntry; 256], // 256 векторов
}
set_handler(vector, handler: u64)— устанавливает обработчик на вектор. Селектор:0x28(kernel code), flags:0x8E(32-bit interrupt gate, ring 0, present).load()—unsafe fn: вызываетlidtс&self.
Обработчики прерываний
Файл: src/cpu/interrupts.rs
Глобальная IDT
pub static mut IDT: InterruptDescriptorTable;
Константы
TLB_SHOOTDOWN_VECTOR: u8 = 0xFD
Ассемблерные заглушки (global_asm!)
page_fault_stub
save all registers (push rax, rcx, rdx, rbx, rbp, rsi, rdi, r8-r15)
mov rdi, [rsp + 15*8] ; error code из стека → 1-й аргумент
call rust_page_fault_handler
restore all registers
add rsp, 8 ; убрать error code
iretq
tlb_shootdown_stub
save all registers
call rust_tlb_shootdown_handler
restore all registers
iretq
init_idt()
- Устанавливает вектор 14 →
page_fault_stub - Устанавливает вектор
TLB_SHOOTDOWN_VECTOR→tlb_shootdown_stub IDT.load()
process_deferred_mmu_events()
Лочит KERNEL_SPACE, вызывает process_pending_revocations() — дренаж очереди отзыва.
rust_page_fault_handler(error_code: u64)
#[unsafe(no_mangle)] pub extern "C" fn
- Читает CR2 (адрес fault)
- Из error_code: бит 1 = write, бит 0 = present
- Сначала
process_deferred_mmu_events()— обработка ревокаций до захвата VMM (deadlock prevention) - Лочит
KERNEL_SPACE, вызываетhandle_fault(virt_addr, write) - При неудаче: паника с деталями (address, read/write, present, error_code)
- При успехе: возврат — инструкция будет перезапущена
rust_tlb_shootdown_handler()
handle_tlb_shootdown_ipi()— локальный сброс TLBsend_eoi()— подтверждение LAPIC
Local APIC
Файл: src/cpu/lapic.rs
Драйвер Local APIC (Advanced Programmable Interrupt Controller).
Константы
LAPIC_DEFAULT_BASE = 0xFEE0_0000 // стандартный MMIO адрес LAPIC
LAPIC_EOI = 0x0B0 // End-Of-Interrupt регистр
LAPIC_ICR_LOW = 0x300 // Interrupt Command Register (low)
LAPIC_VIRT_BASE: AtomicU64
Кэшированный виртуальный адрес LAPIC MMIO (HHDM + default base).
Функции
| Функция | Описание |
|---|---|
init(hhdm_offset) |
Вычисляет и сохраняет LAPIC_VIRT_BASE = 0xFEE0_0000 + hhdm_offset |
current_core_id() -> u32 |
CPUID leaf 1, EBX[31:24] — Initial APIC ID |
write_lapic_reg(offset, value) |
Volatile write u32 в LAPIC MMIO |
send_eoi() |
write_lapic_reg(LAPIC_EOI, 0) — подтверждение прерывания |
broadcast_ipi_exclude_self(vector) |
IPI всем остальным ядрам через ICR (destination shorthand = 10b = all except self) |