x86defs/
apic.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! APIC-related definitions.
5
6use bitfield_struct::bitfield;
7use open_enum::open_enum;
8
9/// The physical address of the APIC at reset.
10pub const APIC_BASE_ADDRESS: u32 = 0xfee00000;
11/// The 4KB page number of the physical address of the APIC at reset.
12pub const APIC_BASE_PAGE: u32 = APIC_BASE_ADDRESS >> 12;
13
14pub const APIC_LEGACY_ID_COUNT: u32 = 255;
15
16/// The APIC base MSR.
17#[bitfield(u64)]
18#[derive(PartialEq, Eq)]
19pub struct ApicBase {
20    _reserved: u8,
21    /// True if this processor is the BSP.
22    pub bsp: bool,
23    _reserved2: bool,
24    pub x2apic: bool,
25    pub enable: bool,
26    /// The page number of the APIC (usually APIC_BASE_PAGE).
27    #[bits(24)]
28    pub base_page: u32,
29    #[bits(28)]
30    _reserved3: u64,
31}
32
33/// Spurious vector register.
34#[bitfield(u32)]
35pub struct Svr {
36    pub vector: u8,
37    pub enable: bool,
38    pub focus_processor_checking: bool,
39    #[bits(2)]
40    _rsvd: u32,
41    pub eoi_broadcast_suppression: bool,
42    #[bits(19)]
43    _rsvd2: u32,
44}
45
46/// Local vector table
47#[bitfield(u32)]
48pub struct Lvt {
49    pub vector: u8,
50    #[bits(3)]
51    pub delivery_mode: u8,
52    _rsvd: bool,
53    pub delivery_status: bool,
54    pub input_pin_polarity: bool,
55    pub remote_irr: bool,
56    pub trigger_mode_level: bool,
57    pub masked: bool,
58    #[bits(2)]
59    pub timer_mode: u8,
60    #[bits(13)]
61    _rsvd2: u32,
62}
63
64open_enum! {
65    pub enum TimerMode: u8 {
66        ONE_SHOT = 0,
67        PERIODIC = 1,
68        TSC_DEADLINE = 2,
69    }
70}
71
72#[bitfield(u32)]
73pub struct Dcr {
74    #[bits(2)]
75    pub value_low: u8,
76    _rsvd: bool,
77    #[bits(1)]
78    pub value_high: u8,
79    #[bits(28)]
80    _rsvd2: u32,
81}
82
83open_enum! {
84    pub enum Dfr: u32 {
85        FLAT_MODE = 0xffff_ffff,
86        CLUSTERED_MODE = 0x0fff_ffff,
87    }
88}
89
90#[bitfield(u64)]
91pub struct Icr {
92    pub vector: u8,
93    #[bits(3)]
94    pub delivery_mode: u8,
95    pub destination_mode_logical: bool,
96    pub delivery_pending: bool,
97    pub reserved1: bool,
98    pub level_assert: bool,
99    pub trigger_mode_level: bool,
100    #[bits(2)]
101    pub remote_read_status: u8,
102    #[bits(2)]
103    pub destination_shorthand: u8,
104    #[bits(12)]
105    pub reserved3: u16,
106    pub x2apic_mda: u32,
107}
108
109impl Icr {
110    pub const fn xapic_mda(&self) -> u8 {
111        (self.x2apic_mda() >> 24) as u8
112    }
113
114    pub fn set_xapic_mda(&mut self, value: u8) {
115        *self = self.with_xapic_mda(value);
116    }
117
118    pub const fn with_xapic_mda(self, value: u8) -> Self {
119        self.with_x2apic_mda((value as u32) << 24)
120    }
121}
122
123#[bitfield(u32)]
124pub struct X2ApicLogicalId {
125    pub logical_id: u16,
126    pub cluster_id: u16,
127}
128
129#[bitfield(u8)]
130pub struct XApicClusterLogicalId {
131    #[bits(4)]
132    pub logical_id: u8,
133    #[bits(4)]
134    pub cluster_id: u8,
135}
136
137open_enum! {
138    pub enum DeliveryMode: u8 {
139        FIXED = 0,
140        LOWEST_PRIORITY = 1,
141        SMI = 2,
142        REMOTE_READ = 3,
143        NMI = 4,
144        INIT = 5,
145        SIPI = 6,
146        EXTINT = 7,
147    }
148}
149
150open_enum! {
151    pub enum DestinationShorthand: u8 {
152        NONE = 0,
153        SELF = 1,
154        ALL_INCLUDING_SELF = 2,
155        ALL_EXCLUDING_SELF = 3,
156    }
157}
158
159open_enum! {
160    pub enum ApicRegister: u8 {
161        ID = 0x2,               // RW
162        VERSION = 0x3,          // RO
163        TPR = 0x8,              // RW
164        APR = 0x9,              // RO
165        PPR = 0xa,              // RO
166        EOI = 0xb,              // WO
167        RRD = 0xc,              // RO
168        LDR = 0xd,              // RW
169        DFR = 0xe,              // RW
170        SVR = 0xf,              // RW
171        ISR0 = 0x10,            // RO
172        ISR1 = 0x11,
173        ISR2 = 0x12,
174        ISR3 = 0x13,
175        ISR4 = 0x14,
176        ISR5 = 0x15,
177        ISR6 = 0x16,
178        ISR7 = 0x17,
179        TMR0 = 0x18,            // RO
180        TMR1 = 0x19,
181        TMR2 = 0x1a,
182        TMR3 = 0x1b,
183        TMR4 = 0x1c,
184        TMR5 = 0x1d,
185        TMR6 = 0x1e,
186        TMR7 = 0x1f,
187        IRR0 = 0x20,            // RO
188        IRR1 = 0x21,
189        IRR2 = 0x22,
190        IRR3 = 0x23,
191        IRR4 = 0x24,
192        IRR5 = 0x25,
193        IRR6 = 0x26,
194        IRR7 = 0x27,
195        ESR = 0x28,             // RW
196        INTEL_LVT_CMCI = 0x2f,  // RW
197        ICR0 = 0x30,            // RW
198        ICR1 = 0x31,            // RW, XAPIC only
199        LVT_TIMER = 0x32,       // RW
200        LVT_THERMAL = 0x33,     // RW
201        LVT_PMC = 0x34,         // RW
202        LVT_LINT0 = 0x35,       // RW
203        LVT_LINT1 = 0x36,       // RW
204        LVT_ERROR = 0x37,       // RW
205        TIMER_ICR = 0x38,       // RW
206        TIMER_CCR = 0x39,       // RO
207        TIMER_DCR = 0x3e,       // RW
208        SELF_IPI = 0x3f,        // WO, X2APIC only
209    }
210}
211
212pub const X2APIC_MSR_BASE: u32 = 0x800;
213pub const X2APIC_MSR_END: u32 = 0x83f;
214
215impl ApicRegister {
216    pub fn x2apic_msr(&self) -> u32 {
217        X2APIC_MSR_BASE + self.0 as u32
218    }
219}
220
221#[bitfield(u32)]
222pub struct ApicVersion {
223    pub version: u8,
224    _rsvd: u8,
225    pub max_lvt_entry: u8,
226    pub eoi_broadcast_suppression: bool,
227    #[bits(7)]
228    _rsvd: u8,
229}