From 345e122dd289b9ffd3ef035f422eab22108e1ff3 Mon Sep 17 00:00:00 2001 From: Tomasz Bursztyka Date: Tue, 6 Apr 2021 11:15:43 +0200 Subject: [PATCH] arch/x86: Add a function to retrieve ID from ACPI's DMAR This will be necessary to get IOAPIC and HPET source ids for VT-D. Signed-off-by: Tomasz Bursztyka --- arch/x86/core/acpi.c | 52 +++++++++++++++++++++++++++++++++++++++++ include/arch/x86/acpi.h | 13 +++++++++++ 2 files changed, 65 insertions(+) diff --git a/arch/x86/core/acpi.c b/arch/x86/core/acpi.c index b0c35d5c9a4..6b2e0c01860 100644 --- a/arch/x86/core/acpi.c +++ b/arch/x86/core/acpi.c @@ -383,3 +383,55 @@ z_acpi_get_dev_scope_paths(struct acpi_dmar_dev_scope *dev_scope, int *n) return dev_scope->path; } + +uint16_t z_acpi_get_dev_id_from_dmar(uint8_t dev_scope_type) +{ + struct acpi_drhd *drhd; + int n_drhd; + + find_dmar(); + + if (dmar == NULL) { + return USHRT_MAX; + } + + drhd = z_acpi_find_drhds(&n_drhd); + + for (; n_drhd > 0; n_drhd--) { + struct acpi_dmar_dev_scope *dev_scope; + int n_ds; + + dev_scope = z_acpi_get_drhd_dev_scopes(drhd, &n_ds); + for (; n_ds > 0; n_ds--) { + if (dev_scope->type == dev_scope_type) { + struct acpi_dmar_dev_path *path; + int n_path; + + path = z_acpi_get_dev_scope_paths(dev_scope, + &n_path); + if (n_path > 0) { + union acpi_dmar_id id; + + /* Let's over simplify for now: + * we don't look for secondary bus + * and extra paths. We just stop here. + */ + + id.bits.bus = dev_scope->start_bus_num; + id.bits.device = path->device; + id.bits.function = path->function; + + return id.raw; + } + } + + dev_scope = (struct acpi_dmar_dev_scope *)( + POINTER_TO_UINT(dev_scope) + dev_scope->length); + } + + drhd = (struct acpi_drhd *)(POINTER_TO_UINT(drhd) + + drhd->entry.length); + } + + return USHRT_MAX; +} diff --git a/include/arch/x86/acpi.h b/include/arch/x86/acpi.h index 559f5ef50e4..ad237f2e560 100644 --- a/include/arch/x86/acpi.h +++ b/include/arch/x86/acpi.h @@ -159,6 +159,16 @@ struct acpi_dmar { struct acpi_dmar_entry remap_entries[]; } __packed; +union acpi_dmar_id { + struct { + uint16_t function : 3; + uint16_t device : 5; + uint16_t bus : 8; + } bits; + + uint16_t raw; +}; + #if defined(CONFIG_ACPI) void *z_acpi_find_table(uint32_t signature); @@ -175,6 +185,8 @@ struct acpi_dmar_dev_scope *z_acpi_get_drhd_dev_scopes(struct acpi_drhd *drhd, struct acpi_dmar_dev_path * z_acpi_get_dev_scope_paths(struct acpi_dmar_dev_scope *dev_scope, int *n); +uint16_t z_acpi_get_dev_id_from_dmar(uint8_t dev_scope_type); + #else /* CONFIG_ACPI */ #define z_acpi_find_table(...) NULL @@ -183,6 +195,7 @@ z_acpi_get_dev_scope_paths(struct acpi_dmar_dev_scope *dev_scope, int *n); #define z_acpi_find_drhds(...) NULL #define z_acpi_get_drhd_dev_scopes(...) NULL #define z_acpi_get_dev_scope_paths(...) NULL +#define z_acpi_get_dev_id_from_dmar(...) USHRT_MAX #endif /* CONFIG_ACPI */