hv: acpi: refine dmar acpi table parse

Now ACRN Hypervisor only support one PCI Segment, this patch add this check.
This patch also fix a small bug: it would trigger false error "DRHD with
INCLUDE_PCI_ALL flag is NOT the last one".

Tracked-On: #5907
Signed-off-by: Fei Li <fei1.li@intel.com>
Reviewed-by: Jason Chen CJ <jason.cj.chen@intel.com>
This commit is contained in:
Fei Li 2022-03-24 19:14:13 +08:00 committed by acrnsi-robot
parent 3f7501db38
commit 2aaf61bef8
1 changed files with 21 additions and 15 deletions

View File

@ -163,7 +163,8 @@ int32_t parse_dmar_table(struct dmar_info *plat_dmar_info)
struct acpi_dmar_header *dmar_header;
struct acpi_dmar_hardware_unit *acpi_drhd;
char *ptr, *ptr_end;
bool is_include_all_emulated = false;
uint32_t include_all_idx = ~0U;
uint16_t segment = 0;
dmar_tbl = (struct acpi_table_dmar *)get_dmar_table();
ASSERT(dmar_tbl != NULL, "");
@ -174,32 +175,37 @@ int32_t parse_dmar_table(struct dmar_info *plat_dmar_info)
plat_dmar_info->drhd_units = drhd_info_array;
for (; ptr < ptr_end; ptr += dmar_header->length) {
dmar_header = (struct acpi_dmar_header *)ptr;
if (dmar_header->length <= 0U) {
pr_err("drhd: corrupted DMAR table, l %d\n", dmar_header->length);
break;
}
ASSERT(dmar_header->length >= sizeof(struct acpi_dmar_header), "corrupted DMAR table");
if (dmar_header->type == ACPI_DMAR_TYPE_HARDWARE_UNIT) {
acpi_drhd = (struct acpi_dmar_hardware_unit *)dmar_header;
/* Treat a valid DRHD has a non-zero base address */
if (acpi_drhd->address == 0UL) {
pr_warn("drhd: a zero base address DRHD. Please fix the BIOS!");
continue;
}
dmar_unit_cnt++;
ASSERT(acpi_drhd->address != 0UL, "a zero base address DRHD. Please fix the BIOS.");
/* Only support single PCI Segment */
if (acpi_drhd->flags & DRHD_FLAG_INCLUDE_PCI_ALL_MASK) {
if (!is_include_all_emulated) {
pr_warn("DRHD with INCLUDE_PCI_ALL flag is NOT the last one!");
if (dmar_unit_cnt == 0U) {
segment = acpi_drhd->segment;
} else {
/* Only support single PCI Segment */
if (segment != acpi_drhd->segment) {
panic("Only support single PCI Segment.");
}
is_include_all_emulated = true;
}
if (acpi_drhd->flags & DRHD_FLAG_INCLUDE_PCI_ALL_MASK) {
/* Check more than one DRHD with INCLUDE_PCI_ALL flag ? */
include_all_idx = dmar_unit_cnt;
}
dmar_unit_cnt++;
plat_dmar_info->drhd_units[dmar_unit_cnt - 1].devices = drhd_dev_scope[dmar_unit_cnt - 1];
handle_one_drhd(acpi_drhd, &(plat_dmar_info->drhd_units[dmar_unit_cnt - 1]));
}
}
if ((include_all_idx != ~0U) && (dmar_unit_cnt != (include_all_idx + 1U))) {
pr_err("DRHD%d with INCLUDE_PCI_ALL flag is NOT the last one. Please fix the BIOS.", include_all_idx);
}
ASSERT(dmar_unit_cnt <= MAX_DRHDS, "parsed dmar_unit_cnt > MAX_DRHDS");
plat_dmar_info->drhd_count = dmar_unit_cnt;