VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMAll/GICAll.cpp@ 99385

最後變更 在這個檔案從99385是 99385,由 vboxsync 提交於 2 年 前

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

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 9.2 KB
 
1/* $Id: GICAll.cpp 99385 2023-04-13 11:05:39Z vboxsync $ */
2/** @file
3 * GIC - Generic Interrupt Controller Architecture (GICv3) - All Contexts.
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.alldomusa.eu.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 "GICInternal.h"
34#include <VBox/vmm/gic.h>
35#include <VBox/vmm/pdmdev.h>
36#include <VBox/vmm/pdmapi.h>
37#include <VBox/vmm/vmcc.h>
38#include <VBox/vmm/vmm.h>
39#include <VBox/vmm/vmcpuset.h>
40#ifdef IN_RING0
41# include <VBox/vmm/gvmm.h>
42#endif
43
44
45/*********************************************************************************************************************************
46* Internal Functions *
47*********************************************************************************************************************************/
48
49
50/*********************************************************************************************************************************
51* Global Variables *
52*********************************************************************************************************************************/
53/**
54 * Reads a GIC register.
55 *
56 * @returns VBox status code.
57 * @param pDevIns The device instance.
58 * @param pVCpu The cross context virtual CPU structure.
59 * @param offReg The offset of the register being read.
60 * @param puValue Where to store the register value.
61 */
62DECLINLINE(VBOXSTRICTRC) gicReadRegister(PPDMDEVINS pDevIns, PVMCPUCC pVCpu, uint16_t offReg, uint32_t *puValue)
63{
64 VMCPU_ASSERT_EMT(pVCpu);
65 RT_NOREF(pDevIns, pVCpu, offReg);
66
67 *puValue = 0;
68 return VINF_SUCCESS;
69}
70
71
72/**
73 * Writes a GIC register.
74 *
75 * @returns Strict VBox status code.
76 * @param pDevIns The device instance.
77 * @param pVCpu The cross context virtual CPU structure.
78 * @param offReg The offset of the register being written.
79 * @param uValue The register value.
80 */
81DECLINLINE(VBOXSTRICTRC) gicWriteRegister(PPDMDEVINS pDevIns, PVMCPUCC pVCpu, uint16_t offReg, uint32_t uValue)
82{
83 VMCPU_ASSERT_EMT(pVCpu);
84 RT_NOREF(pDevIns, pVCpu, offReg, uValue);
85
86 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
87 return rcStrict;
88}
89
90
91/**
92 * Reads a GIC system register.
93 *
94 * @returns Strict VBox status code.
95 * @param pVCpu The cross context virtual CPU structure.
96 * @param u32Reg The system register being read.
97 * @param pu64Value Where to store the read value.
98 */
99VMM_INT_DECL(VBOXSTRICTRC) GICReadSysReg(PVMCPUCC pVCpu, uint32_t u32Reg, uint64_t *pu64Value)
100{
101 /*
102 * Validate.
103 */
104 VMCPU_ASSERT_EMT(pVCpu);
105 Assert(pu64Value);
106
107 *pu64Value = 0;
108 LogFlowFunc(("pVCpu=%p u32Reg=%#x pu64Value=%RX64\n", pVCpu, u32Reg, *pu64Value));
109 return VINF_SUCCESS;
110}
111
112
113/**
114 * Writes an GIC system register.
115 *
116 * @returns Strict VBox status code.
117 * @param pVCpu The cross context virtual CPU structure.
118 * @param u32Reg The system register being written (IPRT system register identifier).
119 * @param u64Value The value to write.
120 */
121VMM_INT_DECL(VBOXSTRICTRC) GICWriteSysReg(PVMCPUCC pVCpu, uint32_t u32Reg, uint64_t u64Value)
122{
123 /*
124 * Validate.
125 */
126 VMCPU_ASSERT_EMT(pVCpu);
127 RT_NOREF(pVCpu, u32Reg, u64Value);
128 LogFlowFunc(("pVCpu=%p u32Reg=%#x u64Value=%RX64\n", pVCpu, u32Reg, u64Value));
129
130 return VINF_SUCCESS;
131}
132
133
134/**
135 * Initializes per-VCPU GIC to the state following a power-up or hardware
136 * reset.
137 *
138 * @param pVCpu The cross context virtual CPU structure.
139 */
140DECLHIDDEN(void) gicResetCpu(PVMCPUCC pVCpu)
141{
142 LogFlowFunc(("GIC%u\n", pVCpu->idCpu));
143 VMCPU_ASSERT_EMT_OR_NOT_RUNNING(pVCpu);
144}
145
146
147/**
148 * @callback_method_impl{FNIOMMMIONEWREAD}
149 */
150DECLCALLBACK(VBOXSTRICTRC) apicReadMmio(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, unsigned cb)
151{
152 NOREF(pvUser);
153 Assert(!(off & 0xf));
154 Assert(cb == 4); RT_NOREF_PV(cb);
155
156 PVMCPUCC pVCpu = PDMDevHlpGetVMCPU(pDevIns);
157 uint16_t offReg = off & 0xff0;
158 uint32_t uValue = 0;
159
160 STAM_COUNTER_INC(&pVCpu->gic.s.CTX_SUFF_Z(StatMmioRead));
161
162 VBOXSTRICTRC rc = VBOXSTRICTRC_VAL(gicReadRegister(pDevIns, pVCpu, offReg, &uValue));
163 *(uint32_t *)pv = uValue;
164
165 Log2(("GIC%u: gicReadMmio: offReg=%#RX16 uValue=%#RX32\n", pVCpu->idCpu, offReg, uValue));
166 return rc;
167}
168
169
170/**
171 * @callback_method_impl{FNIOMMMIONEWWRITE}
172 */
173DECLCALLBACK(VBOXSTRICTRC) gicWriteMmio(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void const *pv, unsigned cb)
174{
175 NOREF(pvUser);
176 Assert(!(off & 0xf));
177 Assert(cb == 4); RT_NOREF_PV(cb);
178
179 PVMCPUCC pVCpu = PDMDevHlpGetVMCPU(pDevIns);
180 uint16_t offReg = off & 0xff0;
181 uint32_t uValue = *(uint32_t *)pv;
182
183 STAM_COUNTER_INC(&pVCpu->gic.s.CTX_SUFF_Z(StatMmioWrite));
184
185 Log2(("GIC%u: gicWriteMmio: offReg=%#RX16 uValue=%#RX32\n", pVCpu->idCpu, offReg, uValue));
186 return gicWriteRegister(pDevIns, pVCpu, offReg, uValue);
187}
188
189
190#ifndef IN_RING3
191
192/**
193 * @callback_method_impl{PDMDEVREGR0,pfnConstruct}
194 */
195static DECLCALLBACK(int) gicRZConstruct(PPDMDEVINS pDevIns)
196{
197 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
198 AssertReleaseFailed();
199 return VINF_SUCCESS;
200}
201#endif /* !IN_RING3 */
202
203/**
204 * GIC device registration structure.
205 */
206const PDMDEVREG g_DeviceGIC =
207{
208 /* .u32Version = */ PDM_DEVREG_VERSION,
209 /* .uReserved0 = */ 0,
210 /* .szName = */ "gic",
211 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RZ | PDM_DEVREG_FLAGS_NEW_STYLE,
212 /* .fClass = */ PDM_DEVREG_CLASS_PIC,
213 /* .cMaxInstances = */ 1,
214 /* .uSharedVersion = */ 42,
215 /* .cbInstanceShared = */ sizeof(GICDEV),
216 /* .cbInstanceCC = */ 0,
217 /* .cbInstanceRC = */ 0,
218 /* .cMaxPciDevices = */ 0,
219 /* .cMaxMsixVectors = */ 0,
220 /* .pszDescription = */ "Generic Interrupt Controller",
221#if defined(IN_RING3)
222 /* .szRCMod = */ "VMMRC.rc",
223 /* .szR0Mod = */ "VMMR0.r0",
224 /* .pfnConstruct = */ gicR3Construct,
225 /* .pfnDestruct = */ gicR3Destruct,
226 /* .pfnRelocate = */ gicR3Relocate,
227 /* .pfnMemSetup = */ NULL,
228 /* .pfnPowerOn = */ NULL,
229 /* .pfnReset = */ gicR3Reset,
230 /* .pfnSuspend = */ NULL,
231 /* .pfnResume = */ NULL,
232 /* .pfnAttach = */ NULL,
233 /* .pfnDetach = */ NULL,
234 /* .pfnQueryInterface = */ NULL,
235 /* .pfnInitComplete = */ NULL,
236 /* .pfnPowerOff = */ NULL,
237 /* .pfnSoftReset = */ NULL,
238 /* .pfnReserved0 = */ NULL,
239 /* .pfnReserved1 = */ NULL,
240 /* .pfnReserved2 = */ NULL,
241 /* .pfnReserved3 = */ NULL,
242 /* .pfnReserved4 = */ NULL,
243 /* .pfnReserved5 = */ NULL,
244 /* .pfnReserved6 = */ NULL,
245 /* .pfnReserved7 = */ NULL,
246#elif defined(IN_RING0)
247 /* .pfnEarlyConstruct = */ NULL,
248 /* .pfnConstruct = */ gicRZConstruct,
249 /* .pfnDestruct = */ NULL,
250 /* .pfnFinalDestruct = */ NULL,
251 /* .pfnRequest = */ NULL,
252 /* .pfnReserved0 = */ NULL,
253 /* .pfnReserved1 = */ NULL,
254 /* .pfnReserved2 = */ NULL,
255 /* .pfnReserved3 = */ NULL,
256 /* .pfnReserved4 = */ NULL,
257 /* .pfnReserved5 = */ NULL,
258 /* .pfnReserved6 = */ NULL,
259 /* .pfnReserved7 = */ NULL,
260#elif defined(IN_RC)
261 /* .pfnConstruct = */ gicRZConstruct,
262 /* .pfnReserved0 = */ NULL,
263 /* .pfnReserved1 = */ NULL,
264 /* .pfnReserved2 = */ NULL,
265 /* .pfnReserved3 = */ NULL,
266 /* .pfnReserved4 = */ NULL,
267 /* .pfnReserved5 = */ NULL,
268 /* .pfnReserved6 = */ NULL,
269 /* .pfnReserved7 = */ NULL,
270#else
271# error "Not in IN_RING3, IN_RING0 or IN_RC!"
272#endif
273 /* .u32VersionEnd = */ PDM_DEVREG_VERSION
274};
275
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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