Core Architecture
Relevant source files
This document explains the fundamental architectural design of the x86_vlapic virtual Local APIC implementation, covering the main components and their interactions. The architecture provides virtualization of x86 Local APIC functionality for hypervisor environments, supporting both legacy xAPIC (MMIO-based) and modern x2APIC (MSR-based) access patterns.
For detailed information about individual register implementations, see Register System. For specific LVT register functionality, see Local Vector Table (LVT).
Main Architectural Components
The x86_vlapic crate implements a three-layer architecture that provides complete virtualization of Local APIC functionality:
flowchart TD subgraph subGraph3["Physical Memory"] PHYS_PAGE["PhysFrame<H>4KB Allocated Page"] end subgraph subGraph2["Register Virtualization Layer"] VAR["VirtualApicRegs<H>4KB Page Management"] LAPIC_REGS["LocalAPICRegsMemory-Mapped Structure"] LVT_CACHE["LocalVectorTableCached LVT State"] SVR_CACHE["SpuriousInterruptVectorRegisterLocalCached SVR State"] end subgraph subGraph1["Device Interface Layer"] ELA["EmulatedLocalApic<H>BaseDeviceOps Implementation"] XAPIC_TRANS["xapic_mmio_access_reg_offset()GuestPhysAddr → ApicRegOffset"] X2APIC_TRANS["x2apic_msr_access_reg()SysRegAddr → ApicRegOffset"] end subgraph subGraph0["Guest VM Access Layer"] GUEST_MMIO["Guest MMIO Access0xFEE0_0000-0xFEE0_0FFF"] GUEST_MSR["Guest MSR Access0x800-0x8FF"] end ELA --> X2APIC_TRANS ELA --> XAPIC_TRANS GUEST_MMIO --> ELA GUEST_MSR --> ELA LAPIC_REGS --> PHYS_PAGE VAR --> LAPIC_REGS VAR --> LVT_CACHE VAR --> SVR_CACHE X2APIC_TRANS --> VAR XAPIC_TRANS --> VAR
Sources: src/lib.rs(L33 - L44) src/vlapic.rs(L15 - L28) src/consts.rs(L200 - L202) src/consts.rs(L213 - L215)
The EmulatedLocalApic<H>
struct serves as the primary device interface, implementing BaseDeviceOps
for both AddrRange<GuestPhysAddr>
(xAPIC) and SysRegAddrRange
(x2APIC) access patterns. It contains a single VirtualApicRegs<H>
instance that manages the actual register virtualization.
Address Translation Architecture
The system implements two distinct address translation paths to convert guest accesses into internal register offsets:
flowchart TD subgraph subGraph2["Common Register Space"] REG_ENUM["ApicRegOffset enumID, Version, TPR, etc."] end subgraph subGraph1["x2APIC Translation Path"] MSR_ADDR["SysRegAddr0x800 + offset"] MSR_SUB["addr - 0x800"] X2APIC_OFFSET["ApicRegOffset"] end subgraph subGraph0["xAPIC Translation Path"] MMIO_ADDR["GuestPhysAddr0xFEE0_0000 + offset"] MMIO_MASK["addr & 0xFFF"] MMIO_SHIFT["result >> 4"] MMIO_OFFSET["ApicRegOffset"] end MMIO_ADDR --> MMIO_MASK MMIO_MASK --> MMIO_SHIFT MMIO_OFFSET --> REG_ENUM MMIO_SHIFT --> MMIO_OFFSET MSR_ADDR --> MSR_SUB MSR_SUB --> X2APIC_OFFSET X2APIC_OFFSET --> REG_ENUM
Sources: src/consts.rs(L200 - L202) src/consts.rs(L213 - L215) src/consts.rs(L117 - L148)
The xapic_mmio_access_reg_offset()
function extracts the register offset from xAPIC MMIO addresses by masking the lower 12 bits and shifting right by 4, effectively converting byte offsets to 16-byte aligned register indices. The x2apic_msr_access_reg()
function performs simple arithmetic subtraction from the MSR base address. Both paths converge on the same ApicRegOffset
enum, enabling unified register handling.
Virtual Register Memory Management
The VirtualApicRegs<H>
struct implements a sophisticated memory management system that provides both hardware-compatible register layout and software-accessible caching:
flowchart TD subgraph subGraph2["Access Patterns"] DIRECT_ACCESS["Direct Hardware Accessvia virtual_lapic pointer"] CACHED_ACCESS["Cached Accessvia _last structures"] end subgraph subGraph1["4KB Physical Page"] LAPIC_LAYOUT["LocalAPICRegs Memory LayoutHardware-compatible structure"] REG_ARRAYS["Register ArraysISR[8], TMR[8], IRR[8]"] LVT_REGS["LVT RegistersTimer, Thermal, PMC, etc."] CTRL_REGS["Control RegistersID, Version, TPR, SVR, etc."] end subgraph subGraph0["VirtualApicRegs Structure"] VLAPIC_PTR["virtual_lapic: NonNull<LocalAPICRegs>Direct memory access"] APIC_PAGE["apic_page: PhysFrame<H>4KB page ownership"] SVR_LAST["svr_last: SpuriousInterruptVectorRegisterLocalChange detection cache"] LVT_LAST["lvt_last: LocalVectorTableCoherent snapshot cache"] end APIC_PAGE --> LAPIC_LAYOUT LAPIC_LAYOUT --> CTRL_REGS LAPIC_LAYOUT --> LVT_REGS LAPIC_LAYOUT --> REG_ARRAYS LVT_LAST --> CACHED_ACCESS SVR_LAST --> CACHED_ACCESS VLAPIC_PTR --> DIRECT_ACCESS VLAPIC_PTR --> LAPIC_LAYOUT
Sources: src/vlapic.rs(L15 - L28) src/vlapic.rs(L32 - L40) src/vlapic.rs(L55 - L59)
The system allocates a zero-initialized 4KB page using PhysFrame::alloc_zero()
and maps the LocalAPICRegs
structure directly onto this memory. The NonNull<LocalAPICRegs>
pointer provides direct access to hardware-compatible register layout, while cached copies in svr_last
and lvt_last
enable change detection and maintain coherent snapshots of critical registers.
Device Interface Implementation
The EmulatedLocalApic<H>
implements dual BaseDeviceOps
traits to handle both xAPIC and x2APIC access patterns:
Sources: src/lib.rs(L67 - L112) src/lib.rs(L114 - L159) src/vlapic.rs(L62 - L176)
Both access patterns converge on the same VirtualApicRegs::handle_read()
and VirtualApicRegs::handle_write()
methods, ensuring consistent behavior regardless of the guest's chosen access mode. The EmulatedLocalApic
provides address range information through address_range()
methods and implements device type identification via emu_type()
returning EmuDeviceTInterruptController
.
Static Memory Layout
The architecture includes a static 4KB page for APIC access virtualization:
Component | Purpose | Memory Management |
---|---|---|
VIRTUAL_APIC_ACCESS_PAGE | Static 4KB page for VMX APIC-access page | Statically allocated, aligned to 4KB |
VirtualApicRegs.apic_page | Dynamic 4KB page for register storage | Dynamically allocated viaPhysFrame::alloc_zero() |
virtual_lapicpointer | Direct access to register structure | Points to dynamically allocated page |
Sources: src/lib.rs(L27 - L30) src/lib.rs(L52 - L56) src/vlapic.rs(L32 - L40)
The static VIRTUAL_APIC_ACCESS_PAGE
supports VMX virtualization features, while the dynamic page in VirtualApicRegs
provides the actual register storage and implements proper memory lifecycle management through the Drop
trait.