* [PATCH 0/4] ACPI / PPTT: Add helpers to fill cpumask from PPTT
@ 2025-06-12 17:13 James Morse
2025-06-12 17:13 ` [PATCH 1/4] ACPI / PPTT: Add a helper to fill a cpumask from a processor container James Morse
` (3 more replies)
0 siblings, 4 replies; 14+ messages in thread
From: James Morse @ 2025-06-12 17:13 UTC (permalink / raw)
To: linux-acpi
Cc: Rafael Wysocki, Len Brown, sudeep.holla, jeremy.linton,
James Morse
This series adds a few helper functions that are needed by the MPAM
driver. The MPAM ACPI tables identifies the caches that MPAM can control
by cache-id. The properties of the cache, such as the CPUs it is
associated with are then found in the PPTT.
Cacheinfo has most of this information, but only once a CPU has come
online. Cacheinfo has to be this way because while the cache properties
are fixed on arm64, they are not fixed for other architectures. (I think
its PowerPC where this stuff can change for offline CPUs)
This is unfortunate as it means MPAM can't be used predictably
on platforms where CPUs are brought online late by user-space.
Adding these PPTT helpers solves this.
This series is based on v6.16-rc1, and can be retrieved from:
https://git.kernel.org/pub/scm/linux/kernel/git/morse/linux.git/ mpam/pptt/v1
The MPAM driver that makes use of these can be found here:
https://git.kernel.org/pub/scm/linux/kernel/git/morse/linux.git mpam/snapshot/v6.16-rc1
What is MPAM? Set your time-machine to 2020:
https://lore.kernel.org/lkml/20201030161120.227225-1-james.morse@arm.com/
If you prefer, I can glom these onto the beginning of the MPAM driver
series - but in its worst case, that is an ~80 patch series. (and who
wants that!)
Bugs welcome,
Thanks,
James
James Morse (4):
ACPI / PPTT: Add a helper to fill a cpumask from a processor container
ACPI / PPTT: Stop acpi_count_levels() expecting callers to clear
levels
ACPI / PPTT: Find cache level by cache-id
ACPI / PPTT: Add a helper to fill a cpumask from a cache_id
drivers/acpi/pptt.c | 238 ++++++++++++++++++++++++++++++++++++++++++-
include/linux/acpi.h | 17 ++++
2 files changed, 254 insertions(+), 1 deletion(-)
--
2.39.5
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 1/4] ACPI / PPTT: Add a helper to fill a cpumask from a processor container
2025-06-12 17:13 [PATCH 0/4] ACPI / PPTT: Add helpers to fill cpumask from PPTT James Morse
@ 2025-06-12 17:13 ` James Morse
2025-06-23 13:08 ` Sudeep Holla
` (2 more replies)
2025-06-12 17:13 ` [PATCH 2/4] ACPI / PPTT: Stop acpi_count_levels() expecting callers to clear levels James Morse
` (2 subsequent siblings)
3 siblings, 3 replies; 14+ messages in thread
From: James Morse @ 2025-06-12 17:13 UTC (permalink / raw)
To: linux-acpi
Cc: Rafael Wysocki, Len Brown, sudeep.holla, jeremy.linton,
James Morse
The PPTT describes CPUs and caches, as well as processor containers.
The ACPI table for MPAM describes the set of CPUs that can access an MSC
with the UID of a processor container.
Add a helper to find the processor container by its id, then walk
the possible CPUs to fill a cpumask with the CPUs that have this
processor container as a parent.
Signed-off-by: James Morse <james.morse@arm.com>
---
drivers/acpi/pptt.c | 91 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/acpi.h | 6 +++
2 files changed, 97 insertions(+)
diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c
index 54676e3d82dd..aaf9b5a26d07 100644
--- a/drivers/acpi/pptt.c
+++ b/drivers/acpi/pptt.c
@@ -298,6 +298,97 @@ static struct acpi_pptt_processor *acpi_find_processor_node(struct acpi_table_he
return NULL;
}
+/**
+ * acpi_pptt_get_child_cpus() - Find all the CPUs below a PPTT processor node
+ * @table_hdr: A reference to the PPTT table.
+ * @parent_node: A pointer to the processor node in the @table_hdr.
+ * @cpus: A cpumask to fill with the CPUs below @parent_node.
+ *
+ * Walks up the PPTT from every possible CPU to find if the provided
+ * @parent_node is a parent of this CPU.
+ */
+static void acpi_pptt_get_child_cpus(struct acpi_table_header *table_hdr,
+ struct acpi_pptt_processor *parent_node,
+ cpumask_t *cpus)
+{
+ struct acpi_pptt_processor *cpu_node;
+ u32 acpi_id;
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ acpi_id = get_acpi_id_for_cpu(cpu);
+ cpu_node = acpi_find_processor_node(table_hdr, acpi_id);
+
+ while (cpu_node) {
+ if (cpu_node == parent_node) {
+ cpumask_set_cpu(cpu, cpus);
+ break;
+ }
+ cpu_node = fetch_pptt_node(table_hdr, cpu_node->parent);
+ }
+ }
+}
+
+/**
+ * acpi_pptt_get_cpus_from_container() - Populate a cpumask with all CPUs in a
+ * processor containers
+ * @acpi_cpu_id: The UID of the processor container.
+ * @cpus The resulting CPU mask.
+ *
+ * Find the specified Processor Container, and fill @cpus with all the cpus
+ * below it.
+ *
+ * Not all 'Processor' entries in the PPTT are either a CPU or a Processor
+ * Container, they may exist purely to describe a Private resource. CPUs
+ * have to be leaves, so a Processor Container is a non-leaf that has the
+ * 'ACPI Processor ID valid' flag set.
+ *
+ * Return: 0 for a complete walk, or an error if the mask is incomplete.
+ */
+int acpi_pptt_get_cpus_from_container(u32 acpi_cpu_id, cpumask_t *cpus)
+{
+ struct acpi_pptt_processor *cpu_node;
+ struct acpi_table_header *table_hdr;
+ struct acpi_subtable_header *entry;
+ bool leaf_flag, has_leaf_flag = false;
+ unsigned long table_end;
+ acpi_status status;
+ u32 proc_sz;
+ int ret = 0;
+
+ cpumask_clear(cpus);
+
+ status = acpi_get_table(ACPI_SIG_PPTT, 0, &table_hdr);
+ if (ACPI_FAILURE(status))
+ return 0;
+
+ if (table_hdr->revision > 1)
+ has_leaf_flag = true;
+
+ table_end = (unsigned long)table_hdr + table_hdr->length;
+ entry = ACPI_ADD_PTR(struct acpi_subtable_header, table_hdr,
+ sizeof(struct acpi_table_pptt));
+ proc_sz = sizeof(struct acpi_pptt_processor);
+ while ((unsigned long)entry + proc_sz < table_end) {
+ cpu_node = (struct acpi_pptt_processor *)entry;
+ if (entry->type == ACPI_PPTT_TYPE_PROCESSOR &&
+ cpu_node->flags & ACPI_PPTT_ACPI_PROCESSOR_ID_VALID) {
+ leaf_flag = cpu_node->flags & ACPI_PPTT_ACPI_LEAF_NODE;
+ if ((has_leaf_flag && !leaf_flag) ||
+ (!has_leaf_flag && !acpi_pptt_leaf_node(table_hdr, cpu_node))) {
+ if (cpu_node->acpi_processor_id == acpi_cpu_id)
+ acpi_pptt_get_child_cpus(table_hdr, cpu_node, cpus);
+ }
+ }
+ entry = ACPI_ADD_PTR(struct acpi_subtable_header, entry,
+ entry->length);
+ }
+
+ acpi_put_table(table_hdr);
+
+ return ret;
+}
+
static u8 acpi_cache_type(enum cache_type type)
{
switch (type) {
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index f102c0fe3431..8c3165c2b083 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -1541,6 +1541,7 @@ int find_acpi_cpu_topology(unsigned int cpu, int level);
int find_acpi_cpu_topology_cluster(unsigned int cpu);
int find_acpi_cpu_topology_package(unsigned int cpu);
int find_acpi_cpu_topology_hetero_id(unsigned int cpu);
+int acpi_pptt_get_cpus_from_container(u32 acpi_cpu_id, cpumask_t *cpus);
#else
static inline int acpi_pptt_cpu_is_thread(unsigned int cpu)
{
@@ -1562,6 +1563,11 @@ static inline int find_acpi_cpu_topology_hetero_id(unsigned int cpu)
{
return -EINVAL;
}
+static inline int acpi_pptt_get_cpus_from_container(u32 acpi_cpu_id,
+ cpumask_t *cpus)
+{
+ return -EINVAL;
+}
#endif
void acpi_arch_init(void);
--
2.39.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 2/4] ACPI / PPTT: Stop acpi_count_levels() expecting callers to clear levels
2025-06-12 17:13 [PATCH 0/4] ACPI / PPTT: Add helpers to fill cpumask from PPTT James Morse
2025-06-12 17:13 ` [PATCH 1/4] ACPI / PPTT: Add a helper to fill a cpumask from a processor container James Morse
@ 2025-06-12 17:13 ` James Morse
2025-06-23 13:10 ` Sudeep Holla
2025-06-12 17:13 ` [PATCH 3/4] ACPI / PPTT: Find cache level by cache-id James Morse
2025-06-12 17:13 ` [PATCH 4/4] ACPI / PPTT: Add a helper to fill a cpumask from a cache_id James Morse
3 siblings, 1 reply; 14+ messages in thread
From: James Morse @ 2025-06-12 17:13 UTC (permalink / raw)
To: linux-acpi
Cc: Rafael Wysocki, Len Brown, sudeep.holla, jeremy.linton,
James Morse
acpi_count_levels() passes the number of levels back via a pointer argument.
It also passes this to acpi_find_cache_level() as the starting_level, and
preserves this value as it walks up the cpu_node tree counting the levels.
The only caller acpi_get_cache_info() happens to have already initialised
levels to zero, which acpi_count_levels() depends on to get the correct
result.
Explicitly zero the levels variable, so the count always starts at zero.
This saves any additional callers having to work out they need to do this.
Signed-off-by: James Morse <james.morse@arm.com>
---
drivers/acpi/pptt.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c
index aaf9b5a26d07..72e6bfc1e358 100644
--- a/drivers/acpi/pptt.c
+++ b/drivers/acpi/pptt.c
@@ -183,7 +183,7 @@ acpi_find_cache_level(struct acpi_table_header *table_hdr,
* @cpu_node: processor node we wish to count caches for
* @levels: Number of levels if success.
* @split_levels: Number of split cache levels (data/instruction) if
- * success. Can by NULL.
+ * success. Can be NULL.
*
* Given a processor node containing a processing unit, walk into it and count
* how many levels exist solely for it, and then walk up each level until we hit
@@ -196,6 +196,8 @@ static void acpi_count_levels(struct acpi_table_header *table_hdr,
struct acpi_pptt_processor *cpu_node,
unsigned int *levels, unsigned int *split_levels)
{
+ *levels = 0;
+
do {
acpi_find_cache_level(table_hdr, cpu_node, levels, split_levels, 0, 0);
cpu_node = fetch_pptt_node(table_hdr, cpu_node->parent);
--
2.39.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 3/4] ACPI / PPTT: Find cache level by cache-id
2025-06-12 17:13 [PATCH 0/4] ACPI / PPTT: Add helpers to fill cpumask from PPTT James Morse
2025-06-12 17:13 ` [PATCH 1/4] ACPI / PPTT: Add a helper to fill a cpumask from a processor container James Morse
2025-06-12 17:13 ` [PATCH 2/4] ACPI / PPTT: Stop acpi_count_levels() expecting callers to clear levels James Morse
@ 2025-06-12 17:13 ` James Morse
2025-06-23 13:21 ` Sudeep Holla
2025-06-12 17:13 ` [PATCH 4/4] ACPI / PPTT: Add a helper to fill a cpumask from a cache_id James Morse
3 siblings, 1 reply; 14+ messages in thread
From: James Morse @ 2025-06-12 17:13 UTC (permalink / raw)
To: linux-acpi
Cc: Rafael Wysocki, Len Brown, sudeep.holla, jeremy.linton,
James Morse
The MPAM table identifies caches by id. The MPAM driver also wants to know
the cache level to determine if the platform is of the shape that can be
managed via resctrl. Cacheinfo has this information, but only for CPUs that
are online.
Waiting for all CPUs to come online is a problem for platforms where
CPUs are brought online late by user-space.
Add a helper that walks every possible cache, until it finds the one
identified by cache-id, then return the level.
acpi_count_levels() expects its levels parameter to be initialised to
zero as it passes it to acpi_find_cache_level() as starting_level.
The existing callers do this. Document it.
Signed-off-by: James Morse <james.morse@arm.com>
---
drivers/acpi/pptt.c | 73 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/acpi.h | 5 +++
2 files changed, 78 insertions(+)
diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c
index 72e6bfc1e358..09be7d52d7ac 100644
--- a/drivers/acpi/pptt.c
+++ b/drivers/acpi/pptt.c
@@ -910,3 +910,76 @@ int find_acpi_cpu_topology_hetero_id(unsigned int cpu)
return find_acpi_cpu_topology_tag(cpu, PPTT_ABORT_PACKAGE,
ACPI_PPTT_ACPI_IDENTICAL);
}
+
+/**
+ * find_acpi_cache_level_from_id() - Get the level of the specified cache
+ * @cache_id: The id field of the unified cache
+ *
+ * Determine the level relative to any CPU for the unified cache identified by
+ * cache_id. This allows the property to be found even if the CPUs are offline.
+ *
+ * The returned level can be used to group unified caches that are peers.
+ *
+ * The PPTT table must be rev 3 or later,
+ *
+ * If one CPUs L2 is shared with another as L3, this function will return
+ * an unpredictable value.
+ *
+ * Return: -ENOENT if the PPTT doesn't exist, or the cache cannot be found.
+ * Otherwise returns a value which represents the level of the specified cache.
+ */
+int find_acpi_cache_level_from_id(u32 cache_id)
+{
+ u32 acpi_cpu_id;
+ acpi_status status;
+ int level, cpu, num_levels;
+ struct acpi_pptt_cache *cache;
+ struct acpi_table_header *table;
+ struct acpi_pptt_cache_v1 *cache_v1;
+ struct acpi_pptt_processor *cpu_node;
+
+ status = acpi_get_table(ACPI_SIG_PPTT, 0, &table);
+ if (ACPI_FAILURE(status)) {
+ acpi_pptt_warn_missing();
+ return -ENOENT;
+ }
+
+ if (table->revision < 3) {
+ acpi_put_table(table);
+ return -ENOENT;
+ }
+
+ /*
+ * If we found the cache first, we'd still need to walk from each CPU
+ * to find the level...
+ */
+ for_each_possible_cpu(cpu) {
+ acpi_cpu_id = get_acpi_id_for_cpu(cpu);
+ cpu_node = acpi_find_processor_node(table, acpi_cpu_id);
+ if (!cpu_node)
+ break;
+ acpi_count_levels(table, cpu_node, &num_levels, NULL);
+
+ /* Start at 1 for L1 */
+ for (level = 1; level <= num_levels; level++) {
+ cache = acpi_find_cache_node(table, acpi_cpu_id,
+ ACPI_PPTT_CACHE_TYPE_UNIFIED,
+ level, &cpu_node);
+ if (!cache)
+ continue;
+
+ cache_v1 = ACPI_ADD_PTR(struct acpi_pptt_cache_v1,
+ cache,
+ sizeof(struct acpi_pptt_cache));
+
+ if (cache->flags & ACPI_PPTT_CACHE_ID_VALID &&
+ cache_v1->cache_id == cache_id) {
+ acpi_put_table(table);
+ return level;
+ }
+ }
+ }
+
+ acpi_put_table(table);
+ return -ENOENT;
+}
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 8c3165c2b083..82947f6d2a43 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -1542,6 +1542,7 @@ int find_acpi_cpu_topology_cluster(unsigned int cpu);
int find_acpi_cpu_topology_package(unsigned int cpu);
int find_acpi_cpu_topology_hetero_id(unsigned int cpu);
int acpi_pptt_get_cpus_from_container(u32 acpi_cpu_id, cpumask_t *cpus);
+int find_acpi_cache_level_from_id(u32 cache_id);
#else
static inline int acpi_pptt_cpu_is_thread(unsigned int cpu)
{
@@ -1568,6 +1569,10 @@ static inline int acpi_pptt_get_cpus_from_container(u32 acpi_cpu_id,
{
return -EINVAL;
}
+static inline int find_acpi_cache_level_from_id(u32 cache_id)
+{
+ return -EINVAL;
+}
#endif
void acpi_arch_init(void);
--
2.39.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 4/4] ACPI / PPTT: Add a helper to fill a cpumask from a cache_id
2025-06-12 17:13 [PATCH 0/4] ACPI / PPTT: Add helpers to fill cpumask from PPTT James Morse
` (2 preceding siblings ...)
2025-06-12 17:13 ` [PATCH 3/4] ACPI / PPTT: Find cache level by cache-id James Morse
@ 2025-06-12 17:13 ` James Morse
2025-06-23 13:22 ` Sudeep Holla
3 siblings, 1 reply; 14+ messages in thread
From: James Morse @ 2025-06-12 17:13 UTC (permalink / raw)
To: linux-acpi
Cc: Rafael Wysocki, Len Brown, sudeep.holla, jeremy.linton,
James Morse, Rohit Mathew
MPAM identifies CPUs by the cache_id in the PPTT cache structure.
The driver needs to know which CPUs are associated with the cache,
the CPUs may not all be online, so cacheinfo does not have the
information.
Add a helper to pull this information out of the PPTT.
CC: Rohit Mathew <Rohit.Mathew@arm.com>
Signed-off-by: James Morse <james.morse@arm.com>
---
drivers/acpi/pptt.c | 70 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/acpi.h | 6 ++++
2 files changed, 76 insertions(+)
diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c
index 09be7d52d7ac..0ecb9378787a 100644
--- a/drivers/acpi/pptt.c
+++ b/drivers/acpi/pptt.c
@@ -983,3 +983,73 @@ int find_acpi_cache_level_from_id(u32 cache_id)
acpi_put_table(table);
return -ENOENT;
}
+
+/**
+ * acpi_pptt_get_cpumask_from_cache_id() - Get the cpus associated with the
+ * specified cache
+ * @cache_id: The id field of the unified cache
+ * @cpus: Where to build the cpumask
+ *
+ * Determine which CPUs are below this cache in the PPTT. This allows the property
+ * to be found even if the CPUs are offline.
+ *
+ * The PPTT table must be rev 3 or later,
+ *
+ * Return: -ENOENT if the PPTT doesn't exist, or the cache cannot be found.
+ * Otherwise returns 0 and sets the cpus in the provided cpumask.
+ */
+int acpi_pptt_get_cpumask_from_cache_id(u32 cache_id, cpumask_t *cpus)
+{
+ u32 acpi_cpu_id;
+ acpi_status status;
+ int level, cpu, num_levels;
+ struct acpi_pptt_cache *cache;
+ struct acpi_table_header *table;
+ struct acpi_pptt_cache_v1 *cache_v1;
+ struct acpi_pptt_processor *cpu_node;
+
+ cpumask_clear(cpus);
+
+ status = acpi_get_table(ACPI_SIG_PPTT, 0, &table);
+ if (ACPI_FAILURE(status)) {
+ acpi_pptt_warn_missing();
+ return -ENOENT;
+ }
+
+ if (table->revision < 3) {
+ acpi_put_table(table);
+ return -ENOENT;
+ }
+
+ /*
+ * If we found the cache first, we'd still need to walk from each cpu.
+ */
+ for_each_possible_cpu(cpu) {
+ acpi_cpu_id = get_acpi_id_for_cpu(cpu);
+ cpu_node = acpi_find_processor_node(table, acpi_cpu_id);
+ if (!cpu_node)
+ break;
+ acpi_count_levels(table, cpu_node, &num_levels, NULL);
+
+ /* Start at 1 for L1 */
+ for (level = 1; level <= num_levels; level++) {
+ cache = acpi_find_cache_node(table, acpi_cpu_id,
+ ACPI_PPTT_CACHE_TYPE_UNIFIED,
+ level, &cpu_node);
+ if (!cache)
+ continue;
+
+ cache_v1 = ACPI_ADD_PTR(struct acpi_pptt_cache_v1,
+ cache,
+ sizeof(struct acpi_pptt_cache));
+
+ if (cache->flags & ACPI_PPTT_CACHE_ID_VALID &&
+ cache_v1->cache_id == cache_id) {
+ cpumask_set_cpu(cpu, cpus);
+ }
+ }
+ }
+
+ acpi_put_table(table);
+ return 0;
+}
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 82947f6d2a43..61ac3d1de1e8 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -1543,6 +1543,7 @@ int find_acpi_cpu_topology_package(unsigned int cpu);
int find_acpi_cpu_topology_hetero_id(unsigned int cpu);
int acpi_pptt_get_cpus_from_container(u32 acpi_cpu_id, cpumask_t *cpus);
int find_acpi_cache_level_from_id(u32 cache_id);
+int acpi_pptt_get_cpumask_from_cache_id(u32 cache_id, cpumask_t *cpus);
#else
static inline int acpi_pptt_cpu_is_thread(unsigned int cpu)
{
@@ -1573,6 +1574,11 @@ static inline int find_acpi_cache_level_from_id(u32 cache_id)
{
return -EINVAL;
}
+static inline int acpi_pptt_get_cpumask_from_cache_id(u32 cache_id,
+ cpumask_t *cpus)
+{
+ return -EINVAL;
+}
#endif
void acpi_arch_init(void);
--
2.39.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 1/4] ACPI / PPTT: Add a helper to fill a cpumask from a processor container
2025-06-12 17:13 ` [PATCH 1/4] ACPI / PPTT: Add a helper to fill a cpumask from a processor container James Morse
@ 2025-06-23 13:08 ` Sudeep Holla
2025-06-26 17:14 ` James Morse
2025-06-23 13:21 ` Sudeep Holla
2025-06-26 17:10 ` James Morse
2 siblings, 1 reply; 14+ messages in thread
From: Sudeep Holla @ 2025-06-23 13:08 UTC (permalink / raw)
To: James Morse; +Cc: linux-acpi, Rafael Wysocki, Len Brown, jeremy.linton
On Thu, Jun 12, 2025 at 05:13:33PM +0000, James Morse wrote:
> The PPTT describes CPUs and caches, as well as processor containers.
> The ACPI table for MPAM describes the set of CPUs that can access an MSC
> with the UID of a processor container.
>
> Add a helper to find the processor container by its id, then walk
> the possible CPUs to fill a cpumask with the CPUs that have this
> processor container as a parent.
>
> Signed-off-by: James Morse <james.morse@arm.com>
> ---
> drivers/acpi/pptt.c | 91 ++++++++++++++++++++++++++++++++++++++++++++
> include/linux/acpi.h | 6 +++
> 2 files changed, 97 insertions(+)
>
> diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c
> index 54676e3d82dd..aaf9b5a26d07 100644
> --- a/drivers/acpi/pptt.c
> +++ b/drivers/acpi/pptt.c
> @@ -298,6 +298,97 @@ static struct acpi_pptt_processor *acpi_find_processor_node(struct acpi_table_he
> return NULL;
> }
>
> +/**
> + * acpi_pptt_get_child_cpus() - Find all the CPUs below a PPTT processor node
> + * @table_hdr: A reference to the PPTT table.
> + * @parent_node: A pointer to the processor node in the @table_hdr.
> + * @cpus: A cpumask to fill with the CPUs below @parent_node.
> + *
Is this cpus mask always cleared before acpi_pptt_get_child_cpus() is called.
Just checking if it makes sense to clear it before we start the loop in this
function or do we have a need to start with a pre-filled cpumask ?
Other than that, LGTM.
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
--
Regards,
Sudeep
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/4] ACPI / PPTT: Stop acpi_count_levels() expecting callers to clear levels
2025-06-12 17:13 ` [PATCH 2/4] ACPI / PPTT: Stop acpi_count_levels() expecting callers to clear levels James Morse
@ 2025-06-23 13:10 ` Sudeep Holla
2025-06-26 17:11 ` James Morse
0 siblings, 1 reply; 14+ messages in thread
From: Sudeep Holla @ 2025-06-23 13:10 UTC (permalink / raw)
To: James Morse; +Cc: linux-acpi, Rafael Wysocki, Len Brown, jeremy.linton
On Thu, Jun 12, 2025 at 05:13:34PM +0000, James Morse wrote:
> acpi_count_levels() passes the number of levels back via a pointer argument.
> It also passes this to acpi_find_cache_level() as the starting_level, and
> preserves this value as it walks up the cpu_node tree counting the levels.
>
> The only caller acpi_get_cache_info() happens to have already initialised
> levels to zero, which acpi_count_levels() depends on to get the correct
> result.
>
> Explicitly zero the levels variable, so the count always starts at zero.
> This saves any additional callers having to work out they need to do this.
>
> Signed-off-by: James Morse <james.morse@arm.com>
> ---
> drivers/acpi/pptt.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c
> index aaf9b5a26d07..72e6bfc1e358 100644
> --- a/drivers/acpi/pptt.c
> +++ b/drivers/acpi/pptt.c
> @@ -183,7 +183,7 @@ acpi_find_cache_level(struct acpi_table_header *table_hdr,
> * @cpu_node: processor node we wish to count caches for
> * @levels: Number of levels if success.
> * @split_levels: Number of split cache levels (data/instruction) if
> - * success. Can by NULL.
> + * success. Can be NULL.
> *
> * Given a processor node containing a processing unit, walk into it and count
> * how many levels exist solely for it, and then walk up each level until we hit
> @@ -196,6 +196,8 @@ static void acpi_count_levels(struct acpi_table_header *table_hdr,
> struct acpi_pptt_processor *cpu_node,
> unsigned int *levels, unsigned int *split_levels)
> {
> + *levels = 0;
> +
Does it make sense to drop similar reset to 0 in acpi_get_cache_info(), just
to be consistent across all callers of acpi_count_levels().
Otherwise, LGTM:
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
--
Regards,
Sudeep
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/4] ACPI / PPTT: Add a helper to fill a cpumask from a processor container
2025-06-12 17:13 ` [PATCH 1/4] ACPI / PPTT: Add a helper to fill a cpumask from a processor container James Morse
2025-06-23 13:08 ` Sudeep Holla
@ 2025-06-23 13:21 ` Sudeep Holla
2025-06-26 17:11 ` James Morse
2025-06-26 17:10 ` James Morse
2 siblings, 1 reply; 14+ messages in thread
From: Sudeep Holla @ 2025-06-23 13:21 UTC (permalink / raw)
To: James Morse
Cc: linux-acpi, Rafael Wysocki, Sudeep Holla, Len Brown,
jeremy.linton
On Thu, Jun 12, 2025 at 05:13:33PM +0000, James Morse wrote:
> The PPTT describes CPUs and caches, as well as processor containers.
> The ACPI table for MPAM describes the set of CPUs that can access an MSC
> with the UID of a processor container.
>
> Add a helper to find the processor container by its id, then walk
> the possible CPUs to fill a cpumask with the CPUs that have this
> processor container as a parent.
>
> Signed-off-by: James Morse <james.morse@arm.com>
> ---
> drivers/acpi/pptt.c | 91 ++++++++++++++++++++++++++++++++++++++++++++
> include/linux/acpi.h | 6 +++
> 2 files changed, 97 insertions(+)
>
> diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c
> index 54676e3d82dd..aaf9b5a26d07 100644
> --- a/drivers/acpi/pptt.c
> +++ b/drivers/acpi/pptt.c
> +
> +/**
> + * acpi_pptt_get_cpus_from_container() - Populate a cpumask with all CPUs in a
> + * processor containers
> + * @acpi_cpu_id: The UID of the processor container.
> + * @cpus The resulting CPU mask.
> + *
> + * Find the specified Processor Container, and fill @cpus with all the cpus
> + * below it.
> + *
> + * Not all 'Processor' entries in the PPTT are either a CPU or a Processor
> + * Container, they may exist purely to describe a Private resource. CPUs
> + * have to be leaves, so a Processor Container is a non-leaf that has the
> + * 'ACPI Processor ID valid' flag set.
> + *
> + * Return: 0 for a complete walk, or an error if the mask is incomplete.
> + */
> +int acpi_pptt_get_cpus_from_container(u32 acpi_cpu_id, cpumask_t *cpus)
> +{
Just noticed now that it is not used anywhere in the series. Can this be added
along with the user later instead ?
--
Regards,
Sudeep
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 3/4] ACPI / PPTT: Find cache level by cache-id
2025-06-12 17:13 ` [PATCH 3/4] ACPI / PPTT: Find cache level by cache-id James Morse
@ 2025-06-23 13:21 ` Sudeep Holla
0 siblings, 0 replies; 14+ messages in thread
From: Sudeep Holla @ 2025-06-23 13:21 UTC (permalink / raw)
To: James Morse; +Cc: linux-acpi, Rafael Wysocki, Len Brown, jeremy.linton
On Thu, Jun 12, 2025 at 05:13:35PM +0000, James Morse wrote:
> The MPAM table identifies caches by id. The MPAM driver also wants to know
> the cache level to determine if the platform is of the shape that can be
> managed via resctrl. Cacheinfo has this information, but only for CPUs that
> are online.
>
> Waiting for all CPUs to come online is a problem for platforms where
> CPUs are brought online late by user-space.
>
> Add a helper that walks every possible cache, until it finds the one
> identified by cache-id, then return the level.
>
> acpi_count_levels() expects its levels parameter to be initialised to
> zero as it passes it to acpi_find_cache_level() as starting_level.
> The existing callers do this. Document it.
>
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
--
Regards,
Sudeep
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 4/4] ACPI / PPTT: Add a helper to fill a cpumask from a cache_id
2025-06-12 17:13 ` [PATCH 4/4] ACPI / PPTT: Add a helper to fill a cpumask from a cache_id James Morse
@ 2025-06-23 13:22 ` Sudeep Holla
0 siblings, 0 replies; 14+ messages in thread
From: Sudeep Holla @ 2025-06-23 13:22 UTC (permalink / raw)
To: James Morse
Cc: linux-acpi, Rafael Wysocki, Len Brown, jeremy.linton,
Rohit Mathew
On Thu, Jun 12, 2025 at 05:13:36PM +0000, James Morse wrote:
> MPAM identifies CPUs by the cache_id in the PPTT cache structure.
>
> The driver needs to know which CPUs are associated with the cache,
> the CPUs may not all be online, so cacheinfo does not have the
> information.
>
> Add a helper to pull this information out of the PPTT.
>
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
--
Regards,
Sudeep
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/4] ACPI / PPTT: Add a helper to fill a cpumask from a processor container
2025-06-12 17:13 ` [PATCH 1/4] ACPI / PPTT: Add a helper to fill a cpumask from a processor container James Morse
2025-06-23 13:08 ` Sudeep Holla
2025-06-23 13:21 ` Sudeep Holla
@ 2025-06-26 17:10 ` James Morse
2 siblings, 0 replies; 14+ messages in thread
From: James Morse @ 2025-06-26 17:10 UTC (permalink / raw)
To: linux-acpi
Cc: Rafael Wysocki, Len Brown, sudeep.holla, jeremy.linton,
Dave P Martin
Hello!
(CC: +Dave Martin)
On 12/06/2025 18:13, James Morse wrote:
> The PPTT describes CPUs and caches, as well as processor containers.
> The ACPI table for MPAM describes the set of CPUs that can access an MSC
> with the UID of a processor container.
>
> Add a helper to find the processor container by its id, then walk
> the possible CPUs to fill a cpumask with the CPUs that have this
> processor container as a parent.
> diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c
> index 54676e3d82dd..aaf9b5a26d07 100644
> --- a/drivers/acpi/pptt.c
> +++ b/drivers/acpi/pptt.c
> @@ -298,6 +298,97 @@ static struct acpi_pptt_processor *acpi_find_processor_node(struct acpi_table_he
> +/**
> + * acpi_pptt_get_cpus_from_container() - Populate a cpumask with all CPUs in a
> + * processor containers
> + * @acpi_cpu_id: The UID of the processor container.
> + * @cpus The resulting CPU mask.
> + *
> + * Find the specified Processor Container, and fill @cpus with all the cpus
> + * below it.
> + *
> + * Not all 'Processor' entries in the PPTT are either a CPU or a Processor
> + * Container, they may exist purely to describe a Private resource. CPUs
> + * have to be leaves, so a Processor Container is a non-leaf that has the
> + * 'ACPI Processor ID valid' flag set.
> + *
> + * Return: 0 for a complete walk, or an error if the mask is incomplete.
> + */
> +int acpi_pptt_get_cpus_from_container(u32 acpi_cpu_id, cpumask_t *cpus)
> +{
> + struct acpi_pptt_processor *cpu_node;
> + struct acpi_table_header *table_hdr;
> + struct acpi_subtable_header *entry;
> + bool leaf_flag, has_leaf_flag = false;
> + unsigned long table_end;
> + acpi_status status;
> + u32 proc_sz;
> + int ret = 0;
> +
> + cpumask_clear(cpus);
> +
> + status = acpi_get_table(ACPI_SIG_PPTT, 0, &table_hdr);
> + if (ACPI_FAILURE(status))
> + return 0;
> +
> + if (table_hdr->revision > 1)
> + has_leaf_flag = true;
> +
> + table_end = (unsigned long)table_hdr + table_hdr->length;
> + entry = ACPI_ADD_PTR(struct acpi_subtable_header, table_hdr,
> + sizeof(struct acpi_table_pptt));
> + proc_sz = sizeof(struct acpi_pptt_processor);
> + while ((unsigned long)entry + proc_sz < table_end) {
Dave Martin picked out an off-by-one here - this pattern was copied from other functions,
then fixed while I was still lugging this around out of tree. Should be:
| while ((unsigned long)entry + proc_sz <= table_end) {
See adfab6b39202481bb43286fff94def4953793fdb.
I've fixed this locally.
> + cpu_node = (struct acpi_pptt_processor *)entry;
> + if (entry->type == ACPI_PPTT_TYPE_PROCESSOR &&
> + cpu_node->flags & ACPI_PPTT_ACPI_PROCESSOR_ID_VALID) {
> + leaf_flag = cpu_node->flags & ACPI_PPTT_ACPI_LEAF_NODE;
> + if ((has_leaf_flag && !leaf_flag) ||
> + (!has_leaf_flag && !acpi_pptt_leaf_node(table_hdr, cpu_node))) {
> + if (cpu_node->acpi_processor_id == acpi_cpu_id)
> + acpi_pptt_get_child_cpus(table_hdr, cpu_node, cpus);
> + }
> + }
> + entry = ACPI_ADD_PTR(struct acpi_subtable_header, entry,
> + entry->length);
> + }
> +
> + acpi_put_table(table_hdr);
> +
> + return ret;
> +}
Thanks,
James
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/4] ACPI / PPTT: Stop acpi_count_levels() expecting callers to clear levels
2025-06-23 13:10 ` Sudeep Holla
@ 2025-06-26 17:11 ` James Morse
0 siblings, 0 replies; 14+ messages in thread
From: James Morse @ 2025-06-26 17:11 UTC (permalink / raw)
To: Sudeep Holla; +Cc: linux-acpi, Rafael Wysocki, Len Brown, jeremy.linton
Hi Sudeep,
On 23/06/2025 14:10, Sudeep Holla wrote:
> On Thu, Jun 12, 2025 at 05:13:34PM +0000, James Morse wrote:
>> acpi_count_levels() passes the number of levels back via a pointer argument.
>> It also passes this to acpi_find_cache_level() as the starting_level, and
>> preserves this value as it walks up the cpu_node tree counting the levels.
>>
>> The only caller acpi_get_cache_info() happens to have already initialised
>> levels to zero, which acpi_count_levels() depends on to get the correct
>> result.
>>
>> Explicitly zero the levels variable, so the count always starts at zero.
>> This saves any additional callers having to work out they need to do this.
>> diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c
>> index aaf9b5a26d07..72e6bfc1e358 100644
>> --- a/drivers/acpi/pptt.c
>> +++ b/drivers/acpi/pptt.c
>> @@ -183,7 +183,7 @@ acpi_find_cache_level(struct acpi_table_header *table_hdr,
>> * @cpu_node: processor node we wish to count caches for
>> * @levels: Number of levels if success.
>> * @split_levels: Number of split cache levels (data/instruction) if
>> - * success. Can by NULL.
>> + * success. Can be NULL.
>> *
>> * Given a processor node containing a processing unit, walk into it and count
>> * how many levels exist solely for it, and then walk up each level until we hit
>> @@ -196,6 +196,8 @@ static void acpi_count_levels(struct acpi_table_header *table_hdr,
>> struct acpi_pptt_processor *cpu_node,
>> unsigned int *levels, unsigned int *split_levels)
>> {
>> + *levels = 0;
>> +
>
> Does it make sense to drop similar reset to 0 in acpi_get_cache_info(), just
> to be consistent across all callers of acpi_count_levels().
acpi_get_cache_info() does this because it can return early, it makes sense that it
already cleared the values it passes back.
> Otherwise, LGTM:
>
> Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
Thanks!
James
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/4] ACPI / PPTT: Add a helper to fill a cpumask from a processor container
2025-06-23 13:21 ` Sudeep Holla
@ 2025-06-26 17:11 ` James Morse
0 siblings, 0 replies; 14+ messages in thread
From: James Morse @ 2025-06-26 17:11 UTC (permalink / raw)
To: Sudeep Holla; +Cc: linux-acpi, Rafael Wysocki, Len Brown, jeremy.linton
Hi Sudeep,
On 23/06/2025 14:21, Sudeep Holla wrote:
> On Thu, Jun 12, 2025 at 05:13:33PM +0000, James Morse wrote:
>> The PPTT describes CPUs and caches, as well as processor containers.
>> The ACPI table for MPAM describes the set of CPUs that can access an MSC
>> with the UID of a processor container.
>>
>> Add a helper to find the processor container by its id, then walk
>> the possible CPUs to fill a cpumask with the CPUs that have this
>> processor container as a parent.
>> diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c
>> index 54676e3d82dd..aaf9b5a26d07 100644
>> --- a/drivers/acpi/pptt.c
>> +++ b/drivers/acpi/pptt.c
>> +
>> +/**
>> + * acpi_pptt_get_cpus_from_container() - Populate a cpumask with all CPUs in a
>> + * processor containers
>> + * @acpi_cpu_id: The UID of the processor container.
>> + * @cpus The resulting CPU mask.
>> + *
>> + * Find the specified Processor Container, and fill @cpus with all the cpus
>> + * below it.
>> + *
>> + * Not all 'Processor' entries in the PPTT are either a CPU or a Processor
>> + * Container, they may exist purely to describe a Private resource. CPUs
>> + * have to be leaves, so a Processor Container is a non-leaf that has the
>> + * 'ACPI Processor ID valid' flag set.
>> + *
>> + * Return: 0 for a complete walk, or an error if the mask is incomplete.
>> + */
>> +int acpi_pptt_get_cpus_from_container(u32 acpi_cpu_id, cpumask_t *cpus)
>> +{
> Just noticed now that it is not used anywhere in the series. Can this be added
> along with the user later instead ?
T'was mentioned in the cover letter - I'll roll these into the series with the driver -
which will unfortunately give you more email. There is another pre-requisite series, which
made posting it like this was going to be easier for reviewers.
Do you have an opinion on how this should get merged?
The MPAM driver may need to go via tip if it has dependencies on resctrl, but also arm64
because it touches the arch code's __cpu_switch_to() path. Adding acpi and potentially
Greg's tree for cacheinfo makes this more complicated. I will probably defer the restrl
parts of the MPAM driver to remove one of these.
Thanks,
James
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/4] ACPI / PPTT: Add a helper to fill a cpumask from a processor container
2025-06-23 13:08 ` Sudeep Holla
@ 2025-06-26 17:14 ` James Morse
0 siblings, 0 replies; 14+ messages in thread
From: James Morse @ 2025-06-26 17:14 UTC (permalink / raw)
To: Sudeep Holla; +Cc: linux-acpi, Rafael Wysocki, Len Brown, jeremy.linton
Hi Sudeep,
On 23/06/2025 14:08, Sudeep Holla wrote:
> On Thu, Jun 12, 2025 at 05:13:33PM +0000, James Morse wrote:
>> The PPTT describes CPUs and caches, as well as processor containers.
>> The ACPI table for MPAM describes the set of CPUs that can access an MSC
>> with the UID of a processor container.
>>
>> Add a helper to find the processor container by its id, then walk
>> the possible CPUs to fill a cpumask with the CPUs that have this
>> processor container as a parent.
>> diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c
>> index 54676e3d82dd..aaf9b5a26d07 100644
>> --- a/drivers/acpi/pptt.c
>> +++ b/drivers/acpi/pptt.c
>> @@ -298,6 +298,97 @@ static struct acpi_pptt_processor *acpi_find_processor_node(struct acpi_table_he
>> return NULL;
>> }
>>
>> +/**
>> + * acpi_pptt_get_child_cpus() - Find all the CPUs below a PPTT processor node
>> + * @table_hdr: A reference to the PPTT table.
>> + * @parent_node: A pointer to the processor node in the @table_hdr.
>> + * @cpus: A cpumask to fill with the CPUs below @parent_node.
>> + *
> Is this cpus mask always cleared before acpi_pptt_get_child_cpus() is called.
> Just checking if it makes sense to clear it before we start the loop in this
> function or do we have a need to start with a pre-filled cpumask ?
It's only got one caller, which does the cpumask_clear() - but I've been bitten by this,
so getting them both to do it would be least surprising.
> Other than that, LGTM.
>
> Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
Thanks!
James
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2025-06-26 17:14 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-12 17:13 [PATCH 0/4] ACPI / PPTT: Add helpers to fill cpumask from PPTT James Morse
2025-06-12 17:13 ` [PATCH 1/4] ACPI / PPTT: Add a helper to fill a cpumask from a processor container James Morse
2025-06-23 13:08 ` Sudeep Holla
2025-06-26 17:14 ` James Morse
2025-06-23 13:21 ` Sudeep Holla
2025-06-26 17:11 ` James Morse
2025-06-26 17:10 ` James Morse
2025-06-12 17:13 ` [PATCH 2/4] ACPI / PPTT: Stop acpi_count_levels() expecting callers to clear levels James Morse
2025-06-23 13:10 ` Sudeep Holla
2025-06-26 17:11 ` James Morse
2025-06-12 17:13 ` [PATCH 3/4] ACPI / PPTT: Find cache level by cache-id James Morse
2025-06-23 13:21 ` Sudeep Holla
2025-06-12 17:13 ` [PATCH 4/4] ACPI / PPTT: Add a helper to fill a cpumask from a cache_id James Morse
2025-06-23 13:22 ` Sudeep Holla
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox