VirtualBox

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

Last change on this file since 93115 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 41.8 KB
Line 
1/* $Id: APICInternal.h 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * APIC - Advanced Programmable Interrupt Controller.
4 */
5
6/*
7 * Copyright (C) 2016-2022 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/apic.h>
25#include <VBox/sup.h>
26#include <VBox/vmm/pdmdev.h>
27
28/** @defgroup grp_apic_int Internal
29 * @ingroup grp_apic
30 * @internal
31 * @{
32 */
33
34/** The APIC hardware version we are emulating. */
35#define XAPIC_HARDWARE_VERSION XAPIC_HARDWARE_VERSION_P4
36
37#if XAPIC_HARDWARE_VERSION == XAPIC_HARDWARE_VERSION_P4
38#define XAPIC_SVR_VALID XAPIC_SVR_VALID_P4
39#define XAPIC_ID_BROADCAST_MASK XAPIC_ID_BROADCAST_MASK_P4
40#else
41# error "Implement Pentium and P6 family APIC architectures"
42#endif
43
44#define VMCPU_TO_XAPICPAGE(a_pVCpu) ((PXAPICPAGE)(CTX_SUFF((a_pVCpu)->apic.s.pvApicPage)))
45#define VMCPU_TO_CXAPICPAGE(a_pVCpu) ((PCXAPICPAGE)(CTX_SUFF((a_pVCpu)->apic.s.pvApicPage)))
46
47#define VMCPU_TO_X2APICPAGE(a_pVCpu) ((PX2APICPAGE)(CTX_SUFF((a_pVCpu)->apic.s.pvApicPage)))
48#define VMCPU_TO_CX2APICPAGE(a_pVCpu) ((PCX2APICPAGE)(CTX_SUFF((a_pVCpu)->apic.s.pvApicPage)))
49
50#define VMCPU_TO_APICCPU(a_pVCpu) (&(a_pVCpu)->apic.s)
51#define VM_TO_APIC(a_pVM) (&(a_pVM)->apic.s)
52#define VM_TO_APICDEV(a_pVM) CTX_SUFF(VM_TO_APIC(a_pVM)->pApicDev)
53#ifdef IN_RING3
54# define VMCPU_TO_DEVINS(a_pVCpu) ((a_pVCpu)->pVMR3->apic.s.pDevInsR3)
55#elif defined(IN_RING0)
56# define VMCPU_TO_DEVINS(a_pVCpu) ((a_pVCpu)->pGVM->apicr0.s.pDevInsR0)
57#endif
58
59#define APICCPU_TO_XAPICPAGE(a_ApicCpu) ((PXAPICPAGE)(CTX_SUFF((a_ApicCpu)->pvApicPage)))
60#define APICCPU_TO_CXAPICPAGE(a_ApicCpu) ((PCXAPICPAGE)(CTX_SUFF((a_ApicCpu)->pvApicPage)))
61
62/** Vector offset in an APIC 256-bit sparse register. */
63#define XAPIC_REG256_VECTOR_OFF(a_Vector) (((a_Vector) & UINT32_C(0xe0)) >> 1)
64/** Bit position at offset in an APIC 256-bit sparse register. */
65#define XAPIC_REG256_VECTOR_BIT(a_Vector) ((a_Vector) & UINT32_C(0x1f))
66
67/** Maximum valid offset for a register (16-byte aligned, 4 byte wide access). */
68#define XAPIC_OFF_MAX_VALID (sizeof(XAPICPAGE) - 4 * sizeof(uint32_t))
69
70/** Whether the APIC is in X2APIC mode or not. */
71#define XAPIC_IN_X2APIC_MODE(a_pVCpu) ( ( ((a_pVCpu)->apic.s.uApicBaseMsr) \
72 & (MSR_IA32_APICBASE_EN | MSR_IA32_APICBASE_EXTD)) \
73 == (MSR_IA32_APICBASE_EN | MSR_IA32_APICBASE_EXTD) )
74
75/**
76 * The xAPIC sparse 256-bit register.
77 */
78typedef union XAPIC256BITREG
79{
80 /** The sparse-bitmap view. */
81 struct
82 {
83 uint32_t u32Reg;
84 uint32_t uReserved0[3];
85 } u[8];
86 /** The 32-bit view. */
87 uint32_t au32[32];
88} XAPIC256BITREG;
89/** Pointer to an xAPIC sparse bitmap register. */
90typedef XAPIC256BITREG *PXAPIC256BITREG;
91/** Pointer to a const xAPIC sparse bitmap register. */
92typedef XAPIC256BITREG const *PCXAPIC256BITREG;
93AssertCompileSize(XAPIC256BITREG, 128);
94
95/**
96 * The xAPIC memory layout as per Intel/AMD specs.
97 */
98typedef struct XAPICPAGE
99{
100 /* 0x00 - Reserved. */
101 uint32_t uReserved0[8];
102 /* 0x20 - APIC ID. */
103 struct
104 {
105 uint8_t u8Reserved0[3];
106 uint8_t u8ApicId;
107 uint32_t u32Reserved0[3];
108 } id;
109 /* 0x30 - APIC version register. */
110 union
111 {
112 struct
113 {
114#if XAPIC_HARDWARE_VERSION == XAPIC_HARDWARE_VERSION_P4
115 uint8_t u8Version;
116#else
117# error "Implement Pentium and P6 family APIC architectures"
118#endif
119 uint8_t uReserved0;
120 uint8_t u8MaxLvtEntry;
121 uint8_t fEoiBroadcastSupression : 1;
122 uint8_t u7Reserved1 : 7;
123 uint32_t u32Reserved0[3];
124 } u;
125 struct
126 {
127 uint32_t u32Version;
128 uint32_t u32Reserved0[3];
129 } all;
130 } version;
131 /* 0x40 - Reserved. */
132 uint32_t uReserved1[16];
133 /* 0x80 - Task Priority Register (TPR). */
134 struct
135 {
136 uint8_t u8Tpr;
137 uint8_t u8Reserved0[3];
138 uint32_t u32Reserved0[3];
139 } tpr;
140 /* 0x90 - Arbitration Priority Register (APR). */
141 struct
142 {
143 uint8_t u8Apr;
144 uint8_t u8Reserved0[3];
145 uint32_t u32Reserved0[3];
146 } apr;
147 /* 0xA0 - Processor Priority Register (PPR). */
148 struct
149 {
150 uint8_t u8Ppr;
151 uint8_t u8Reserved0[3];
152 uint32_t u32Reserved0[3];
153 } ppr;
154 /* 0xB0 - End Of Interrupt Register (EOI). */
155 struct
156 {
157 uint32_t u32Eoi;
158 uint32_t u32Reserved0[3];
159 } eoi;
160 /* 0xC0 - Remote Read Register (RRD). */
161 struct
162 {
163 uint32_t u32Rrd;
164 uint32_t u32Reserved0[3];
165 } rrd;
166 /* 0xD0 - Logical Destination Register (LDR). */
167 union
168 {
169 struct
170 {
171 uint8_t u8Reserved0[3];
172 uint8_t u8LogicalApicId;
173 uint32_t u32Reserved0[3];
174 } u;
175 struct
176 {
177 uint32_t u32Ldr;
178 uint32_t u32Reserved0[3];
179 } all;
180 } ldr;
181 /* 0xE0 - Destination Format Register (DFR). */
182 union
183 {
184 struct
185 {
186 uint32_t u28ReservedMb1 : 28; /* MB1 */
187 uint32_t u4Model : 4;
188 uint32_t u32Reserved0[3];
189 } u;
190 struct
191 {
192 uint32_t u32Dfr;
193 uint32_t u32Reserved0[3];
194 } all;
195 } dfr;
196 /* 0xF0 - Spurious-Interrupt Vector Register (SVR). */
197 union
198 {
199 struct
200 {
201 uint32_t u8SpuriousVector : 8;
202 uint32_t fApicSoftwareEnable : 1;
203 uint32_t u3Reserved0 : 3;
204 uint32_t fSupressEoiBroadcast : 1;
205 uint32_t u19Reserved1 : 19;
206 uint32_t u32Reserved0[3];
207 } u;
208 struct
209 {
210 uint32_t u32Svr;
211 uint32_t u32Reserved0[3];
212 } all;
213 } svr;
214 /* 0x100 - In-service Register (ISR). */
215 XAPIC256BITREG isr;
216 /* 0x180 - Trigger Mode Register (TMR). */
217 XAPIC256BITREG tmr;
218 /* 0x200 - Interrupt Request Register (IRR). */
219 XAPIC256BITREG irr;
220 /* 0x280 - Error Status Register (ESR). */
221 union
222 {
223 struct
224 {
225#if XAPIC_HARDWARE_VERSION == XAPIC_HARDWARE_VERSION_P4
226 uint32_t u4Reserved0 : 4;
227#else
228# error "Implement Pentium and P6 family APIC architectures"
229#endif
230 uint32_t fRedirectableIpi : 1;
231 uint32_t fSendIllegalVector : 1;
232 uint32_t fRcvdIllegalVector : 1;
233 uint32_t fIllegalRegAddr : 1;
234 uint32_t u24Reserved1 : 24;
235 uint32_t u32Reserved0[3];
236 } u;
237 struct
238 {
239 uint32_t u32Errors;
240 uint32_t u32Reserved0[3];
241 } all;
242 } esr;
243 /* 0x290 - Reserved. */
244 uint32_t uReserved2[28];
245 /* 0x300 - Interrupt Command Register (ICR) - Low. */
246 union
247 {
248 struct
249 {
250 uint32_t u8Vector : 8;
251 uint32_t u3DeliveryMode : 3;
252 uint32_t u1DestMode : 1;
253 uint32_t u1DeliveryStatus : 1;
254 uint32_t fReserved0 : 1;
255 uint32_t u1Level : 1;
256 uint32_t u1TriggerMode : 1;
257 uint32_t u2Reserved1 : 2;
258 uint32_t u2DestShorthand : 2;
259 uint32_t u12Reserved2 : 12;
260 uint32_t u32Reserved0[3];
261 } u;
262 struct
263 {
264 uint32_t u32IcrLo;
265 uint32_t u32Reserved0[3];
266 } all;
267 } icr_lo;
268 /* 0x310 - Interrupt Comannd Register (ICR) - High. */
269 union
270 {
271 struct
272 {
273 uint32_t u24Reserved0 : 24;
274 uint32_t u8Dest : 8;
275 uint32_t u32Reserved0[3];
276 } u;
277 struct
278 {
279 uint32_t u32IcrHi;
280 uint32_t u32Reserved0[3];
281 } all;
282 } icr_hi;
283 /* 0x320 - Local Vector Table (LVT) Timer Register. */
284 union
285 {
286 struct
287 {
288 uint32_t u8Vector : 8;
289 uint32_t u4Reserved0 : 4;
290 uint32_t u1DeliveryStatus : 1;
291 uint32_t u3Reserved1 : 3;
292 uint32_t u1Mask : 1;
293 uint32_t u2TimerMode : 2;
294 uint32_t u13Reserved2 : 13;
295 uint32_t u32Reserved0[3];
296 } u;
297 struct
298 {
299 uint32_t u32LvtTimer;
300 uint32_t u32Reserved0[3];
301 } all;
302 } lvt_timer;
303 /* 0x330 - Local Vector Table (LVT) Thermal Sensor Register. */
304#if XAPIC_HARDWARE_VERSION == XAPIC_HARDWARE_VERSION_P4
305 union
306 {
307 struct
308 {
309 uint32_t u8Vector : 8;
310 uint32_t u3DeliveryMode : 3;
311 uint32_t u1Reserved0 : 1;
312 uint32_t u1DeliveryStatus : 1;
313 uint32_t u3Reserved1 : 3;
314 uint32_t u1Mask : 1;
315 uint32_t u15Reserved2 : 15;
316 uint32_t u32Reserved0[3];
317 } u;
318 struct
319 {
320 uint32_t u32LvtThermal;
321 uint32_t u32Reserved0[3];
322 } all;
323 } lvt_thermal;
324#else
325# error "Implement Pentium and P6 family APIC architectures"
326#endif
327 /* 0x340 - Local Vector Table (LVT) Performance Monitor Counter (PMC) Register. */
328 union
329 {
330 struct
331 {
332 uint32_t u8Vector : 8;
333 uint32_t u3DeliveryMode : 3;
334 uint32_t u1Reserved0 : 1;
335 uint32_t u1DeliveryStatus : 1;
336 uint32_t u3Reserved1 : 3;
337 uint32_t u1Mask : 1;
338 uint32_t u15Reserved2 : 15;
339 uint32_t u32Reserved0[3];
340 } u;
341 struct
342 {
343 uint32_t u32LvtPerf;
344 uint32_t u32Reserved0[3];
345 } all;
346 } lvt_perf;
347 /* 0x350 - Local Vector Table (LVT) LINT0 Register. */
348 union
349 {
350 struct
351 {
352 uint32_t u8Vector : 8;
353 uint32_t u3DeliveryMode : 3;
354 uint32_t u1Reserved0 : 1;
355 uint32_t u1DeliveryStatus : 1;
356 uint32_t u1IntrPolarity : 1;
357 uint32_t u1RemoteIrr : 1;
358 uint32_t u1TriggerMode : 1;
359 uint32_t u1Mask : 1;
360 uint32_t u15Reserved2 : 15;
361 uint32_t u32Reserved0[3];
362 } u;
363 struct
364 {
365 uint32_t u32LvtLint0;
366 uint32_t u32Reserved0[3];
367 } all;
368 } lvt_lint0;
369 /* 0x360 - Local Vector Table (LVT) LINT1 Register. */
370 union
371 {
372 struct
373 {
374 uint32_t u8Vector : 8;
375 uint32_t u3DeliveryMode : 3;
376 uint32_t u1Reserved0 : 1;
377 uint32_t u1DeliveryStatus : 1;
378 uint32_t u1IntrPolarity : 1;
379 uint32_t u1RemoteIrr : 1;
380 uint32_t u1TriggerMode : 1;
381 uint32_t u1Mask : 1;
382 uint32_t u15Reserved2 : 15;
383 uint32_t u32Reserved0[3];
384 } u;
385 struct
386 {
387 uint32_t u32LvtLint1;
388 uint32_t u32Reserved0[3];
389 } all;
390 } lvt_lint1;
391 /* 0x370 - Local Vector Table (LVT) Error Register. */
392 union
393 {
394 struct
395 {
396 uint32_t u8Vector : 8;
397 uint32_t u4Reserved0 : 4;
398 uint32_t u1DeliveryStatus : 1;
399 uint32_t u3Reserved1 : 3;
400 uint32_t u1Mask : 1;
401 uint32_t u15Reserved2 : 15;
402 uint32_t u32Reserved0[3];
403 } u;
404 struct
405 {
406 uint32_t u32LvtError;
407 uint32_t u32Reserved0[3];
408 } all;
409 } lvt_error;
410 /* 0x380 - Timer Initial Counter Register. */
411 struct
412 {
413 uint32_t u32InitialCount;
414 uint32_t u32Reserved0[3];
415 } timer_icr;
416 /* 0x390 - Timer Current Counter Register. */
417 struct
418 {
419 uint32_t u32CurrentCount;
420 uint32_t u32Reserved0[3];
421 } timer_ccr;
422 /* 0x3A0 - Reserved. */
423 uint32_t u32Reserved3[16];
424 /* 0x3E0 - Timer Divide Configuration Register. */
425 union
426 {
427 struct
428 {
429 uint32_t u2DivideValue0 : 2;
430 uint32_t u1Reserved0 : 1;
431 uint32_t u1DivideValue1 : 1;
432 uint32_t u28Reserved1 : 28;
433 uint32_t u32Reserved0[3];
434 } u;
435 struct
436 {
437 uint32_t u32DivideValue;
438 uint32_t u32Reserved0[3];
439 } all;
440 } timer_dcr;
441 /* 0x3F0 - Reserved. */
442 uint8_t u8Reserved0[3088];
443} XAPICPAGE;
444/** Pointer to a XAPICPAGE struct. */
445typedef XAPICPAGE *PXAPICPAGE;
446/** Pointer to a const XAPICPAGE struct. */
447typedef const XAPICPAGE *PCXAPICPAGE;
448AssertCompileSize(XAPICPAGE, 4096);
449AssertCompileMemberOffset(XAPICPAGE, id, XAPIC_OFF_ID);
450AssertCompileMemberOffset(XAPICPAGE, version, XAPIC_OFF_VERSION);
451AssertCompileMemberOffset(XAPICPAGE, tpr, XAPIC_OFF_TPR);
452AssertCompileMemberOffset(XAPICPAGE, apr, XAPIC_OFF_APR);
453AssertCompileMemberOffset(XAPICPAGE, ppr, XAPIC_OFF_PPR);
454AssertCompileMemberOffset(XAPICPAGE, eoi, XAPIC_OFF_EOI);
455AssertCompileMemberOffset(XAPICPAGE, rrd, XAPIC_OFF_RRD);
456AssertCompileMemberOffset(XAPICPAGE, ldr, XAPIC_OFF_LDR);
457AssertCompileMemberOffset(XAPICPAGE, dfr, XAPIC_OFF_DFR);
458AssertCompileMemberOffset(XAPICPAGE, svr, XAPIC_OFF_SVR);
459AssertCompileMemberOffset(XAPICPAGE, isr, XAPIC_OFF_ISR0);
460AssertCompileMemberOffset(XAPICPAGE, tmr, XAPIC_OFF_TMR0);
461AssertCompileMemberOffset(XAPICPAGE, irr, XAPIC_OFF_IRR0);
462AssertCompileMemberOffset(XAPICPAGE, esr, XAPIC_OFF_ESR);
463AssertCompileMemberOffset(XAPICPAGE, icr_lo, XAPIC_OFF_ICR_LO);
464AssertCompileMemberOffset(XAPICPAGE, icr_hi, XAPIC_OFF_ICR_HI);
465AssertCompileMemberOffset(XAPICPAGE, lvt_timer, XAPIC_OFF_LVT_TIMER);
466AssertCompileMemberOffset(XAPICPAGE, lvt_thermal, XAPIC_OFF_LVT_THERMAL);
467AssertCompileMemberOffset(XAPICPAGE, lvt_perf, XAPIC_OFF_LVT_PERF);
468AssertCompileMemberOffset(XAPICPAGE, lvt_lint0, XAPIC_OFF_LVT_LINT0);
469AssertCompileMemberOffset(XAPICPAGE, lvt_lint1, XAPIC_OFF_LVT_LINT1);
470AssertCompileMemberOffset(XAPICPAGE, lvt_error, XAPIC_OFF_LVT_ERROR);
471AssertCompileMemberOffset(XAPICPAGE, timer_icr, XAPIC_OFF_TIMER_ICR);
472AssertCompileMemberOffset(XAPICPAGE, timer_ccr, XAPIC_OFF_TIMER_CCR);
473AssertCompileMemberOffset(XAPICPAGE, timer_dcr, XAPIC_OFF_TIMER_DCR);
474
475/**
476 * The x2APIC memory layout as per Intel/AMD specs.
477 */
478typedef struct X2APICPAGE
479{
480 /* 0x00 - Reserved. */
481 uint32_t uReserved0[8];
482 /* 0x20 - APIC ID. */
483 struct
484 {
485 uint32_t u32ApicId;
486 uint32_t u32Reserved0[3];
487 } id;
488 /* 0x30 - APIC version register. */
489 union
490 {
491 struct
492 {
493 uint8_t u8Version;
494 uint8_t u8Reserved0;
495 uint8_t u8MaxLvtEntry;
496 uint8_t fEoiBroadcastSupression : 1;
497 uint8_t u7Reserved1 : 7;
498 uint32_t u32Reserved0[3];
499 } u;
500 struct
501 {
502 uint32_t u32Version;
503 uint32_t u32Reserved2[3];
504 } all;
505 } version;
506 /* 0x40 - Reserved. */
507 uint32_t uReserved1[16];
508 /* 0x80 - Task Priority Register (TPR). */
509 struct
510 {
511 uint8_t u8Tpr;
512 uint8_t u8Reserved0[3];
513 uint32_t u32Reserved0[3];
514 } tpr;
515 /* 0x90 - Reserved. */
516 uint32_t uReserved2[4];
517 /* 0xA0 - Processor Priority Register (PPR). */
518 struct
519 {
520 uint8_t u8Ppr;
521 uint8_t u8Reserved0[3];
522 uint32_t u32Reserved0[3];
523 } ppr;
524 /* 0xB0 - End Of Interrupt Register (EOI). */
525 struct
526 {
527 uint32_t u32Eoi;
528 uint32_t u32Reserved0[3];
529 } eoi;
530 /* 0xC0 - Remote Read Register (RRD). */
531 struct
532 {
533 uint32_t u32Rrd;
534 uint32_t u32Reserved0[3];
535 } rrd;
536 /* 0xD0 - Logical Destination Register (LDR). */
537 struct
538 {
539 uint32_t u32LogicalApicId;
540 uint32_t u32Reserved1[3];
541 } ldr;
542 /* 0xE0 - Reserved. */
543 uint32_t uReserved3[4];
544 /* 0xF0 - Spurious-Interrupt Vector Register (SVR). */
545 union
546 {
547 struct
548 {
549 uint32_t u8SpuriousVector : 8;
550 uint32_t fApicSoftwareEnable : 1;
551 uint32_t u3Reserved0 : 3;
552 uint32_t fSupressEoiBroadcast : 1;
553 uint32_t u19Reserved1 : 19;
554 uint32_t u32Reserved0[3];
555 } u;
556 struct
557 {
558 uint32_t u32Svr;
559 uint32_t uReserved0[3];
560 } all;
561 } svr;
562 /* 0x100 - In-service Register (ISR). */
563 XAPIC256BITREG isr;
564 /* 0x180 - Trigger Mode Register (TMR). */
565 XAPIC256BITREG tmr;
566 /* 0x200 - Interrupt Request Register (IRR). */
567 XAPIC256BITREG irr;
568 /* 0x280 - Error Status Register (ESR). */
569 union
570 {
571 struct
572 {
573#if XAPIC_HARDWARE_VERSION == XAPIC_HARDWARE_VERSION_P4
574 uint32_t u4Reserved0 : 4;
575#else
576# error "Implement Pentium and P6 family APIC architectures"
577#endif
578 uint32_t fRedirectableIpi : 1;
579 uint32_t fSendIllegalVector : 1;
580 uint32_t fRcvdIllegalVector : 1;
581 uint32_t fIllegalRegAddr : 1;
582 uint32_t u24Reserved1 : 24;
583 uint32_t uReserved0[3];
584 } u;
585 struct
586 {
587 uint32_t u32Errors;
588 uint32_t u32Reserved0[3];
589 } all;
590 } esr;
591 /* 0x290 - Reserved. */
592 uint32_t uReserved4[28];
593 /* 0x300 - Interrupt Command Register (ICR) - Low. */
594 union
595 {
596 struct
597 {
598 uint32_t u8Vector : 8;
599 uint32_t u3DeliveryMode : 3;
600 uint32_t u1DestMode : 1;
601 uint32_t u2Reserved0 : 2;
602 uint32_t u1Level : 1;
603 uint32_t u1TriggerMode : 1;
604 uint32_t u2Reserved1 : 2;
605 uint32_t u2DestShorthand : 2;
606 uint32_t u12Reserved2 : 12;
607 uint32_t u32Reserved0[3];
608 } u;
609 struct
610 {
611 uint32_t u32IcrLo;
612 uint32_t u32Reserved3[3];
613 } all;
614 } icr_lo;
615 /* 0x310 - Interrupt Comannd Register (ICR) - High. */
616 struct
617 {
618 uint32_t u32IcrHi;
619 uint32_t uReserved1[3];
620 } icr_hi;
621 /* 0x320 - Local Vector Table (LVT) Timer Register. */
622 union
623 {
624 struct
625 {
626 uint32_t u8Vector : 8;
627 uint32_t u4Reserved0 : 4;
628 uint32_t u1DeliveryStatus : 1;
629 uint32_t u3Reserved1 : 3;
630 uint32_t u1Mask : 1;
631 uint32_t u2TimerMode : 2;
632 uint32_t u13Reserved2 : 13;
633 uint32_t u32Reserved0[3];
634 } u;
635 struct
636 {
637 uint32_t u32LvtTimer;
638 uint32_t u32Reserved0[3];
639 } all;
640 } lvt_timer;
641 /* 0x330 - Local Vector Table (LVT) Thermal Sensor Register. */
642 union
643 {
644 struct
645 {
646 uint32_t u8Vector : 8;
647 uint32_t u3DeliveryMode : 3;
648 uint32_t u1Reserved0 : 1;
649 uint32_t u1DeliveryStatus : 1;
650 uint32_t u3Reserved1 : 3;
651 uint32_t u1Mask : 1;
652 uint32_t u15Reserved2 : 15;
653 uint32_t u32Reserved0[3];
654 } u;
655 struct
656 {
657 uint32_t u32LvtThermal;
658 uint32_t uReserved0[3];
659 } all;
660 } lvt_thermal;
661 /* 0x340 - Local Vector Table (LVT) Performance Monitor Counter (PMC) Register. */
662 union
663 {
664 struct
665 {
666 uint32_t u8Vector : 8;
667 uint32_t u3DeliveryMode : 3;
668 uint32_t u1Reserved0 : 1;
669 uint32_t u1DeliveryStatus : 1;
670 uint32_t u3Reserved1 : 3;
671 uint32_t u1Mask : 1;
672 uint32_t u15Reserved2 : 15;
673 uint32_t u32Reserved0[3];
674 } u;
675 struct
676 {
677 uint32_t u32LvtPerf;
678 uint32_t u32Reserved0[3];
679 } all;
680 } lvt_perf;
681 /* 0x350 - Local Vector Table (LVT) LINT0 Register. */
682 union
683 {
684 struct
685 {
686 uint32_t u8Vector : 8;
687 uint32_t u3DeliveryMode : 3;
688 uint32_t u1Reserved0 : 1;
689 uint32_t u1DeliveryStatus : 1;
690 uint32_t u1IntrPolarity : 1;
691 uint32_t u1RemoteIrr : 1;
692 uint32_t u1TriggerMode : 1;
693 uint32_t u1Mask : 1;
694 uint32_t u15Reserved2 : 15;
695 uint32_t u32Reserved0[3];
696 } u;
697 struct
698 {
699 uint32_t u32LvtLint0;
700 uint32_t u32Reserved0[3];
701 } all;
702 } lvt_lint0;
703 /* 0x360 - Local Vector Table (LVT) LINT1 Register. */
704 union
705 {
706 struct
707 {
708 uint32_t u8Vector : 8;
709 uint32_t u3DeliveryMode : 3;
710 uint32_t u1Reserved0 : 1;
711 uint32_t u1DeliveryStatus : 1;
712 uint32_t u1IntrPolarity : 1;
713 uint32_t u1RemoteIrr : 1;
714 uint32_t u1TriggerMode : 1;
715 uint32_t u1Mask : 1;
716 uint32_t u15Reserved2 : 15;
717 uint32_t u32Reserved0[3];
718 } u;
719 struct
720 {
721 uint32_t u32LvtLint1;
722 uint32_t u32Reserved0[3];
723 } all;
724 } lvt_lint1;
725 /* 0x370 - Local Vector Table (LVT) Error Register. */
726 union
727 {
728 struct
729 {
730 uint32_t u8Vector : 8;
731 uint32_t u4Reserved0 : 4;
732 uint32_t u1DeliveryStatus : 1;
733 uint32_t u3Reserved1 : 3;
734 uint32_t u1Mask : 1;
735 uint32_t u15Reserved2 : 15;
736 uint32_t u32Reserved0[3];
737 } u;
738 struct
739 {
740 uint32_t u32LvtError;
741 uint32_t u32Reserved0[3];
742 } all;
743 } lvt_error;
744 /* 0x380 - Timer Initial Counter Register. */
745 struct
746 {
747 uint32_t u32InitialCount;
748 uint32_t u32Reserved0[3];
749 } timer_icr;
750 /* 0x390 - Timer Current Counter Register. */
751 struct
752 {
753 uint32_t u32CurrentCount;
754 uint32_t u32Reserved0[3];
755 } timer_ccr;
756 /* 0x3A0 - Reserved. */
757 uint32_t uReserved5[16];
758 /* 0x3E0 - Timer Divide Configuration Register. */
759 union
760 {
761 struct
762 {
763 uint32_t u2DivideValue0 : 2;
764 uint32_t u1Reserved0 : 1;
765 uint32_t u1DivideValue1 : 1;
766 uint32_t u28Reserved1 : 28;
767 uint32_t u32Reserved0[3];
768 } u;
769 struct
770 {
771 uint32_t u32DivideValue;
772 uint32_t u32Reserved0[3];
773 } all;
774 } timer_dcr;
775 /* 0x3F0 - Self IPI Register. */
776 struct
777 {
778 uint32_t u8Vector : 8;
779 uint32_t u24Reserved0 : 24;
780 uint32_t u32Reserved0[3];
781 } self_ipi;
782 /* 0x400 - Reserved. */
783 uint8_t u8Reserved0[3072];
784} X2APICPAGE;
785/** Pointer to a X2APICPAGE struct. */
786typedef X2APICPAGE *PX2APICPAGE;
787/** Pointer to a const X2APICPAGE struct. */
788typedef const X2APICPAGE *PCX2APICPAGE;
789AssertCompileSize(X2APICPAGE, 4096);
790AssertCompileSize(X2APICPAGE, sizeof(XAPICPAGE));
791AssertCompileMemberOffset(X2APICPAGE, id, XAPIC_OFF_ID);
792AssertCompileMemberOffset(X2APICPAGE, version, XAPIC_OFF_VERSION);
793AssertCompileMemberOffset(X2APICPAGE, tpr, XAPIC_OFF_TPR);
794AssertCompileMemberOffset(X2APICPAGE, ppr, XAPIC_OFF_PPR);
795AssertCompileMemberOffset(X2APICPAGE, eoi, XAPIC_OFF_EOI);
796AssertCompileMemberOffset(X2APICPAGE, rrd, XAPIC_OFF_RRD);
797AssertCompileMemberOffset(X2APICPAGE, ldr, XAPIC_OFF_LDR);
798AssertCompileMemberOffset(X2APICPAGE, svr, XAPIC_OFF_SVR);
799AssertCompileMemberOffset(X2APICPAGE, isr, XAPIC_OFF_ISR0);
800AssertCompileMemberOffset(X2APICPAGE, tmr, XAPIC_OFF_TMR0);
801AssertCompileMemberOffset(X2APICPAGE, irr, XAPIC_OFF_IRR0);
802AssertCompileMemberOffset(X2APICPAGE, esr, XAPIC_OFF_ESR);
803AssertCompileMemberOffset(X2APICPAGE, icr_lo, XAPIC_OFF_ICR_LO);
804AssertCompileMemberOffset(X2APICPAGE, icr_hi, XAPIC_OFF_ICR_HI);
805AssertCompileMemberOffset(X2APICPAGE, lvt_timer, XAPIC_OFF_LVT_TIMER);
806AssertCompileMemberOffset(X2APICPAGE, lvt_thermal, XAPIC_OFF_LVT_THERMAL);
807AssertCompileMemberOffset(X2APICPAGE, lvt_perf, XAPIC_OFF_LVT_PERF);
808AssertCompileMemberOffset(X2APICPAGE, lvt_lint0, XAPIC_OFF_LVT_LINT0);
809AssertCompileMemberOffset(X2APICPAGE, lvt_lint1, XAPIC_OFF_LVT_LINT1);
810AssertCompileMemberOffset(X2APICPAGE, lvt_error, XAPIC_OFF_LVT_ERROR);
811AssertCompileMemberOffset(X2APICPAGE, timer_icr, XAPIC_OFF_TIMER_ICR);
812AssertCompileMemberOffset(X2APICPAGE, timer_ccr, XAPIC_OFF_TIMER_CCR);
813AssertCompileMemberOffset(X2APICPAGE, timer_dcr, XAPIC_OFF_TIMER_DCR);
814AssertCompileMemberOffset(X2APICPAGE, self_ipi, X2APIC_OFF_SELF_IPI);
815
816/**
817 * APIC MSR access error.
818 * @note The values must match the array indices in apicMsrAccessError().
819 */
820typedef enum APICMSRACCESS
821{
822 /** MSR read while not in x2APIC. */
823 APICMSRACCESS_INVALID_READ_MODE = 0,
824 /** MSR write while not in x2APIC. */
825 APICMSRACCESS_INVALID_WRITE_MODE,
826 /** MSR read for a reserved/unknown/invalid MSR. */
827 APICMSRACCESS_READ_RSVD_OR_UNKNOWN,
828 /** MSR write for a reserved/unknown/invalid MSR. */
829 APICMSRACCESS_WRITE_RSVD_OR_UNKNOWN,
830 /** MSR read for a write-only MSR. */
831 APICMSRACCESS_READ_WRITE_ONLY,
832 /** MSR write for a read-only MSR. */
833 APICMSRACCESS_WRITE_READ_ONLY,
834 /** MSR read to reserved bits. */
835 APICMSRACCESS_READ_RSVD_BITS,
836 /** MSR write to reserved bits. */
837 APICMSRACCESS_WRITE_RSVD_BITS,
838 /** MSR write with invalid value. */
839 APICMSRACCESS_WRITE_INVALID,
840 /** MSR write disallowed due to incompatible config. */
841 APICMSRACCESS_WRITE_DISALLOWED_CONFIG,
842 /** MSR read disallowed due to incompatible config. */
843 APICMSRACCESS_READ_DISALLOWED_CONFIG,
844 /** Count of enum members (don't use). */
845 APICMSRACCESS_COUNT
846} APICMSRACCESS;
847
848
849/** @def APIC_CACHE_LINE_SIZE
850 * Padding (in bytes) for aligning data in different cache lines. Present
851 * generation x86 CPUs use 64-byte cache lines[1]. However, Intel NetBurst
852 * architecture supposedly uses 128-byte cache lines[2]. Since 128 is a
853 * multiple of 64, we use the larger one here.
854 *
855 * [1] - Intel spec "Table 11-1. Characteristics of the Caches, TLBs, Store
856 * Buffer, and Write Combining Buffer in Intel 64 and IA-32 Processors"
857 * [2] - Intel spec. 8.10.6.7 "Place Locks and Semaphores in Aligned, 128-Byte
858 * Blocks of Memory".
859 */
860#define APIC_CACHE_LINE_SIZE 128
861
862/**
863 * APIC Pending-Interrupt Bitmap (PIB).
864 */
865typedef struct APICPIB
866{
867 uint64_t volatile au64VectorBitmap[4];
868 uint32_t volatile fOutstandingNotification;
869 uint8_t au8Reserved[APIC_CACHE_LINE_SIZE - sizeof(uint32_t) - (sizeof(uint64_t) * 4)];
870} APICPIB;
871AssertCompileMemberOffset(APICPIB, fOutstandingNotification, 256 / 8);
872AssertCompileSize(APICPIB, APIC_CACHE_LINE_SIZE);
873/** Pointer to a pending-interrupt bitmap. */
874typedef APICPIB *PAPICPIB;
875/** Pointer to a const pending-interrupt bitmap. */
876typedef const APICPIB *PCAPICPIB;
877
878/**
879 * APIC PDM instance data (per-VM).
880 */
881typedef struct APICDEV
882{
883 /** The MMIO handle. */
884 IOMMMIOHANDLE hMmio;
885} APICDEV;
886/** Pointer to an APIC device. */
887typedef APICDEV *PAPICDEV;
888/** Pointer to a const APIC device. */
889typedef APICDEV const *PCAPICDEV;
890
891
892/**
893 * The APIC GVM instance data.
894 */
895typedef struct APICR0PERVM
896{
897 /** The ring-0 device instance. */
898 PPDMDEVINSR0 pDevInsR0;
899} APICR0PERVM;
900
901
902/**
903 * APIC VM Instance data.
904 */
905typedef struct APIC
906{
907 /** The ring-3 device instance. */
908 PPDMDEVINSR3 pDevInsR3;
909
910 /** @name The APIC pending-interrupt bitmap (PIB).
911 * @{ */
912 /** The host-context physical address of the PIB. */
913 RTHCPHYS HCPhysApicPib;
914 /** The ring-0 memory object of the PIB. */
915 RTR0MEMOBJ hMemObjApicPibR0;
916 /** The ring-3 mapping of the memory object of the PIB. */
917 RTR0MEMOBJ hMapObjApicPibR0;
918 /** The APIC PIB virtual address - R0 ptr. */
919 R0PTRTYPE(void *) pvApicPibR0;
920 /** The APIC PIB virtual address - R3 ptr. */
921 R3PTRTYPE(void *) pvApicPibR3;
922 /** The size of the page in bytes. */
923 uint32_t cbApicPib;
924 /** @} */
925
926 /** @name Other miscellaneous data.
927 * @{ */
928 /** Whether full APIC register virtualization is enabled. */
929 bool fVirtApicRegsEnabled;
930 /** Whether posted-interrupt processing is enabled. */
931 bool fPostedIntrsEnabled;
932 /** Whether TSC-deadline timer mode is supported for the guest. */
933 bool fSupportsTscDeadline;
934 /** Whether this VM has an IO-APIC. */
935 bool fIoApicPresent;
936 /** Whether R0 is enabled or not (applies to MSR handling as well). */
937 bool fR0Enabled;
938 /** Whether RC is enabled or not (applies to MSR handling as well). */
939 bool fRCEnabled;
940 /** Whether Hyper-V x2APIC compatibility mode is enabled. */
941 bool fHyperVCompatMode;
942 /** Enable horrible macOS workaround where the ID register has the value
943 * shifted up 24 bits to be compatible with buggy code in
944 * i386_init.c/vstart(). Only applied if we're in typical macOS 64-bit
945 * kernel load area and macOS kernel selector value (8), as we must not ever
946 * apply this to the EFI code. */
947 bool fMacOSWorkaround;
948 /** The max supported APIC mode from CFGM. */
949 PDMAPICMODE enmMaxMode;
950 /** @} */
951} APIC;
952/** Pointer to APIC VM instance data. */
953typedef APIC *PAPIC;
954/** Pointer to const APIC VM instance data. */
955typedef APIC const *PCAPIC;
956AssertCompileMemberAlignment(APIC, cbApicPib, 8);
957AssertCompileSizeAlignment(APIC, 8);
958
959/**
960 * APIC VMCPU Instance data.
961 */
962typedef struct APICCPU
963{
964 /** @name The APIC page.
965 * @{ */
966 /** The host-context physical address of the page. */
967 RTHCPHYS HCPhysApicPage;
968 /** The ring-0 memory object of the page. */
969 RTR0MEMOBJ hMemObjApicPageR0;
970 /** The ring-3 mapping of the memory object of the page. */
971 RTR0MEMOBJ hMapObjApicPageR0;
972 /** The APIC page virtual address - R0 ptr. */
973 R0PTRTYPE(void *) pvApicPageR0;
974 /** The APIC page virtual address - R3 ptr. */
975 R3PTRTYPE(void *) pvApicPageR3;
976 /** The size of the page in bytes. */
977 uint32_t cbApicPage;
978 /** @} */
979
980 /** @name Auxiliary state.
981 * @{ */
982 /** The error status register's internal state. */
983 uint32_t uEsrInternal;
984 /** The APIC base MSR.*/
985 uint64_t volatile uApicBaseMsr;
986 /** @} */
987
988 /** @name The pending-interrupt bitmaps (PIB).
989 * @{ */
990 /** The host-context physical address of the page. */
991 RTHCPHYS HCPhysApicPib;
992 /** The APIC PIB virtual address - R0 ptr. */
993 R0PTRTYPE(void *) pvApicPibR0;
994 /** The APIC PIB virtual address - R3 ptr. */
995 R3PTRTYPE(void *) pvApicPibR3;
996 /** The APIC PIB for level-sensitive interrupts. */
997 APICPIB ApicPibLevel;
998 /** @} */
999
1000 /** @name Other miscellaneous data.
1001 * @{ */
1002 /** Whether the LINT0 interrupt line is active. */
1003 bool volatile fActiveLint0;
1004 /** Whether the LINT1 interrupt line is active. */
1005 bool volatile fActiveLint1;
1006 /** Alignment padding. */
1007 uint8_t auAlignment2[6];
1008 /** The source tags corresponding to each interrupt vector (debugging). */
1009 uint32_t auSrcTags[256];
1010 /** @} */
1011
1012 /** @name The APIC timer.
1013 * @{ */
1014 /** The timer. */
1015 TMTIMERHANDLE hTimer;
1016 /** The time stamp when the timer was initialized.
1017 * @note Access protected by the timer critsect. */
1018 uint64_t u64TimerInitial;
1019 /** Cache of timer initial count of the frequency hint to TM. */
1020 uint32_t uHintedTimerInitialCount;
1021 /** Cache of timer shift of the frequency hint to TM. */
1022 uint32_t uHintedTimerShift;
1023 /** The timer description. */
1024 char szTimerDesc[16];
1025 /** @} */
1026
1027 /** @name Log Max counters
1028 * @{ */
1029 uint32_t cLogMaxAccessError;
1030 uint32_t cLogMaxSetApicBaseAddr;
1031 uint32_t cLogMaxGetApicBaseAddr;
1032 uint32_t uAlignment4;
1033 /** @} */
1034
1035 /** @name APIC statistics.
1036 * @{ */
1037#ifdef VBOX_WITH_STATISTICS
1038 /** Number of MMIO reads in RZ. */
1039 STAMCOUNTER StatMmioReadRZ;
1040 /** Number of MMIO reads in R3. */
1041 STAMCOUNTER StatMmioReadR3;
1042
1043 /** Number of MMIO writes in RZ. */
1044 STAMCOUNTER StatMmioWriteRZ;
1045 /** Number of MMIO writes in R3. */
1046 STAMCOUNTER StatMmioWriteR3;
1047
1048 /** Number of MSR reads in RZ. */
1049 STAMCOUNTER StatMsrReadRZ;
1050 /** Number of MSR reads in R3. */
1051 STAMCOUNTER StatMsrReadR3;
1052
1053 /** Number of MSR writes in RZ. */
1054 STAMCOUNTER StatMsrWriteRZ;
1055 /** Number of MSR writes in R3. */
1056 STAMCOUNTER StatMsrWriteR3;
1057
1058 /** Profiling of APICUpdatePendingInterrupts(). */
1059 STAMPROFILE StatUpdatePendingIntrs;
1060 /** Profiling of apicPostInterrupt(). */
1061 STAMPROFILE StatPostIntr;
1062 /** Number of times an interrupt is already pending in
1063 * apicPostInterrupts().*/
1064 STAMCOUNTER StatPostIntrAlreadyPending;
1065 /** Number of times the timer callback is invoked. */
1066 STAMCOUNTER StatTimerCallback;
1067 /** Number of times the TPR is written. */
1068 STAMCOUNTER StatTprWrite;
1069 /** Number of times the TPR is read. */
1070 STAMCOUNTER StatTprRead;
1071 /** Number of times the EOI is written. */
1072 STAMCOUNTER StatEoiWrite;
1073 /** Number of times TPR masks an interrupt in apicGetInterrupt(). */
1074 STAMCOUNTER StatMaskedByTpr;
1075 /** Number of times PPR masks an interrupt in apicGetInterrupt(). */
1076 STAMCOUNTER StatMaskedByPpr;
1077 /** Number of times the timer ICR is written. */
1078 STAMCOUNTER StatTimerIcrWrite;
1079 /** Number of times the ICR Lo (send IPI) is written. */
1080 STAMCOUNTER StatIcrLoWrite;
1081 /** Number of times the ICR Hi is written. */
1082 STAMCOUNTER StatIcrHiWrite;
1083 /** Number of times the full ICR (x2APIC send IPI) is written. */
1084 STAMCOUNTER StatIcrFullWrite;
1085 /** Number of times the DCR is written. */
1086 STAMCOUNTER StatDcrWrite;
1087 /** Number of times the DFR is written. */
1088 STAMCOUNTER StatDfrWrite;
1089 /** Number of times the LDR is written. */
1090 STAMCOUNTER StatLdrWrite;
1091 /** Number of times the APIC-ID MSR is read. */
1092 STAMCOUNTER StatIdMsrRead;
1093 /** Number of times the LVT timer is written. */
1094 STAMCOUNTER StatLvtTimerWrite;
1095#endif
1096 /** Number of apicPostInterrupt() calls. */
1097 STAMCOUNTER StatPostIntrCnt;
1098 /** Number of interrupts broken down by vector. */
1099 STAMCOUNTER aStatVectors[256];
1100 /** @} */
1101} APICCPU;
1102/** Pointer to APIC VMCPU instance data. */
1103typedef APICCPU *PAPICCPU;
1104/** Pointer to a const APIC VMCPU instance data. */
1105typedef APICCPU const *PCAPICCPU;
1106AssertCompileMemberAlignment(APICCPU, uApicBaseMsr, 8);
1107
1108/**
1109 * APIC operating modes as returned by apicGetMode().
1110 *
1111 * The values match hardware states.
1112 * See Intel spec. 10.12.1 "Detecting and Enabling x2APIC Mode".
1113 */
1114typedef enum APICMODE
1115{
1116 APICMODE_DISABLED = 0,
1117 APICMODE_INVALID,
1118 APICMODE_XAPIC,
1119 APICMODE_X2APIC
1120} APICMODE;
1121
1122/**
1123 * Gets the timer shift value.
1124 *
1125 * @returns The timer shift value.
1126 * @param pXApicPage The xAPIC page.
1127 */
1128DECLINLINE(uint8_t) apicGetTimerShift(PCXAPICPAGE pXApicPage)
1129{
1130 /* See Intel spec. 10.5.4 "APIC Timer". */
1131 uint32_t uShift = pXApicPage->timer_dcr.u.u2DivideValue0 | (pXApicPage->timer_dcr.u.u1DivideValue1 << 2);
1132 return (uShift + 1) & 7;
1133}
1134
1135
1136const char *apicGetModeName(APICMODE enmMode);
1137const char *apicGetDestFormatName(XAPICDESTFORMAT enmDestFormat);
1138const char *apicGetDeliveryModeName(XAPICDELIVERYMODE enmDeliveryMode);
1139const char *apicGetDestModeName(XAPICDESTMODE enmDestMode);
1140const char *apicGetTriggerModeName(XAPICTRIGGERMODE enmTriggerMode);
1141const char *apicGetDestShorthandName(XAPICDESTSHORTHAND enmDestShorthand);
1142const char *apicGetTimerModeName(XAPICTIMERMODE enmTimerMode);
1143void apicHintTimerFreq(PPDMDEVINS pDevIns, PAPICCPU pApicCpu, uint32_t uInitialCount, uint8_t uTimerShift);
1144APICMODE apicGetMode(uint64_t uApicBaseMsr);
1145
1146DECLCALLBACK(VBOXSTRICTRC) apicReadMmio(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, unsigned cb);
1147DECLCALLBACK(VBOXSTRICTRC) apicWriteMmio(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void const *pv, unsigned cb);
1148
1149bool apicPostInterrupt(PVMCPUCC pVCpu, uint8_t uVector, XAPICTRIGGERMODE enmTriggerMode, uint32_t uSrcTag);
1150void apicStartTimer(PVMCPUCC pVCpu, uint32_t uInitialCount);
1151void apicClearInterruptFF(PVMCPUCC pVCpu, PDMAPICIRQ enmType);
1152void apicInitIpi(PVMCPUCC pVCpu);
1153void apicResetCpu(PVMCPUCC pVCpu, bool fResetApicBaseMsr);
1154
1155DECLCALLBACK(int) apicR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg);
1156DECLCALLBACK(int) apicR3Destruct(PPDMDEVINS pDevIns);
1157DECLCALLBACK(void) apicR3Relocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta);
1158DECLCALLBACK(void) apicR3Reset(PPDMDEVINS pDevIns);
1159DECLCALLBACK(int) apicR3InitComplete(PPDMDEVINS pDevIns);
1160
1161/** @} */
1162
1163#endif /* !VMM_INCLUDED_SRC_include_APICInternal_h */
1164
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