feat: docs & ARCH 2.2, 2.3, 2.4
This commit is contained in:
115
kernel/docs/cpu/lapic.md
Normal file
115
kernel/docs/cpu/lapic.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# Local APIC: `lapic.rs`
|
||||
|
||||
## Аппаратная модель
|
||||
|
||||
**Local APIC** (Advanced Programmable Interrupt Controller) — это
|
||||
встроенный в каждое ядро x86-64 контроллер прерываний.
|
||||
|
||||
```
|
||||
Local APIC (MMIO, начиная с 0xFEE00_000)
|
||||
┌──────────────────────────────┐
|
||||
│ 0x020: IRR (In-Service Reg) │
|
||||
│ 0x030: TMR (Trigger Mode) │
|
||||
│ 0x080: EOI │ ← запись 0 = подтверждение прерывания
|
||||
│ 0x0B0: LINT0/LINT1 │
|
||||
│ 0x0E0: Timer │
|
||||
│ 0x200: LVT Error │
|
||||
│ 0x300: ICR (Interrupt Cmd) │ ← отправка межпроцессорного прерывания
|
||||
│ 0x310: ICR_HIGH (APIC ID) │
|
||||
└──────────────────────────────┘
|
||||
```
|
||||
|
||||
## Регистры
|
||||
|
||||
| Смещение | Регистр | Назначение |
|
||||
|----------|---------|------------|
|
||||
| 0x0B0 | EOI | End Of Interrupt — подтверждение обработки |
|
||||
| 0x300 | ICR (low) | Interrupt Command Register — отправка IPI |
|
||||
| 0x310 | ICR (high) | Destination APIC ID |
|
||||
|
||||
## Инициализация
|
||||
|
||||
```rust
|
||||
static LAPIC_VIRT_BASE: AtomicU64 = AtomicU64::new(0);
|
||||
|
||||
pub fn init() {
|
||||
// LAPIC отображён bootloader'ом в HHDM по адресу 0xFEE00_000
|
||||
LAPIC_VIRT_BASE.store(LAPIC_DEFAULT_BASE + get_hhdm(), Ordering::SeqCst);
|
||||
}
|
||||
```
|
||||
|
||||
LAPIC расположен по физическому адресу `0xFEE0_0000`. Ядро получает
|
||||
виртуальный базовый адрес, добавляя HHDM offset.
|
||||
|
||||
## Доступ к регистрам
|
||||
|
||||
```rust
|
||||
#[inline(always)]
|
||||
fn write_lapic_reg(offset: u64, value: u32) {
|
||||
let base = LAPIC_VIRT_BASE.load(Ordering::Relaxed);
|
||||
if base == 0 { return; } // LAPIC ещё не инициализирован
|
||||
unsafe { core::ptr::write_volatile((base + offset) as *mut u32, value) }
|
||||
}
|
||||
```
|
||||
|
||||
- `write_volatile` — запрещает компилятору оптимизировать обращение
|
||||
(регистры MMIO).
|
||||
- `Relaxed` ordering — для отладки/инициализации достаточно.
|
||||
|
||||
## Операции
|
||||
|
||||
### send_eoi() — конец прерывания
|
||||
|
||||
```rust
|
||||
pub fn send_eoi() {
|
||||
write_lapic_reg(LAPIC_EOI, 0); // 0x0B0
|
||||
}
|
||||
```
|
||||
|
||||
### broadcast_ipi_exclude_self(vector) — IPI всем, кроме себя
|
||||
|
||||
```rust
|
||||
pub fn broadcast_ipi_exclude_self(vector: u8) {
|
||||
// ICR[19:18] = 10b (All Excluding Self)
|
||||
// ICR[14] = 1 (Assert)
|
||||
// ICR[7:0] = vector
|
||||
let icr_low = (2 << 18) | (1 << 14) | (vector as u32);
|
||||
write_lapic_reg(LAPIC_ICR_LOW, icr_low);
|
||||
}
|
||||
```
|
||||
|
||||
Используется для TLB shootdown — необходимо разослать всем ядрам
|
||||
(кроме текущего) IPI с вектором `TLB_SHOOTDOWN_VECTOR`.
|
||||
|
||||
### current_core_id() — определение текущего ядра
|
||||
|
||||
```rust
|
||||
pub fn current_core_id() -> u32 {
|
||||
// CPUID leaf 1: EBX[31:24] = Local APIC ID
|
||||
let mut ebx: u32;
|
||||
asm!(
|
||||
"mov {tmp:r}, rbx", // спрятать rbx (резерв LLVM)
|
||||
"mov eax, 1", "cpuid",
|
||||
"mov {out:e}, ebx", // сохранить EBX
|
||||
"mov rbx, {tmp:r}", // восстановить rbx
|
||||
tmp = out(reg) _,
|
||||
out = out(reg) ebx,
|
||||
...
|
||||
);
|
||||
ebx >> 24
|
||||
}
|
||||
```
|
||||
|
||||
**RBX проблема:** LLVM резервирует RBX, поэтому его нужно сохранять
|
||||
и восстанавливать вручную вокруг CPUID инструкции.
|
||||
|
||||
## Тонкости
|
||||
|
||||
1. **MMIO vs MSR**: LAPIC можно программировать через MSR (IA32_APIC_BASE)
|
||||
и через MMIO. Bootloader (Limine) настраивает MMIO mapping в HHDM.
|
||||
2. **Инициализация**: LAPIC уже включён bootloader'ом. `init()` просто
|
||||
сохраняет виртуальный адрес.
|
||||
3. **x2APIC**: не используется (в текущей версии — MMIO xAPIC).
|
||||
4. **EOI**: обязателен после каждого прерывания от LAPIC (включая IPI).
|
||||
5. **ICR запись**: после записи в ICR Low, шина APIC доставляет
|
||||
прерывание. Запись блокирующая (ждёт готовности шины).
|
||||
Reference in New Issue
Block a user