LAPIC
This document describes the Local APIC implementation in the Kyronix kernel. It is the child of x86-64 Architecture.
Source
kernel/arch/x86_64/lapic.c
Overview
The Local APIC (Advanced Programmable Interrupt Controller) provides per-CPU interrupt handling, Inter-Processor Interrupts (IPIs), and the LAPIC timer. The MMIO registers are mapped at virtual address 0xfffffe0000000000.
Initialization
- Read
IA32_APIC_BASEMSR to get physical MMIO address - Enable LAPIC if disabled (set
IA32_APIC_BASE_ENABLE) - Map physical LAPIC to
LAPIC_VIRTwithVMM_KDATA | VMM_PCD(page-cache disabled for MMIO) - Enable Spurious Vector Register (SVR) with spurious vector
- Mask error, thermal, performance, and timer LVT entries
- Clear Task Priority Register (TPR)
- Read LAPIC ID and version
Key Functions
| Function | Description |
|---|---|
lapic_init() | Full LAPIC initialization and MMIO mapping |
lapic_eoi() | Write 0 to EOI register (end-of-interrupt) |
lapic_send_ipi(lapic_id, icr_lo) | Send IPI to specific LAPIC |
lapic_send_ipi_self(icr_lo) | Send self-IPI |
lapic_calibrate_timer() | Calibrate LAPIC timer against PIT |
lapic_timer_start_periodic(hz) | Start periodic timer at given frequency |
lapic_timer_freq() | Return calibrated timer frequency (ticks/ms) |
Timer Calibration
The calibration algorithm:
- Set LAPIC timer to one-shot mode with divisor
0x0Band initial count0xFFFFFFFF - Count 5 PIT counter wraps (each wrap = one PIT period)
- Compute
remaining = 0xFFFFFFFF - current_count - Derive
g_lapic_timer_freq = remaining / 5(ticks per millisecond)
The LAPIC timer is then started in periodic mode at 250 Hz for scheduling ticks.
IPI Mechanism
Inter-Processor Interrupts are sent via the Interrupt Command Register (ICR):
- Wait for send-pending bit to clear
- Write target LAPIC ID to ICR_HI
- Write delivery info to ICR_LO
- Wait for send-pending to clear again
Register Layout
| Offset | Register | Description |
|---|---|---|
| 0x20 | TPR | Task Priority Register |
| 0x80 | EOI | End of Interrupt |
| 0xB0 | ICR_LO | Interrupt Command (low) |
| 0xC0 | ICR_HI | Interrupt Command (high) |
| 0xD0 | SVR | Spurious Vector Register |
| 0x320 | LVT Timer | Timer LVT entry |
| 0x350 | LVT LINT0 | LINT0 LVT entry |
| 0x360 | LVT LINT1 | LINT1 LVT entry |
| 0x370 | LVT Error | Error LVT entry |
Last reviewed: 2026-07-22