VirtualBox

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

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

APIC: Drop APICDEV::pDevInsR3 as nobody uses it. bugref:9218

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