VirtualBox

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

Last change on this file since 103415 was 102517, checked in by vboxsync, 12 months ago

Main/ConsoleImplConfigArmV8.cpp: Get rid of most hardcoded addresses and introduce a (very barebones right now) resource manager for managing the address map and interrupt assignments, most of the MMIO regions are now moved to the top of the address space. Only exception is the flash device holding the firmware and the MMIO region for PCI MEM32 BARs, bugref:10528

  • 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 102517 2023-12-07 10:28:20Z 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 GCPhysStart;
69 RTGCPHYS GCPhysEnd;
70
71 MemoryRange(const char *pszName, RTGCPHYS GCPhysStart, RTGCPHYS GCPhysEnd)
72 {
73 RTStrCopy(this->szDevName, sizeof(szDevName), pszName);
74 this->GCPhysStart = GCPhysStart;
75 this->GCPhysEnd = 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.

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