VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/BusAssignmentManager.cpp@ 93309

Last change on this file since 93309 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.4 KB
Line 
1/* $Id: BusAssignmentManager.cpp 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * VirtualBox bus slots assignment manager
4 */
5
6/*
7 * Copyright (C) 2010-2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#define LOG_GROUP LOG_GROUP_MAIN
19#include "LoggingNew.h"
20
21#include "BusAssignmentManager.h"
22
23#include <iprt/asm.h>
24#include <iprt/string.h>
25
26#include <VBox/vmm/cfgm.h>
27#include <VBox/com/array.h>
28
29#include <map>
30#include <vector>
31#include <algorithm>
32
33struct DeviceAssignmentRule
34{
35 const char *pszName;
36 int iBus;
37 int iDevice;
38 int iFn;
39 int iPriority;
40};
41
42struct DeviceAliasRule
43{
44 const char *pszDevName;
45 const char *pszDevAlias;
46};
47
48/* Those rules define PCI slots assignment */
49/** @note
50 * The EFI takes assumptions about PCI slot assignments which are different
51 * from the following tables in certain cases, for example the IDE device
52 * is assumed to be 00:01.1! */
53
54/* Device Bus Device Function Priority */
55
56/* Generic rules */
57static const DeviceAssignmentRule g_aGenericRules[] =
58{
59 /* VGA controller */
60 {"vga", 0, 2, 0, 0},
61
62 /* VMM device */
63 {"VMMDev", 0, 4, 0, 0},
64
65 /* Audio controllers */
66 {"ichac97", 0, 5, 0, 0},
67 {"hda", 0, 5, 0, 0},
68
69 /* Storage controllers */
70 {"buslogic", 0, 21, 0, 1},
71 {"lsilogicsas", 0, 22, 0, 1},
72 {"nvme", 0, 14, 0, 1},
73 {"virtio-scsi", 0, 15, 0, 1},
74
75 /* USB controllers */
76 {"usb-ohci", 0, 6, 0, 0},
77 {"usb-ehci", 0, 11, 0, 0},
78 {"usb-xhci", 0, 12, 0, 0},
79
80 /* ACPI controller */
81#if 0
82 // It really should be this for 440FX chipset (part of PIIX4 actually)
83 {"acpi", 0, 1, 3, 0},
84#else
85 {"acpi", 0, 7, 0, 0},
86#endif
87
88 /* Network controllers */
89 /* the first network card gets the PCI ID 3, the next 3 gets 8..10,
90 * next 4 get 16..19. In "VMWare compatibility" mode the IDs 3 and 17
91 * swap places, i.e. the first card goes to ID 17=0x11. */
92 {"nic", 0, 3, 0, 1},
93 {"nic", 0, 8, 0, 1},
94 {"nic", 0, 9, 0, 1},
95 {"nic", 0, 10, 0, 1},
96 {"nic", 0, 16, 0, 1},
97 {"nic", 0, 17, 0, 1},
98 {"nic", 0, 18, 0, 1},
99 {"nic", 0, 19, 0, 1},
100
101 /* ISA/LPC controller */
102 {"lpc", 0, 31, 0, 0},
103
104 { NULL, -1, -1, -1, 0}
105};
106
107/* PIIX3 chipset rules */
108static const DeviceAssignmentRule g_aPiix3Rules[] =
109{
110 {"piix3ide", 0, 1, 1, 0},
111 {"ahci", 0, 13, 0, 1},
112 {"lsilogic", 0, 20, 0, 1},
113 {"pcibridge", 0, 24, 0, 0},
114 {"pcibridge", 0, 25, 0, 0},
115 { NULL, -1, -1, -1, 0}
116};
117
118
119/* ICH9 chipset rules */
120static const DeviceAssignmentRule g_aIch9Rules[] =
121{
122 /* Host Controller */
123 {"i82801", 0, 30, 0, 0},
124
125 /* Those are functions of LPC at 00:1e:00 */
126 /**
127 * Please note, that for devices being functions, like we do here, device 0
128 * must be multifunction, i.e. have header type 0x80. Our LPC device is.
129 * Alternative approach is to assign separate slot to each device.
130 */
131 {"piix3ide", 0, 31, 1, 2},
132 {"ahci", 0, 31, 2, 2},
133 {"smbus", 0, 31, 3, 2},
134 {"usb-ohci", 0, 31, 4, 2},
135 {"usb-ehci", 0, 31, 5, 2},
136 {"thermal", 0, 31, 6, 2},
137
138 /* to make sure rule never used before rules assigning devices on it */
139 {"ich9pcibridge", 0, 24, 0, 10},
140 {"ich9pcibridge", 0, 25, 0, 10},
141 {"ich9pcibridge", 2, 24, 0, 9}, /* Bridges must be instantiated depth */
142 {"ich9pcibridge", 2, 25, 0, 9}, /* first (assumption in PDM and other */
143 {"ich9pcibridge", 4, 24, 0, 8}, /* places), so make sure that nested */
144 {"ich9pcibridge", 4, 25, 0, 8}, /* bridges are added to the last bridge */
145 {"ich9pcibridge", 6, 24, 0, 7}, /* only, avoiding the need to re-sort */
146 {"ich9pcibridge", 6, 25, 0, 7}, /* everything before starting the VM. */
147 {"ich9pcibridge", 8, 24, 0, 6},
148 {"ich9pcibridge", 8, 25, 0, 6},
149 {"ich9pcibridge", 10, 24, 0, 5},
150 {"ich9pcibridge", 10, 25, 0, 5},
151
152 /* Storage controllers */
153 {"ahci", 1, 0, 0, 0},
154 {"ahci", 1, 1, 0, 0},
155 {"ahci", 1, 2, 0, 0},
156 {"ahci", 1, 3, 0, 0},
157 {"ahci", 1, 4, 0, 0},
158 {"ahci", 1, 5, 0, 0},
159 {"ahci", 1, 6, 0, 0},
160 {"lsilogic", 1, 7, 0, 0},
161 {"lsilogic", 1, 8, 0, 0},
162 {"lsilogic", 1, 9, 0, 0},
163 {"lsilogic", 1, 10, 0, 0},
164 {"lsilogic", 1, 11, 0, 0},
165 {"lsilogic", 1, 12, 0, 0},
166 {"lsilogic", 1, 13, 0, 0},
167 {"buslogic", 1, 14, 0, 0},
168 {"buslogic", 1, 15, 0, 0},
169 {"buslogic", 1, 16, 0, 0},
170 {"buslogic", 1, 17, 0, 0},
171 {"buslogic", 1, 18, 0, 0},
172 {"buslogic", 1, 19, 0, 0},
173 {"buslogic", 1, 20, 0, 0},
174 {"lsilogicsas", 1, 21, 0, 0},
175 {"lsilogicsas", 1, 26, 0, 0},
176 {"lsilogicsas", 1, 27, 0, 0},
177 {"lsilogicsas", 1, 28, 0, 0},
178 {"lsilogicsas", 1, 29, 0, 0},
179 {"lsilogicsas", 1, 30, 0, 0},
180 {"lsilogicsas", 1, 31, 0, 0},
181
182 /* NICs */
183 {"nic", 2, 0, 0, 0},
184 {"nic", 2, 1, 0, 0},
185 {"nic", 2, 2, 0, 0},
186 {"nic", 2, 3, 0, 0},
187 {"nic", 2, 4, 0, 0},
188 {"nic", 2, 5, 0, 0},
189 {"nic", 2, 6, 0, 0},
190 {"nic", 2, 7, 0, 0},
191 {"nic", 2, 8, 0, 0},
192 {"nic", 2, 9, 0, 0},
193 {"nic", 2, 10, 0, 0},
194 {"nic", 2, 11, 0, 0},
195 {"nic", 2, 12, 0, 0},
196 {"nic", 2, 13, 0, 0},
197 {"nic", 2, 14, 0, 0},
198 {"nic", 2, 15, 0, 0},
199 {"nic", 2, 16, 0, 0},
200 {"nic", 2, 17, 0, 0},
201 {"nic", 2, 18, 0, 0},
202 {"nic", 2, 19, 0, 0},
203 {"nic", 2, 20, 0, 0},
204 {"nic", 2, 21, 0, 0},
205 {"nic", 2, 26, 0, 0},
206 {"nic", 2, 27, 0, 0},
207 {"nic", 2, 28, 0, 0},
208 {"nic", 2, 29, 0, 0},
209 {"nic", 2, 30, 0, 0},
210 {"nic", 2, 31, 0, 0},
211
212 /* Storage controller #2 (NVMe, virtio-scsi) */
213 {"nvme", 3, 0, 0, 0},
214 {"nvme", 3, 1, 0, 0},
215 {"nvme", 3, 2, 0, 0},
216 {"nvme", 3, 3, 0, 0},
217 {"nvme", 3, 4, 0, 0},
218 {"nvme", 3, 5, 0, 0},
219 {"nvme", 3, 6, 0, 0},
220 {"virtio-scsi", 3, 7, 0, 0},
221 {"virtio-scsi", 3, 8, 0, 0},
222 {"virtio-scsi", 3, 9, 0, 0},
223 {"virtio-scsi", 3, 10, 0, 0},
224 {"virtio-scsi", 3, 11, 0, 0},
225 {"virtio-scsi", 3, 12, 0, 0},
226 {"virtio-scsi", 3, 13, 0, 0},
227
228 { NULL, -1, -1, -1, 0}
229};
230
231
232#ifdef VBOX_WITH_IOMMU_AMD
233/*
234 * AMD IOMMU and LSI Logic controller rules.
235 *
236 * Since the PCI slot (BDF=00:20.0) of the LSI Logic controller
237 * conflicts with the SB I/O APIC, we assign the LSI Logic controller
238 * to device number 23 when the VM is configured for an AMD IOMMU.
239 */
240static const DeviceAssignmentRule g_aIch9IommuAmdRules[] =
241{
242 /* AMD IOMMU. */
243 {"iommu-amd", 0, 0, 0, 0},
244 /* AMD IOMMU: Reserved for southbridge I/O APIC. */
245 {"sb-ioapic", 0, 20, 0, 0},
246
247 /* Storage controller */
248 {"lsilogic", 0, 23, 0, 1},
249 { NULL, -1, -1, -1, 0}
250};
251#endif
252
253#ifdef VBOX_WITH_IOMMU_INTEL
254/*
255 * Intel IOMMU.
256 * The VT-d misc, address remapping, system management device is
257 * located at BDF 0:5:0 on real hardware but we use 0:1:0 since that
258 * slot isn't used for anything else.
259 *
260 * While we could place the I/O APIC anywhere, we keep it consistent
261 * with the AMD IOMMU and we assign the LSI Logic controller to
262 * device number 23 (and I/O APIC at device 20).
263 */
264static const DeviceAssignmentRule g_aIch9IommuIntelRules[] =
265{
266 /* Intel IOMMU. */
267 {"iommu-intel", 0, 1, 0, 0},
268 /* Intel IOMMU: Reserved for I/O APIC. */
269 {"sb-ioapic", 0, 20, 0, 0},
270
271 /* Storage controller */
272 {"lsilogic", 0, 23, 0, 1},
273 { NULL, -1, -1, -1, 0}
274};
275#endif
276
277/* LSI Logic Controller. */
278static const DeviceAssignmentRule g_aIch9LsiRules[] =
279{
280 /* Storage controller */
281 {"lsilogic", 0, 20, 0, 1},
282 { NULL, -1, -1, -1, 0}
283};
284
285/* Aliasing rules */
286static const DeviceAliasRule g_aDeviceAliases[] =
287{
288 {"e1000", "nic"},
289 {"pcnet", "nic"},
290 {"virtio-net", "nic"},
291 {"ahci", "storage"},
292 {"lsilogic", "storage"},
293 {"buslogic", "storage"},
294 {"lsilogicsas", "storage"},
295 {"nvme", "storage"},
296 {"virtio-scsi", "storage"}
297};
298
299struct BusAssignmentManager::State
300{
301 struct PCIDeviceRecord
302 {
303 char szDevName[32];
304 PCIBusAddress HostAddress;
305
306 PCIDeviceRecord(const char *pszName, PCIBusAddress aHostAddress)
307 {
308 RTStrCopy(this->szDevName, sizeof(szDevName), pszName);
309 this->HostAddress = aHostAddress;
310 }
311
312 PCIDeviceRecord(const char *pszName)
313 {
314 RTStrCopy(this->szDevName, sizeof(szDevName), pszName);
315 }
316
317 bool operator<(const PCIDeviceRecord &a) const
318 {
319 return RTStrNCmp(szDevName, a.szDevName, sizeof(szDevName)) < 0;
320 }
321
322 bool operator==(const PCIDeviceRecord &a) const
323 {
324 return RTStrNCmp(szDevName, a.szDevName, sizeof(szDevName)) == 0;
325 }
326 };
327
328 typedef std::map<PCIBusAddress,PCIDeviceRecord> PCIMap;
329 typedef std::vector<PCIBusAddress> PCIAddrList;
330 typedef std::vector<const DeviceAssignmentRule *> PCIRulesList;
331 typedef std::map<PCIDeviceRecord,PCIAddrList> ReversePCIMap;
332
333 volatile int32_t cRefCnt;
334 ChipsetType_T mChipsetType;
335 const char * mpszBridgeName;
336 IommuType_T mIommuType;
337 PCIMap mPCIMap;
338 ReversePCIMap mReversePCIMap;
339
340 State()
341 : cRefCnt(1), mChipsetType(ChipsetType_Null), mpszBridgeName("unknownbridge")
342 {}
343 ~State()
344 {}
345
346 HRESULT init(ChipsetType_T chipsetType, IommuType_T iommuType);
347
348 HRESULT record(const char *pszName, PCIBusAddress& GuestAddress, PCIBusAddress HostAddress);
349 HRESULT autoAssign(const char *pszName, PCIBusAddress& Address);
350 bool checkAvailable(PCIBusAddress& Address);
351 bool findPCIAddress(const char *pszDevName, int iInstance, PCIBusAddress& Address);
352
353 const char *findAlias(const char *pszName);
354 void addMatchingRules(const char *pszName, PCIRulesList& aList);
355 void listAttachedPCIDevices(std::vector<PCIDeviceInfo> &aAttached);
356};
357
358HRESULT BusAssignmentManager::State::init(ChipsetType_T chipsetType, IommuType_T iommuType)
359{
360 if (iommuType != IommuType_None)
361 {
362#if defined(VBOX_WITH_IOMMU_AMD) && defined(VBOX_WITH_IOMMU_INTEL)
363 Assert(iommuType == IommuType_AMD || iommuType == IommuType_Intel);
364#elif defined(VBOX_WITH_IOMMU_AMD)
365 Assert(iommuType == IommuType_AMD);
366#elif defined(VBOX_WITH_IOMMU_INTEL)
367 Assert(iommuType == IommuType_Intel);
368#endif
369 }
370
371 mChipsetType = chipsetType;
372 mIommuType = iommuType;
373 switch (chipsetType)
374 {
375 case ChipsetType_PIIX3:
376 mpszBridgeName = "pcibridge";
377 break;
378 case ChipsetType_ICH9:
379 mpszBridgeName = "ich9pcibridge";
380 break;
381 default:
382 mpszBridgeName = "unknownbridge";
383 AssertFailed();
384 break;
385 }
386 return S_OK;
387}
388
389HRESULT BusAssignmentManager::State::record(const char *pszName, PCIBusAddress& Address, PCIBusAddress HostAddress)
390{
391 PCIDeviceRecord devRec(pszName, HostAddress);
392
393 /* Remember address -> device mapping */
394 mPCIMap.insert(PCIMap::value_type(Address, devRec));
395
396 ReversePCIMap::iterator it = mReversePCIMap.find(devRec);
397 if (it == mReversePCIMap.end())
398 {
399 mReversePCIMap.insert(ReversePCIMap::value_type(devRec, PCIAddrList()));
400 it = mReversePCIMap.find(devRec);
401 }
402
403 /* Remember device name -> addresses mapping */
404 it->second.push_back(Address);
405
406 return S_OK;
407}
408
409bool BusAssignmentManager::State::findPCIAddress(const char *pszDevName, int iInstance, PCIBusAddress& Address)
410{
411 PCIDeviceRecord devRec(pszDevName);
412
413 ReversePCIMap::iterator it = mReversePCIMap.find(devRec);
414 if (it == mReversePCIMap.end())
415 return false;
416
417 if (iInstance >= (int)it->second.size())
418 return false;
419
420 Address = it->second[iInstance];
421 return true;
422}
423
424void BusAssignmentManager::State::addMatchingRules(const char *pszName, PCIRulesList& aList)
425{
426 size_t iRuleset, iRule;
427 const DeviceAssignmentRule *aArrays[3] = {g_aGenericRules, NULL, NULL};
428
429 switch (mChipsetType)
430 {
431 case ChipsetType_PIIX3:
432 aArrays[1] = g_aPiix3Rules;
433 break;
434 case ChipsetType_ICH9:
435 {
436 aArrays[1] = g_aIch9Rules;
437#ifdef VBOX_WITH_IOMMU_AMD
438 if (mIommuType == IommuType_AMD)
439 aArrays[2] = g_aIch9IommuAmdRules;
440 else
441#endif
442#ifdef VBOX_WITH_IOMMU_INTEL
443 if (mIommuType == IommuType_Intel)
444 aArrays[2] = g_aIch9IommuIntelRules;
445 else
446#endif
447 {
448 aArrays[2] = g_aIch9LsiRules;
449 }
450 break;
451 }
452 default:
453 AssertFailed();
454 break;
455 }
456
457 for (iRuleset = 0; iRuleset < RT_ELEMENTS(aArrays); iRuleset++)
458 {
459 if (aArrays[iRuleset] == NULL)
460 continue;
461
462 for (iRule = 0; aArrays[iRuleset][iRule].pszName != NULL; iRule++)
463 {
464 if (RTStrCmp(pszName, aArrays[iRuleset][iRule].pszName) == 0)
465 aList.push_back(&aArrays[iRuleset][iRule]);
466 }
467 }
468}
469
470const char *BusAssignmentManager::State::findAlias(const char *pszDev)
471{
472 for (size_t iAlias = 0; iAlias < RT_ELEMENTS(g_aDeviceAliases); iAlias++)
473 {
474 if (strcmp(pszDev, g_aDeviceAliases[iAlias].pszDevName) == 0)
475 return g_aDeviceAliases[iAlias].pszDevAlias;
476 }
477 return NULL;
478}
479
480static bool RuleComparator(const DeviceAssignmentRule *r1, const DeviceAssignmentRule *r2)
481{
482 return (r1->iPriority > r2->iPriority);
483}
484
485HRESULT BusAssignmentManager::State::autoAssign(const char *pszName, PCIBusAddress& Address)
486{
487 PCIRulesList matchingRules;
488
489 addMatchingRules(pszName, matchingRules);
490 const char *pszAlias = findAlias(pszName);
491 if (pszAlias)
492 addMatchingRules(pszAlias, matchingRules);
493
494 AssertMsg(matchingRules.size() > 0, ("No rule for %s(%s)\n", pszName, pszAlias));
495
496 stable_sort(matchingRules.begin(), matchingRules.end(), RuleComparator);
497
498 for (size_t iRule = 0; iRule < matchingRules.size(); iRule++)
499 {
500 const DeviceAssignmentRule *rule = matchingRules[iRule];
501
502 Address.miBus = rule->iBus;
503 Address.miDevice = rule->iDevice;
504 Address.miFn = rule->iFn;
505
506 if (checkAvailable(Address))
507 return S_OK;
508 }
509 AssertLogRelMsgFailed(("BusAssignmentManager: All possible candidate positions for %s exhausted\n", pszName));
510
511 return E_INVALIDARG;
512}
513
514bool BusAssignmentManager::State::checkAvailable(PCIBusAddress& Address)
515{
516 PCIMap::const_iterator it = mPCIMap.find(Address);
517
518 return (it == mPCIMap.end());
519}
520
521void BusAssignmentManager::State::listAttachedPCIDevices(std::vector<PCIDeviceInfo> &aAttached)
522{
523 aAttached.resize(mPCIMap.size());
524
525 size_t i = 0;
526 PCIDeviceInfo dev;
527 for (PCIMap::const_iterator it = mPCIMap.begin(); it != mPCIMap.end(); ++it, ++i)
528 {
529 dev.strDeviceName = it->second.szDevName;
530 dev.guestAddress = it->first;
531 dev.hostAddress = it->second.HostAddress;
532 aAttached[i] = dev;
533 }
534}
535
536BusAssignmentManager::BusAssignmentManager()
537 : pState(NULL)
538{
539 pState = new State();
540 Assert(pState);
541}
542
543BusAssignmentManager::~BusAssignmentManager()
544{
545 if (pState)
546 {
547 delete pState;
548 pState = NULL;
549 }
550}
551
552BusAssignmentManager *BusAssignmentManager::createInstance(ChipsetType_T chipsetType, IommuType_T iommuType)
553{
554 BusAssignmentManager *pInstance = new BusAssignmentManager();
555 pInstance->pState->init(chipsetType, iommuType);
556 Assert(pInstance);
557 return pInstance;
558}
559
560void BusAssignmentManager::AddRef()
561{
562 ASMAtomicIncS32(&pState->cRefCnt);
563}
564void BusAssignmentManager::Release()
565{
566 if (ASMAtomicDecS32(&pState->cRefCnt) == 0)
567 delete this;
568}
569
570DECLINLINE(HRESULT) InsertConfigInteger(PCFGMNODE pCfg, const char *pszName, uint64_t u64)
571{
572 int vrc = CFGMR3InsertInteger(pCfg, pszName, u64);
573 if (RT_FAILURE(vrc))
574 return E_INVALIDARG;
575
576 return S_OK;
577}
578
579DECLINLINE(HRESULT) InsertConfigNode(PCFGMNODE pNode, const char *pcszName, PCFGMNODE *ppChild)
580{
581 int vrc = CFGMR3InsertNode(pNode, pcszName, ppChild);
582 if (RT_FAILURE(vrc))
583 return E_INVALIDARG;
584
585 return S_OK;
586}
587
588
589HRESULT BusAssignmentManager::assignPCIDeviceImpl(const char *pszDevName,
590 PCFGMNODE pCfg,
591 PCIBusAddress& GuestAddress,
592 PCIBusAddress HostAddress,
593 bool fGuestAddressRequired)
594{
595 HRESULT rc = S_OK;
596
597 if (!GuestAddress.valid())
598 rc = pState->autoAssign(pszDevName, GuestAddress);
599 else
600 {
601 bool fAvailable = pState->checkAvailable(GuestAddress);
602
603 if (!fAvailable)
604 {
605 if (fGuestAddressRequired)
606 rc = E_ACCESSDENIED;
607 else
608 rc = pState->autoAssign(pszDevName, GuestAddress);
609 }
610 }
611
612 if (FAILED(rc))
613 return rc;
614
615 Assert(GuestAddress.valid() && pState->checkAvailable(GuestAddress));
616
617 rc = pState->record(pszDevName, GuestAddress, HostAddress);
618 if (FAILED(rc))
619 return rc;
620
621 if (pCfg)
622 {
623 rc = InsertConfigInteger(pCfg, "PCIBusNo", GuestAddress.miBus);
624 if (FAILED(rc))
625 return rc;
626 rc = InsertConfigInteger(pCfg, "PCIDeviceNo", GuestAddress.miDevice);
627 if (FAILED(rc))
628 return rc;
629 rc = InsertConfigInteger(pCfg, "PCIFunctionNo", GuestAddress.miFn);
630 if (FAILED(rc))
631 return rc;
632 }
633
634 /* Check if the bus is still unknown, i.e. the bridge to it is missing */
635 if ( GuestAddress.miBus > 0
636 && !hasPCIDevice(pState->mpszBridgeName, GuestAddress.miBus - 1))
637 {
638 PCFGMNODE pDevices = CFGMR3GetParent(CFGMR3GetParent(pCfg));
639 AssertLogRelMsgReturn(pDevices, ("BusAssignmentManager: cannot find base device configuration\n"), E_UNEXPECTED);
640 PCFGMNODE pBridges = CFGMR3GetChild(pDevices, "ich9pcibridge");
641 AssertLogRelMsgReturn(pBridges, ("BusAssignmentManager: cannot find bridge configuration base\n"), E_UNEXPECTED);
642
643 /* Device should be on a not yet existing bus, add it automatically */
644 for (int iBridge = 0; iBridge <= GuestAddress.miBus - 1; iBridge++)
645 {
646 if (!hasPCIDevice(pState->mpszBridgeName, iBridge))
647 {
648 PCIBusAddress BridgeGuestAddress;
649 rc = pState->autoAssign(pState->mpszBridgeName, BridgeGuestAddress);
650 if (FAILED(rc))
651 return rc;
652 if (BridgeGuestAddress.miBus > iBridge)
653 AssertLogRelMsgFailedReturn(("BusAssignmentManager: cannot create bridge for bus %i because the possible parent bus positions are exhausted\n", iBridge + 1), E_UNEXPECTED);
654
655 PCFGMNODE pInst;
656 InsertConfigNode(pBridges, Utf8StrFmt("%d", iBridge).c_str(), &pInst);
657 InsertConfigInteger(pInst, "Trusted", 1);
658 rc = assignPCIDevice(pState->mpszBridgeName, pInst);
659 if (FAILED(rc))
660 return rc;
661 }
662 }
663 }
664
665 return S_OK;
666}
667
668
669bool BusAssignmentManager::findPCIAddress(const char *pszDevName, int iInstance, PCIBusAddress& Address)
670{
671 return pState->findPCIAddress(pszDevName, iInstance, Address);
672}
673void BusAssignmentManager::listAttachedPCIDevices(std::vector<PCIDeviceInfo> &aAttached)
674{
675 pState->listAttachedPCIDevices(aAttached);
676}
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