Register Constants and Offsets

Relevant source files

This document covers the register constant definitions and address offset mappings used by the virtual Local APIC implementation. It documents the ApicRegOffset enum that standardizes access to all APIC registers, the index enums for register arrays, and the address translation functions that convert between xAPIC MMIO addresses and x2APIC MSR addresses to unified register offsets.

For information about the actual register layouts and bit field definitions, see the Local Vector Table documentation (3.2) and Control and Status Registers (3.3).

ApicRegOffset Enum

The ApicRegOffset enum serves as the central abstraction for all APIC register types, providing a unified interface for both xAPIC and x2APIC access modes. Each variant corresponds to a specific APIC register defined in the Intel x86 architecture specification.

flowchart TD
subgraph subGraph5["ApicRegOffset Register Categories"]
    subgraph LVT_Registers["Local Vector Table"]
        TimerInitCount["TimerInitCount (0x38)"]
        TimerCurCount["TimerCurCount (0x39)"]
        TimerDivConf["TimerDivConf (0x3E)"]
        LvtTimer["LvtTimer (0x32)"]
        LvtThermal["LvtThermal (0x33)"]
        LvtPmc["LvtPmc (0x34)"]
        LvtLint0["LvtLint0 (0x35)"]
        LvtLint1["LvtLint1 (0x36)"]
        LvtErr["LvtErr (0x37)"]
        LvtCMCI["LvtCMCI (0x2F)"]
        ISR["ISR[0-7] (0x10-0x17)"]
        TMR["TMR[0-7] (0x18-0x1F)"]
        IRR["IRR[0-7] (0x20-0x27)"]
        EOI["EOI (0xB)"]
        SIVR["SIVR (0xF)"]
        ESR["ESR (0x28)"]
        ICRLow["ICRLow (0x30)"]
        ICRHi["ICRHi (0x31)"]
        ID["ID (0x2)"]
        Version["Version (0x3)"]
        TPR["TPR (0x8)"]
        APR["APR (0x9)"]
        PPR["PPR (0xA)"]
        subgraph Interrupt_Management["Interrupt Management"]
            subgraph Control_Registers["Control Registers"]
                TimerInitCount["TimerInitCount (0x38)"]
                TimerCurCount["TimerCurCount (0x39)"]
                TimerDivConf["TimerDivConf (0x3E)"]
                LvtTimer["LvtTimer (0x32)"]
                LvtThermal["LvtThermal (0x33)"]
                LvtPmc["LvtPmc (0x34)"]
                LvtLint0["LvtLint0 (0x35)"]
                ISR["ISR[0-7] (0x10-0x17)"]
                TMR["TMR[0-7] (0x18-0x1F)"]
                IRR["IRR[0-7] (0x20-0x27)"]
                EOI["EOI (0xB)"]
                SIVR["SIVR (0xF)"]
                ESR["ESR (0x28)"]
                ICRLow["ICRLow (0x30)"]
                ICRHi["ICRHi (0x31)"]
                ID["ID (0x2)"]
                Version["Version (0x3)"]
                TPR["TPR (0x8)"]
                APR["APR (0x9)"]
                PPR["PPR (0xA)"]
                subgraph Timer_Subsystem["Timer Subsystem"]
                    subgraph Register_Arrays["Register Arrays"]
                        TimerInitCount["TimerInitCount (0x38)"]
                        TimerCurCount["TimerCurCount (0x39)"]
                        TimerDivConf["TimerDivConf (0x3E)"]
                        LvtTimer["LvtTimer (0x32)"]
                        LvtThermal["LvtThermal (0x33)"]
                        LvtPmc["LvtPmc (0x34)"]
                        LvtLint0["LvtLint0 (0x35)"]
                        ISR["ISR[0-7] (0x10-0x17)"]
                        TMR["TMR[0-7] (0x18-0x1F)"]
                        IRR["IRR[0-7] (0x20-0x27)"]
                        EOI["EOI (0xB)"]
                        SIVR["SIVR (0xF)"]
                        ESR["ESR (0x28)"]
                        ICRLow["ICRLow (0x30)"]
                        ID["ID (0x2)"]
                        Version["Version (0x3)"]
                        TPR["TPR (0x8)"]
                        APR["APR (0x9)"]
                    end
                end
            end
        end
    end
end

The enum implements a from method that performs offset-to-register mapping based on the numeric offset values defined in the Intel specification. Register arrays like ISR, TMR, and IRR use index-based variants to represent their 8-register sequences.

Sources: src/consts.rs(L61 - L114)  src/consts.rs(L116 - L148) 

Register Array Index Enums

Three specialized index enums handle the APIC's 256-bit register arrays, each consisting of 8 consecutive 32-bit registers:

Array TypeIndex EnumRegister RangePurpose
In-Service RegisterISRIndex0x10-0x17Tracks interrupts currently being serviced
Trigger Mode RegisterTMRIndex0x18-0x1FStores trigger mode for each interrupt vector
Interrupt Request RegisterIRRIndex0x20-0x27Queues pending interrupt requests
flowchart TD
subgraph Concrete_Types["Concrete Index Types"]
    ISRIndex["ISRIndex (ISR0-ISR7)"]
    TMRIndex["TMRIndex (TMR0-TMR7)"]
    IRRIndex["IRRIndex (IRR0-IRR7)"]
