VirtualBox

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

Last change on this file since 61581 was 61581, checked in by vboxsync, 8 years ago

VMM/APIC: Fix remote IRR bit for level-triggered LINT0 interrupts and make LINT0/LINT1 only edge-triggered interrupts
on an edge-transition to the active state. For this we need to track the interrupt line state for LINT0/LINT1 pins.
Saved-state change will follow.

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