From b265154139b59295f7f2138459606e797a12d9f5 Mon Sep 17 00:00:00 2001 From: Oliver O'Halloran Date: Thu, 9 Mar 2017 13:28:41 +1100 Subject: [PATCH] hdata/cpu: account for p9 shared caches On P9 the L2 and L3 caches are shared between pairs of SMT=4 cores. Currently this is not accounted for when creating caches nodes in the device tree. This patch adds additional checking so that a cache node is only created for the first core in the pair and the second core will reference the cache correctly. Signed-off-by: Oliver O'Halloran Acked-by: Balbir Singh Signed-off-by: Stewart Smith --- hdata/cpu-common.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/hdata/cpu-common.c b/hdata/cpu-common.c index 50c6adc766c0..9a05227f5ab9 100644 --- a/hdata/cpu-common.c +++ b/hdata/cpu-common.c @@ -313,24 +313,45 @@ static struct dt_node *l2_cache_node(struct dt_node *cpus, return node; } +static struct dt_node *find_l2_node(struct dt_node *cpus, u32 unit_addr) +{ + char name[32]; + + snprintf(name, sizeof(name), "l2-cache@%.08x", unit_addr); + return dt_find_by_name(cpus, name); +} + uint32_t add_core_cache_info(struct dt_node *cpus, const struct sppcia_cpu_cache *cache, - uint32_t int_server, int okay) + uint32_t core_pir, int okay) { struct dt_node *l2_node, *l3_node, *l35_node; uint32_t unit_addr; - /* Use Processor Interrupt Line to genarate cache unit address */ - unit_addr = 0x20 << 24 | int_server; + /* + * On P9 the L2 is shared by pairs of SMT=4 cores. We only want + * to create a cache node for the first of these so we mask off + * the low PIR bits to get the unit address of the shared cache. + */ + if (proc_gen == proc_gen_p9) { + core_pir &= ~0x7; + + l2_node = find_l2_node(cpus, 0x20 << 24 | core_pir); + if (l2_node) + return l2_node->phandle; + } + + unit_addr = 0x20 << 24 | core_pir; l2_node = l2_cache_node(cpus, cache, unit_addr, okay); - unit_addr = 0x30 << 24 | int_server; + unit_addr = 0x30 << 24 | core_pir; l3_node = l3_cache_node(cpus, cache, unit_addr, okay); + /* Represents the next level of cache in the memory hierarchy */ dt_add_property_cells(l2_node, "l2-cache", l3_node->phandle); if (be32_to_cpu(cache->l35_dcache_size_kb)) { - unit_addr = 0x35 << 24 | int_server; + unit_addr = 0x35 << 24 | core_pir; l35_node = l35_cache_node(cpus, cache, unit_addr, okay); dt_add_property_cells(l3_node, "l2-cache", l35_node->phandle); }