VirtualBox

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

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

APIC: Converted the timer pointers to timer handles. This requires PPDMDEVINS to be accessible when called directly from the VMM, so adding pointers to the APIC specific GVM and VM structures. bugref:9218

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 54.5 KB
Line 
1/* $Id: APICInternal.h 82031 2019-11-20 16:11:16Z 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 /** The device instance - R3 Ptr. */
1164 PPDMDEVINSR3 pDevInsR3;
1165} APICDEV;
1166/** Pointer to an APIC device. */
1167typedef APICDEV *PAPICDEV;
1168/** Pointer to a const APIC device. */
1169typedef APICDEV const *PCAPICDEV;
1170
1171
1172/**
1173 * The APIC GVM instance data.
1174 */
1175typedef struct APICR0PERVM
1176{
1177 /** The ring-0 device instance. */
1178 PPDMDEVINSR0 pDevInsR0;
1179} APICR0PERVM;
1180
1181
1182/**
1183 * APIC VM Instance data.
1184 */
1185typedef struct APIC
1186{
1187 /** @name The APIC PDM device instance.
1188 * @{ */
1189 /** The APIC device - R0 ptr. */
1190 R0PTRTYPE(PAPICDEV) pApicDevR0;
1191 /** The APIC device - R3 ptr. */
1192 R3PTRTYPE(PAPICDEV) pApicDevR3;
1193 /** The ring-3 device instance. */
1194 PPDMDEVINSR3 pDevInsR3;
1195 /** @} */
1196
1197 /** @name The APIC pending-interrupt bitmap (PIB).
1198 * @{ */
1199 /** The host-context physical address of the PIB. */
1200 RTHCPHYS HCPhysApicPib;
1201 /** The ring-0 memory object of the PIB. */
1202 RTR0MEMOBJ hMemObjApicPibR0;
1203 /** The ring-3 mapping of the memory object of the PIB. */
1204 RTR0MEMOBJ hMapObjApicPibR0;
1205 /** The APIC PIB virtual address - R0 ptr. */
1206 R0PTRTYPE(void *) pvApicPibR0;
1207 /** The APIC PIB virtual address - R3 ptr. */
1208 R3PTRTYPE(void *) pvApicPibR3;
1209 /** The size of the page in bytes. */
1210 uint32_t cbApicPib;
1211 /** Alignment padding. */
1212 uint32_t u32Aligment0;
1213 /** @} */
1214
1215 /** @name Other miscellaneous data.
1216 * @{ */
1217 /** Whether full APIC register virtualization is enabled. */
1218 bool fVirtApicRegsEnabled;
1219 /** Whether posted-interrupt processing is enabled. */
1220 bool fPostedIntrsEnabled;
1221 /** Whether TSC-deadline timer mode is supported for the guest. */
1222 bool fSupportsTscDeadline;
1223 /** Whether this VM has an IO-APIC. */
1224 bool fIoApicPresent;
1225 /** Whether R0 is enabled or not (applies to MSR handling as well). */
1226 bool fR0Enabled;
1227 /** Whether RC is enabled or not (applies to MSR handling as well). */
1228 bool fRCEnabled;
1229 /** Whether Hyper-V x2APIC compatibility mode is enabled. */
1230 bool fHyperVCompatMode;
1231 /** Alignment padding. */
1232 bool afAlignment[1];
1233 /** The max supported APIC mode from CFGM. */
1234 PDMAPICMODE enmMaxMode;
1235 /** Alignment padding. */
1236 uint32_t u32Alignment1;
1237 /** @} */
1238} APIC;
1239/** Pointer to APIC VM instance data. */
1240typedef APIC *PAPIC;
1241/** Pointer to const APIC VM instance data. */
1242typedef APIC const *PCAPIC;
1243AssertCompileMemberAlignment(APIC, cbApicPib, 8);
1244AssertCompileMemberAlignment(APIC, fVirtApicRegsEnabled, 8);
1245AssertCompileMemberAlignment(APIC, enmMaxMode, 8);
1246AssertCompileSizeAlignment(APIC, 8);
1247
1248/**
1249 * APIC VMCPU Instance data.
1250 */
1251typedef struct APICCPU
1252{
1253 /** @name The APIC page.
1254 * @{ */
1255 /** The host-context physical address of the page. */
1256 RTHCPHYS HCPhysApicPage;
1257 /** The ring-0 memory object of the page. */
1258 RTR0MEMOBJ hMemObjApicPageR0;
1259 /** The ring-3 mapping of the memory object of the page. */
1260 RTR0MEMOBJ hMapObjApicPageR0;
1261 /** The APIC page virtual address - R0 ptr. */
1262 R0PTRTYPE(void *) pvApicPageR0;
1263 /** The APIC page virtual address - R3 ptr. */
1264 R3PTRTYPE(void *) pvApicPageR3;
1265 /** The size of the page in bytes. */
1266 uint32_t cbApicPage;
1267 /** @} */
1268
1269 /** @name Auxiliary state.
1270 * @{ */
1271 /** The error status register's internal state. */
1272 uint32_t uEsrInternal;
1273 /** The APIC base MSR.*/
1274 uint64_t volatile uApicBaseMsr;
1275 /** @} */
1276
1277 /** @name The pending-interrupt bitmaps (PIB).
1278 * @{ */
1279 /** The host-context physical address of the page. */
1280 RTHCPHYS HCPhysApicPib;
1281 /** The APIC PIB virtual address - R0 ptr. */
1282 R0PTRTYPE(void *) pvApicPibR0;
1283 /** The APIC PIB virtual address - R3 ptr. */
1284 R3PTRTYPE(void *) pvApicPibR3;
1285 /** The APIC PIB for level-sensitive interrupts. */
1286 APICPIB ApicPibLevel;
1287 /** @} */
1288
1289 /** @name Other miscellaneous data.
1290 * @{ */
1291 /** Whether the LINT0 interrupt line is active. */
1292 bool volatile fActiveLint0;
1293 /** Whether the LINT1 interrupt line is active. */
1294 bool volatile fActiveLint1;
1295 /** Alignment padding. */
1296 uint8_t auAlignment2[6];
1297 /** The source tags corresponding to each interrupt vector (debugging). */
1298 uint32_t auSrcTags[256];
1299 /** @} */
1300
1301 /** @name The APIC timer.
1302 * @{ */
1303 /** The timer. */
1304 TMTIMERHANDLE hTimer;
1305 /** The time stamp when the timer was initialized. */
1306 uint64_t u64TimerInitial;
1307 /** Cache of timer initial count of the frequency hint to TM. */
1308 uint32_t uHintedTimerInitialCount;
1309 /** Cache of timer shift of the frequency hint to TM. */
1310 uint32_t uHintedTimerShift;
1311 /** The timer critical sect protecting @a u64TimerInitial */
1312 PDMCRITSECT TimerCritSect;
1313 /** The timer description. */
1314 char szTimerDesc[32];
1315 /** @} */
1316
1317 /** @name Log Max counters
1318 * @{ */
1319 uint32_t cLogMaxAccessError;
1320 uint32_t cLogMaxSetApicBaseAddr;
1321 uint32_t cLogMaxGetApicBaseAddr;
1322 uint32_t uAlignment4;
1323 /** @} */
1324
1325#ifdef VBOX_WITH_STATISTICS
1326 /** @name APIC statistics.
1327 * @{ */
1328 /** Number of MMIO reads in RZ. */
1329 STAMCOUNTER StatMmioReadRZ;
1330 /** Number of MMIO reads in R3. */
1331 STAMCOUNTER StatMmioReadR3;
1332
1333 /** Number of MMIO writes in RZ. */
1334 STAMCOUNTER StatMmioWriteRZ;
1335 /** Number of MMIO writes in R3. */
1336 STAMCOUNTER StatMmioWriteR3;
1337
1338 /** Number of MSR reads in RZ. */
1339 STAMCOUNTER StatMsrReadRZ;
1340 /** Number of MSR reads in R3. */
1341 STAMCOUNTER StatMsrReadR3;
1342
1343 /** Number of MSR writes in RZ. */
1344 STAMCOUNTER StatMsrWriteRZ;
1345 /** Number of MSR writes in R3. */
1346 STAMCOUNTER StatMsrWriteR3;
1347
1348 /** Profiling of APICUpdatePendingInterrupts(). */
1349 STAMPROFILE StatUpdatePendingIntrs;
1350 /** Profiling of apicPostInterrupt(). */
1351 STAMPROFILE StatPostIntr;
1352 /** Number of times an interrupt is already pending in
1353 * apicPostInterrupts().*/
1354 STAMCOUNTER StatPostIntrAlreadyPending;
1355 /** Number of times the timer callback is invoked. */
1356 STAMCOUNTER StatTimerCallback;
1357 /** Number of times the TPR is written. */
1358 STAMCOUNTER StatTprWrite;
1359 /** Number of times the TPR is read. */
1360 STAMCOUNTER StatTprRead;
1361 /** Number of times the EOI is written. */
1362 STAMCOUNTER StatEoiWrite;
1363 /** Number of times TPR masks an interrupt in apicGetInterrupt(). */
1364 STAMCOUNTER StatMaskedByTpr;
1365 /** Number of times PPR masks an interrupt in apicGetInterrupt(). */
1366 STAMCOUNTER StatMaskedByPpr;
1367 /** Number of times the timer ICR is written. */
1368 STAMCOUNTER StatTimerIcrWrite;
1369 /** Number of times the ICR Lo (send IPI) is written. */
1370 STAMCOUNTER StatIcrLoWrite;
1371 /** Number of times the ICR Hi is written. */
1372 STAMCOUNTER StatIcrHiWrite;
1373 /** Number of times the full ICR (x2APIC send IPI) is written. */
1374 STAMCOUNTER StatIcrFullWrite;
1375 /** @} */
1376#endif
1377} APICCPU;
1378/** Pointer to APIC VMCPU instance data. */
1379typedef APICCPU *PAPICCPU;
1380/** Pointer to a const APIC VMCPU instance data. */
1381typedef APICCPU const *PCAPICCPU;
1382AssertCompileMemberAlignment(APICCPU, uApicBaseMsr, 8);
1383
1384/**
1385 * APIC operating modes as returned by apicGetMode().
1386 *
1387 * The values match hardware states.
1388 * See Intel spec. 10.12.1 "Detecting and Enabling x2APIC Mode".
1389 */
1390typedef enum APICMODE
1391{
1392 APICMODE_DISABLED = 0,
1393 APICMODE_INVALID,
1394 APICMODE_XAPIC,
1395 APICMODE_X2APIC
1396} APICMODE;
1397
1398/**
1399 * Gets the timer shift value.
1400 *
1401 * @returns The timer shift value.
1402 * @param pXApicPage The xAPIC page.
1403 */
1404DECLINLINE(uint8_t) apicGetTimerShift(PCXAPICPAGE pXApicPage)
1405{
1406 /* See Intel spec. 10.5.4 "APIC Timer". */
1407 uint32_t uShift = pXApicPage->timer_dcr.u.u2DivideValue0 | (pXApicPage->timer_dcr.u.u1DivideValue1 << 2);
1408 return (uShift + 1) & 7;
1409}
1410
1411RT_C_DECLS_BEGIN
1412
1413
1414/** @def APICBOTHCBDECL
1415 * Macro for declaring a callback which is static in HC and exported in GC.
1416 */
1417#if defined(IN_RC) || defined(IN_RING0)
1418# define APICBOTHCBDECL(type) DECLEXPORT(type)
1419#else
1420# define APICBOTHCBDECL(type) DECLCALLBACK(type)
1421#endif
1422
1423const char *apicGetModeName(APICMODE enmMode);
1424const char *apicGetDestFormatName(XAPICDESTFORMAT enmDestFormat);
1425const char *apicGetDeliveryModeName(XAPICDELIVERYMODE enmDeliveryMode);
1426const char *apicGetDestModeName(XAPICDESTMODE enmDestMode);
1427const char *apicGetTriggerModeName(XAPICTRIGGERMODE enmTriggerMode);
1428const char *apicGetDestShorthandName(XAPICDESTSHORTHAND enmDestShorthand);
1429const char *apicGetTimerModeName(XAPICTIMERMODE enmTimerMode);
1430void apicHintTimerFreq(PPDMDEVINS pDevIns, PAPICCPU pApicCpu, uint32_t uInitialCount, uint8_t uTimerShift);
1431APICMODE apicGetMode(uint64_t uApicBaseMsr);
1432
1433APICBOTHCBDECL(uint64_t) apicGetBaseMsr(PPDMDEVINS pDevIns, PVMCPU pVCpu);
1434APICBOTHCBDECL(VBOXSTRICTRC) apicSetBaseMsr(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint64_t uBase);
1435APICBOTHCBDECL(uint8_t) apicGetTpr(PPDMDEVINS pDevIns, PVMCPU pVCpu, bool *pfPending, uint8_t *pu8PendingIntr);
1436APICBOTHCBDECL(void) apicSetTpr(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t u8Tpr);
1437APICBOTHCBDECL(uint64_t) apicGetTimerFreq(PPDMDEVINS pDevIns);
1438DECLCALLBACK(VBOXSTRICTRC) apicReadMmio(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, unsigned cb);
1439DECLCALLBACK(VBOXSTRICTRC) apicWriteMmio(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void const *pv, unsigned cb);
1440APICBOTHCBDECL(VBOXSTRICTRC) apicReadMsr(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint32_t u32Reg, uint64_t *pu64Val);
1441APICBOTHCBDECL(VBOXSTRICTRC) apicWriteMsr(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint32_t u32Reg, uint64_t u64Val);
1442APICBOTHCBDECL(int) apicGetInterrupt(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t *puVector, uint32_t *puTagSrc);
1443APICBOTHCBDECL(VBOXSTRICTRC) apicLocalInterrupt(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t u8Pin, uint8_t u8Level, int rcRZ);
1444APICBOTHCBDECL(int) apicBusDeliver(PPDMDEVINS pDevIns, uint8_t uDest, uint8_t uDestMode, uint8_t uDeliveryMode,
1445 uint8_t uVector, uint8_t uPolarity, uint8_t uTriggerMode, uint32_t uSrcTag);
1446
1447VMM_INT_DECL(bool) apicPostInterrupt(PVMCPUCC pVCpu, uint8_t uVector, XAPICTRIGGERMODE enmTriggerMode, uint32_t uSrcTag);
1448VMM_INT_DECL(void) apicStartTimer(PVMCPUCC pVCpu, uint32_t uInitialCount);
1449VMM_INT_DECL(void) apicClearInterruptFF(PVMCPUCC pVCpu, PDMAPICIRQ enmType);
1450void apicInitIpi(PVMCPUCC pVCpu);
1451void apicResetCpu(PVMCPUCC pVCpu, bool fResetApicBaseMsr);
1452
1453DECLCALLBACK(int) apicR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg);
1454DECLCALLBACK(int) apicR3Destruct(PPDMDEVINS pDevIns);
1455DECLCALLBACK(void) apicR3Relocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta);
1456DECLCALLBACK(void) apicR3Reset(PPDMDEVINS pDevIns);
1457DECLCALLBACK(int) apicR3InitComplete(PPDMDEVINS pDevIns);
1458
1459RT_C_DECLS_END
1460
1461/** @} */
1462
1463#endif /* !VMM_INCLUDED_SRC_include_APICInternal_h */
1464
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