Skip to content

Commit 94a456a

Browse files
amerritt-intelwenlingz
authored andcommitted
HV: refactor device_to_dmaru
On server platforms, DMAR DRHD device scope entries may contain PCI bridges. Bridges in the DRHD device scope indicate this IOMMU translates for all devices on the hierarchy below that bridge. ACRN is unaware of bridge types in the device scope, and adds these directly to its internal representation of a DRHD. When looking up a BDF within these DRHD entries, device_to_dmaru assumes all entries are Endpoints, comparing BDF to BDF. Thus device to DMAR unit fails, because it treats a bridge as an Endpoint type. This change leverages prior patches by converting a BDF to the associated device DRHD index, and uses that index to obtain the correct DRHD state. Handling a bridge in other ways may require maintaining a bus list for each, or replacing each bridge in the dev scope with a set of all device BDFs underneath it. Server platforms can have hundreds of PCI devices, thus making the device scope artificially large is unwieldy. Tracked-On: #4134 Signed-off-by: Alexander Merritt <alex.merritt@intel.com> Reviewed-by: Eddie Dong <eddie.dong@intel.com> Reviewed-by: Jason Chen CJ <jason.cj.chen@intel.com>
1 parent 34c75a0 commit 94a456a

File tree

1 file changed

+15
-21
lines changed

1 file changed

+15
-21
lines changed

hypervisor/arch/x86/vtd.c

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <logmsg.h>
2222
#include <board.h>
2323
#include <vm_configurations.h>
24+
#include <pci.h>
2425

2526
#define DBG_IOMMU 0
2627

@@ -555,30 +556,23 @@ static struct dmar_drhd_rt *ioapic_to_dmaru(uint16_t ioapic_id, union pci_bdf *s
555556

556557
static struct dmar_drhd_rt *device_to_dmaru(uint8_t bus, uint8_t devfun)
557558
{
558-
struct dmar_drhd_rt *dmar_unit = NULL;
559-
uint32_t i, j;
560-
561-
for (j = 0U; j < platform_dmar_info->drhd_count; j++) {
562-
dmar_unit = &dmar_drhd_units[j];
563-
564-
for (i = 0U; i < dmar_unit->drhd->dev_cnt; i++) {
565-
if ((dmar_unit->drhd->devices[i].bus == bus) &&
566-
(dmar_unit->drhd->devices[i].devfun == devfun)) {
567-
break;
568-
}
569-
}
559+
struct dmar_drhd_rt *dmaru = NULL;
560+
uint16_t bdf = ((uint16_t)bus << 8U) | devfun;
561+
uint32_t index = pci_lookup_drhd_for_pbdf(bdf);
570562

571-
if ((i != dmar_unit->drhd->dev_cnt) || ((dmar_unit->drhd->flags & DRHD_FLAG_INCLUDE_PCI_ALL_MASK) != 0U)) {
572-
break;
573-
}
574-
}
575-
576-
/* not found */
577-
if (j == platform_dmar_info->drhd_count) {
578-
dmar_unit = NULL;
563+
if (index == INVALID_DRHD_INDEX) {
564+
pr_fatal("BDF %02x:%02x:%x has no IOMMU\n", bus, devfun >> 3U, devfun & 7U);
565+
/*
566+
* pci_lookup_drhd_for_pbdf would return -1U for any of the reasons
567+
* 1) PCI device with bus, devfun does not exist on platform
568+
* 2) ACRN had issues finding the device with bus, devfun during init
569+
* 3) DMAR tables provided by ACPI for this platform are incorrect
570+
*/
571+
} else {
572+
dmaru = &dmar_drhd_units[index];
579573
}
580574

581-
return dmar_unit;
575+
return dmaru;
582576
}
583577

584578
static void dmar_issue_qi_request(struct dmar_drhd_rt *dmar_unit, struct dmar_entry invalidate_desc)

0 commit comments

Comments
 (0)