VirtualBox

source: vbox/trunk/src/VBox/VMM/include/GICInternal.h@ 109226

Last change on this file since 109226 was 109226, checked in by vboxsync, 2 weeks ago

VMM/GIC: bugref:10877 GIC ITS, MSI/LPIs work-in-progress.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.5 KB
Line 
1/* $Id: GICInternal.h 109226 2025-05-12 12:37:55Z vboxsync $ */
2/** @file
3 * GIC - Generic Interrupt Controller Architecture (GIC).
4 */
5
6/*
7 * Copyright (C) 2023-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#ifndef VMM_INCLUDED_SRC_include_GICInternal_h
29#define VMM_INCLUDED_SRC_include_GICInternal_h
30#ifndef RT_WITHOUT_PRAGMA_ONCE
31# pragma once
32#endif
33
34#include <VBox/gic.h>
35#include <VBox/vmm/pdmdev.h>
36#include <VBox/vmm/pdmgic.h>
37#include <VBox/vmm/stam.h>
38
39#include "GITSInternal.h"
40
41/** @defgroup grp_gic_int Internal
42 * @ingroup grp_gic
43 * @internal
44 * @{
45 */
46
47#ifdef VBOX_INCLUDED_vmm_pdmgic_h
48/** The VirtualBox GIC backend. */
49extern const PDMGICBACKEND g_GicBackend;
50# ifdef RT_OS_DARWIN
51/** The Hypervisor.Framework GIC backend. */
52extern const PDMGICBACKEND g_GicHvfBackend;
53# elif defined(RT_OS_WINDOWS)
54/** The Hyper-V GIC backend. */
55extern const PDMGICBACKEND g_GicHvBackend;
56# elif defined(RT_OS_LINUX)
57/** The KVM GIC backend. */
58extern const PDMGICBACKEND g_GicKvmBackend;
59# endif
60#endif
61
62#define VMCPU_TO_GICCPU(a_pVCpu) (&(a_pVCpu)->gic.s)
63#define VM_TO_GIC(a_pVM) (&(a_pVM)->gic.s)
64#define VM_TO_GICDEV(a_pVM) CTX_SUFF(VM_TO_GIC(a_pVM)->pGicDev)
65#define GICDEV_TO_GITSDEV(a_GicDev) (&(a_GicDev)->Gits)
66#ifdef IN_RING3
67# define VMCPU_TO_DEVINS(a_pVCpu) ((a_pVCpu)->pVMR3->gic.s.pDevInsR3)
68#elif defined(IN_RING0)
69# error "Not implemented!"
70#endif
71
72/** Acquire the device critical section. */
73#define GIC_CRIT_SECT_ENTER(a_pDevIns) \
74 do \
75 { \
76 int const rcLock_ = PDMDevHlpCritSectEnter((a_pDevIns), (a_pDevIns)->pCritSectRoR3, VINF_SUCCESS); \
77 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV((a_pDevIns), (a_pDevIns)->pCritSectRoR3, rcLock_); \
78 } while(0)
79
80/** Release the device critical section. */
81#define GIC_CRIT_SECT_LEAVE(a_pDevIns) PDMDevHlpCritSectLeave((a_pDevIns), (a_pDevIns)->CTX_SUFF(pCritSectRo))
82
83/** Returns whether the critical section is held. */
84#define GIC_CRIT_SECT_IS_OWNER(a_pDevIns) PDMDevHlpCritSectIsOwner((a_pDevIns), (a_pDevIns)->CTX_SUFF(pCritSectRo))
85
86/** Returns whether the given register offset is within the specified range. */
87#define GIC_IS_REG_IN_RANGE(a_offReg, a_offFirst, a_cbRegion) ((uint32_t)(a_offReg) - (a_offFirst) < (a_cbRegion))
88
89/** @def GIC_SET_REG_U64_FULL
90 * Sets a 64-bit GIC register.
91 * @param a_uReg The 64-bit register to set.
92 * @param a_uValue The 64-bit value being written.
93 * @param a_fRwMask The 64-bit mask of valid read-write bits.
94 */
95#define GIC_SET_REG_U64_FULL(a_uReg, a_uValue, a_fRwMask) \
96 do \
97 { \
98 AssertCompile(sizeof(a_uReg) == sizeof(uint64_t)); \
99 AssertCompile(sizeof(a_fRwMask) == sizeof(uint64_t)); \
100 (a_uReg) = ((a_uReg) & ~(a_fRwMask)) | ((a_uValue) & (a_fRwMask)); \
101 } while (0)
102
103/** @def GIC_SET_REG_U64_LO
104 * Sets the lower half of a 64-bit GIC register.
105 * @param a_uReg The lower half of a 64-bit register to set.
106 * @param a_uValue The value being written (only lower 32-bits are used).
107 * @param a_fRwMask The 64-bit mask of valid read-write bits.
108 */
109#define GIC_SET_REG_U64_LO(a_uReg, a_uValue, a_fRwMask) \
110 do \
111 { \
112 AssertCompile(sizeof(a_uReg) == sizeof(uint32_t)); \
113 AssertCompile(sizeof(a_fRwMask) == sizeof(uint64_t)); \
114 (a_uReg) = ((a_uReg) & ~(RT_LO_U32(a_fRwMask))) | ((uint32_t)(a_uValue) & (RT_LO_U32(a_fRwMask))); \
115 } while (0)
116
117/** @def GIC_SET_REG_U64_HI
118 * Sets the upper half of a 64-bit GIC register.
119 * @param a_uReg The upper half of the 64-bit register to set.
120 * @param a_uValue The value being written (only lower 32-bits are used).
121 * @param a_fRwMask The 64-bit mask of valid read-write bits.
122 */
123#define GIC_SET_REG_U64_HI(a_uReg, a_uValue, a_fRwMask) \
124 do \
125 { \
126 AssertCompile(sizeof(a_uReg) == sizeof(uint32_t)); \
127 AssertCompile(sizeof(a_fRwMask) == sizeof(uint64_t)); \
128 (a_uReg) = ((a_uReg) & ~(RT_HI_U32(a_fRwMask))) | ((uint32_t)(a_uValue) & (RT_HI_U32(a_fRwMask))); \
129 } while (0)
130
131/** @def GIC_SET_REG_U32
132 * Sets a 32-bit GIC register.
133 * @param a_uReg The 32-bit register to set.
134 * @param a_uValue The 32-bit value being written (only lower 32-bits are
135 * used).
136 * @param a_fRwMask The mask of valid read-write bits (only lower 32-bits are
137 * used).
138 */
139#define GIC_SET_REG_U32(a_uReg, a_uValue, a_fRwMask) \
140 do \
141 { \
142 AssertCompile(sizeof(a_uReg) == sizeof(uint32_t)); \
143 (a_uReg) = ((a_uReg) & ~(a_fRwMask)) | ((uint32_t)(a_uValue) & (uint32_t)(a_fRwMask)); \
144 } while (0)
145
146/**
147 * GIC PDM instance data (per-VM).
148 */
149typedef struct GICDEV
150{
151 /** @name Distributor register state.
152 * @{
153 */
154 /** Interrupt group bitmap. */
155 uint32_t bmIntrGroup[64];
156 /** Interrupt config bitmap (edge-triggered vs level-sensitive). */
157 uint32_t bmIntrConfig[128];
158 /** Interrupt enabled bitmap. */
159 uint32_t bmIntrEnabled[64];
160 /** Interrupt pending bitmap. */
161 uint32_t bmIntrPending[64];
162 /** Interrupt active bitmap. */
163 uint32_t bmIntrActive[64];
164 /** Interrupt priorities. */
165 uint8_t abIntrPriority[2048];
166 /** Interrupt routing info. */
167 uint32_t au32IntrRouting[2048];
168 /** Interrupt routine mode bitmap. */
169 uint32_t bmIntrRoutingMode[64];
170 /** Flag whether group 0 interrupts are enabled. */
171 bool fIntrGroup0Enabled;
172 /** Flag whether group 1 interrupts are enabled. */
173 bool fIntrGroup1Enabled;
174 /** Flag whether affinity routing is enabled. */
175 bool fAffRoutingEnabled;
176 /** @} */
177
178 /** @name Configurables.
179 * @{ */
180 /** The GIC architecture revision (GICD_PIDR2.ArchRev and GICR_PIDR2.ArchRev). */
181 uint8_t uArchRev;
182 /** The GIC architecture minor revision (currently 1 as we only support GICv3.1). */
183 uint8_t uArchRevMinor;
184 /** The maximum SPI supported (GICD_TYPER.ItLinesNumber). */
185 uint8_t uMaxSpi;
186 /** Whether extended SPIs are supported (GICD_ESPI). */
187 bool fExtSpi;
188 /** The maximum extended SPI supported (GICD_TYPER.ESPI_range). */
189 uint8_t uMaxExtSpi;
190 /** Whether extended PPIs are supported. */
191 bool fExtPpi;
192 /** The maximum extended PPI supported (GICR_TYPER.PPInum). */
193 uint8_t uMaxExtPpi;
194 /** Whether range-selector is supported (GICD_TYPER.RSS and ICC_CTLR_EL1.RSS). */
195 bool fRangeSel;
196 /** Whether NMIs are supported (GICD_TYPER.NMI). */
197 bool fNmi;
198 /** Whether message-based interrupts are supported (GICD_TYPER.MBIS). */
199 bool fMbi;
200 /** Whether non-zero affinity 3 levels are supported (GICD_TYPER.A3V) and
201 * (ICC_CTLR.A3V). */
202 bool fAff3Levels;
203 /** Whether LPIs are supported (GICD_TYPER.PLPIS). */
204 bool fLpi;
205 /** The maximum LPI supported (GICD_TYPER.num_LPI). */
206 uint8_t uMaxLpi;
207 /** @} */
208
209 /** @name GITS device data and LPIs.
210 * @{ */
211 /** Whether LPIs are enabled (GICR_CTLR.EnableLpis of all redistributors). */
212 bool fEnableLpis;
213 /** Padding. */
214 bool afPadding1[3];
215 /** ITS device state. */
216 GITSDEV Gits;
217 /** LPI config table. */
218 uint8_t abLpiConfig[4096];
219 /** The LPI config table base register (GICR_PROPBASER). */
220 RTUINT64U uLpiConfigBaseReg;
221 /** The LPI pending table base register (GICR_PENDBASER). */
222 RTUINT64U uLpiPendingBaseReg;
223 /** @} */
224
225 /** @name MMIO data.
226 * @{ */
227 /** The distributor MMIO handle. */
228 IOMMMIOHANDLE hMmioDist;
229 /** The redistributor MMIO handle. */
230 IOMMMIOHANDLE hMmioReDist;
231 /** The interrupt translation service MMIO handle. */
232 IOMMMIOHANDLE hMmioGits;
233 /** The physical address of the ITS. */
234 RTGCPHYS GCPhysGits;
235 /** @} */
236} GICDEV;
237/** Pointer to a GIC device. */
238typedef GICDEV *PGICDEV;
239/** Pointer to a const GIC device. */
240typedef GICDEV const *PCGICDEV;
241AssertCompileMemberSizeAlignment(GICDEV, Gits, 8);
242AssertCompileMemberAlignment(GICDEV, abLpiConfig, 8);
243AssertCompileMemberAlignment(GICDEV, hMmioDist, 8);
244
245/**
246 * GIC VM Instance data.
247 */
248typedef struct GIC
249{
250 /** The ring-3 device instance. */
251 PPDMDEVINSR3 pDevInsR3;
252} GIC;
253/** Pointer to GIC VM instance data. */
254typedef GIC *PGIC;
255/** Pointer to const GIC VM instance data. */
256typedef GIC const *PCGIC;
257AssertCompileSizeAlignment(GIC, 8);
258
259/**
260 * GIC VMCPU Instance data.
261 */
262typedef struct GICCPU
263{
264 /** @name Redistributor register state.
265 * @{ */
266 /** Interrupt group bitmap. */
267 uint32_t bmIntrGroup[3];
268 /** Interrupt config bitmap (edge-triggered vs level-sensitive). */
269 uint32_t bmIntrConfig[6];
270 /** Interrupt enabled bitmap. */
271 uint32_t bmIntrEnabled[3];
272 /** Interrupt pending bitmap. */
273 uint32_t bmIntrPending[3];
274 /** Interrupt active bitmap. */
275 uint32_t bmIntrActive[3];
276 /** Interrupt priorities. */
277 uint8_t abIntrPriority[96];
278 /** @} */
279
280 /** @name ICC system register state.
281 * @{ */
282 /** The control register (ICC_CTLR_EL1). */
283 uint64_t uIccCtlr;
284 /** The interrupt priority mask of the CPU interface (ICC_PMR_EL1). */
285 uint8_t bIntrPriorityMask;
286 /** The index to the current running priority. */
287 uint8_t idxRunningPriority;
288 /** The running priorities caused by preemption. */
289 uint8_t abRunningPriorities[256];
290 /** The active priorities group 0 bitmap. */
291 uint32_t bmActivePriorityGroup0[4];
292 /** The active priorities group 0 bitmap. */
293 uint32_t bmActivePriorityGroup1[4];
294 /** The binary point register for group 0 interrupts. */
295 uint8_t bBinaryPtGroup0;
296 /** The binary point register for group 1 interrupts. */
297 uint8_t bBinaryPtGroup1;
298 /** Flag whether group 0 interrupts are enabled. */
299 bool fIntrGroup0Enabled;
300 /** Flag whether group 1 interrupts are enabled. */
301 bool fIntrGroup1Enabled;
302 /** @} */
303
304 /** @name LPIs.
305 * @{ */
306 /** LPI pending bitmap. */
307 uint64_t bmLpiPending[64];
308 /** @} */
309
310 /** @name Statistics.
311 * @{ */
312#ifdef VBOX_WITH_STATISTICS
313 /** Number of MMIO reads. */
314 STAMCOUNTER StatMmioRead;
315 /** Number of MMIO writes. */
316 STAMCOUNTER StatMmioWrite;
317 /** Number of MSR reads. */
318 STAMCOUNTER StatSysRegRead;
319 /** Number of MSR writes. */
320 STAMCOUNTER StatSysRegWrite;
321 /** Number of set SPI callbacks. */
322 STAMCOUNTER StatSetSpi;
323 /** Number of set PPI callbacks. */
324 STAMCOUNTER StatSetPpi;
325 /** Number of SGIs generated. */
326 STAMCOUNTER StatSetSgi;
327
328 /** Profiling of interrupt acknowledge (IAR). */
329 STAMPROFILE StatProfIntrAck;
330 /** Profiling of set SPI callback. */
331 STAMPROFILE StatProfSetSpi;
332 /** Profiling of set PPI callback. */
333 STAMPROFILE StatProfSetPpi;
334 /** Profiling of set SGI function. */
335 STAMPROFILE StatProfSetSgi;
336#endif
337 /** @} */
338} GICCPU;
339/** Pointer to GIC VMCPU instance data. */
340typedef GICCPU *PGICCPU;
341/** Pointer to a const GIC VMCPU instance data. */
342typedef GICCPU const *PCGICCPU;
343/* Ensure the LPI pending bitmap's capacity is sufficient for the number of LPIs we support. */
344AssertCompileMemberSize(GICCPU, bmLpiPending, RT_ELEMENTS(GICDEV::abLpiConfig) / 8);
345AssertCompileMemberAlignment(GICCPU, bmLpiPending, 8);
346
347DECL_HIDDEN_CALLBACK(VBOXSTRICTRC) gicDistMmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, unsigned cb);
348DECL_HIDDEN_CALLBACK(VBOXSTRICTRC) gicDistMmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void const *pv, unsigned cb);
349DECL_HIDDEN_CALLBACK(VBOXSTRICTRC) gicReDistMmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, unsigned cb);
350DECL_HIDDEN_CALLBACK(VBOXSTRICTRC) gicReDistMmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void const *pv, unsigned cb);
351DECL_HIDDEN_CALLBACK(VBOXSTRICTRC) gicItsMmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void const *pv, unsigned cb);
352DECL_HIDDEN_CALLBACK(VBOXSTRICTRC) gicItsMmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, unsigned cb);
353
354DECLHIDDEN(void) gicReDistSetLpi(PPDMDEVINS pDevIns, PVMCPUCC pVCpu, uint16_t uIntId, bool fAsserted);
355DECLHIDDEN(void) gicDistReadLpiConfigTableFromMem(PPDMDEVINS pDevIns);
356DECLHIDDEN(bool) gicDistIsLpiValid(PPDMDEVINS pDevIns, uint16_t uIntId);
357
358DECLHIDDEN(void) gicResetCpu(PPDMDEVINS pDevIns, PVMCPUCC pVCpu);
359DECLHIDDEN(void) gicReset(PPDMDEVINS pDevIns);
360DECLHIDDEN(uint16_t) gicReDistGetIntIdFromIndex(uint16_t idxIntr);
361DECLHIDDEN(uint16_t) gicDistGetIntIdFromIndex(uint16_t idxIntr);
362
363DECLCALLBACK(int) gicR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg);
364DECLCALLBACK(int) gicR3Destruct(PPDMDEVINS pDevIns);
365DECLCALLBACK(void) gicR3Reset(PPDMDEVINS pDevIns);
366
367/** @} */
368
369#endif /* !VMM_INCLUDED_SRC_include_GICInternal_h */
370
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