end
subgraph Index_Enum_Pattern["Index Enum Pattern"]
    IndexEnum["Index0 through Index7"]
    subgraph Generated_Methods["Generated Methods"]
        from_method["from(usize) -> Self"]
        as_usize_method["as_usize() -> usize"]
        display_method["Display trait"]
    end
end

IndexEnum --> as_usize_method
IndexEnum --> display_method
IndexEnum --> from_method

The define_index_enum! macro generates identical implementations for all three index types, providing type-safe indexing into the 8-register arrays while maintaining zero runtime cost through const evaluation.

Sources: src/consts.rs(L3 - L54)  src/consts.rs(L56 - L58) 

Address Translation Functions

The virtual APIC supports both xAPIC (MMIO-based) and x2APIC (MSR-based) access modes through dedicated address translation functions that convert guest addresses to ApicRegOffset values.

flowchart TD
subgraph Unified_Output["Unified Register Access"]
    ApicRegOffset_Output["ApicRegOffset enumNormalized register identifier"]
end
subgraph Translation_Functions["Translation Functions"]
    xapic_mmio_access_reg_offset["xapic_mmio_access_reg_offset()(addr & 0xFFF) >> 4"]
    x2apic_msr_access_reg["x2apic_msr_access_reg()addr - 0x800"]
end
subgraph Guest_Access_Methods["Guest Access Methods"]
    xAPIC_MMIO["xAPIC MMIO AccessGuestPhysAddr0xFEE0_0000-0xFEE0_0FFF"]
    x2APIC_MSR["x2APIC MSR AccessSysRegAddr0x800-0x8FF"]
end

x2APIC_MSR --> x2apic_msr_access_reg
x2apic_msr_access_reg --> ApicRegOffset_Output
xAPIC_MMIO --> xapic_mmio_access_reg_offset
xapic_mmio_access_reg_offset --> ApicRegOffset_Output

xAPIC MMIO Translation

The xapic_mmio_access_reg_offset function extracts the 12-bit offset from the guest physical address and shifts right by 4 bits to obtain the register index. This follows the xAPIC specification where registers are aligned on 16-byte boundaries within the 4KB APIC page.

Address RangeCalculationRegister Type
0xFEE0_0020(0x20 & 0xFFF) >> 4 = 0x2ID Register
0xFEE0_0100(0x100 & 0xFFF) >> 4 = 0x10ISR[0]
0xFEE0_0320(0x320 & 0xFFF) >> 4 = 0x32LVT Timer

x2APIC MSR Translation

The x2apic_msr_access_reg function performs simple offset subtraction from the MSR base address 0x800. x2APIC mode provides a flat MSR address space for APIC registers.

MSR AddressCalculationRegister Type
0x8020x802 - 0x800 = 0x2ID Register
0x8100x810 - 0x800 = 0x10ISR[0]
0x8320x832 - 0x800 = 0x32LVT Timer

Sources: src/consts.rs(L192 - L203)  src/consts.rs(L205 - L216) 

Reset Values and Default Constants

The system defines standard reset values for APIC registers according to Intel specifications:

flowchart TD
subgraph Address_Constants["Address Space Constants"]
    X2APIC_MSE_REG_SIZE["X2APIC_MSE_REG_SIZE0x100256 MSR range"]
    subgraph Reset_Constants["Reset Value Constants"]
        DEFAULT_APIC_BASE["DEFAULT_APIC_BASE0xFEE0_0000xAPIC MMIO base"]
        APIC_MMIO_SIZE["APIC_MMIO_SIZE0x10004KB page size"]
        X2APIC_MSE_REG_BASE["X2APIC_MSE_REG_BASE0x800x2APIC MSR base"]
        RESET_LVT_REG["RESET_LVT_REG0x0001_0000LVT registers after reset"]
        RESET_SPURIOUS_INTERRUPT_VECTOR["RESET_SPURIOUS_INTERRUPT_VECTOR0x0000_00FFSIVR after reset"]
    end
end
ConstantValuePurposeSpecification Reference
RESET_LVT_REG0x0001_0000LVT register reset stateIntel Manual 11.5.1
RESET_SPURIOUS_INTERRUPT_VECTOR0x0000_00FFSIVR reset stateIntel Manual 11.9
DEFAULT_APIC_BASE0xFEE0_0000Standard xAPIC MMIO baseIntel Manual 11.4.1
APIC_MMIO_SIZE0x1000xAPIC page sizeIntel Manual 11.4.1

The reset values ensure that LVT registers start in a masked state (bit 16 set) and the spurious interrupt vector defaults to vector 0xFF, providing safe initialization conditions for the virtual APIC.

Sources: src/consts.rs(L183 - L191)  src/consts.rs(L197 - L198)  src/consts.rs(L210 - L211)