VirtualBox

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

Last change on this file since 80651 was 80531, checked in by vboxsync, 5 years ago

VMM,Devices: Some PDM device model refactoring. bugref:9218

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