fix: bugs
This commit is contained in:
142
kernel/docs/interrupts.md
Normal file
142
kernel/docs/interrupts.md
Normal 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) |
|
||||
Reference in New Issue
Block a user