VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/ResourceAssignmentManager.cpp

Last change on this file was 104028, checked in by vboxsync, 7 weeks ago

Main/ResourceAssignmentManager.cpp: Make it build on linux.arm64 (gcc complains about shadowed variables), bugref:10391

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.9 KB
Line 
1/* $Id: ResourceAssignmentManager.cpp 104028 2024-03-24 18:35:08Z vboxsync $ */
2/** @file
3 * VirtualBox bus slots assignment manager
4 */
5
6/*
7 * Copyright (C) 2010-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_MAIN
33#include "LoggingNew.h"
34
35#include "ResourceAssignmentManager.h"
36
37#include <iprt/asm.h>
38#include <iprt/string.h>
39
40#include <VBox/vmm/cfgm.h>
41#include <VBox/vmm/vmmr3vtable.h>
42#include <VBox/com/array.h>
43
44#include <map>
45#include <vector>
46#include <algorithm>
47
48
49/*********************************************************************************************************************************
50* Structures and Typedefs *
51*********************************************************************************************************************************/
52
53
54/*********************************************************************************************************************************
55* Global Variables *
56*********************************************************************************************************************************/
57
58
59/**
60 * Resource assignment manage state data.
61 * @internal
62 */
63struct ResourceAssignmentManager::State
64{
65 struct MemoryRange
66 {
67 char szDevName[32];
68 RTGCPHYS mGCPhysStart;
69 RTGCPHYS mGCPhysEnd;
70
71 MemoryRange(const char *pszName, RTGCPHYS GCPhysStart, RTGCPHYS GCPhysEnd)
72 {
73 RTStrCopy(this->szDevName, sizeof(szDevName), pszName);
74 this->mGCPhysStart = GCPhysStart;
75 this->mGCPhysEnd = GCPhysEnd;
76 }
77
78 bool operator==(const MemoryRange &a) const
79 {
80 return RTStrNCmp(szDevName, a.szDevName, sizeof(szDevName)) == 0;
81 }
82 };
83
84 typedef std::vector<MemoryRange> AddrRangeList;
85
86 ChipsetType_T mChipsetType;
87 IommuType_T mIommuType;
88 PCVMMR3VTABLE mpVMM;
89 AddrRangeList mAddrRanges;
90
91 RTGCPHYS mGCPhysMmioStartOrig;
92 RTGCPHYS mGCPhysMmioStart;
93 RTGCPHYS mGCPhysMmio32StartOrig;
94 RTGCPHYS mGCPhysMmio32Start;
95 RTGCPHYS mcbMmio32;
96 RTGCPHYS mGCPhysRamStart;
97 uint32_t mcInterrupts;
98 uint32_t miInterrupt;
99
100 State()
101 : mChipsetType(ChipsetType_Null), mpVMM(NULL)
102 {}
103 ~State()
104 {}
105
106 HRESULT init(PCVMMR3VTABLE pVMM, ChipsetType_T chipsetType, IommuType_T iommuType,
107 RTGCPHYS GCPhysMmioTop, RTGCPHYS GCPhysRamStart,
108 RTGCPHYS GCPhysMmio32Start, RTGCPHYS cbMmio32, uint32_t cInterrupts);
109
110 HRESULT addAddrRange(const char *pszName, RTGCPHYS GCPhysStart, RTGCPHYS GCPhysEnd);
111};
112
113
114HRESULT ResourceAssignmentManager::State::init(PCVMMR3VTABLE pVMM, ChipsetType_T chipsetType, IommuType_T iommuType,
115 RTGCPHYS GCPhysMmioTop, RTGCPHYS GCPhysRamStart,
116 RTGCPHYS GCPhysMmio32Start, RTGCPHYS cbMmio32, uint32_t cInterrupts)
117{
118 mpVMM = pVMM;
119
120 Assert(chipsetType == ChipsetType_ARMv8Virtual);
121 Assert(iommuType == IommuType_None); /* For now no IOMMU support on ARMv8. */
122
123 mChipsetType = chipsetType;
124 mIommuType = iommuType;
125 mGCPhysMmioStart = GCPhysMmioTop;
126 mGCPhysMmioStartOrig = GCPhysMmioTop;
127 mGCPhysRamStart = GCPhysRamStart;
128 mGCPhysMmio32Start = GCPhysMmio32Start;
129 mGCPhysMmio32StartOrig = GCPhysMmio32Start;
130 mcbMmio32 = cbMmio32;
131 mcInterrupts = cInterrupts;
132 miInterrupt = 0;
133 return S_OK;
134}
135
136HRESULT ResourceAssignmentManager::State::addAddrRange(const char *pszName, RTGCPHYS GCPhysStart, RTGCPHYS cbRegion)
137{
138 MemoryRange memRange(pszName, GCPhysStart, GCPhysStart + cbRegion - 1);
139 mAddrRanges.push_back(memRange);
140 return S_OK;
141}
142
143ResourceAssignmentManager::ResourceAssignmentManager()
144 : pState(NULL)
145{
146 pState = new State();
147 Assert(pState);
148}
149
150ResourceAssignmentManager::~ResourceAssignmentManager()
151{
152 if (pState)
153 {
154 delete pState;
155 pState = NULL;
156 }
157}
158
159ResourceAssignmentManager *ResourceAssignmentManager::createInstance(PCVMMR3VTABLE pVMM, ChipsetType_T chipsetType, IommuType_T iommuType,
160 RTGCPHYS GCPhysMmioTop, RTGCPHYS GCPhysRamStart,
161 RTGCPHYS GCPhysMmio32Start, RTGCPHYS cbMmio32,
162 uint32_t cInterrupts)
163{
164 ResourceAssignmentManager *pInstance = new ResourceAssignmentManager();
165 pInstance->pState->init(pVMM, chipsetType, iommuType, GCPhysMmioTop, GCPhysRamStart, GCPhysMmio32Start, cbMmio32, cInterrupts);
166 Assert(pInstance);
167 return pInstance;
168}
169
170HRESULT ResourceAssignmentManager::assignMmioRegion(const char *pszName, RTGCPHYS cbRegion, PRTGCPHYS pGCPhysStart, PRTGCPHYS pcbRegion)
171{
172 RTGCPHYS cbRegionAligned = RT_ALIGN_T(cbRegion, _4K, RTGCPHYS);
173 RTGCPHYS GCPhysMmioStart = pState->mGCPhysMmioStart - cbRegionAligned;
174
175 if (GCPhysMmioStart < pState->mGCPhysRamStart)
176 {
177 AssertLogRelMsgFailed(("ResourceAssignmentManager: MMIO range for %s would overlap RAM region\n", pszName));
178 return E_INVALIDARG;
179 }
180
181 *pGCPhysStart = GCPhysMmioStart;
182 *pcbRegion = cbRegionAligned;
183 pState->mGCPhysMmioStart -= cbRegionAligned;
184 pState->addAddrRange(pszName, GCPhysMmioStart, cbRegionAligned);
185 return S_OK;
186}
187
188HRESULT ResourceAssignmentManager::assignMmio32Region(const char *pszName, RTGCPHYS cbRegion, PRTGCPHYS pGCPhysStart, PRTGCPHYS pcbRegion)
189{
190 RTGCPHYS cbRegionAligned = RT_ALIGN_T(cbRegion, _4K, RTGCPHYS);
191 RTGCPHYS GCPhysMmioStart = pState->mGCPhysMmio32Start;
192
193 if (GCPhysMmioStart > pState->mGCPhysRamStart)
194 {
195 AssertLogRelMsgFailed(("ResourceAssignmentManager: MMIO32 range for %s would overlap RAM region\n", pszName));
196 return E_INVALIDARG;
197 }
198
199 *pGCPhysStart = GCPhysMmioStart;
200 *pcbRegion = cbRegionAligned;
201 pState->mGCPhysMmio32Start += cbRegionAligned;
202 pState->addAddrRange(pszName, GCPhysMmioStart, cbRegionAligned);
203 return S_OK;
204}
205
206HRESULT ResourceAssignmentManager::assignMmioRegionAligned(const char *pszName, RTGCPHYS cbRegion, RTGCPHYS cbAlignment, PRTGCPHYS pGCPhysStart, PRTGCPHYS pcbRegion)
207{
208 RTGCPHYS cbRegionAligned = RT_ALIGN_T(cbRegion, cbAlignment, RTGCPHYS);
209 RTGCPHYS GCPhysMmioStart = pState->mGCPhysMmioStart - cbRegionAligned;
210
211 GCPhysMmioStart = GCPhysMmioStart & ~(cbAlignment - 1);
212 if (GCPhysMmioStart < pState->mGCPhysRamStart)
213 {
214 AssertLogRelMsgFailed(("ResourceAssignmentManager: MMIO range for %s would overlap RAM region\n", pszName));
215 return E_INVALIDARG;
216 }
217
218 *pGCPhysStart = GCPhysMmioStart;
219 *pcbRegion = cbRegionAligned;
220 pState->mGCPhysMmioStart = GCPhysMmioStart;
221 pState->addAddrRange(pszName, GCPhysMmioStart, cbRegionAligned);
222 return S_OK;
223}
224
225HRESULT ResourceAssignmentManager::assignFixedAddress(const char *pszName, RTGCPHYS GCPhysStart, RTGCPHYS cbRegion)
226{
227 RT_NOREF(pszName, GCPhysStart, cbRegion);
228 AssertReleaseFailed();
229 return S_OK;
230}
231
232HRESULT ResourceAssignmentManager::assignRamRegion(const char *pszName, RTGCPHYS cbRam, PRTGCPHYS pGCPhysStart)
233{
234 if (pState->mGCPhysRamStart + cbRam > pState->mGCPhysMmioStart)
235 {
236 AssertLogRelMsgFailed(("ResourceAssignmentManager: RAM range for %s would overlap MMIO range\n", pszName));
237 return E_INVALIDARG;
238 }
239
240 *pGCPhysStart = pState->mGCPhysRamStart;
241 pState->mGCPhysRamStart += cbRam;
242 pState->addAddrRange(pszName, *pGCPhysStart, cbRam);
243 return S_OK;
244}
245
246HRESULT ResourceAssignmentManager::assignInterrupts(const char *pszName, uint32_t cInterrupts, uint32_t *piInterruptFirst)
247{
248 if (pState->miInterrupt + cInterrupts > pState->mcInterrupts)
249 {
250 AssertLogRelMsgFailed(("ResourceAssignmentManager: Interrupt count for %s exceeds number of available interrupts\n", pszName));
251 return E_INVALIDARG;
252 }
253
254 *piInterruptFirst = pState->miInterrupt;
255 pState->miInterrupt += cInterrupts;
256 return S_OK;
257}
258
259HRESULT ResourceAssignmentManager::assignSingleInterrupt(const char *pszName, uint32_t *piInterrupt)
260{
261 return assignInterrupts(pszName, 1, piInterrupt);
262}
263
264HRESULT ResourceAssignmentManager::queryMmioRegion(PRTGCPHYS pGCPhysMmioStart, PRTGCPHYS pcbMmio)
265{
266 *pGCPhysMmioStart = pState->mGCPhysMmioStart;
267 *pcbMmio = pState->mGCPhysMmioStartOrig - pState->mGCPhysMmioStart;
268 return S_OK;
269}
270
271HRESULT ResourceAssignmentManager::queryMmio32Region(PRTGCPHYS pGCPhysMmioStart, PRTGCPHYS pcbMmio)
272{
273 *pGCPhysMmioStart = pState->mGCPhysMmio32StartOrig;
274 *pcbMmio = pState->mcbMmio32;
275 return S_OK;
276}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use