VirtualBox

source: vbox/trunk/src/VBox/VMM/include/APICInternal.h@ 76488

Last change on this file since 76488 was 76402, checked in by vboxsync, 6 years ago

VBox/vmm/apic.h: Try avoid dragging in pdmdev.h, so use function for APIC device registration rather than exposing g_DeviceAPIC. bugref:9344

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 54.7 KB
Line 
1/* $Id: APICInternal.h 76402 2018-12-23 15:13:04Z vboxsync $ */
2/** @file
3 * APIC - Advanced Programmable Interrupt Controller.
4 */
5
6/*
7 * Copyright (C) 2016-2017 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifndef ___APICInternal_h
19#define ___APICInternal_h
20
21#include <VBox/sup.h>
22#include <VBox/types.h>
23#include <VBox/vmm/apic.h>
24#include <VBox/vmm/pdmdev.h>
25
26/** @defgroup grp_apic_int Internal
27 * @ingroup grp_apic
28 * @internal
29 * @{
30 */
31
32/** The APIC hardware version number for Pentium 4. */
33#define XAPIC_HARDWARE_VERSION_P4 UINT8_C(0x14)
34/** Maximum number of LVT entries for Pentium 4. */
35#define XAPIC_MAX_LVT_ENTRIES_P4 UINT8_C(6)
36/** Size of the APIC ID bits for Pentium 4. */
37#define XAPIC_APIC_ID_BIT_COUNT_P4 UINT8_C(8)
38
39/** The APIC hardware version number for Pentium 6. */
40#define XAPIC_HARDWARE_VERSION_P6 UINT8_C(0x10)
41/** Maximum number of LVT entries for Pentium 6. */
42#define XAPIC_MAX_LVT_ENTRIES_P6 UINT8_C(4)
43/** Size of the APIC ID bits for Pentium 6. */
44#define XAPIC_APIC_ID_BIT_COUNT_P6 UINT8_C(4)
45
46/** The APIC hardware version we are emulating. */
47#define XAPIC_HARDWARE_VERSION XAPIC_HARDWARE_VERSION_P4
48
49#define VMCPU_TO_XAPICPAGE(a_pVCpu) ((PXAPICPAGE)(CTX_SUFF((a_pVCpu)->apic.s.pvApicPage)))
50#define VMCPU_TO_CXAPICPAGE(a_pVCpu) ((PCXAPICPAGE)(CTX_SUFF((a_pVCpu)->apic.s.pvApicPage)))
51
52#define VMCPU_TO_X2APICPAGE(a_pVCpu) ((PX2APICPAGE)(CTX_SUFF((a_pVCpu)->apic.s.pvApicPage)))
53#define VMCPU_TO_CX2APICPAGE(a_pVCpu) ((PCX2APICPAGE)(CTX_SUFF((a_pVCpu)->apic.s.pvApicPage)))
54
55#define VMCPU_TO_APICCPU(a_pVCpu) (&(a_pVCpu)->apic.s)
56#define VM_TO_APIC(a_pVM) (&(a_pVM)->apic.s)
57#define VM_TO_APICDEV(a_pVM) CTX_SUFF(VM_TO_APIC(a_pVM)->pApicDev)
58
59#define APICCPU_TO_XAPICPAGE(a_ApicCpu) ((PXAPICPAGE)(CTX_SUFF((a_ApicCpu)->pvApicPage)))
60#define APICCPU_TO_CXAPICPAGE(a_ApicCpu) ((PCXAPICPAGE)(CTX_SUFF((a_ApicCpu)->pvApicPage)))
61
62/** Whether the APIC is in X2APIC mode or not. */
63#define XAPIC_IN_X2APIC_MODE(a_pVCpu) ( ( ((a_pVCpu)->apic.s.uApicBaseMsr) \
64 & (MSR_IA32_APICBASE_EN | MSR_IA32_APICBASE_EXTD)) \
65 == (MSR_IA32_APICBASE_EN | MSR_IA32_APICBASE_EXTD) )
66
67/** Get an xAPIC page offset for an x2APIC MSR value. */
68#define X2APIC_GET_XAPIC_OFF(a_uMsr) ((((a_uMsr) - MSR_IA32_X2APIC_START) << 4) & UINT32_C(0xff0))
69/** Get an x2APIC MSR for an xAPIC page offset. */
70#define XAPIC_GET_X2APIC_MSR(a_offReg) ((((a_offReg) & UINT32_C(0xff0)) >> 4) | MSR_IA32_X2APIC_START)
71
72/** Illegal APIC vector value start. */
73#define XAPIC_ILLEGAL_VECTOR_START UINT8_C(0)
74/** Illegal APIC vector value end (inclusive). */
75#define XAPIC_ILLEGAL_VECTOR_END UINT8_C(15)
76/** Reserved APIC vector value start. */
77#define XAPIC_RSVD_VECTOR_START UINT8_C(16)
78/** Reserved APIC vector value end (inclusive). */
79#define XAPIC_RSVD_VECTOR_END UINT8_C(31)
80
81/** Vector offset in an APIC 256-bit sparse register. */
82#define XAPIC_REG256_VECTOR_OFF(a_Vector) (((a_Vector) & UINT32_C(0xe0)) >> 1)
83/** Bit position at offset in an APIC 256-bit sparse register. */
84#define XAPIC_REG256_VECTOR_BIT(a_Vector) ((a_Vector) & UINT32_C(0x1f))
85
86/** Maximum valid offset for a register (16-byte aligned, 4 byte wide access). */
87#define XAPIC_OFF_MAX_VALID (sizeof(XAPICPAGE) - 4 * sizeof(uint32_t))
88
89#if XAPIC_HARDWARE_VERSION == XAPIC_HARDWARE_VERSION_P6
90/** ESR - Send checksum error. */
91# define XAPIC_ESR_SEND_CHKSUM_ERROR RT_BIT(0)
92/** ESR - Send accept error. */
93# define XAPIC_ESR_RECV_CHKSUM_ERROR RT_BIT(1)
94/** ESR - Send accept error. */
95# define XAPIC_ESR_SEND_ACCEPT_ERROR RT_BIT(2)
96/** ESR - Receive accept error. */
97# define XAPIC_ESR_RECV_ACCEPT_ERROR RT_BIT(3)
98#endif
99/** ESR - Redirectable IPI. */
100#define XAPIC_ESR_REDIRECTABLE_IPI RT_BIT(4)
101/** ESR - Send accept error. */
102#define XAPIC_ESR_SEND_ILLEGAL_VECTOR RT_BIT(5)
103/** ESR - Send accept error. */
104#define XAPIC_ESR_RECV_ILLEGAL_VECTOR RT_BIT(6)
105/** ESR - Send accept error. */
106#define XAPIC_ESR_ILLEGAL_REG_ADDRESS RT_BIT(7)
107/** ESR - Valid write-only bits. */
108#define XAPIC_ESR_WO_VALID UINT32_C(0x0)
109
110/** TPR - Valid bits. */
111#define XAPIC_TPR_VALID UINT32_C(0xff)
112/** TPR - Task-priority class. */
113#define XAPIC_TPR_TP UINT32_C(0xf0)
114/** TPR - Task-priority subclass. */
115#define XAPIC_TPR_TP_SUBCLASS UINT32_C(0x0f)
116/** TPR - Gets the task-priority class. */
117#define XAPIC_TPR_GET_TP(a_Tpr) ((a_Tpr) & XAPIC_TPR_TP)
118/** TPR - Gets the task-priority subclass. */
119#define XAPIC_TPR_GET_TP_SUBCLASS(a_Tpr) ((a_Tpr) & XAPIC_TPR_TP_SUBCLASS)
120
121/** PPR - Valid bits. */
122#define XAPIC_PPR_VALID UINT32_C(0xff)
123/** PPR - Processor-priority class. */
124#define XAPIC_PPR_PP UINT32_C(0xf0)
125/** PPR - Processor-priority subclass. */
126#define XAPIC_PPR_PP_SUBCLASS UINT32_C(0x0f)
127/** PPR - Get the processor-priority class. */
128#define XAPIC_PPR_GET_PP(a_Ppr) ((a_Ppr) & XAPIC_PPR_PP)
129/** PPR - Get the processor-priority subclass. */
130#define XAPIC_PPR_GET_PP_SUBCLASS(a_Ppr) ((a_Ppr) & XAPIC_PPR_PP_SUBCLASS)
131
132/** Timer mode - One-shot. */
133#define XAPIC_TIMER_MODE_ONESHOT UINT32_C(0)
134/** Timer mode - Periodic. */
135#define XAPIC_TIMER_MODE_PERIODIC UINT32_C(1)
136/** Timer mode - TSC deadline. */
137#define XAPIC_TIMER_MODE_TSC_DEADLINE UINT32_C(2)
138
139/** LVT - The vector. */
140#define XAPIC_LVT_VECTOR UINT32_C(0xff)
141/** LVT - Gets the vector from an LVT entry. */
142#define XAPIC_LVT_GET_VECTOR(a_Lvt) ((a_Lvt) & XAPIC_LVT_VECTOR)
143/** LVT - The mask. */
144#define XAPIC_LVT_MASK RT_BIT(16)
145/** LVT - Is the LVT masked? */
146#define XAPIC_LVT_IS_MASKED(a_Lvt) RT_BOOL((a_Lvt) & XAPIC_LVT_MASK)
147/** LVT - Timer mode. */
148#define XAPIC_LVT_TIMER_MODE RT_BIT(17)
149/** LVT - Timer TSC-deadline timer mode. */
150#define XAPIC_LVT_TIMER_TSCDEADLINE RT_BIT(18)
151/** LVT - Gets the timer mode. */
152#define XAPIC_LVT_GET_TIMER_MODE(a_Lvt) (XAPICTIMERMODE)(((a_Lvt) >> 17) & UINT32_C(3))
153/** LVT - Delivery mode. */
154#define XAPIC_LVT_DELIVERY_MODE (RT_BIT(8) | RT_BIT(9) | RT_BIT(10))
155/** LVT - Gets the delivery mode. */
156#define XAPIC_LVT_GET_DELIVERY_MODE(a_Lvt) (XAPICDELIVERYMODE)(((a_Lvt) >> 8) & UINT32_C(7))
157/** LVT - Delivery status. */
158#define XAPIC_LVT_DELIVERY_STATUS RT_BIT(12)
159/** LVT - Trigger mode. */
160#define XAPIC_LVT_TRIGGER_MODE RT_BIT(15)
161/** LVT - Gets the trigger mode. */
162#define XAPIC_LVT_GET_TRIGGER_MODE(a_Lvt) (XAPICTRIGGERMODE)(((a_Lvt) >> 15) & UINT32_C(1))
163/** LVT - Remote IRR. */
164#define XAPIC_LVT_REMOTE_IRR RT_BIT(14)
165/** LVT - Gets the Remote IRR. */
166#define XAPIC_LVT_GET_REMOTE_IRR(a_Lvt) (((a_Lvt) >> 14) & 1)
167/** LVT - Interrupt Input Pin Polarity. */
168#define XAPIC_LVT_POLARITY RT_BIT(13)
169/** LVT - Gets the Interrupt Input Pin Polarity. */
170#define XAPIC_LVT_GET_POLARITY(a_Lvt) (((a_Lvt) >> 13) & 1)
171/** LVT - Valid bits common to all LVTs. */
172#define XAPIC_LVT_COMMON_VALID (XAPIC_LVT_VECTOR | XAPIC_LVT_DELIVERY_STATUS | XAPIC_LVT_MASK)
173/** LVT CMCI - Valid bits. */
174#define XAPIC_LVT_CMCI_VALID (XAPIC_LVT_COMMON_VALID | XAPIC_LVT_DELIVERY_MODE)
175/** LVT Timer - Valid bits. */
176#define XAPIC_LVT_TIMER_VALID (XAPIC_LVT_COMMON_VALID | XAPIC_LVT_TIMER_MODE | XAPIC_LVT_TIMER_TSCDEADLINE)
177/** LVT Thermal - Valid bits. */
178#define XAPIC_LVT_THERMAL_VALID (XAPIC_LVT_COMMON_VALID | XAPIC_LVT_DELIVERY_MODE)
179/** LVT Perf - Valid bits. */
180#define XAPIC_LVT_PERF_VALID (XAPIC_LVT_COMMON_VALID | XAPIC_LVT_DELIVERY_MODE)
181/** LVT LINTx - Valid bits. */
182#define XAPIC_LVT_LINT_VALID ( XAPIC_LVT_COMMON_VALID | XAPIC_LVT_DELIVERY_MODE | XAPIC_LVT_DELIVERY_STATUS \
183 | XAPIC_LVT_POLARITY | XAPIC_LVT_REMOTE_IRR | XAPIC_LVT_TRIGGER_MODE)
184/** LVT Error - Valid bits. */
185#define XAPIC_LVT_ERROR_VALID (XAPIC_LVT_COMMON_VALID)
186
187/** SVR - The vector. */
188#define XAPIC_SVR_VECTOR UINT32_C(0xff)
189/** SVR - APIC Software enable. */
190#define XAPIC_SVR_SOFTWARE_ENABLE RT_BIT(8)
191/** SVR - Supress EOI broadcast. */
192#define XAPIC_SVR_SUPRESS_EOI_BROADCAST RT_BIT(12)
193#if XAPIC_HARDWARE_VERSION == XAPIC_HARDWARE_VERSION_P4
194/** SVR - Valid bits. */
195# define XAPIC_SVR_VALID (XAPIC_SVR_VECTOR | XAPIC_SVR_SOFTWARE_ENABLE)
196#else
197# error "Implement Pentium and P6 family APIC architectures"
198#endif
199
200/** DFR - Valid bits. */
201#define XAPIC_DFR_VALID UINT32_C(0xf0000000)
202/** DFR - Reserved bits that must always remain set. */
203#define XAPIC_DFR_RSVD_MB1 UINT32_C(0x0fffffff)
204/** DFR - The model. */
205#define XAPIC_DFR_MODEL UINT32_C(0xf)
206/** DFR - Gets the destination model. */
207#define XAPIC_DFR_GET_MODEL(a_uReg) (((a_uReg) >> 28) & XAPIC_DFR_MODEL)
208
209/** LDR - Valid bits. */
210#define XAPIC_LDR_VALID UINT32_C(0xff000000)
211/** LDR - Cluster ID mask (x2APIC). */
212#define X2APIC_LDR_CLUSTER_ID UINT32_C(0xffff0000)
213/** LDR - Mask of the LDR cluster ID (x2APIC). */
214#define X2APIC_LDR_GET_CLUSTER_ID(a_uReg) ((a_uReg) & X2APIC_LDR_CLUSTER_ID)
215/** LDR - Mask of the LDR logical ID (x2APIC). */
216#define X2APIC_LDR_LOGICAL_ID UINT32_C(0x0000ffff)
217
218/** LDR - Flat mode logical ID mask. */
219#define XAPIC_LDR_FLAT_LOGICAL_ID UINT32_C(0xff)
220/** LDR - Clustered mode cluster ID mask. */
221#define XAPIC_LDR_CLUSTERED_CLUSTER_ID UINT32_C(0xf0)
222/** LDR - Clustered mode logical ID mask. */
223#define XAPIC_LDR_CLUSTERED_LOGICAL_ID UINT32_C(0x0f)
224/** LDR - Gets the clustered mode cluster ID. */
225#define XAPIC_LDR_CLUSTERED_GET_CLUSTER_ID(a_uReg) ((a_uReg) & XAPIC_LDR_CLUSTERED_CLUSTER_ID)
226
227
228/** EOI - Valid write-only bits. */
229#define XAPIC_EOI_WO_VALID UINT32_C(0x0)
230/** Timer ICR - Valid bits. */
231#define XAPIC_TIMER_ICR_VALID UINT32_C(0xffffffff)
232/** Timer DCR - Valid bits. */
233#define XAPIC_TIMER_DCR_VALID (RT_BIT(0) | RT_BIT(1) | RT_BIT(3))
234
235/** Self IPI - Valid bits. */
236#define XAPIC_SELF_IPI_VALID UINT32_C(0xff)
237/** Self IPI - The vector. */
238#define XAPIC_SELF_IPI_VECTOR UINT32_C(0xff)
239/** Self IPI - Gets the vector. */
240#define XAPIC_SELF_IPI_GET_VECTOR(a_uReg) ((a_uReg) & XAPIC_SELF_IPI_VECTOR)
241
242/** ICR Low - The Vector. */
243#define XAPIC_ICR_LO_VECTOR UINT32_C(0xff)
244/** ICR Low - Gets the vector. */
245#define XAPIC_ICR_LO_GET_VECTOR(a_uIcr) ((a_uIcr) & XAPIC_ICR_LO_VECTOR)
246/** ICR Low - The delivery mode. */
247#define XAPIC_ICR_LO_DELIVERY_MODE (RT_BIT(8) | RT_BIT(9) | RT_BIT(10))
248/** ICR Low - The destination mode. */
249#define XAPIC_ICR_LO_DEST_MODE RT_BIT(11)
250/** ICR Low - The delivery status. */
251#define XAPIC_ICR_LO_DELIVERY_STATUS RT_BIT(12)
252/** ICR Low - The level. */
253#define XAPIC_ICR_LO_LEVEL RT_BIT(14)
254/** ICR Low - The trigger mode. */
255#define XAPIC_ICR_TRIGGER_MODE RT_BIT(15)
256/** ICR Low - The destination shorthand. */
257#define XAPIC_ICR_LO_DEST_SHORTHAND (RT_BIT(18) | RT_BIT(19))
258/** ICR Low - Valid write bits. */
259#define XAPIC_ICR_LO_WR_VALID ( XAPIC_ICR_LO_VECTOR | XAPIC_ICR_LO_DELIVERY_MODE | XAPIC_ICR_LO_DEST_MODE \
260 | XAPIC_ICR_LO_LEVEL | XAPIC_ICR_TRIGGER_MODE | XAPIC_ICR_LO_DEST_SHORTHAND)
261
262/** ICR High - The destination field. */
263#define XAPIC_ICR_HI_DEST UINT32_C(0xff000000)
264/** ICR High - Get the destination field. */
265#define XAPIC_ICR_HI_GET_DEST(a_u32IcrHi) (((a_u32IcrHi) >> 24) & XAPIC_ICR_HI_DEST)
266/** ICR High - Valid write bits in xAPIC mode. */
267#define XAPIC_ICR_HI_WR_VALID XAPIC_ICR_HI_DEST
268
269/** APIC ID broadcast mask - x2APIC mode. */
270#define X2APIC_ID_BROADCAST_MASK UINT32_C(0xffffffff)
271#if XAPIC_HARDWARE_VERSION == XAPIC_HARDWARE_VERSION_P4
272/** APIC ID broadcast mask - xAPIC mode. */
273# define XAPIC_ID_BROADCAST_MASK UINT32_C(0xff)
274#else
275# error "Implement Pentium and P6 family APIC architectures"
276#endif
277
278/**
279 * The xAPIC sparse 256-bit register.
280 */
281typedef union XAPIC256BITREG
282{
283 /** The sparse-bitmap view. */
284 struct
285 {
286 uint32_t u32Reg;
287 uint32_t uReserved0[3];
288 } u[8];
289 /** The 32-bit view. */
290 uint32_t au32[32];
291} XAPIC256BITREG;
292/** Pointer to an xAPIC sparse bitmap register. */
293typedef XAPIC256BITREG *PXAPIC256BITREG;
294/** Pointer to a const xAPIC sparse bitmap register. */
295typedef XAPIC256BITREG const *PCXAPIC256BITREG;
296AssertCompileSize(XAPIC256BITREG, 128);
297
298/**
299 * The xAPIC memory layout as per Intel/AMD specs.
300 */
301typedef struct XAPICPAGE
302{
303 /* 0x00 - Reserved. */
304 uint32_t uReserved0[8];
305 /* 0x20 - APIC ID. */
306 struct
307 {
308 uint8_t u8Reserved0[3];
309 uint8_t u8ApicId;
310 uint32_t u32Reserved0[3];
311 } id;
312 /* 0x30 - APIC version register. */
313 union
314 {
315 struct
316 {
317#if XAPIC_HARDWARE_VERSION == XAPIC_HARDWARE_VERSION_P4
318 uint8_t u8Version;
319#else
320# error "Implement Pentium and P6 family APIC architectures"
321#endif
322 uint8_t uReserved0;
323 uint8_t u8MaxLvtEntry;
324 uint8_t fEoiBroadcastSupression : 1;
325 uint8_t u7Reserved1 : 7;
326 uint32_t u32Reserved0[3];
327 } u;
328 struct
329 {
330 uint32_t u32Version;
331 uint32_t u32Reserved0[3];
332 } all;
333 } version;
334 /* 0x40 - Reserved. */
335 uint32_t uReserved1[16];
336 /* 0x80 - Task Priority Register (TPR). */
337 struct
338 {
339 uint8_t u8Tpr;
340 uint8_t u8Reserved0[3];
341 uint32_t u32Reserved0[3];
342 } tpr;
343 /* 0x90 - Arbitration Priority Register (APR). */
344 struct
345 {
346 uint8_t u8Apr;
347 uint8_t u8Reserved0[3];
348 uint32_t u32Reserved0[3];
349 } apr;
350 /* 0xA0 - Processor Priority Register (PPR). */
351 struct
352 {
353 uint8_t u8Ppr;
354 uint8_t u8Reserved0[3];
355 uint32_t u32Reserved0[3];
356 } ppr;
357 /* 0xB0 - End Of Interrupt Register (EOI). */
358 struct
359 {
360 uint32_t u32Eoi;
361 uint32_t u32Reserved0[3];
362 } eoi;
363 /* 0xC0 - Remote Read Register (RRD). */
364 struct
365 {
366 uint32_t u32Rrd;
367 uint32_t u32Reserved0[3];
368 } rrd;
369 /* 0xD0 - Logical Destination Register (LDR). */
370 union
371 {
372 struct
373 {
374 uint8_t u8Reserved0[3];
375 uint8_t u8LogicalApicId;
376 uint32_t u32Reserved0[3];
377 } u;
378 struct
379 {
380 uint32_t u32Ldr;
381 uint32_t u32Reserved0[3];
382 } all;
383 } ldr;
384 /* 0xE0 - Destination Format Register (DFR). */
385 union
386 {
387 struct
388 {
389 uint32_t u28ReservedMb1 : 28; /* MB1 */
390 uint32_t u4Model : 4;
391 uint32_t u32Reserved0[3];
392 } u;
393 struct
394 {
395 uint32_t u32Dfr;
396 uint32_t u32Reserved0[3];
397 } all;
398 } dfr;
399 /* 0xF0 - Spurious-Interrupt Vector Register (SVR). */
400 union
401 {
402 struct
403 {
404 uint32_t u8SpuriousVector : 8;
405 uint32_t fApicSoftwareEnable : 1;
406 uint32_t u3Reserved0 : 3;
407 uint32_t fSupressEoiBroadcast : 1;
408 uint32_t u19Reserved1 : 19;
409 uint32_t u32Reserved0[3];
410 } u;
411 struct
412 {
413 uint32_t u32Svr;
414 uint32_t u32Reserved0[3];
415 } all;
416 } svr;
417 /* 0x100 - In-service Register (ISR). */
418 XAPIC256BITREG isr;
419 /* 0x180 - Trigger Mode Register (TMR). */
420 XAPIC256BITREG tmr;
421 /* 0x200 - Interrupt Request Register (IRR). */
422 XAPIC256BITREG irr;
423 /* 0x280 - Error Status Register (ESR). */
424 union
425 {
426 struct
427 {
428#if XAPIC_HARDWARE_VERSION == XAPIC_HARDWARE_VERSION_P4
429 uint32_t u4Reserved0 : 4;
430#else
431# error "Implement Pentium and P6 family APIC architectures"
432#endif
433 uint32_t fRedirectableIpi : 1;
434 uint32_t fSendIllegalVector : 1;
435 uint32_t fRcvdIllegalVector : 1;
436 uint32_t fIllegalRegAddr : 1;
437 uint32_t u24Reserved1 : 24;
438 uint32_t u32Reserved0[3];
439 } u;
440 struct
441 {
442 uint32_t u32Errors;
443 uint32_t u32Reserved0[3];
444 } all;
445 } esr;
446 /* 0x290 - Reserved. */
447 uint32_t uReserved2[28];
448 /* 0x300 - Interrupt Command Register (ICR) - Low. */
449 union
450 {
451 struct
452 {
453 uint32_t u8Vector : 8;
454 uint32_t u3DeliveryMode : 3;
455 uint32_t u1DestMode : 1;
456 uint32_t u1DeliveryStatus : 1;
457 uint32_t fReserved0 : 1;
458 uint32_t u1Level : 1;
459 uint32_t u1TriggerMode : 1;
460 uint32_t u2Reserved1 : 2;
461 uint32_t u2DestShorthand : 2;
462 uint32_t u12Reserved2 : 12;
463 uint32_t u32Reserved0[3];
464 } u;
465 struct
466 {
467 uint32_t u32IcrLo;
468 uint32_t u32Reserved0[3];
469 } all;
470 } icr_lo;
471 /* 0x310 - Interrupt Comannd Register (ICR) - High. */
472 union
473 {
474 struct
475 {
476 uint32_t u24Reserved0 : 24;
477 uint32_t u8Dest : 8;
478 uint32_t u32Reserved0[3];
479 } u;
480 struct
481 {
482 uint32_t u32IcrHi;
483 uint32_t u32Reserved0[3];
484 } all;
485 } icr_hi;
486 /* 0x320 - Local Vector Table (LVT) Timer Register. */
487 union
488 {
489 struct
490 {
491 uint32_t u8Vector : 8;
492 uint32_t u4Reserved0 : 4;
493 uint32_t u1DeliveryStatus : 1;
494 uint32_t u3Reserved1 : 3;
495 uint32_t u1Mask : 1;
496 uint32_t u2TimerMode : 2;
497 uint32_t u13Reserved2 : 13;
498 uint32_t u32Reserved0[3];
499 } u;
500 struct
501 {
502 uint32_t u32LvtTimer;
503 uint32_t u32Reserved0[3];
504 } all;
505 } lvt_timer;
506 /* 0x330 - Local Vector Table (LVT) Thermal Sensor Register. */
507#if XAPIC_HARDWARE_VERSION == XAPIC_HARDWARE_VERSION_P4
508 union
509 {
510 struct
511 {
512 uint32_t u8Vector : 8;
513 uint32_t u3DeliveryMode : 3;
514 uint32_t u1Reserved0 : 1;
515 uint32_t u1DeliveryStatus : 1;
516 uint32_t u3Reserved1 : 3;
517 uint32_t u1Mask : 1;
518 uint32_t u15Reserved2 : 15;
519 uint32_t u32Reserved0[3];
520 } u;
521 struct
522 {
523 uint32_t u32LvtThermal;
524 uint32_t u32Reserved0[3];
525 } all;
526 } lvt_thermal;
527#else
528# error "Implement Pentium and P6 family APIC architectures"
529#endif
530 /* 0x340 - Local Vector Table (LVT) Performance Monitor Counter (PMC) Register. */
531 union
532 {
533 struct
534 {
535 uint32_t u8Vector : 8;
536 uint32_t u3DeliveryMode : 3;
537 uint32_t u1Reserved0 : 1;
538 uint32_t u1DeliveryStatus : 1;
539 uint32_t u3Reserved1 : 3;
540 uint32_t u1Mask : 1;
541 uint32_t u15Reserved2 : 15;
542 uint32_t u32Reserved0[3];
543 } u;
544 struct
545 {
546 uint32_t u32LvtPerf;
547 uint32_t u32Reserved0[3];
548 } all;
549 } lvt_perf;
550 /* 0x350 - Local Vector Table (LVT) LINT0 Register. */
551 union
552 {
553 struct
554 {
555 uint32_t u8Vector : 8;
556 uint32_t u3DeliveryMode : 3;
557 uint32_t u1Reserved0 : 1;
558 uint32_t u1DeliveryStatus : 1;
559 uint32_t u1IntrPolarity : 1;
560 uint32_t u1RemoteIrr : 1;
561 uint32_t u1TriggerMode : 1;
562 uint32_t u1Mask : 1;
563 uint32_t u15Reserved2 : 15;
564 uint32_t u32Reserved0[3];
565 } u;
566 struct
567 {
568 uint32_t u32LvtLint0;
569 uint32_t u32Reserved0[3];
570 } all;
571 } lvt_lint0;
572 /* 0x360 - Local Vector Table (LVT) LINT1 Register. */
573 union
574 {
575 struct
576 {
577 uint32_t u8Vector : 8;
578 uint32_t u3DeliveryMode : 3;
579 uint32_t u1Reserved0 : 1;
580 uint32_t u1DeliveryStatus : 1;
581 uint32_t u1IntrPolarity : 1;
582 uint32_t u1RemoteIrr : 1;
583 uint32_t u1TriggerMode : 1;
584 uint32_t u1Mask : 1;
585 uint32_t u15Reserved2 : 15;
586 uint32_t u32Reserved0[3];
587 } u;
588 struct
589 {
590 uint32_t u32LvtLint1;
591 uint32_t u32Reserved0[3];
592 } all;
593 } lvt_lint1;
594 /* 0x370 - Local Vector Table (LVT) Error Register. */
595 union
596 {
597 struct
598 {
599 uint32_t u8Vector : 8;
600 uint32_t u4Reserved0 : 4;
601 uint32_t u1DeliveryStatus : 1;
602 uint32_t u3Reserved1 : 3;
603 uint32_t u1Mask : 1;
604 uint32_t u15Reserved2 : 15;
605 uint32_t u32Reserved0[3];
606 } u;
607 struct
608 {
609 uint32_t u32LvtError;
610 uint32_t u32Reserved0[3];
611 } all;
612 } lvt_error;
613 /* 0x380 - Timer Initial Counter Register. */
614 struct
615 {
616 uint32_t u32InitialCount;
617 uint32_t u32Reserved0[3];
618 } timer_icr;
619 /* 0x390 - Timer Current Counter Register. */
620 struct
621 {
622 uint32_t u32CurrentCount;
623 uint32_t u32Reserved0[3];
624 } timer_ccr;
625 /* 0x3A0 - Reserved. */
626 uint32_t u32Reserved3[16];
627 /* 0x3E0 - Timer Divide Configuration Register. */
628 union
629 {
630 struct
631 {
632 uint32_t u2DivideValue0 : 2;
633 uint32_t u1Reserved0 : 1;
634 uint32_t u1DivideValue1 : 1;
635 uint32_t u28Reserved1 : 28;
636 uint32_t u32Reserved0[3];
637 } u;
638 struct
639 {
640 uint32_t u32DivideValue;
641 uint32_t u32Reserved0[3];
642 } all;
643 } timer_dcr;
644 /* 0x3F0 - Reserved. */
645 uint8_t u8Reserved0[3088];
646} XAPICPAGE;
647/** Pointer to a XAPICPAGE struct. */
648typedef XAPICPAGE *PXAPICPAGE;
649/** Pointer to a const XAPICPAGE struct. */
650typedef const XAPICPAGE *PCXAPICPAGE;
651AssertCompileSize(XAPICPAGE, 4096);
652AssertCompileMemberOffset(XAPICPAGE, id, XAPIC_OFF_ID);
653AssertCompileMemberOffset(XAPICPAGE, version, XAPIC_OFF_VERSION);
654AssertCompileMemberOffset(XAPICPAGE, tpr, XAPIC_OFF_TPR);
655AssertCompileMemberOffset(XAPICPAGE, apr, XAPIC_OFF_APR);
656AssertCompileMemberOffset(XAPICPAGE, ppr, XAPIC_OFF_PPR);
657AssertCompileMemberOffset(XAPICPAGE, eoi, XAPIC_OFF_EOI);
658AssertCompileMemberOffset(XAPICPAGE, rrd, XAPIC_OFF_RRD);
659AssertCompileMemberOffset(XAPICPAGE, ldr, XAPIC_OFF_LDR);
660AssertCompileMemberOffset(XAPICPAGE, dfr, XAPIC_OFF_DFR);
661AssertCompileMemberOffset(XAPICPAGE, svr, XAPIC_OFF_SVR);
662AssertCompileMemberOffset(XAPICPAGE, isr, XAPIC_OFF_ISR0);
663AssertCompileMemberOffset(XAPICPAGE, tmr, XAPIC_OFF_TMR0);
664AssertCompileMemberOffset(XAPICPAGE, irr, XAPIC_OFF_IRR0);
665AssertCompileMemberOffset(XAPICPAGE, esr, XAPIC_OFF_ESR);
666AssertCompileMemberOffset(XAPICPAGE, icr_lo, XAPIC_OFF_ICR_LO);
667AssertCompileMemberOffset(XAPICPAGE, icr_hi, XAPIC_OFF_ICR_HI);
668AssertCompileMemberOffset(XAPICPAGE, lvt_timer, XAPIC_OFF_LVT_TIMER);
669AssertCompileMemberOffset(XAPICPAGE, lvt_thermal, XAPIC_OFF_LVT_THERMAL);
670AssertCompileMemberOffset(XAPICPAGE, lvt_perf, XAPIC_OFF_LVT_PERF);
671AssertCompileMemberOffset(XAPICPAGE, lvt_lint0, XAPIC_OFF_LVT_LINT0);
672AssertCompileMemberOffset(XAPICPAGE, lvt_lint1, XAPIC_OFF_LVT_LINT1);
673AssertCompileMemberOffset(XAPICPAGE, lvt_error, XAPIC_OFF_LVT_ERROR);
674AssertCompileMemberOffset(XAPICPAGE, timer_icr, XAPIC_OFF_TIMER_ICR);
675AssertCompileMemberOffset(XAPICPAGE, timer_ccr, XAPIC_OFF_TIMER_CCR);
676AssertCompileMemberOffset(XAPICPAGE, timer_dcr, XAPIC_OFF_TIMER_DCR);
677
678/**
679 * The x2APIC memory layout as per Intel/AMD specs.
680 */
681typedef struct X2APICPAGE
682{
683 /* 0x00 - Reserved. */
684 uint32_t uReserved0[8];
685 /* 0x20 - APIC ID. */
686 struct
687 {
688 uint32_t u32ApicId;
689 uint32_t u32Reserved0[3];
690 } id;
691 /* 0x30 - APIC version register. */
692 union
693 {
694 struct
695 {
696 uint8_t u8Version;
697 uint8_t u8Reserved0;
698 uint8_t u8MaxLvtEntry;
699 uint8_t fEoiBroadcastSupression : 1;
700 uint8_t u7Reserved1 : 7;
701 uint32_t u32Reserved0[3];
702 } u;
703 struct
704 {
705 uint32_t u32Version;
706 uint32_t u32Reserved2[3];
707 } all;
708 } version;
709 /* 0x40 - Reserved. */
710 uint32_t uReserved1[16];
711 /* 0x80 - Task Priority Register (TPR). */
712 struct
713 {
714 uint8_t u8Tpr;
715 uint8_t u8Reserved0[3];
716 uint32_t u32Reserved0[3];
717 } tpr;
718 /* 0x90 - Reserved. */
719 uint32_t uReserved2[4];
720 /* 0xA0 - Processor Priority Register (PPR). */
721 struct
722 {
723 uint8_t u8Ppr;
724 uint8_t u8Reserved0[3];
725 uint32_t u32Reserved0[3];
726 } ppr;
727 /* 0xB0 - End Of Interrupt Register (EOI). */
728 struct
729 {
730 uint32_t u32Eoi;
731 uint32_t u32Reserved0[3];
732 } eoi;
733 /* 0xC0 - Remote Read Register (RRD). */
734 struct
735 {
736 uint32_t u32Rrd;
737 uint32_t u32Reserved0[3];
738 } rrd;
739 /* 0xD0 - Logical Destination Register (LDR). */
740 struct
741 {
742 uint32_t u32LogicalApicId;
743 uint32_t u32Reserved1[3];
744 } ldr;
745 /* 0xE0 - Reserved. */
746 uint32_t uReserved3[4];
747 /* 0xF0 - Spurious-Interrupt Vector Register (SVR). */
748 union
749 {
750 struct
751 {
752 uint32_t u8SpuriousVector : 8;
753 uint32_t fApicSoftwareEnable : 1;
754 uint32_t u3Reserved0 : 3;
755 uint32_t fSupressEoiBroadcast : 1;
756 uint32_t u19Reserved1 : 19;
757 uint32_t u32Reserved0[3];
758 } u;
759 struct
760 {
761 uint32_t u32Svr;
762 uint32_t uReserved0[3];
763 } all;
764 } svr;
765 /* 0x100 - In-service Register (ISR). */
766 XAPIC256BITREG isr;
767 /* 0x180 - Trigger Mode Register (TMR). */
768 XAPIC256BITREG tmr;
769 /* 0x200 - Interrupt Request Register (IRR). */
770 XAPIC256BITREG irr;
771 /* 0x280 - Error Status Register (ESR). */
772 union
773 {
774 struct
775 {
776#if XAPIC_HARDWARE_VERSION == XAPIC_HARDWARE_VERSION_P4
777 uint32_t u4Reserved0 : 4;
778#else
779# error "Implement Pentium and P6 family APIC architectures"
780#endif
781 uint32_t fRedirectableIpi : 1;
782 uint32_t fSendIllegalVector : 1;
783 uint32_t fRcvdIllegalVector : 1;
784 uint32_t fIllegalRegAddr : 1;
785 uint32_t u24Reserved1 : 24;
786 uint32_t uReserved0[3];
787 } u;
788 struct
789 {
790 uint32_t u32Errors;
791 uint32_t u32Reserved0[3];
792 } all;
793 } esr;
794 /* 0x290 - Reserved. */
795 uint32_t uReserved4[28];
796 /* 0x300 - Interrupt Command Register (ICR) - Low. */
797 union
798 {
799 struct
800 {
801 uint32_t u8Vector : 8;
802 uint32_t u3DeliveryMode : 3;
803 uint32_t u1DestMode : 1;
804 uint32_t u2Reserved0 : 2;
805 uint32_t u1Level : 1;
806 uint32_t u1TriggerMode : 1;
807 uint32_t u2Reserved1 : 2;
808 uint32_t u2DestShorthand : 2;
809 uint32_t u12Reserved2 : 12;
810 uint32_t u32Reserved0[3];
811 } u;
812 struct
813 {
814 uint32_t u32IcrLo;
815 uint32_t u32Reserved3[3];
816 } all;
817 } icr_lo;
818 /* 0x310 - Interrupt Comannd Register (ICR) - High. */
819 struct
820 {
821 uint32_t u32IcrHi;
822 uint32_t uReserved1[3];
823 } icr_hi;
824 /* 0x320 - Local Vector Table (LVT) Timer Register. */
825 union
826 {
827 struct
828 {
829 uint32_t u8Vector : 8;
830 uint32_t u4Reserved0 : 4;
831 uint32_t u1DeliveryStatus : 1;
832 uint32_t u3Reserved1 : 3;
833 uint32_t u1Mask : 1;
834 uint32_t u2TimerMode : 2;
835 uint32_t u13Reserved2 : 13;
836 uint32_t u32Reserved0[3];
837 } u;
838 struct
839 {
840 uint32_t u32LvtTimer;
841 uint32_t u32Reserved0[3];
842 } all;
843 } lvt_timer;
844 /* 0x330 - Local Vector Table (LVT) Thermal Sensor Register. */
845 union
846 {
847 struct
848 {
849 uint32_t u8Vector : 8;
850 uint32_t u3DeliveryMode : 3;
851 uint32_t u1Reserved0 : 1;
852 uint32_t u1DeliveryStatus : 1;
853 uint32_t u3Reserved1 : 3;
854 uint32_t u1Mask : 1;
855 uint32_t u15Reserved2 : 15;
856 uint32_t u32Reserved0[3];
857 } u;
858 struct
859 {
860 uint32_t u32LvtThermal;
861 uint32_t uReserved0[3];
862 } all;
863 } lvt_thermal;
864 /* 0x340 - Local Vector Table (LVT) Performance Monitor Counter (PMC) Register. */
865 union
866 {
867 struct
868 {
869 uint32_t u8Vector : 8;
870 uint32_t u3DeliveryMode : 3;
871 uint32_t u1Reserved0 : 1;
872 uint32_t u1DeliveryStatus : 1;
873 uint32_t u3Reserved1 : 3;
874 uint32_t u1Mask : 1;
875 uint32_t u15Reserved2 : 15;
876 uint32_t u32Reserved0[3];
877 } u;
878 struct
879 {
880 uint32_t u32LvtPerf;
881 uint32_t u32Reserved0[3];
882 } all;
883 } lvt_perf;
884 /* 0x350 - Local Vector Table (LVT) LINT0 Register. */
885 union
886 {
887 struct
888 {
889 uint32_t u8Vector : 8;
890 uint32_t u3DeliveryMode : 3;
891 uint32_t u1Reserved0 : 1;
892 uint32_t u1DeliveryStatus : 1;
893 uint32_t u1IntrPolarity : 1;
894 uint32_t u1RemoteIrr : 1;
895 uint32_t u1TriggerMode : 1;
896 uint32_t u1Mask : 1;
897 uint32_t u15Reserved2 : 15;
898 uint32_t u32Reserved0[3];
899 } u;
900 struct
901 {
902 uint32_t u32LvtLint0;
903 uint32_t u32Reserved0[3];
904 } all;
905 } lvt_lint0;
906 /* 0x360 - Local Vector Table (LVT) LINT1 Register. */
907 union
908 {
909 struct
910 {
911 uint32_t u8Vector : 8;
912 uint32_t u3DeliveryMode : 3;
913 uint32_t u1Reserved0 : 1;
914 uint32_t u1DeliveryStatus : 1;
915 uint32_t u1IntrPolarity : 1;
916 uint32_t u1RemoteIrr : 1;
917 uint32_t u1TriggerMode : 1;
918 uint32_t u1Mask : 1;
919 uint32_t u15Reserved2 : 15;
920 uint32_t u32Reserved0[3];
921 } u;
922 struct
923 {
924 uint32_t u32LvtLint1;
925 uint32_t u32Reserved0[3];
926 } all;
927 } lvt_lint1;
928 /* 0x370 - Local Vector Table (LVT) Error Register. */
929 union
930 {
931 struct
932 {
933 uint32_t u8Vector : 8;
934 uint32_t u4Reserved0 : 4;
935 uint32_t u1DeliveryStatus : 1;
936 uint32_t u3Reserved1 : 3;
937 uint32_t u1Mask : 1;
938 uint32_t u15Reserved2 : 15;
939 uint32_t u32Reserved0[3];
940 } u;
941 struct
942 {
943 uint32_t u32LvtError;
944 uint32_t u32Reserved0[3];
945 } all;
946 } lvt_error;
947 /* 0x380 - Timer Initial Counter Register. */
948 struct
949 {
950 uint32_t u32InitialCount;
951 uint32_t u32Reserved0[3];
952 } timer_icr;
953 /* 0x390 - Timer Current Counter Register. */
954 struct
955 {
956 uint32_t u32CurrentCount;
957 uint32_t u32Reserved0[3];
958 } timer_ccr;
959 /* 0x3A0 - Reserved. */
960 uint32_t uReserved5[16];
961 /* 0x3E0 - Timer Divide Configuration Register. */
962 union
963 {
964 struct
965 {
966 uint32_t u2DivideValue0 : 2;
967 uint32_t u1Reserved0 : 1;
968 uint32_t u1DivideValue1 : 1;
969 uint32_t u28Reserved1 : 28;
970 uint32_t u32Reserved0[3];
971 } u;
972 struct
973 {
974 uint32_t u32DivideValue;
975 uint32_t u32Reserved0[3];
976 } all;
977 } timer_dcr;
978 /* 0x3F0 - Self IPI Register. */
979 struct
980 {
981 uint32_t u8Vector : 8;
982 uint32_t u24Reserved0 : 24;
983 uint32_t u32Reserved0[3];
984 } self_ipi;
985 /* 0x400 - Reserved. */
986 uint8_t u8Reserved0[3072];
987} X2APICPAGE;
988/** Pointer to a X2APICPAGE struct. */
989typedef X2APICPAGE *PX2APICPAGE;
990/** Pointer to a const X2APICPAGE struct. */
991typedef const X2APICPAGE *PCX2APICPAGE;
992AssertCompileSize(X2APICPAGE, 4096);
993AssertCompileSize(X2APICPAGE, sizeof(XAPICPAGE));
994AssertCompileMemberOffset(X2APICPAGE, id, XAPIC_OFF_ID);
995AssertCompileMemberOffset(X2APICPAGE, version, XAPIC_OFF_VERSION);
996AssertCompileMemberOffset(X2APICPAGE, tpr, XAPIC_OFF_TPR);
997AssertCompileMemberOffset(X2APICPAGE, ppr, XAPIC_OFF_PPR);
998AssertCompileMemberOffset(X2APICPAGE, eoi, XAPIC_OFF_EOI);
999AssertCompileMemberOffset(X2APICPAGE, rrd, XAPIC_OFF_RRD);
1000AssertCompileMemberOffset(X2APICPAGE, ldr, XAPIC_OFF_LDR);
1001AssertCompileMemberOffset(X2APICPAGE, svr, XAPIC_OFF_SVR);
1002AssertCompileMemberOffset(X2APICPAGE, isr, XAPIC_OFF_ISR0);
1003AssertCompileMemberOffset(X2APICPAGE, tmr, XAPIC_OFF_TMR0);
1004AssertCompileMemberOffset(X2APICPAGE, irr, XAPIC_OFF_IRR0);
1005AssertCompileMemberOffset(X2APICPAGE, esr, XAPIC_OFF_ESR);
1006AssertCompileMemberOffset(X2APICPAGE, icr_lo, XAPIC_OFF_ICR_LO);
1007AssertCompileMemberOffset(X2APICPAGE, icr_hi, XAPIC_OFF_ICR_HI);
1008AssertCompileMemberOffset(X2APICPAGE, lvt_timer, XAPIC_OFF_LVT_TIMER);
1009AssertCompileMemberOffset(X2APICPAGE, lvt_thermal, XAPIC_OFF_LVT_THERMAL);
1010AssertCompileMemberOffset(X2APICPAGE, lvt_perf, XAPIC_OFF_LVT_PERF);
1011AssertCompileMemberOffset(X2APICPAGE, lvt_lint0, XAPIC_OFF_LVT_LINT0);
1012AssertCompileMemberOffset(X2APICPAGE, lvt_lint1, XAPIC_OFF_LVT_LINT1);
1013AssertCompileMemberOffset(X2APICPAGE, lvt_error, XAPIC_OFF_LVT_ERROR);
1014AssertCompileMemberOffset(X2APICPAGE, timer_icr, XAPIC_OFF_TIMER_ICR);
1015AssertCompileMemberOffset(X2APICPAGE, timer_ccr, XAPIC_OFF_TIMER_CCR);
1016AssertCompileMemberOffset(X2APICPAGE, timer_dcr, XAPIC_OFF_TIMER_DCR);
1017AssertCompileMemberOffset(X2APICPAGE, self_ipi, X2APIC_OFF_SELF_IPI);
1018
1019/**
1020 * APIC MSR access error.
1021 * @note The values must match the array indices in apicMsrAccessError().
1022 */
1023typedef enum APICMSRACCESS
1024{
1025 /** MSR read while not in x2APIC. */
1026 APICMSRACCESS_INVALID_READ_MODE = 0,
1027 /** MSR write while not in x2APIC. */
1028 APICMSRACCESS_INVALID_WRITE_MODE,
1029 /** MSR read for a reserved/unknown/invalid MSR. */
1030 APICMSRACCESS_READ_RSVD_OR_UNKNOWN,
1031 /** MSR write for a reserved/unknown/invalid MSR. */
1032 APICMSRACCESS_WRITE_RSVD_OR_UNKNOWN,
1033 /** MSR read for a write-only MSR. */
1034 APICMSRACCESS_READ_WRITE_ONLY,
1035 /** MSR write for a read-only MSR. */
1036 APICMSRACCESS_WRITE_READ_ONLY,
1037 /** MSR read to reserved bits. */
1038 APICMSRACCESS_READ_RSVD_BITS,
1039 /** MSR write to reserved bits. */
1040 APICMSRACCESS_WRITE_RSVD_BITS,
1041 /** MSR write with invalid value. */
1042 APICMSRACCESS_WRITE_INVALID,
1043 /** MSR write disallowed due to incompatible config. */
1044 APICMSRACCESS_WRITE_DISALLOWED_CONFIG,
1045 /** MSR read disallowed due to incompatible config. */
1046 APICMSRACCESS_READ_DISALLOWED_CONFIG,
1047 /** Count of enum members (don't use). */
1048 APICMSRACCESS_COUNT
1049} APICMSRACCESS;
1050
1051/** @name xAPIC Destination Format Register bits.
1052 * See Intel spec. 10.6.2.2 "Logical Destination Mode".
1053 * @{ */
1054typedef enum XAPICDESTFORMAT
1055{
1056 XAPICDESTFORMAT_FLAT = 0xf,
1057 XAPICDESTFORMAT_CLUSTER = 0
1058} XAPICDESTFORMAT;
1059/** @} */
1060
1061/** @name xAPIC Timer Mode bits.
1062 * See Intel spec. 10.5.1 "Local Vector Table".
1063 * @{ */
1064typedef enum XAPICTIMERMODE
1065{
1066 XAPICTIMERMODE_ONESHOT = XAPIC_TIMER_MODE_ONESHOT,
1067 XAPICTIMERMODE_PERIODIC = XAPIC_TIMER_MODE_PERIODIC,
1068 XAPICTIMERMODE_TSC_DEADLINE = XAPIC_TIMER_MODE_TSC_DEADLINE
1069} XAPICTIMERMODE;
1070/** @} */
1071
1072/** @name xAPIC Interrupt Command Register bits.
1073 * See Intel spec. 10.6.1 "Interrupt Command Register (ICR)".
1074 * See Intel spec. 10.5.1 "Local Vector Table".
1075 * @{ */
1076/**
1077 * xAPIC destination shorthand.
1078 */
1079typedef enum XAPICDESTSHORTHAND
1080{
1081 XAPICDESTSHORTHAND_NONE = 0,
1082 XAPICDESTSHORTHAND_SELF,
1083 XAPIDDESTSHORTHAND_ALL_INCL_SELF,
1084 XAPICDESTSHORTHAND_ALL_EXCL_SELF
1085} XAPICDESTSHORTHAND;
1086
1087/**
1088 * xAPIC INIT level de-assert delivery mode.
1089 */
1090typedef enum XAPICINITLEVEL
1091{
1092 XAPICINITLEVEL_DEASSERT = 0,
1093 XAPICINITLEVEL_ASSERT
1094} XAPICLEVEL;
1095
1096/**
1097 * xAPIC destination mode.
1098 */
1099typedef enum XAPICDESTMODE
1100{
1101 XAPICDESTMODE_PHYSICAL = 0,
1102 XAPICDESTMODE_LOGICAL
1103} XAPICDESTMODE;
1104
1105/**
1106 * xAPIC delivery mode type.
1107 */
1108typedef enum XAPICDELIVERYMODE
1109{
1110 XAPICDELIVERYMODE_FIXED = 0,
1111 XAPICDELIVERYMODE_LOWEST_PRIO = 1,
1112 XAPICDELIVERYMODE_SMI = 2,
1113 XAPICDELIVERYMODE_NMI = 4,
1114 XAPICDELIVERYMODE_INIT = 5,
1115 XAPICDELIVERYMODE_STARTUP = 6,
1116 XAPICDELIVERYMODE_EXTINT = 7
1117} XAPICDELIVERYMODE;
1118/** @} */
1119
1120/** @def APIC_CACHE_LINE_SIZE
1121 * Padding (in bytes) for aligning data in different cache lines. Present
1122 * generation x86 CPUs use 64-byte cache lines[1]. However, Intel NetBurst
1123 * architecture supposedly uses 128-byte cache lines[2]. Since 128 is a
1124 * multiple of 64, we use the larger one here.
1125 *
1126 * [1] - Intel spec "Table 11-1. Characteristics of the Caches, TLBs, Store
1127 * Buffer, and Write Combining Buffer in Intel 64 and IA-32 Processors"
1128 * [2] - Intel spec. 8.10.6.7 "Place Locks and Semaphores in Aligned, 128-Byte
1129 * Blocks of Memory".
1130 */
1131#define APIC_CACHE_LINE_SIZE 128
1132
1133/**
1134 * APIC Pending-Interrupt Bitmap (PIB).
1135 */
1136typedef struct APICPIB
1137{
1138 uint64_t volatile au64VectorBitmap[4];
1139 uint32_t volatile fOutstandingNotification;
1140 uint8_t au8Reserved[APIC_CACHE_LINE_SIZE - sizeof(uint32_t) - (sizeof(uint64_t) * 4)];
1141} APICPIB;
1142AssertCompileMemberOffset(APICPIB, fOutstandingNotification, 256 / 8);
1143AssertCompileSize(APICPIB, APIC_CACHE_LINE_SIZE);
1144/** Pointer to a pending-interrupt bitmap. */
1145typedef APICPIB *PAPICPIB;
1146/** Pointer to a const pending-interrupt bitmap. */
1147typedef const APICPIB *PCAPICPIB;
1148
1149/**
1150 * APIC PDM instance data (per-VM).
1151 */
1152typedef struct APICDEV
1153{
1154 /** The device instance - R3 Ptr. */
1155 PPDMDEVINSR3 pDevInsR3;
1156 /** Alignment padding. */
1157 R3PTRTYPE(void *) pvAlignment0;
1158
1159 /** The device instance - R0 Ptr. */
1160 PPDMDEVINSR0 pDevInsR0;
1161 /** Alignment padding. */
1162 R0PTRTYPE(void *) pvAlignment1;
1163
1164 /** The device instance - RC Ptr. */
1165 PPDMDEVINSRC pDevInsRC;
1166} APICDEV;
1167/** Pointer to an APIC device. */
1168typedef APICDEV *PAPICDEV;
1169/** Pointer to a const APIC device. */
1170typedef APICDEV const *PCAPICDEV;
1171
1172/**
1173 * APIC VM Instance data.
1174 */
1175typedef struct APIC
1176{
1177 /** @name The APIC PDM device instance.
1178 * @{ */
1179 /** The APIC device - R0 ptr. */
1180 R0PTRTYPE(PAPICDEV) pApicDevR0;
1181 /** The APIC device - R3 ptr. */
1182 R3PTRTYPE(PAPICDEV) pApicDevR3;
1183 /** The APIC device - RC ptr. */
1184 RCPTRTYPE(PAPICDEV) pApicDevRC;
1185 /** Alignment padding. */
1186 RTRCPTR RCPtrAlignment0;
1187 /** @} */
1188
1189 /** @name The APIC pending-interrupt bitmap (PIB).
1190 * @{ */
1191 /** The host-context physical address of the PIB. */
1192 RTHCPHYS HCPhysApicPib;
1193 /** The ring-0 memory object of the PIB. */
1194 RTR0MEMOBJ hMemObjApicPibR0;
1195 /** The ring-3 mapping of the memory object of the PIB. */
1196 RTR0MEMOBJ hMapObjApicPibR0;
1197 /** The APIC PIB virtual address - R0 ptr. */
1198 R0PTRTYPE(void *) pvApicPibR0;
1199 /** The APIC PIB virtual address - R3 ptr. */
1200 R3PTRTYPE(void *) pvApicPibR3;
1201 /** The APIC PIB virtual address - RC ptr. */
1202 RCPTRTYPE(void *) pvApicPibRC;
1203 /** Alignment padding. */
1204 RTRCPTR RCPtrAlignment1;
1205 /** The size of the page in bytes. */
1206 uint32_t cbApicPib;
1207 /** Alignment padding. */
1208 uint32_t u32Aligment0;
1209 /** @} */
1210
1211 /** @name Other miscellaneous data.
1212 * @{ */
1213 /** Whether full APIC register virtualization is enabled. */
1214 bool fVirtApicRegsEnabled;
1215 /** Whether posted-interrupt processing is enabled. */
1216 bool fPostedIntrsEnabled;
1217 /** Whether TSC-deadline timer mode is supported for the guest. */
1218 bool fSupportsTscDeadline;
1219 /** Whether this VM has an IO-APIC. */
1220 bool fIoApicPresent;
1221 /** Whether RZ is enabled or not (applies to MSR handling as well). */
1222 bool fRZEnabled;
1223 /** Whether Hyper-V x2APIC compatibility mode is enabled. */
1224 bool fHyperVCompatMode;
1225 /** Alignment padding. */
1226 bool afAlignment[2];
1227 /** The max supported APIC mode from CFGM. */
1228 PDMAPICMODE enmMaxMode;
1229 /** Alignment padding. */
1230 uint32_t u32Alignment1;
1231 /** @} */
1232} APIC;
1233/** Pointer to APIC VM instance data. */
1234typedef APIC *PAPIC;
1235/** Pointer to const APIC VM instance data. */
1236typedef APIC const *PCAPIC;
1237AssertCompileMemberAlignment(APIC, cbApicPib, 8);
1238AssertCompileMemberAlignment(APIC, fVirtApicRegsEnabled, 8);
1239AssertCompileMemberAlignment(APIC, enmMaxMode, 8);
1240AssertCompileSizeAlignment(APIC, 8);
1241
1242/**
1243 * APIC VMCPU Instance data.
1244 */
1245typedef struct APICCPU
1246{
1247 /** @name The APIC page.
1248 * @{ */
1249 /** The host-context physical address of the page. */
1250 RTHCPHYS HCPhysApicPage;
1251 /** The ring-0 memory object of the page. */
1252 RTR0MEMOBJ hMemObjApicPageR0;
1253 /** The ring-3 mapping of the memory object of the page. */
1254 RTR0MEMOBJ hMapObjApicPageR0;
1255 /** The APIC page virtual address - R0 ptr. */
1256 R0PTRTYPE(void *) pvApicPageR0;
1257 /** The APIC page virtual address - R3 ptr. */
1258 R3PTRTYPE(void *) pvApicPageR3;
1259 /** The APIC page virtual address - RC ptr. */
1260 RCPTRTYPE(void *) pvApicPageRC;
1261 /** Alignment padding. */
1262 RTRCPTR RCPtrAlignment0;
1263 /** The size of the page in bytes. */
1264 uint32_t cbApicPage;
1265 /** @} */
1266
1267 /** @name Auxiliary state.
1268 * @{ */
1269 /** The error status register's internal state. */
1270 uint32_t uEsrInternal;
1271 /** The APIC base MSR.*/
1272 uint64_t volatile uApicBaseMsr;
1273 /** @} */
1274
1275 /** @name The pending-interrupt bitmaps (PIB).
1276 * @{ */
1277 /** The host-context physical address of the page. */
1278 RTHCPHYS HCPhysApicPib;
1279 /** The APIC PIB virtual address - R0 ptr. */
1280 R0PTRTYPE(void *) pvApicPibR0;
1281 /** The APIC PIB virtual address - R3 ptr. */
1282 R3PTRTYPE(void *) pvApicPibR3;
1283 /** The APIC PIB virtual address - RC ptr. */
1284 RCPTRTYPE(void *) pvApicPibRC;
1285 /** Alignment padding. */
1286 RTRCPTR RCPtrAlignment1;
1287 /** The APIC PIB for level-sensitive interrupts. */
1288 APICPIB ApicPibLevel;
1289 /** @} */
1290
1291 /** @name Other miscellaneous data.
1292 * @{ */
1293 /** Whether the LINT0 interrupt line is active. */
1294 bool volatile fActiveLint0;
1295 /** Whether the LINT1 interrupt line is active. */
1296 bool volatile fActiveLint1;
1297 /** Alignment padding. */
1298 uint8_t auAlignment2[6];
1299 /** The source tags corresponding to each interrupt vector (debugging). */
1300 uint32_t auSrcTags[256];
1301 /** @} */
1302
1303 /** @name The APIC timer.
1304 * @{ */
1305 /** The timer - R0 ptr. */
1306 PTMTIMERR0 pTimerR0;
1307 /** The timer - R3 ptr. */
1308 PTMTIMERR3 pTimerR3;
1309 /** The timer - RC ptr. */
1310 PTMTIMERRC pTimerRC;
1311 /** Alignment padding. */
1312 RTRCPTR RCPtrAlignment3;
1313 /** The timer critical sect protecting @a u64TimerInitial */
1314 PDMCRITSECT TimerCritSect;
1315 /** The time stamp when the timer was initialized. */
1316 uint64_t u64TimerInitial;
1317 /** Cache of timer initial count of the frequency hint to TM. */
1318 uint32_t uHintedTimerInitialCount;
1319 /** Cache of timer shift of the frequency hint to TM. */
1320 uint32_t uHintedTimerShift;
1321 /** The timer description. */
1322 char szTimerDesc[32];
1323 /** @} */
1324
1325 /** @name Log Max counters
1326 * @{ */
1327 uint32_t cLogMaxAccessError;
1328 uint32_t cLogMaxSetApicBaseAddr;
1329 uint32_t cLogMaxGetApicBaseAddr;
1330 uint32_t uAlignment4;
1331 /** @} */
1332
1333#ifdef VBOX_WITH_STATISTICS
1334 /** @name APIC statistics.
1335 * @{ */
1336 /** Number of MMIO reads in RZ. */
1337 STAMCOUNTER StatMmioReadRZ;
1338 /** Number of MMIO reads in R3. */
1339 STAMCOUNTER StatMmioReadR3;
1340
1341 /** Number of MMIO writes in RZ. */
1342 STAMCOUNTER StatMmioWriteRZ;
1343 /** Number of MMIO writes in R3. */
1344 STAMCOUNTER StatMmioWriteR3;
1345
1346 /** Number of MSR reads in RZ. */
1347 STAMCOUNTER StatMsrReadRZ;
1348 /** Number of MSR reads in R3. */
1349 STAMCOUNTER StatMsrReadR3;
1350
1351 /** Number of MSR writes in RZ. */
1352 STAMCOUNTER StatMsrWriteRZ;
1353 /** Number of MSR writes in R3. */
1354 STAMCOUNTER StatMsrWriteR3;
1355
1356 /** Profiling of APICUpdatePendingInterrupts(). */
1357 STAMPROFILE StatUpdatePendingIntrs;
1358 /** Profiling of apicPostInterrupt(). */
1359 STAMPROFILE StatPostIntr;
1360 /** Number of times an interrupt is already pending in
1361 * apicPostInterrupts().*/
1362 STAMCOUNTER StatPostIntrAlreadyPending;
1363 /** Number of times the timer callback is invoked. */
1364 STAMCOUNTER StatTimerCallback;
1365 /** Number of times the TPR is written. */
1366 STAMCOUNTER StatTprWrite;
1367 /** Number of times the TPR is read. */
1368 STAMCOUNTER StatTprRead;
1369 /** Number of times the EOI is written. */
1370 STAMCOUNTER StatEoiWrite;
1371 /** Number of times TPR masks an interrupt in apicGetInterrupt(). */
1372 STAMCOUNTER StatMaskedByTpr;
1373 /** Number of times PPR masks an interrupt in apicGetInterrupt(). */
1374 STAMCOUNTER StatMaskedByPpr;
1375 /** Number of times the timer ICR is written. */
1376 STAMCOUNTER StatTimerIcrWrite;
1377 /** Number of times the ICR Lo (send IPI) is written. */
1378 STAMCOUNTER StatIcrLoWrite;
1379 /** Number of times the ICR Hi is written. */
1380 STAMCOUNTER StatIcrHiWrite;
1381 /** Number of times the full ICR (x2APIC send IPI) is written. */
1382 STAMCOUNTER StatIcrFullWrite;
1383 /** @} */
1384#endif
1385} APICCPU;
1386/** Pointer to APIC VMCPU instance data. */
1387typedef APICCPU *PAPICCPU;
1388/** Pointer to a const APIC VMCPU instance data. */
1389typedef APICCPU const *PCAPICCPU;
1390AssertCompileMemberAlignment(APICCPU, uApicBaseMsr, 8);
1391
1392/**
1393 * APIC operating modes as returned by apicGetMode().
1394 *
1395 * The values match hardware states.
1396 * See Intel spec. 10.12.1 "Detecting and Enabling x2APIC Mode".
1397 */
1398typedef enum APICMODE
1399{
1400 APICMODE_DISABLED = 0,
1401 APICMODE_INVALID,
1402 APICMODE_XAPIC,
1403 APICMODE_X2APIC
1404} APICMODE;
1405
1406/**
1407 * Gets the timer shift value.
1408 *
1409 * @returns The timer shift value.
1410 * @param pXApicPage The xAPIC page.
1411 */
1412DECLINLINE(uint8_t) apicGetTimerShift(PCXAPICPAGE pXApicPage)
1413{
1414 /* See Intel spec. 10.5.4 "APIC Timer". */
1415 uint32_t uShift = pXApicPage->timer_dcr.u.u2DivideValue0 | (pXApicPage->timer_dcr.u.u1DivideValue1 << 2);
1416 return (uShift + 1) & 7;
1417}
1418
1419RT_C_DECLS_BEGIN
1420
1421
1422/** @def APICBOTHCBDECL
1423 * Macro for declaring a callback which is static in HC and exported in GC.
1424 */
1425#if defined(IN_RC) || defined(IN_RING0)
1426# define APICBOTHCBDECL(type) DECLEXPORT(type)
1427#else
1428# define APICBOTHCBDECL(type) DECLCALLBACK(type)
1429#endif
1430
1431const char *apicGetModeName(APICMODE enmMode);
1432const char *apicGetDestFormatName(XAPICDESTFORMAT enmDestFormat);
1433const char *apicGetDeliveryModeName(XAPICDELIVERYMODE enmDeliveryMode);
1434const char *apicGetDestModeName(XAPICDESTMODE enmDestMode);
1435const char *apicGetTriggerModeName(XAPICTRIGGERMODE enmTriggerMode);
1436const char *apicGetDestShorthandName(XAPICDESTSHORTHAND enmDestShorthand);
1437const char *apicGetTimerModeName(XAPICTIMERMODE enmTimerMode);
1438void apicHintTimerFreq(PAPICCPU pApicCpu, uint32_t uInitialCount, uint8_t uTimerShift);
1439APICMODE apicGetMode(uint64_t uApicBaseMsr);
1440
1441APICBOTHCBDECL(uint64_t) apicGetBaseMsr(PPDMDEVINS pDevIns, PVMCPU pVCpu);
1442APICBOTHCBDECL(VBOXSTRICTRC) apicSetBaseMsr(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint64_t uBase);
1443APICBOTHCBDECL(uint8_t) apicGetTpr(PPDMDEVINS pDevIns, PVMCPU pVCpu, bool *pfPending, uint8_t *pu8PendingIntr);
1444APICBOTHCBDECL(void) apicSetTpr(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t u8Tpr);
1445APICBOTHCBDECL(uint64_t) apicGetTimerFreq(PPDMDEVINS pDevIns);
1446APICBOTHCBDECL(int) apicReadMmio(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb);
1447APICBOTHCBDECL(int) apicWriteMmio(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb);
1448APICBOTHCBDECL(VBOXSTRICTRC) apicReadMsr(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint32_t u32Reg, uint64_t *pu64Val);
1449APICBOTHCBDECL(VBOXSTRICTRC) apicWriteMsr(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint32_t u32Reg, uint64_t u64Val);
1450APICBOTHCBDECL(int) apicGetInterrupt(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t *puVector, uint32_t *puTagSrc);
1451APICBOTHCBDECL(VBOXSTRICTRC) apicLocalInterrupt(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t u8Pin, uint8_t u8Level, int rcRZ);
1452APICBOTHCBDECL(int) apicBusDeliver(PPDMDEVINS pDevIns, uint8_t uDest, uint8_t uDestMode, uint8_t uDeliveryMode,
1453 uint8_t uVector, uint8_t uPolarity, uint8_t uTriggerMode, uint32_t uSrcTag);
1454
1455VMM_INT_DECL(bool) apicPostInterrupt(PVMCPU pVCpu, uint8_t uVector, XAPICTRIGGERMODE enmTriggerMode, uint32_t uSrcTag);
1456VMM_INT_DECL(void) apicStartTimer(PVMCPU pVCpu, uint32_t uInitialCount);
1457VMM_INT_DECL(void) apicStopTimer(PVMCPU pVCpu);
1458VMM_INT_DECL(void) apicSetInterruptFF(PVMCPU pVCpu, PDMAPICIRQ enmType);
1459VMM_INT_DECL(void) apicClearInterruptFF(PVMCPU pVCpu, PDMAPICIRQ enmType);
1460void apicInitIpi(PVMCPU pVCpu);
1461void apicResetCpu(PVMCPU pVCpu, bool fResetApicBaseMsr);
1462
1463RT_C_DECLS_END
1464
1465/** @} */
1466
1467#endif
1468
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette