VirtualBox

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

Last change on this file since 72064 was 69111, checked in by vboxsync, 7 years ago

(C) year

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

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