From: James Morse <james.morse(a)arm.com>
commit 3ec28b81de7f3d17f0f253d4ec0f7e6c068cc0c8 openEuler-1.0
hulk inclusion
category: feature
bugzilla: 28055
CVE: NA
------------------------------
The MPAM table holds a PPTT-offset that describes a cache. Add a
helper acpi_pptt_validate_cache_node(), which checks this offset
really is in the PPTT, on a node boundary, and that node really
is a cache.
With this the MPAM probe code can go poking through struct cacheinfo
looking for a level with a matching firmware_node.
Signed-off-by: James Morse <james.morse(a)arm.com>
Signed-off-by: Wang ShaoBo <bobo.shaobowang(a)huawei.com>
Reviewed-By: Xie XiuQi <xiexiuqi(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Signed-off-by: Xin Hao <haoxing990(a)gmail.com>
---
drivers/acpi/pptt.c | 38 ++++++++++++++++++++++++++++++++++++++
include/linux/acpi.h | 4 ++++
2 files changed, 42 insertions(+)
diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c
index 750295c486b7..f0aa0b4d721a 100644
--- a/drivers/acpi/pptt.c
+++ b/drivers/acpi/pptt.c
@@ -280,6 +280,44 @@ static struct acpi_pptt_processor *acpi_find_processor_node(struct
acpi_table_he
return NULL;
}
+/**
+ * acpi_validate_cache_node() - Given an offset in the table, check this is
+ * a cache node.
+ * Used for cross-table pointers.
+ *
+ * Return the cache pointer for a valid cache, or NULL.
+ */
+struct acpi_pptt_cache *
+acpi_pptt_validate_cache_node(struct acpi_table_header *table_hdr, u32 offset)
+{
+ struct acpi_subtable_header *entry, *cache;
+ unsigned long table_end;
+
+ if ((offset < sizeof(*table_hdr)) || (offset >= table_hdr->length))
+ return NULL;
+
+ table_end = (unsigned long)table_hdr + table_hdr->length;
+ entry = ACPI_ADD_PTR(struct acpi_subtable_header, table_hdr,
+ sizeof(struct acpi_table_pptt));
+
+ cache = ACPI_ADD_PTR(struct acpi_subtable_header, table_hdr, offset);
+
+ /* Walk every node to check offset is on a node boundary */
+ while ((unsigned long)(entry + 1) < table_end) {
+ if (entry->length == 0) {
+ pr_err("Invalid zero length subtable\n");
+ break;
+ }
+ if ((entry->type == ACPI_PPTT_TYPE_CACHE) && (entry == cache))
+ return (struct acpi_pptt_cache *)entry;
+
+ entry = ACPI_ADD_PTR(struct acpi_subtable_header, entry,
+ entry->length);
+ }
+
+ return NULL;
+}
+
static int acpi_find_cache_levels(struct acpi_table_header *table_hdr,
u32 acpi_cpu_id)
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 2ed8bbe56bf4..63fb5bcb1a65 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -664,6 +664,10 @@ static inline u64 acpi_arch_get_root_pointer(void)
}
#endif
+struct acpi_pptt_cache *
+acpi_pptt_validate_cache_node(struct acpi_table_header *table_hdr,
+ u32 offset);
+
#else /* !CONFIG_ACPI */
#define acpi_disabled 1
--
2.31.0