1use bitfield_struct::bitfield;
7use open_enum::open_enum;
8
9pub const APIC_BASE_ADDRESS: u32 = 0xfee00000;
11pub const APIC_BASE_PAGE: u32 = APIC_BASE_ADDRESS >> 12;
13
14pub const APIC_LEGACY_ID_COUNT: u32 = 255;
15
16#[bitfield(u64)]
18#[derive(PartialEq, Eq)]
19pub struct ApicBase {
20 _reserved: u8,
21 pub bsp: bool,
23 _reserved2: bool,
24 pub x2apic: bool,
25 pub enable: bool,
26 #[bits(24)]
28 pub base_page: u32,
29 #[bits(28)]
30 _reserved3: u64,
31}
32
33#[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#[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, VERSION = 0x3, TPR = 0x8, APR = 0x9, PPR = 0xa, EOI = 0xb, RRD = 0xc, LDR = 0xd, DFR = 0xe, SVR = 0xf, ISR0 = 0x10, ISR1 = 0x11,
173 ISR2 = 0x12,
174 ISR3 = 0x13,
175 ISR4 = 0x14,
176 ISR5 = 0x15,
177 ISR6 = 0x16,
178 ISR7 = 0x17,
179 TMR0 = 0x18, TMR1 = 0x19,
181 TMR2 = 0x1a,
182 TMR3 = 0x1b,
183 TMR4 = 0x1c,
184 TMR5 = 0x1d,
185 TMR6 = 0x1e,
186 TMR7 = 0x1f,
187 IRR0 = 0x20, IRR1 = 0x21,
189 IRR2 = 0x22,
190 IRR3 = 0x23,
191 IRR4 = 0x24,
192 IRR5 = 0x25,
193 IRR6 = 0x26,
194 IRR7 = 0x27,
195 ESR = 0x28, INTEL_LVT_CMCI = 0x2f, ICR0 = 0x30, ICR1 = 0x31, LVT_TIMER = 0x32, LVT_THERMAL = 0x33, LVT_PMC = 0x34, LVT_LINT0 = 0x35, LVT_LINT1 = 0x36, LVT_ERROR = 0x37, TIMER_ICR = 0x38, TIMER_CCR = 0x39, TIMER_DCR = 0x3e, SELF_IPI = 0x3f, }
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}