VirtualBox

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

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

VMM: Kicking out raw-mode - APIC. bugref:9517

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