107 lines
5.5 KiB
Markdown
107 lines
5.5 KiB
Markdown
# CPU подсистема: концептуальная модель
|
||
|
||
## Состав и ответственность
|
||
|
||
CPU подсистема отвечает за:
|
||
|
||
1. **Обработку прерываний и исключений** — IDT, обработчики.
|
||
2. **Исключения ранней загрузки** — пока ядро ещё не полностью инициализировано.
|
||
3. **TLB Shootdown** — межпроцессорное прерывание для синхронизации TLB.
|
||
4. **Local APIC** — программируемый контроллер прерываний.
|
||
|
||
```
|
||
CPU Subsystem
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ CPU Core #0 │
|
||
│ │
|
||
│ ┌──────────────┐ ┌─────────────────────────┐ │
|
||
│ │ LAPIC │ │ IDT │ │
|
||
│ │ │ │ │ │
|
||
│ │ ICR ────────┼────────► 0: #DE (Divide Error) │ │
|
||
│ │ EOI │ │ 1: #DB (Debug) │ │
|
||
│ │ (timer) │ │ ... │ │
|
||
│ │ │ │ 8: #DF (Double Fault) │ │
|
||
│ │ │ │ 13: #GP (GPF) │ │
|
||
│ │ │ │ 14: #PF (Page Fault) │ │
|
||
│ │ │ │ ... │ │
|
||
│ │ │ │ 0xFD: TLB Shootdown │ │
|
||
│ └──────────────┘ └─────────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
## Модули
|
||
|
||
| Файл | Компонент | Функция |
|
||
|------|-----------|---------|
|
||
| `idt.rs` | IDT структуры | Определение IdtEntry, IdtPtr, InterruptDescriptorTable |
|
||
| `interrupts.rs` | Обработчики | Early handlers, Page Fault, Double Fault, GPF, TLB shootdown |
|
||
| `lapic.rs` | Local APIC | Инициализация LAPIC, EOI, broadcast IPI |
|
||
|
||
## Порядок инициализации
|
||
|
||
```
|
||
kmain()
|
||
│
|
||
├── cpu::interrupts::init_early_exceptions()
|
||
│ └── IDT для векторов 0-31 + TLB shootdown (0xFD)
|
||
│
|
||
├── ... (PMM, LAPIC, Page tables) ...
|
||
│
|
||
├── cpu::interrupts::init_idt()
|
||
│ └── Перезагрузка IDT с полными обработчиками
|
||
│
|
||
├── STI (разрешение прерываний)
|
||
│
|
||
└── ... (работа с прерываниями)
|
||
```
|
||
|
||
## Обработка исключений: два этапа
|
||
|
||
### Этап 1: Early (до VMM)
|
||
|
||
На раннем этапе загрузки (до настройки page tables и heap) ядро
|
||
не может обрабатывать сложные исключения. Для векторов 0-31
|
||
устанавливаются `early_handler_N`, которые:
|
||
|
||
1. Пушат вектор и (возможно) dummy error code.
|
||
2. Переходят в `early_common`.
|
||
3. Сохраняют все регистры.
|
||
4. Вызывают `rust_early_exception_handler(vector, error_code)`.
|
||
5. Паникуют (HALT).
|
||
|
||
### Этап 2: Полный (после VMM)
|
||
|
||
После инициализации VMM три критических исключения получают
|
||
полноценные обработчики:
|
||
|
||
- **Page Fault (#PF, вектор 14)**: попытка обработать (COW, lazy).
|
||
- **Double Fault (#DF, вектор 8)**: HALT с сообщением.
|
||
- **General Protection Fault (#GPF, вектор 13)**: HALT с сообщением.
|
||
- **TLB Shootdown (вектор 0xFD)**: межпроцессорный TLB сброс.
|
||
|
||
## TLB Shootdown: модель
|
||
|
||
При изменении page tables на одном ядре, TLB других ядер устаревает.
|
||
Протокол:
|
||
|
||
```
|
||
CPU 0 (инициатор) CPU 1 (мишень)
|
||
│ │
|
||
├── local_tlb_flush_asid() │
|
||
├── SHOOTDOWN_LOCK.lock() │
|
||
├── SHOOTDOWN_ASID = asid │
|
||
├── SHOOTDOWN_ACK = 0 │
|
||
├── LAPIC: broadcast IPI │
|
||
│ (вектор TLB_SHOOTDOWN_VECTOR) ───► прерывание!
|
||
│ ├── handle_tlb_shootdown_ipi()
|
||
│ ├── local_tlb_flush_asid()
|
||
│ ├── SHOOTDOWN_ACK |= 1 << core
|
||
│ ├── LAPIC::send_eoi()
|
||
│ └── iretq
|
||
│ │
|
||
├── spin_loop() ◄────────────────────┤
|
||
│ (ждёт ACK от всех ядер) │
|
||
├── SHOOTDOWN_LOCK.unlock() │
|
||
└── continue │
|
||
```
|