Skip to content

Commit 6b585f4

Browse files
robherringgregkh
authored andcommitted
cacheinfo: Set cache 'id' based on DT data
Use the minimum CPU h/w id of the CPUs associated with the cache for the cache 'id'. This will provide a stable id value for a given system. As we need to check all possible CPUs, we can't use the shared_cpu_map which is just online CPUs. As there's not a cache to CPUs mapping in DT, we have to walk all CPU nodes and then walk cache levels. The cache_id exposed to user-space has historically been 32 bits, and is too late to change. This value is parsed into a u32 by user-space libraries such as libvirt: https://github.com/libvirt/libvirt/blob/master/src/util/virresctrl.c#L1588 Give up on assigning cache-id's if a CPU h/w id greater than 32 bits is found. match_cache_node() does not make use of the __free() cleanup helpers because of_find_next_cache_node(prev) does not drop a reference to prev, and its too easy to accidentally drop the reference on cpu, which belongs to for_each_of_cpu_node(). Cc: "Rafael J. Wysocki" <rafael@kernel.org> Signed-off-by: Rob Herring <robh@kernel.org> [ ben: converted to use the __free cleanup idiom ] Signed-off-by: Ben Horgan <ben.horgan@arm.com> [ morse: Add checks to give up if a value larger than 32 bits is seen. ] Signed-off-by: James Morse <james.morse@arm.com> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Reviewed-by: Gavin Shan <gshan@redhat.com> Link: https://lore.kernel.org/r/20250711182743.30141-2-james.morse@arm.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 35cff7a commit 6b585f4

1 file changed

Lines changed: 45 additions & 0 deletions

File tree

drivers/base/cacheinfo.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
99

1010
#include <linux/acpi.h>
11+
#include <linux/bitfield.h>
1112
#include <linux/bitops.h>
1213
#include <linux/cacheinfo.h>
1314
#include <linux/compiler.h>
@@ -183,6 +184,49 @@ static bool cache_node_is_unified(struct cacheinfo *this_leaf,
183184
return of_property_read_bool(np, "cache-unified");
184185
}
185186

187+
static bool match_cache_node(struct device_node *cpu,
188+
const struct device_node *cache_node)
189+
{
190+
struct device_node *prev, *cache = of_find_next_cache_node(cpu);
191+
192+
while (cache) {
193+
if (cache == cache_node) {
194+
of_node_put(cache);
195+
return true;
196+
}
197+
198+
prev = cache;
199+
cache = of_find_next_cache_node(cache);
200+
of_node_put(prev);
201+
}
202+
203+
return false;
204+
}
205+
206+
static void cache_of_set_id(struct cacheinfo *this_leaf,
207+
struct device_node *cache_node)
208+
{
209+
struct device_node *cpu;
210+
u32 min_id = ~0;
211+
212+
for_each_of_cpu_node(cpu) {
213+
u64 id = of_get_cpu_hwid(cpu, 0);
214+
215+
if (FIELD_GET(GENMASK_ULL(63, 32), id)) {
216+
of_node_put(cpu);
217+
return;
218+
}
219+
220+
if (match_cache_node(cpu, cache_node))
221+
min_id = min(min_id, id);
222+
}
223+
224+
if (min_id != ~0) {
225+
this_leaf->id = min_id;
226+
this_leaf->attributes |= CACHE_ID;
227+
}
228+
}
229+
186230
static void cache_of_set_props(struct cacheinfo *this_leaf,
187231
struct device_node *np)
188232
{
@@ -198,6 +242,7 @@ static void cache_of_set_props(struct cacheinfo *this_leaf,
198242
cache_get_line_size(this_leaf, np);
199243
cache_nr_sets(this_leaf, np);
200244
cache_associativity(this_leaf);
245+
cache_of_set_id(this_leaf, np);
201246
}
202247

203248
static int cache_setup_of_node(unsigned int cpu)

0 commit comments

Comments
 (0)