|
[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 |