fix: bugs

This commit is contained in:
Faynot
2026-07-06 00:25:49 +03:00
parent 1b38c7f445
commit c092a81331
23 changed files with 2502 additions and 123 deletions

142
kernel/docs/interrupts.md Normal file
View File

@@ -0,0 +1,142 @@
# Прерывания
---
## IDT (Interrupt Descriptor Table)
**Файл**: `src/cpu/idt.rs`
### IdtEntry — `#[repr(C, packed)]`
Структура записи IDT (x86-64):
```rust
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)]`
```rust
struct IdtPtr {
limit: u16, // размер IDT - 1
base: u64, // адрес IDT
}
```
Загружается инструкцией `lidt`.
### InterruptDescriptorTable
```rust
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
```rust
pub static mut IDT: InterruptDescriptorTable;
```
### Константы
`TLB_SHOOTDOWN_VECTOR: u8 = 0xFD`
### Ассемблерные заглушки (global_asm!)
#### `page_fault_stub`
```asm
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`
```asm
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`
1. Читает CR2 (адрес fault)
2. Из error_code: бит 1 = write, бит 0 = present
3. **Сначала** `process_deferred_mmu_events()` — обработка ревокаций до захвата VMM (deadlock prevention)
4. Лочит `KERNEL_SPACE`, вызывает `handle_fault(virt_addr, write)`
5. При неудаче: паника с деталями (address, read/write, present, error_code)
6. При успехе: возврат — инструкция будет перезапущена
### `rust_tlb_shootdown_handler()`
1. `handle_tlb_shootdown_ipi()` — локальный сброс TLB
2. `send_eoi()` — подтверждение LAPIC
---
## Local APIC
**Файл**: `src/cpu/lapic.rs`
Драйвер Local APIC (Advanced Programmable Interrupt Controller).
### Константы
```rust
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) |