feat: docs & ARCH 2.2, 2.3, 2.4

This commit is contained in:
Faynot
2026-07-07 16:40:41 +03:00
parent c092a81331
commit 1bfde637d0
50 changed files with 5113 additions and 1823 deletions

115
kernel/docs/cpu/idt.md Normal file
View File

@@ -0,0 +1,115 @@
# Interrupt Descriptor Table: `idt.rs`
## Аппаратная модель
IDT (Interrupt Descriptor Table) — это таблица из 256 entry (по 16 байт каждая),
которая сообщает CPU, куда передавать управление при прерываниях и исключениях.
```
IDT:
┌──────┬──────────────────────────────────────────────────────┐
│ 0 │ #DE — Divide Error │
│ 1 │ #DB — Debug │
│ 2 │ #NMI — Non-Maskable Interrupt │
│ 3 │ #BP — Breakpoint │
│ 4 │ #OF — Overflow │
│ 5 │ #BR — Bound Range Exceeded │
│ 6 │ #UD — Undefined Opcode │
│ 7 │ #NM — Device Not Available │
│ 8 │ #DF — Double Fault │
│ 9 │ #MF — Coprocessor Segment Overrun │
│ 10 │ #TS — Invalid TSS │
│ 11 │ #NP — Segment Not Present │
│ 12 │ #SS — Stack-Segment Fault │
│ 13 │ #GP — General Protection Fault │
│ 14 │ #PF — Page Fault │
│ 15-31│ Reserved / CPU exceptions │
│ 32-255│ User-defined (hardware interrupts) │
└──────┴──────────────────────────────────────────────────────┘
```
Загрузка IDT: инструкция `lidt [idtr_ptr]`, где `idtr_ptr` — это
6-байтовая структура `IdtPtr`:
```
IdtPtr:
┌──────────┬──────────┐
│ limit:16 │ base:48 │
└──────────┴──────────┘
```
## IdtEntry — 16-байтовая запись
```rust
#[repr(C, packed)]
pub struct IdtEntry {
offset_low: u16, // Бит 0:15 адреса обработчика
selector: u16, // Селектор сегмента кода (0x28 для ядра)
ist: u8, // Interrupt Stack Table
type_attr: u8, // Тип вентиля + флаги
offset_mid: u16, // Бит 16:31 адреса обработчика
offset_high: u32, // Бит 32:63 адреса обработчика
ignore: u32, // Зарезервировано
}
```
**type_attr:**
- Бит 7: Present (должен быть 1)
- Бит 6-5: DPL (Descriptor Privilege Level)
- Бит 4: Reserved (0)
- Бит 3-0: Gate Type (0xE = Interrupt Gate, 0xF = Trap Gate)
`set_handler(handler, selector, flags)`:
```rust
pub fn set_handler(&mut self, handler: u64, selector: u16, flags: u8) {
self.offset_low = handler as u16;
self.selector = selector;
self.ist = 0;
self.type_attr = flags | 0x80; // Present bit forced on
self.offset_mid = (handler >> 16) as u16;
self.offset_high = (handler >> 32) as u32;
}
```
## InterruptDescriptorTable — 256 entry
```rust
pub struct InterruptDescriptorTable {
entries: [IdtEntry; 256], // 256 × 16 = 4096 байт
}
```
**Методы:**
- `set_handler(vector, handler)` — устанавливает обработчик с
селектором 0x28 (GDT code segment) и type_attr 0x8E
(Interrupt Gate, Ring 0, Present).
- `load()``lidt` инструкция.
```rust
pub unsafe fn load(&'static self) {
let ptr = IdtPtr {
limit: (size_of::<Self>() - 1) as u16, // 4095
base: self as *const _ as u64,
};
asm!("lidt [{}]", in(reg) &ptr);
}
```
## Глобальная IDT
```rust
pub static mut IDT: InterruptDescriptorTable = InterruptDescriptorTable::new();
```
`static mut` — потому что IDT модифицируется в ранней инициализации,
до включения прерываний. Потенциально может быть заменён на `static`
с `UnsafeCell`.
## Детали конфигурации
- **Selector**: `0x28` — это GDT entry для ring 0 code segment
(дескриптор 5, 5 × 8 = 0x28). Селектор сегмента кода в long mode.
- **Type 0x8E**: `1000_1110` = бит 7 (Present) + бит 3:0 = 1110
(Interrupt Gate, 32-bit). В 64-bit режиме все вентили — 64-bit,
флаг 0xE остаётся корректным.
- **IST**: 0 — не используем Interrupt Stack Table (один стек для
всех обработчиков).