VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/GICR3.cpp@ 99385

Last change on this file since 99385 was 99385, checked in by vboxsync, 20 months ago

VMM/ArmV8: Skeleton of the GICv3 interrupt controller emulation, bugref:10404

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.6 KB
Line 
1/* $Id: GICR3.cpp 99385 2023-04-13 11:05:39Z vboxsync $ */
2/** @file
3 * GIC - Generic Interrupt Controller Architecture (GICv3).
4 */
5
6/*
7 * Copyright (C) 2023 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
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_DEV_APIC
33#include <VBox/log.h>
34#include "GICInternal.h"
35#include <VBox/vmm/gic.h>
36#include <VBox/vmm/cpum.h>
37#include <VBox/vmm/hm.h>
38#include <VBox/vmm/mm.h>
39#include <VBox/vmm/pdmdev.h>
40#include <VBox/vmm/ssm.h>
41#include <VBox/vmm/vm.h>
42
43#include <iprt/armv8.h>
44
45
46#ifndef VBOX_DEVICE_STRUCT_TESTCASE
47
48
49/*********************************************************************************************************************************
50* Defined Constants And Macros *
51*********************************************************************************************************************************/
52# define GIC_SYSREGRANGE(a_uFirst, a_uLast, a_szName) \
53 { (a_uFirst), (a_uLast), kCpumSysRegRdFn_GicV3Icc, kCpumSysRegWrFn_GicV3Icc, 0, 0, 0, 0, 0, 0, a_szName, { 0 }, { 0 }, { 0 }, { 0 } }
54
55/*********************************************************************************************************************************
56* Global Variables *
57*********************************************************************************************************************************/
58/**
59 * System register ranges for the GICv3.
60 */
61static CPUMSYSREGRANGE const g_aSysRegRanges_GICv3[] =
62{
63 GIC_SYSREGRANGE(ARMV8_AARCH64_SYSREG_ICC_PMR_EL1, ARMV8_AARCH64_SYSREG_ICC_PMR_EL1, "ICC_PMR_EL1"),
64 GIC_SYSREGRANGE(ARMV8_AARCH64_SYSREG_ICC_IAR0_EL1, ARMV8_AARCH64_SYSREG_ICC_AP0R3_EL1, "ICC_IAR0_EL1 - ICC_AP0R3_EL1"),
65 GIC_SYSREGRANGE(ARMV8_AARCH64_SYSREG_ICC_AP1R0_EL1, ARMV8_AARCH64_SYSREG_ICC_NMIAR1_EL1, "ICC_AP1R0_EL1 - ICC_NMIAR1_EL1"),
66 GIC_SYSREGRANGE(ARMV8_AARCH64_SYSREG_ICC_DIR_EL1, ARMV8_AARCH64_SYSREG_ICC_SGI0R_EL1, "ICC_DIR_EL1 - ICC_SGI0R_EL1"),
67 GIC_SYSREGRANGE(ARMV8_AARCH64_SYSREG_ICC_IAR1_EL1, ARMV8_AARCH64_SYSREG_ICC_IGRPEN1_EL1, "ICC_IAR1_EL1 - ICC_IGRPEN1_EL1"),
68};
69
70
71/**
72 * @interface_method_impl{PDMDEVREG,pfnReset}
73 */
74DECLCALLBACK(void) gicR3Reset(PPDMDEVINS pDevIns)
75{
76 PVM pVM = PDMDevHlpGetVM(pDevIns);
77 VM_ASSERT_EMT0(pVM);
78 VM_ASSERT_IS_NOT_RUNNING(pVM);
79
80 LogFlow(("GIC: gicR3Reset\n"));
81
82 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
83 {
84 PVMCPU pVCpuDest = pVM->apCpusR3[idCpu];
85
86 gicResetCpu(pVCpuDest);
87 }
88}
89
90
91/**
92 * @interface_method_impl{PDMDEVREG,pfnRelocate}
93 */
94DECLCALLBACK(void) gicR3Relocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
95{
96 RT_NOREF(pDevIns, offDelta);
97}
98
99
100/**
101 * Initializes the GIC state.
102 *
103 * @returns VBox status code.
104 * @param pVM The cross context VM structure.
105 */
106static int gicR3InitState(PVM pVM)
107{
108 LogFlowFunc(("pVM=%p\n", pVM));
109
110 RT_NOREF(pVM);
111 return VINF_SUCCESS;
112}
113
114
115/**
116 * @interface_method_impl{PDMDEVREG,pfnDestruct}
117 */
118DECLCALLBACK(int) gicR3Destruct(PPDMDEVINS pDevIns)
119{
120 LogFlowFunc(("pDevIns=%p\n", pDevIns));
121 PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
122
123 return VINF_SUCCESS;
124}
125
126
127/**
128 * @interface_method_impl{PDMDEVREG,pfnConstruct}
129 */
130DECLCALLBACK(int) gicR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
131{
132 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
133 PGICDEV pGicDev = PDMDEVINS_2_DATA(pDevIns, PGICDEV);
134 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
135 PVM pVM = PDMDevHlpGetVM(pDevIns);
136 PGIC pGic = VM_TO_GIC(pVM);
137 Assert(iInstance == 0); NOREF(iInstance);
138
139 /*
140 * Init the data.
141 */
142 pGic->pDevInsR3 = pDevIns;
143
144 /*
145 * Validate GIC settings.
146 */
147 PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "DistributorMmioBase|RedistributorMmioBase", "");
148
149 /*
150 * Disable automatic PDM locking for this device.
151 */
152 int rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
153 AssertRCReturn(rc, rc);
154
155 /*
156 * Register the GIC with PDM.
157 */
158 rc = PDMDevHlpApicRegister(pDevIns);
159 AssertLogRelRCReturn(rc, rc);
160
161 /*
162 * Initialize the GIC state.
163 */
164 for (uint32_t i = 0; i < RT_ELEMENTS(g_aSysRegRanges_GICv3); i++)
165 {
166 rc = CPUMR3SysRegRangesInsert(pVM, &g_aSysRegRanges_GICv3[i]);
167 AssertLogRelRCReturn(rc, rc);
168 }
169
170 /* Finally, initialize the state. */
171 rc = gicR3InitState(pVM);
172 AssertRCReturn(rc, rc);
173
174 /*
175 * Register the MMIO ranges.
176 */
177#if 0
178 rc = PDMDevHlpMmioCreateAndMap(pDevIns, GCPhysApicBase, sizeof(XAPICPAGE), apicWriteMmio, apicReadMmio,
179 IOMMMIO_FLAGS_READ_DWORD | IOMMMIO_FLAGS_WRITE_DWORD_ZEROED, "APIC", &pApicDev->hMmio);
180 AssertRCReturn(rc, rc);
181#endif
182
183 /*
184 * Statistics.
185 */
186#define GIC_REG_COUNTER(a_pvReg, a_pszNameFmt, a_pszDesc) \
187 PDMDevHlpSTAMRegisterF(pDevIns, a_pvReg, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, \
188 STAMUNIT_OCCURENCES, a_pszDesc, a_pszNameFmt, idCpu)
189#define GIC_PROF_COUNTER(a_pvReg, a_pszNameFmt, a_pszDesc) \
190 PDMDevHlpSTAMRegisterF(pDevIns, a_pvReg, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, \
191 STAMUNIT_TICKS_PER_CALL, a_pszDesc, a_pszNameFmt, idCpu)
192
193 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
194 {
195 PVMCPU pVCpu = pVM->apCpusR3[idCpu];
196 PGICCPU pGicCpu = VMCPU_TO_GICCPU(pVCpu);
197
198#ifdef VBOX_WITH_STATISTICS
199# if 0 /* No R0 for now. */
200 GIC_REG_COUNTER(&pGicCpu->StatMmioReadRZ, "%u/RZ/MmioRead", "Number of APIC MMIO reads in RZ.");
201 GIC_REG_COUNTER(&pGicCpu->StatMmioWriteRZ, "%u/RZ/MmioWrite", "Number of APIC MMIO writes in RZ.");
202 GIC_REG_COUNTER(&pGicCpu->StatMsrReadRZ, "%u/RZ/MsrRead", "Number of APIC MSR reads in RZ.");
203 GIC_REG_COUNTER(&pGicCpu->StatMsrWriteRZ, "%u/RZ/MsrWrite", "Number of APIC MSR writes in RZ.");
204# endif
205
206 GIC_REG_COUNTER(&pGicCpu->StatMmioReadR3, "%u/R3/MmioRead", "Number of APIC MMIO reads in R3.");
207 GIC_REG_COUNTER(&pGicCpu->StatMmioWriteR3, "%u/R3/MmioWrite", "Number of APIC MMIO writes in R3.");
208 GIC_REG_COUNTER(&pGicCpu->StatSysRegReadR3, "%u/R3/SysRegRead", "Number of GIC system register reads in R3.");
209 GIC_REG_COUNTER(&pGicCpu->StatSysRegWriteR3, "%u/R3/SysRegWrite", "Number of GIC system register writes in R3.");
210#endif
211 }
212
213# undef GIC_PROF_COUNTER
214
215 return VINF_SUCCESS;
216}
217
218#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
219
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