VirtualBox

source: vbox/trunk/include/VBox/vmm/pdmapic.h@ 107113

Last change on this file since 107113 was 107113, checked in by vboxsync, 4 months ago

VMM: bugref:10759 Restructure the APIC to allow different backends to be used.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 36.4 KB
Line 
1/** @file
2 * PDM - Pluggable Device Manager, APIC Interface.
3 */
4
5/*
6 * Copyright (C) 2024 Oracle and/or its affiliates.
7 *
8 * This file is part of VirtualBox base platform packages, as
9 * available from https://www.virtualbox.org.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation, in version 3 of the
14 * License.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <https://www.gnu.org/licenses>.
23 *
24 * The contents of this file may alternatively be used under the terms
25 * of the Common Development and Distribution License Version 1.0
26 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
27 * in the VirtualBox distribution, in which case the provisions of the
28 * CDDL are applicable instead of those of the GPL.
29 *
30 * You may elect to license modified versions of this file under the
31 * terms and conditions of either the GPL or the CDDL or both.
32 *
33 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
34 */
35
36#ifndef VBOX_INCLUDED_vmm_pdmapic_h
37#define VBOX_INCLUDED_vmm_pdmapic_h
38#ifndef RT_WITHOUT_PRAGMA_ONCE
39# pragma once
40#endif
41
42#include <VBox/types.h>
43#include <VBox/apic.h>
44struct PDMDEVREGCB;
45
46/** @defgroup grp_pdm_apic The local APIC PDM API
47 * @ingroup grp_pdm
48 * @{
49 */
50
51RT_C_DECLS_BEGIN
52
53/**
54 * APIC mode argument for apicR3SetCpuIdFeatureLevel.
55 *
56 * Also used in saved-states, CFGM don't change existing values.
57 */
58typedef enum PDMAPICMODE
59{
60 /** Invalid 0 entry. */
61 PDMAPICMODE_INVALID = 0,
62 /** No APIC. */
63 PDMAPICMODE_NONE,
64 /** Standard APIC (X86_CPUID_FEATURE_EDX_APIC). */
65 PDMAPICMODE_APIC,
66 /** Intel X2APIC (X86_CPUID_FEATURE_ECX_X2APIC). */
67 PDMAPICMODE_X2APIC,
68 /** The usual 32-bit paranoia. */
69 PDMAPICMODE_32BIT_HACK = 0x7fffffff
70} PDMAPICMODE;
71
72/**
73 * APIC irq argument for pfnSetInterruptFF and pfnClearInterruptFF.
74 */
75typedef enum PDMAPICIRQ
76{
77 /** Invalid 0 entry. */
78 PDMAPICIRQ_INVALID = 0,
79 /** Normal hardware interrupt. */
80 PDMAPICIRQ_HARDWARE,
81 /** NMI. */
82 PDMAPICIRQ_NMI,
83 /** SMI. */
84 PDMAPICIRQ_SMI,
85 /** ExtINT (HW interrupt via PIC). */
86 PDMAPICIRQ_EXTINT,
87 /** Interrupt arrived, needs to be updated to the IRR. */
88 PDMAPICIRQ_UPDATE_PENDING,
89 /** The usual 32-bit paranoia. */
90 PDMAPICIRQ_32BIT_HACK = 0x7fffffff
91} PDMAPICIRQ;
92
93/**
94 * The type of PDM APIC backend.
95 */
96typedef enum PDMAPICBACKENDTYPE
97{
98 /** None/Invalid PDM APIC backend. */
99 PDMAPICBACKENDTYPE_NONE = 0,
100 /** VirtualBox backend. */
101 PDMAPICBACKENDTYPE_VBOX,
102 /** KVM backend. */
103 PDMAPICBACKENDTYPE_KVM,
104 /** Hyper-V backend. */
105 PDMAPICBACKENDTYPE_HYPERV,
106 /** Hypervisor.Framework backend. */
107 PDMAPICBACKENDTYPE_HVF,
108 /** End of valid PDM APIC backend values. */
109 PDMAPICBACKENDTYPE_END,
110 /** The usual 32-bit paranoia. */
111 PDMAPICBACKENDTYPE_32BIT_HACK = 0x7fffffff
112} PDMAPICBACKENDTYPE;
113
114/**
115 * PDM APIC backend ring-3 API.
116 */
117typedef struct PDMAPICBACKENDR3
118{
119 /**
120 * Returns whether the APIC is hardware enabled or not.
121 *
122 * @returns true if enabled, false otherwise.
123 * @param pVCpu The cross context virtual CPU structure.
124 */
125 DECLR3CALLBACKMEMBER(bool, pfnIsEnabled, (PCVMCPUCC pVCpu));
126
127 /**
128 * Initializes per-VCPU APIC to the state following an INIT reset
129 * ("Wait-for-SIPI" state).
130 *
131 * @param pVCpu The cross context virtual CPU structure.
132 */
133 DECLR3CALLBACKMEMBER(void, pfnInitIpi, (PVMCPUCC pVCpu));
134
135 /**
136 * Gets the APIC base MSR (no checks are performed wrt APIC hardware or its
137 * state).
138 *
139 * @returns The base MSR value.
140 * @param pVCpu The cross context virtual CPU structure.
141 */
142 DECLR3CALLBACKMEMBER(uint64_t, pfnGetBaseMsrNoCheck, (PCVMCPUCC pVCpu));
143
144 /**
145 * Gets the APIC base MSR.
146 *
147 * @returns Strict VBox status code.
148 * @param pVCpu The cross context virtual CPU structure.
149 * @param pu64Value Where to store the MSR value.
150 */
151 DECLR3CALLBACKMEMBER(VBOXSTRICTRC, pfnGetBaseMsr, (PVMCPUCC pVCpu, uint64_t *pu64Value));
152
153 /**
154 * Sets the APIC base MSR.
155 *
156 * @returns VBox status code - no informational ones, esp. not
157 * VINF_CPUM_R3_MSR_WRITE. Only the following two:
158 * @retval VINF_SUCCESS
159 * @retval VERR_CPUM_RAISE_GP_0
160 *
161 * @param pVCpu The cross context virtual CPU structure.
162 * @param u64BaseMsr The value to set.
163 */
164 DECLR3CALLBACKMEMBER(int, pfnSetBaseMsr, (PVMCPUCC pVCpu, uint64_t u64BaseMsr));
165
166 /**
167 * Reads a 32-bit register at a specified offset.
168 *
169 * @returns The value at the specified offset.
170 * @param pVCpu The cross context virtual CPU structure.
171 * @param offReg The offset of the register being read.
172 */
173 DECLR3CALLBACKMEMBER(uint32_t, pfnReadRaw32, (PCVMCPUCC pVCpu, uint16_t offReg));
174
175 /**
176 * Reads an APIC MSR.
177 *
178 * @returns Strict VBox status code.
179 * @param pVCpu The cross context virtual CPU structure.
180 * @param u32Reg The MSR being read.
181 * @param pu64Value Where to store the read value.
182 */
183 DECLR3CALLBACKMEMBER(VBOXSTRICTRC, pfnReadMsr, (PVMCPUCC pVCpu, uint32_t u32Reg, uint64_t *pu64Value));
184
185 /**
186 * Writes an APIC MSR.
187 *
188 * @returns Strict VBox status code.
189 * @param pVCpu The cross context virtual CPU structure.
190 * @param u32Reg The MSR being written.
191 * @param u64Value The value to write.
192 */
193 DECLR3CALLBACKMEMBER(VBOXSTRICTRC, pfnWriteMsr, (PVMCPUCC pVCpu, uint32_t u32Reg, uint64_t u64Value));
194
195 /**
196 * Gets the APIC TPR (Task Priority Register).
197 *
198 * @returns VBox status code.
199 * @param pVCpu The cross context virtual CPU structure.
200 * @param pu8Tpr Where to store the TPR.
201 * @param pfPending Where to store whether there is a pending interrupt
202 * (optional, can be NULL).
203 * @param pu8PendingIntr Where to store the highest-priority pending interrupt
204 * (optional, can be NULL).
205 */
206 DECLR3CALLBACKMEMBER(int, pfnGetTpr, (PCVMCPUCC pVCpu, uint8_t *pu8Tpr, bool *pfPending, uint8_t *pu8PendingIntr));
207
208 /**
209 * Sets the TPR (Task Priority Register).
210 *
211 * @retval VINF_SUCCESS
212 * @retval VERR_CPUM_RAISE_GP_0
213 * @retval VERR_PDM_NO_APIC_INSTANCE
214 *
215 * @param pVCpu The cross context virtual CPU structure.
216 * @param u8Tpr The TPR value to set.
217 * @param fForceX2ApicBehavior Pretend the APIC is in x2APIC mode during
218 * this write.
219 */
220 DECLR3CALLBACKMEMBER(int, pfnSetTpr, (PVMCPUCC pVCpu, uint8_t u8Tpr, bool fForceX2ApicBehaviour));
221
222 /**
223 * Gets the Interrupt Command Register (ICR), without performing any interface
224 * checks.
225 *
226 * @returns The ICR value.
227 * @param pVCpu The cross context virtual CPU structure.
228 */
229 DECLR3CALLBACKMEMBER(uint64_t, pfnGetIcrNoCheck, (PVMCPUCC pVCpu));
230
231 /**
232 * Sets the Interrupt Command Register (ICR).
233 *
234 * @returns Strict VBox status code.
235 * @param pVCpu The cross context virtual CPU structure.
236 * @param u64Icr The ICR (High and Low combined).
237 * @param rcRZ The return code if the operation cannot be performed
238 * in the current context.
239 *
240 * @remarks This function is used by both x2APIC interface and the Hyper-V
241 * interface, see APICHvSetIcr. The Hyper-V spec isn't clear what
242 * happens when invalid bits are set. For the time being, it will
243 * \#GP like a regular x2APIC access.
244 */
245 DECLR3CALLBACKMEMBER(VBOXSTRICTRC, pfnSetIcr, (PVMCPUCC pVCpu, uint64_t uIcr, int rcRZ));
246
247 /**
248 * Gets the APIC timer frequency.
249 *
250 * @returns Strict VBox status code.
251 * @param pVM The cross context VM structure.
252 * @param pu64Value Where to store the timer frequency.
253 */
254 DECLR3CALLBACKMEMBER(int, pfnGetTimerFreq, (PVMCC pVM, uint64_t *pu64Value));
255
256 /**
257 * Assert/de-assert the local APIC's LINT0/LINT1 interrupt pins.
258 *
259 * @returns Strict VBox status code.
260 * @param pVCpu The cross context virtual CPU structure.
261 * @param u8Pin The interrupt pin (0 for LINT0 or 1 for LINT1).
262 * @param u8Level The level (0 for low or 1 for high).
263 * @param rcRZ The return code if the operation cannot be performed in
264 * the current context.
265 *
266 * @note All callers totally ignores the status code!
267 */
268 DECLR3CALLBACKMEMBER(VBOXSTRICTRC, pfnSetLocalInterrupt, (PVMCPUCC pVCpu, uint8_t u8Pin, uint8_t u8Level, int rcRZ));
269
270 /**
271 * Gets the next highest-priority interrupt from the APIC, marking it as an
272 * "in-service" interrupt.
273 *
274 * @returns VBox status code.
275 * @param pVCpu The cross context virtual CPU structure.
276 * @param pu8Vector Where to store the vector.
277 * @param puSrcTag Where to store the interrupt source tag (debugging).
278 */
279 DECLR3CALLBACKMEMBER(int, pfnGetInterrupt, (PVMCPUCC pVCpu, uint8_t *pu8Vector, uint32_t *pu32TagSrc));
280
281 /**
282 * Posts an interrupt to a target APIC.
283 *
284 * This function handles interrupts received from the system bus or
285 * interrupts generated locally from the LVT or via a self IPI.
286 *
287 * Don't use this function to try and deliver ExtINT style interrupts.
288 *
289 * @returns true if the interrupt was accepted, false otherwise.
290 * @param pVCpu The cross context virtual CPU structure.
291 * @param uVector The vector of the interrupt to be posted.
292 * @param fAutoEoi Whether this interrupt has automatic EOI
293 * treatment.
294 * @param enmTriggerMode The trigger mode of the interrupt.
295 * @param uSrcTag The interrupt source tag (debugging).
296 *
297 * @thread Any.
298 */
299 DECLR3CALLBACKMEMBER(bool, pfnPostInterrupt, (PVMCPUCC pVCpu, uint8_t uVector, XAPICTRIGGERMODE enmTriggerMode, bool fAutoEoi,
300 uint32_t uSrcTag));
301
302 /**
303 * Updating pending interrupts into the IRR if required.
304 *
305 * @param pVCpu The cross context virtual CPU structure.
306 */
307 DECLR3CALLBACKMEMBER(void, pfnUpdatePendingInterrupts, (PVMCPUCC pVCpu));
308
309 /**
310 * Delivers an interrupt message via the system bus.
311 *
312 * @returns VBox status code.
313 * @param pVM The cross context VM structure.
314 * @param uDest The destination mask.
315 * @param uDestMode The destination mode.
316 * @param uDeliveryMode The delivery mode.
317 * @param uVector The interrupt vector.
318 * @param uPolarity The interrupt line polarity.
319 * @param uTriggerMode The trigger mode.
320 * @param uSrcTag The interrupt source tag (debugging).
321 */
322 DECLR3CALLBACKMEMBER(int, pfnBusDeliver, (PVMCC pVM, uint8_t uDest, uint8_t uDestMode, uint8_t uDeliveryMode, uint8_t uVector,
323 uint8_t uPolarity, uint8_t uTriggerMode, uint32_t uTagSrc));
324
325 /**
326 * Sets the End-Of-Interrupt (EOI) register.
327 *
328 * @returns Strict VBox status code.
329 * @param pVCpu The cross context virtual CPU structure.
330 * @param uEoi The EOI value.
331 * @param fForceX2ApicBehaviour Pretend the APIC is in x2APIC mode during
332 * this write.
333 */
334 DECLR3CALLBACKMEMBER(VBOXSTRICTRC, pfnSetEoi, (PVMCPUCC pVCpu, uint32_t uEoi, bool fForceX2ApicBehaviour));
335
336 /**
337 * Sets whether Hyper-V compatibility mode (MSR interface) is enabled or not.
338 * @see APICR3HvSetCompatMode for details.
339 *
340 * @returns VBox status code.
341 * @param pVM The cross context VM structure.
342 * @param fHyperVCompatMode Whether the compatibility mode is enabled.
343 */
344 DECLR3CALLBACKMEMBER(int, pfnHvSetCompatMode, (PVMCC pVM, bool fHyperVCompatMode));
345
346 /** @name Reserved for future (MBZ).
347 * @{ */
348 DECLR3CALLBACKMEMBER(int, pfnReserved0, (void));
349 DECLR3CALLBACKMEMBER(int, pfnReserved1, (void));
350 DECLR3CALLBACKMEMBER(int, pfnReserved2, (void));
351 DECLR3CALLBACKMEMBER(int, pfnReserved3, (void));
352 DECLR3CALLBACKMEMBER(int, pfnReserved4, (void));
353 DECLR3CALLBACKMEMBER(int, pfnReserved5, (void));
354 DECLR3CALLBACKMEMBER(int, pfnReserved6, (void));
355 DECLR3CALLBACKMEMBER(int, pfnReserved7, (void));
356 DECLR3CALLBACKMEMBER(int, pfnReserved8, (void));
357 /** @} */
358} PDMAPICBACKENDR3;
359/** Pointer to ring-3 APIC backend. */
360typedef R3PTRTYPE(struct PDMAPICBACKENDR3 *) PPDMAPICBACKENDR3;
361/** Const pointer to ring-3 APIC backend. */
362typedef R3PTRTYPE(const struct PDMAPICBACKENDR3 *) PCPDMAPICBACKENDR3;
363AssertCompileSizeAlignment(PDMAPICBACKENDR3, 8);
364
365/**
366 * PDM APIC backend ring-0 API.
367 */
368typedef struct PDMAPICBACKENDR0
369{
370 /**
371 * Returns whether the APIC is hardware enabled or not.
372 *
373 * @returns true if enabled, false otherwise.
374 * @param pVCpu The cross context virtual CPU structure.
375 */
376 DECLR0CALLBACKMEMBER(bool, pfnIsEnabled, (PCVMCPUCC pVCpu));
377
378 /**
379 * Initializes per-VCPU APIC to the state following an INIT reset
380 * ("Wait-for-SIPI" state).
381 *
382 * @param pVCpu The cross context virtual CPU structure.
383 */
384 DECLR0CALLBACKMEMBER(void, pfnInitIpi, (PVMCPUCC pVCpu));
385
386 /**
387 * Gets the APIC base MSR (no checks are performed wrt APIC hardware or its
388 * state).
389 *
390 * @returns The base MSR value.
391 * @param pVCpu The cross context virtual CPU structure.
392 */
393 DECLR0CALLBACKMEMBER(uint64_t, pfnGetBaseMsrNoCheck, (PCVMCPUCC pVCpu));
394
395 /**
396 * Gets the APIC base MSR.
397 *
398 * @returns Strict VBox status code.
399 * @param pVCpu The cross context virtual CPU structure.
400 * @param pu64Value Where to store the MSR value.
401 */
402 DECLR0CALLBACKMEMBER(VBOXSTRICTRC, pfnGetBaseMsr, (PVMCPUCC pVCpu, uint64_t *pu64Value));
403
404 /**
405 * Sets the APIC base MSR.
406 *
407 * @returns VBox status code.
408 * @param pVCpu The cross context virtual CPU structure.
409 * @param u64BaseMsr The value to set.
410 */
411 DECLR0CALLBACKMEMBER(int, pfnSetBaseMsr, (PVMCPUCC pVCpu, uint64_t u64BaseMsr));
412
413 /**
414 * Reads a 32-bit register at a specified offset.
415 *
416 * @returns The value at the specified offset.
417 * @param pVCpu The cross context virtual CPU structure.
418 * @param offReg The offset of the register being read.
419 */
420 DECLR0CALLBACKMEMBER(uint32_t, pfnReadRaw32, (PCVMCPUCC pVCpu, uint16_t offReg));
421
422 /**
423 * Reads an APIC MSR.
424 *
425 * @returns Strict VBox status code.
426 * @param pVCpu The cross context virtual CPU structure.
427 * @param u32Reg The MSR being read.
428 * @param pu64Value Where to store the read value.
429 */
430 DECLR0CALLBACKMEMBER(VBOXSTRICTRC, pfnReadMsr, (PVMCPUCC pVCpu, uint32_t u32Reg, uint64_t *pu64Value));
431
432 /**
433 * Writes an APIC MSR.
434 *
435 * @returns Strict VBox status code.
436 * @param pVCpu The cross context virtual CPU structure.
437 * @param u32Reg The MSR being written.
438 * @param u64Value The value to write.
439 */
440 DECLR0CALLBACKMEMBER(VBOXSTRICTRC, pfnWriteMsr, (PVMCPUCC pVCpu, uint32_t u32Reg, uint64_t u64Value));
441
442 /**
443 * Gets the APIC TPR (Task Priority Register).
444 *
445 * @returns VBox status code.
446 * @param pVCpu The cross context virtual CPU structure.
447 * @param pu8Tpr Where to store the TPR.
448 * @param pfPending Where to store whether there is a pending interrupt
449 * (optional, can be NULL).
450 * @param pu8PendingIntr Where to store the highest-priority pending interrupt
451 * (optional, can be NULL).
452 */
453 DECLR0CALLBACKMEMBER(int, pfnGetTpr, (PCVMCPUCC pVCpu, uint8_t *pu8Tpr, bool *pfPending, uint8_t *pu8PendingIntr));
454
455 /**
456 * Sets the TPR (Task Priority Register).
457 *
458 * @retval VINF_SUCCESS
459 * @retval VERR_CPUM_RAISE_GP_0
460 * @retval VERR_PDM_NO_APIC_INSTANCE
461 *
462 * @param pVCpu The cross context virtual CPU structure.
463 * @param u8Tpr The TPR value to set.
464 * @param fForceX2ApicBehavior Pretend the APIC is in x2APIC mode during
465 * this write.
466 */
467 DECLR0CALLBACKMEMBER(int, pfnSetTpr, (PVMCPUCC pVCpu, uint8_t u8Tpr, bool fForceX2ApicBehaviour));
468
469 /**
470 * Gets the Interrupt Command Register (ICR), without performing any interface
471 * checks.
472 *
473 * @returns The ICR value.
474 * @param pVCpu The cross context virtual CPU structure.
475 */
476 DECLR0CALLBACKMEMBER(uint64_t, pfnGetIcrNoCheck, (PVMCPUCC pVCpu));
477
478 /**
479 * Sets the Interrupt Command Register (ICR).
480 *
481 * @returns Strict VBox status code.
482 * @param pVCpu The cross context virtual CPU structure.
483 * @param u64Icr The ICR (High and Low combined).
484 * @param rcRZ The return code if the operation cannot be performed
485 * in the current context.
486 *
487 * @remarks This function is used by both x2APIC interface and the Hyper-V
488 * interface, see APICHvSetIcr. The Hyper-V spec isn't clear what
489 * happens when invalid bits are set. For the time being, it will
490 * \#GP like a regular x2APIC access.
491 */
492 DECLR0CALLBACKMEMBER(VBOXSTRICTRC, pfnSetIcr, (PVMCPUCC pVCpu, uint64_t uIcr, int rcRZ));
493
494 /**
495 * Gets the APIC timer frequency.
496 *
497 * @returns Strict VBox status code.
498 * @param pVM The cross context VM structure.
499 * @param pu64Value Where to store the timer frequency.
500 */
501 DECLR0CALLBACKMEMBER(int, pfnGetTimerFreq, (PVMCC pVM, uint64_t *pu64Value));
502
503 /**
504 * Assert/de-assert the local APIC's LINT0/LINT1 interrupt pins.
505 *
506 * @returns Strict VBox status code.
507 * @param pVCpu The cross context virtual CPU structure.
508 * @param u8Pin The interrupt pin (0 for LINT0 or 1 for LINT1).
509 * @param u8Level The level (0 for low or 1 for high).
510 * @param rcRZ The return code if the operation cannot be performed in
511 * the current context.
512 *
513 * @note All callers totally ignores the status code!
514 */
515 DECLR0CALLBACKMEMBER(VBOXSTRICTRC, pfnSetLocalInterrupt, (PVMCPUCC pVCpu, uint8_t u8Pin, uint8_t u8Level, int rcRZ));
516
517 /**
518 * Gets the next highest-priority interrupt from the APIC, marking it as an
519 * "in-service" interrupt.
520 *
521 * @returns VBox status code.
522 * @param pVCpu The cross context virtual CPU structure.
523 * @param pu8Vector Where to store the vector.
524 * @param puSrcTag Where to store the interrupt source tag (debugging).
525 */
526 DECLR0CALLBACKMEMBER(int, pfnGetInterrupt, (PVMCPUCC pVCpu, uint8_t *pu8Vector, uint32_t *pu32TagSrc));
527
528 /**
529 * Posts an interrupt to a target APIC.
530 *
531 * This function handles interrupts received from the system bus or
532 * interrupts generated locally from the LVT or via a self IPI.
533 *
534 * Don't use this function to try and deliver ExtINT style interrupts.
535 *
536 * @returns true if the interrupt was accepted, false otherwise.
537 * @param pVCpu The cross context virtual CPU structure.
538 * @param uVector The vector of the interrupt to be posted.
539 * @param fAutoEoi Whether this interrupt has automatic EOI
540 * treatment.
541 * @param enmTriggerMode The trigger mode of the interrupt.
542 * @param uSrcTag The interrupt source tag (debugging).
543 *
544 * @thread Any.
545 */
546 DECLR0CALLBACKMEMBER(bool, pfnPostInterrupt, (PVMCPUCC pVCpu, uint8_t uVector, XAPICTRIGGERMODE enmTriggerMode, bool fAutoEoi,
547 uint32_t uSrcTag));
548
549 /**
550 * Updating pending interrupts into the IRR if required.
551 *
552 * @param pVCpu The cross context virtual CPU structure.
553 */
554 DECLR0CALLBACKMEMBER(void, pfnUpdatePendingInterrupts, (PVMCPUCC pVCpu));
555
556 /**
557 * Delivers an interrupt message via the system bus.
558 *
559 * @returns VBox status code.
560 * @param pVM The cross context VM structure.
561 * @param uDest The destination mask.
562 * @param uDestMode The destination mode.
563 * @param uDeliveryMode The delivery mode.
564 * @param uVector The interrupt vector.
565 * @param uPolarity The interrupt line polarity.
566 * @param uTriggerMode The trigger mode.
567 * @param uSrcTag The interrupt source tag (debugging).
568 */
569 DECLR0CALLBACKMEMBER(int, pfnBusDeliver, (PVMCC pVM, uint8_t uDest, uint8_t uDestMode, uint8_t uDeliveryMode, uint8_t uVector,
570 uint8_t uPolarity, uint8_t uTriggerMode, uint32_t uTagSrc));
571
572 /**
573 * Sets the End-Of-Interrupt (EOI) register.
574 *
575 * @returns Strict VBox status code.
576 * @param pVCpu The cross context virtual CPU structure.
577 * @param uEoi The EOI value.
578 * @param fForceX2ApicBehaviour Pretend the APIC is in x2APIC mode during
579 * this write.
580 */
581 DECLR0CALLBACKMEMBER(VBOXSTRICTRC, pfnSetEoi, (PVMCPUCC pVCpu, uint32_t uEoi, bool fForceX2ApicBehaviour));
582
583 /**
584 * Gets the APIC page pointers for the specified VCPU.
585 *
586 * @returns VBox status code.
587 * @param pVCpu The cross context virtual CPU structure.
588 * @param pHCPhys Where to store the host-context physical address.
589 * @param pR0Ptr Where to store the ring-0 address.
590 * @param pR3Ptr Where to store the ring-3 address (optional).
591 */
592 DECLR0CALLBACKMEMBER(int, pfnGetApicPageForCpu, (PCVMCPUCC pVCpu, PRTHCPHYS pHCPhys, PRTR0PTR pR0Ptr, PRTR3PTR pR3Ptr));
593
594 /** @name Reserved for future (MBZ).
595 * @{ */
596 DECLR0CALLBACKMEMBER(int, pfnReserved0, (void));
597 DECLR0CALLBACKMEMBER(int, pfnReserved1, (void));
598 DECLR0CALLBACKMEMBER(int, pfnReserved2, (void));
599 DECLR0CALLBACKMEMBER(int, pfnReserved3, (void));
600 DECLR0CALLBACKMEMBER(int, pfnReserved4, (void));
601 DECLR0CALLBACKMEMBER(int, pfnReserved5, (void));
602 DECLR0CALLBACKMEMBER(int, pfnReserved6, (void));
603 DECLR0CALLBACKMEMBER(int, pfnReserved7, (void));
604 DECLR0CALLBACKMEMBER(int, pfnReserved8, (void));
605 /** @} */
606} PDMAPICBACKENDR0;
607/** Pointer to ring-0 APIC backend. */
608typedef R0PTRTYPE(struct PDMAPICBACKENDR0 *) PPDMAPICBACKENDR0;
609/** Const pointer to ring-0 APIC backend. */
610typedef R0PTRTYPE(const struct PDMAPICBACKENDR0 *) PCPDMAPICBACKENDR0;
611AssertCompileSizeAlignment(PDMAPICBACKENDR0, 8);
612
613/**
614 * PDM APIC backend RC API.
615 */
616typedef struct PDMAPICBACKENDRC
617{
618 /**
619 * Returns whether the APIC is hardware enabled or not.
620 *
621 * @returns true if enabled, false otherwise.
622 * @param pVCpu The cross context virtual CPU structure.
623 */
624 DECLRGCALLBACKMEMBER(bool, pfnIsEnabled, (PCVMCPUCC pVCpu));
625
626 /**
627 * Initializes per-VCPU APIC to the state following an INIT reset
628 * ("Wait-for-SIPI" state).
629 *
630 * @param pVCpu The cross context virtual CPU structure.
631 */
632 DECLRGCALLBACKMEMBER(void, pfnInitIpi, (PVMCPUCC pVCpu));
633
634 /**
635 * Gets the APIC base MSR (no checks are performed wrt APIC hardware or its
636 * state).
637 *
638 * @returns The base MSR value.
639 * @param pVCpu The cross context virtual CPU structure.
640 */
641 DECLRGCALLBACKMEMBER(uint64_t, pfnGetBaseMsrNoCheck, (PCVMCPUCC pVCpu));
642
643 /**
644 * Gets the APIC base MSR.
645 *
646 * @returns Strict VBox status code.
647 * @param pVCpu The cross context virtual CPU structure.
648 * @param pu64Value Where to store the MSR value.
649 */
650 DECLRGCALLBACKMEMBER(VBOXSTRICTRC, pfnGetBaseMsr, (PVMCPUCC pVCpu, uint64_t *pu64Value));
651
652 /**
653 * Sets the APIC base MSR.
654 *
655 * @returns VBox status code.
656 * @param pVCpu The cross context virtual CPU structure.
657 * @param u64BaseMsr The value to set.
658 */
659 DECLRGCALLBACKMEMBER(int, pfnSetBaseMsr, (PVMCPUCC pVCpu, uint64_t u64BaseMsr));
660
661 /**
662 * Reads a 32-bit register at a specified offset.
663 *
664 * @returns The value at the specified offset.
665 * @param pVCpu The cross context virtual CPU structure.
666 * @param offReg The offset of the register being read.
667 */
668 DECLRGCALLBACKMEMBER(uint32_t, pfnReadRaw32, (PCVMCPUCC pVCpu, uint16_t offReg));
669
670 /**
671 * Reads an APIC MSR.
672 *
673 * @returns Strict VBox status code.
674 * @param pVCpu The cross context virtual CPU structure.
675 * @param u32Reg The MSR being read.
676 * @param pu64Value Where to store the read value.
677 */
678 DECLRGCALLBACKMEMBER(VBOXSTRICTRC, pfnReadMsr, (PVMCPUCC pVCpu, uint32_t u32Reg, uint64_t *pu64Value));
679
680 /**
681 * Writes an APIC MSR.
682 *
683 * @returns Strict VBox status code.
684 * @param pVCpu The cross context virtual CPU structure.
685 * @param u32Reg The MSR being written.
686 * @param u64Value The value to write.
687 */
688 DECLRGCALLBACKMEMBER(VBOXSTRICTRC, pfnWriteMsr, (PVMCPUCC pVCpu, uint32_t u32Reg, uint64_t u64Value));
689
690 /**
691 * Gets the APIC TPR (Task Priority Register).
692 *
693 * @returns VBox status code.
694 * @param pVCpu The cross context virtual CPU structure.
695 * @param pu8Tpr Where to store the TPR.
696 * @param pfPending Where to store whether there is a pending interrupt
697 * (optional, can be NULL).
698 * @param pu8PendingIntr Where to store the highest-priority pending interrupt
699 * (optional, can be NULL).
700 */
701 DECLRGCALLBACKMEMBER(int, pfnGetTpr, (PCVMCPUCC pVCpu, uint8_t *pu8Tpr, bool *pfPending, uint8_t *pu8PendingIntr));
702
703 /**
704 * Sets the TPR (Task Priority Register).
705 *
706 * @retval VINF_SUCCESS
707 * @retval VERR_CPUM_RAISE_GP_0
708 * @retval VERR_PDM_NO_APIC_INSTANCE
709 *
710 * @param pVCpu The cross context virtual CPU structure.
711 * @param u8Tpr The TPR value to set.
712 * @param fForceX2ApicBehavior Pretend the APIC is in x2APIC mode during
713 * this write.
714 */
715 DECLRGCALLBACKMEMBER(int, pfnSetTpr, (PVMCPUCC pVCpu, uint8_t u8Tpr, bool fForceX2ApicBehaviour));
716
717 /**
718 * Gets the Interrupt Command Register (ICR), without performing any interface
719 * checks.
720 *
721 * @returns The ICR value.
722 * @param pVCpu The cross context virtual CPU structure.
723 */
724 DECLRGCALLBACKMEMBER(uint64_t, pfnGetIcrNoCheck, (PVMCPUCC pVCpu));
725
726 /**
727 * Sets the Interrupt Command Register (ICR).
728 *
729 * @returns Strict VBox status code.
730 * @param pVCpu The cross context virtual CPU structure.
731 * @param u64Icr The ICR (High and Low combined).
732 * @param rcRZ The return code if the operation cannot be performed
733 * in the current context.
734 *
735 * @remarks This function is used by both x2APIC interface and the Hyper-V
736 * interface, see APICHvSetIcr. The Hyper-V spec isn't clear what
737 * happens when invalid bits are set. For the time being, it will
738 * \#GP like a regular x2APIC access.
739 */
740 DECLRGCALLBACKMEMBER(VBOXSTRICTRC, pfnSetIcr, (PVMCPUCC pVCpu, uint64_t uIcr, int rcRZ));
741
742 /**
743 * Gets the APIC timer frequency.
744 *
745 * @returns Strict VBox status code.
746 * @param pVM The cross context VM structure.
747 * @param pu64Value Where to store the timer frequency.
748 */
749 DECLRGCALLBACKMEMBER(int, pfnGetTimerFreq, (PVMCC pVM, uint64_t *pu64Value));
750
751 /**
752 * Assert/de-assert the local APIC's LINT0/LINT1 interrupt pins.
753 *
754 * @returns Strict VBox status code.
755 * @param pVCpu The cross context virtual CPU structure.
756 * @param u8Pin The interrupt pin (0 for LINT0 or 1 for LINT1).
757 * @param u8Level The level (0 for low or 1 for high).
758 * @param rcRZ The return code if the operation cannot be performed in
759 * the current context.
760 *
761 * @note All callers totally ignores the status code!
762 */
763 DECLRGCALLBACKMEMBER(VBOXSTRICTRC, pfnSetLocalInterrupt, (PVMCPUCC pVCpu, uint8_t u8Pin, uint8_t u8Level, int rcRZ));
764
765 /**
766 * Gets the next highest-priority interrupt from the APIC, marking it as an
767 * "in-service" interrupt.
768 *
769 * @returns VBox status code.
770 * @param pVCpu The cross context virtual CPU structure.
771 * @param pu8Vector Where to store the vector.
772 * @param puSrcTag Where to store the interrupt source tag (debugging).
773 */
774 DECLRGCALLBACKMEMBER(int, pfnGetInterrupt, (PVMCPUCC pVCpu, uint8_t *pu8Vector, uint32_t *pu32TagSrc));
775
776 /**
777 * Posts an interrupt to a target APIC.
778 *
779 * This function handles interrupts received from the system bus or
780 * interrupts generated locally from the LVT or via a self IPI.
781 *
782 * Don't use this function to try and deliver ExtINT style interrupts.
783 *
784 * @returns true if the interrupt was accepted, false otherwise.
785 * @param pVCpu The cross context virtual CPU structure.
786 * @param uVector The vector of the interrupt to be posted.
787 * @param fAutoEoi Whether this interrupt has automatic EOI
788 * treatment.
789 * @param enmTriggerMode The trigger mode of the interrupt.
790 * @param uSrcTag The interrupt source tag (debugging).
791 *
792 * @thread Any.
793 */
794 DECLRGCALLBACKMEMBER(bool, pfnPostInterrupt, (PVMCPUCC pVCpu, uint8_t uVector, XAPICTRIGGERMODE enmTriggerMode, bool fAutoEoi,
795 uint32_t uSrcTag));
796
797 /**
798 * Updating pending interrupts into the IRR if required.
799 *
800 * @param pVCpu The cross context virtual CPU structure.
801 */
802 DECLRGCALLBACKMEMBER(void, pfnUpdatePendingInterrupts, (PVMCPUCC pVCpu));
803
804 /**
805 * Delivers an interrupt message via the system bus.
806 *
807 * @returns VBox status code.
808 * @param pVM The cross context VM structure.
809 * @param uDest The destination mask.
810 * @param uDestMode The destination mode.
811 * @param uDeliveryMode The delivery mode.
812 * @param uVector The interrupt vector.
813 * @param uPolarity The interrupt line polarity.
814 * @param uTriggerMode The trigger mode.
815 * @param uSrcTag The interrupt source tag (debugging).
816 */
817 DECLRGCALLBACKMEMBER(int, pfnBusDeliver, (PVMCC pVM, uint8_t uDest, uint8_t uDestMode, uint8_t uDeliveryMode, uint8_t uVector,
818 uint8_t uPolarity, uint8_t uTriggerMode, uint32_t uTagSrc));
819
820 /**
821 * Sets the End-Of-Interrupt (EOI) register.
822 *
823 * @returns Strict VBox status code.
824 * @param pVCpu The cross context virtual CPU structure.
825 * @param uEoi The EOI value.
826 * @param fForceX2ApicBehaviour Pretend the APIC is in x2APIC mode during
827 * this write.
828 */
829 DECLRGCALLBACKMEMBER(VBOXSTRICTRC, pfnSetEoi, (PVMCPUCC pVCpu, uint32_t uEoi, bool fForceX2ApicBehaviour));
830
831 /** @name Reserved for future (MBZ).
832 * @{ */
833 DECLRGCALLBACKMEMBER(int, pfnReserved0, (void));
834 DECLRGCALLBACKMEMBER(int, pfnReserved1, (void));
835 DECLRGCALLBACKMEMBER(int, pfnReserved2, (void));
836 DECLRGCALLBACKMEMBER(int, pfnReserved3, (void));
837 DECLRGCALLBACKMEMBER(int, pfnReserved4, (void));
838 DECLRGCALLBACKMEMBER(int, pfnReserved5, (void));
839 DECLRGCALLBACKMEMBER(int, pfnReserved6, (void));
840 DECLRGCALLBACKMEMBER(int, pfnReserved7, (void));
841 DECLRGCALLBACKMEMBER(int, pfnReserved8, (void));
842 DECLRGCALLBACKMEMBER(int, pfnReserved9, (void));
843 /** @} */
844} PDMAPICBACKENDRC;
845/** Pointer to raw-mode context APIC backend. */
846typedef RCPTRTYPE(struct PDMAPICBACKENDRC *) PPDMAPICBACKENDRC;
847/** Const pointer to raw-mode context APIC backend. */
848typedef RCPTRTYPE(const struct PDMAPICBACKENDRC *) PCPDMAPICBACKENDRC;
849AssertCompileSizeAlignment(PDMAPICBACKENDRC, 8);
850AssertCompile(sizeof(PDMAPICBACKENDR3) == sizeof(PDMAPICBACKENDR0));
851AssertCompile(sizeof(PDMAPICBACKENDR3) == sizeof(PDMAPICBACKENDRC));
852
853/** @typedef PDMAPICBACKENDR3
854 * A current context PDM APIC backend. */
855/** @typedef PPDMAPICBACKENDR3
856 * Pointer to a current context PDM APIC backend. */
857/** @typedef PCPDMAPICBACKENDR3
858 * Pointer to a const current context PDM APIC backend. */
859#if defined(IN_RING3) || defined(DOXYGEN_RUNNING)
860typedef PDMAPICBACKENDR3 PDMAPICBACKEND;
861typedef PPDMAPICBACKENDR3 PPDMAPICBACKEND;
862typedef PCPDMAPICBACKENDR3 PCPDMAPICBACKEND;
863#elif defined(IN_RING0)
864typedef PDMAPICBACKENDR0 PDMAPICBACKEND;
865typedef PPDMAPICBACKENDR0 PPDMAPICBACKEND;
866typedef PCPDMAPICBACKENDR0 PCPDMAPICBACKEND;
867#elif defined(IN_RC)
868typedef PDMAPICBACKENDRC PDMAPICBACKEND;
869typedef PPDMAPICBACKENDRC PPDMAPICBACKEND;
870typedef PCPDMAPICBACKENDRC PCPDMAPICBACKEND;
871#else
872# error "Not IN_RING3, IN_RING0 or IN_RC"
873#endif
874
875VMM_INT_DECL(int) PDMApicRegisterBackend(PVMCC pVM, PDMAPICBACKENDTYPE enmBackendType, PCPDMAPICBACKEND pBackend);
876
877VMM_INT_DECL(void) PDMApicUpdatePendingInterrupts(PVMCPUCC pVCpu);
878VMM_INT_DECL(int) PDMApicGetTpr(PCVMCPUCC pVCpu, uint8_t *pu8Tpr, bool *pfPending, uint8_t *pu8PendingIntr);
879VMM_INT_DECL(int) PDMApicSetTpr(PVMCPUCC pVCpu, uint8_t u8Tpr);
880VMM_INT_DECL(bool) PDMApicIsEnabled(PCVMCPUCC pVCpu);
881VMM_INT_DECL(VBOXSTRICTRC) PDMApicReadMsr(PVMCPUCC pVCpu, uint32_t u32Reg, uint64_t *pu64Value);
882VMM_INT_DECL(VBOXSTRICTRC) PDMApicWriteMsr(PVMCPUCC pVCpu, uint32_t u32Reg, uint64_t u64Value);
883VMM_INT_DECL(int) PDMApicGetTimerFreq(PVMCC pVM, uint64_t *pu64Value);
884VMM_INT_DECL(VBOXSTRICTRC) PDMApicSetLocalInterrupt(PVMCPUCC pVCpu, uint8_t u8Pin, uint8_t u8Level, int rcRZ);
885VMM_INT_DECL(uint64_t) PDMApicGetBaseMsrNoCheck(PCVMCPUCC pVCpu);
886VMM_INT_DECL(VBOXSTRICTRC) PDMApicGetBaseMsr(PVMCPUCC pVCpu, uint64_t *pu64Value);
887VMM_INT_DECL(int) PDMApicSetBaseMsr(PVMCPUCC pVCpu, uint64_t u64BaseMsr);
888VMM_INT_DECL(int) PDMApicGetInterrupt(PVMCPUCC pVCpu, uint8_t *pu8Vector, uint32_t *pu32TagSrc);
889VMM_INT_DECL(int) PDMApicBusDeliver(PVMCC pVM, uint8_t uDest, uint8_t uDestMode, uint8_t uDeliveryMode, uint8_t uVector,
890 uint8_t uPolarity, uint8_t uTriggerMode, uint32_t uTagSrc);
891#ifdef IN_RING0
892VMM_INT_DECL(int) PDMR0ApicGetApicPageForCpu(PCVMCPUCC pVCpu, PRTHCPHYS pHCPhys, PRTR0PTR pR0Ptr, PRTR3PTR pR3Ptr);
893#endif
894
895/** @name Hyper-V interface (Ring-3 and all-context API).
896 * @{ */
897#ifdef IN_RING3
898VMMR3_INT_DECL(int) PDMR3ApicHvSetCompatMode(PVM pVM, bool fHyperVCompatMode);
899#endif
900VMM_INT_DECL(void) PDMApicHvSendInterrupt(PVMCPUCC pVCpu, uint8_t uVector, bool fAutoEoi, XAPICTRIGGERMODE enmTriggerMode);
901VMM_INT_DECL(VBOXSTRICTRC) PDMApicHvSetTpr(PVMCPUCC pVCpu, uint8_t uTpr);
902VMM_INT_DECL(uint8_t) PDMApicHvGetTpr(PVMCPUCC pVCpu);
903VMM_INT_DECL(VBOXSTRICTRC) PDMApicHvSetIcr(PVMCPUCC pVCpu, uint64_t uIcr);
904VMM_INT_DECL(uint64_t) PDMApicHvGetIcr(PVMCPUCC pVCpu);
905VMM_INT_DECL(VBOXSTRICTRC) PDMApicHvSetEoi(PVMCPUCC pVCpu, uint32_t uEoi);
906/** @} */
907
908#ifdef IN_RING3
909/** @defgroup grp_pdm_apic_r3 The PDM APIC Host Context Ring-3 API
910 * @{
911 */
912VMMR3_INT_DECL(void) PDMR3ApicInitIpi(PVMCPU pVCpu);
913/** @} */
914#endif /* IN_RING3 */
915
916RT_C_DECLS_END
917
918/** @} */
919
920#endif /* !VBOX_INCLUDED_vmm_pdmapic_h */
921
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette