VirtualBox

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

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

CPUM,APIC: Per-CPU APIC CPUID feature bit and MSR_IA32_APICBASE GP mask adjustments.

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