[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen master] VT-d: parse ACPI "SoC Integrated Address Translation Cache Reporting Structure"s
commit b5996ab2840268529ff508713377c762c5517a36 Author: Jan Beulich <jbeulich@xxxxxxxx> AuthorDate: Mon May 6 14:52:12 2024 +0200 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Mon May 6 14:52:12 2024 +0200 VT-d: parse ACPI "SoC Integrated Address Translation Cache Reporting Structure"s This is a prereq to us, in particular, respecting the "ATC required" flag. Note that ACPI_SATC_ATC_REQUIRED has its #define put in dmar.h, as we try to keep actbl*.h in sync what Linux (who in turn inherit from ACPI CA) has. Note further that some perhaps sub-optimal style aspects are mainly the way they are in order to stay consistent with other pre-existing code. Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Acked-by: Roger Pau Monné <roger.pau@xxxxxxxxxx> --- xen/drivers/passthrough/vtd/dmar.c | 95 ++++++++++++++++++++++++++++++++++++++ xen/drivers/passthrough/vtd/dmar.h | 11 +++++ xen/include/acpi/actbl2.h | 12 ++++- 3 files changed, 117 insertions(+), 1 deletion(-) diff --git a/xen/drivers/passthrough/vtd/dmar.c b/xen/drivers/passthrough/vtd/dmar.c index 882340b7ee..91c22b8330 100644 --- a/xen/drivers/passthrough/vtd/dmar.c +++ b/xen/drivers/passthrough/vtd/dmar.c @@ -47,6 +47,7 @@ LIST_HEAD_READ_MOSTLY(acpi_drhd_units); LIST_HEAD_READ_MOSTLY(acpi_rmrr_units); static LIST_HEAD_READ_MOSTLY(acpi_atsr_units); static LIST_HEAD_READ_MOSTLY(acpi_rhsa_units); +static LIST_HEAD_READ_MOSTLY(acpi_satc_units); static struct acpi_table_header *__read_mostly dmar_table; static int __read_mostly dmar_flags; @@ -750,6 +751,93 @@ acpi_parse_one_rhsa(struct acpi_dmar_header *header) return ret; } +static int __init register_one_satc(struct acpi_satc_unit *satcu) +{ + bool ignore = false; + unsigned int i = 0; + int ret = 0; + + /* Skip checking if segment is not accessible yet. */ + if ( !pci_known_segment(satcu->segment) ) + i = UINT_MAX; + + for ( ; i < satcu->scope.devices_cnt; i++ ) + { + uint8_t b = PCI_BUS(satcu->scope.devices[i]); + uint8_t d = PCI_SLOT(satcu->scope.devices[i]); + uint8_t f = PCI_FUNC(satcu->scope.devices[i]); + + if ( !pci_device_detect(satcu->segment, b, d, f) ) + { + dprintk(XENLOG_WARNING VTDPREFIX, + " Non-existent device (%pp) is reported in SATC scope!\n", + &PCI_SBDF(satcu->segment, b, d, f)); + ignore = true; + } + else + { + ignore = false; + break; + } + } + + if ( ignore ) + { + dprintk(XENLOG_WARNING VTDPREFIX, + " Ignore SATC for seg %04x as no device under its scope is PCI discoverable\n", + satcu->segment); + return 1; + } + + if ( iommu_verbose ) + printk(VTDPREFIX " ATC required: %d\n", satcu->atc_required); + + list_add(&satcu->list, &acpi_satc_units); + + return ret; +} + +static int __init +acpi_parse_one_satc(const struct acpi_dmar_header *header) +{ + const struct acpi_dmar_satc *satc = + container_of(header, const struct acpi_dmar_satc, header); + struct acpi_satc_unit *satcu; + const void *dev_scope_start, *dev_scope_end; + int ret = acpi_dmar_check_length(header, sizeof(*satc)); + + if ( ret ) + return ret; + + satcu = xzalloc(struct acpi_satc_unit); + if ( !satcu ) + return -ENOMEM; + + satcu->segment = satc->segment; + satcu->atc_required = satc->flags & ACPI_SATC_ATC_REQUIRED; + + dev_scope_start = (const void *)(satc + 1); + dev_scope_end = (const void *)satc + header->length; + ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end, + &satcu->scope, SATC_TYPE, satc->segment); + + if ( !ret && satcu->scope.devices_cnt ) + ret = register_one_satc(satcu); + + if ( ret ) + { + scope_devices_free(&satcu->scope); + xfree(satcu); + } + + /* + * register_one_satc() returns greater than 0 when a specified PCIe + * device cannot be detected. To prevent VT-d from being disabled in + * such cases, make the return value 0 here. + */ + return ret > 0 ? 0 : ret; +} + static int __init cf_check acpi_parse_dmar(struct acpi_table_header *table) { struct acpi_table_dmar *dmar; @@ -803,6 +891,13 @@ static int __init cf_check acpi_parse_dmar(struct acpi_table_header *table) printk(VTDPREFIX "found ACPI_DMAR_RHSA:\n"); ret = acpi_parse_one_rhsa(entry_header); break; + + case ACPI_DMAR_TYPE_SATC: + if ( iommu_verbose ) + printk(VTDPREFIX "found ACPI_DMAR_SATC:\n"); + ret = acpi_parse_one_satc(entry_header); + break; + default: dprintk(XENLOG_WARNING VTDPREFIX, "Ignore unknown DMAR structure type (%#x)\n", diff --git a/xen/drivers/passthrough/vtd/dmar.h b/xen/drivers/passthrough/vtd/dmar.h index a1f2353a51..61f71ca5e6 100644 --- a/xen/drivers/passthrough/vtd/dmar.h +++ b/xen/drivers/passthrough/vtd/dmar.h @@ -91,6 +91,16 @@ struct acpi_rhsa_unit { u32 proximity_domain; }; +struct acpi_satc_unit { + struct dmar_scope scope; + struct list_head list; + uint16_t segment; + bool atc_required:1; +}; + +/* In lieu of a definition in actbl2.h. */ +#define ACPI_SATC_ATC_REQUIRED (1U << 0) + #define for_each_drhd_unit(drhd) \ list_for_each_entry(drhd, &acpi_drhd_units, list) @@ -106,6 +116,7 @@ struct acpi_atsr_unit *acpi_find_matched_atsr_unit(const struct pci_dev *); #define DMAR_TYPE 1 #define RMRR_TYPE 2 #define ATSR_TYPE 3 +#define SATC_TYPE 4 #define DMAR_OPERATION_TIMEOUT MILLISECS(1000) diff --git a/xen/include/acpi/actbl2.h b/xen/include/acpi/actbl2.h index 2ad08ea467..ee96e990d6 100644 --- a/xen/include/acpi/actbl2.h +++ b/xen/include/acpi/actbl2.h @@ -345,7 +345,8 @@ enum acpi_dmar_type { ACPI_DMAR_TYPE_RESERVED_MEMORY = 1, ACPI_DMAR_TYPE_ATSR = 2, ACPI_DMAR_HARDWARE_AFFINITY = 3, - ACPI_DMAR_TYPE_RESERVED = 4 /* 4 and greater are reserved */ + ACPI_DMAR_TYPE_SATC = 5, + ACPI_DMAR_TYPE_RESERVED = 7 /* 7 and greater are reserved */ }; /* DMAR Device Scope structure */ @@ -427,6 +428,15 @@ struct acpi_dmar_rhsa { u32 proximity_domain; }; +/* 5: SOC Integrated Address Translation Cache Reporting Structure */ + +struct acpi_dmar_satc { + struct acpi_dmar_header header; + uint8_t flags; + uint8_t reserved; + uint16_t segment; +}; + /******************************************************************************* * * HPET - High Precision Event Timer table -- generated by git-patchbot for /home/xen/git/xen.git#master
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |