hdata/cpu: account for p9 shared caches

Submitted by Oliver O'Halloran on March 9, 2017, 2:28 a.m.

Details

Message ID 20170309022841.32295-1-oohall@gmail.com
State Accepted
Headers show

Commit Message

Oliver O'Halloran March 9, 2017, 2:28 a.m.
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 <oohall@gmail.com>
---
 hdata/cpu-common.c | 31 ++++++++++++++++++++++++++-----
 1 file changed, 26 insertions(+), 5 deletions(-)

Comments

Balbir Singh March 9, 2017, 2:27 p.m.
On Thu, 2017-03-09 at 13:28 +1100, Oliver O'Halloran wrote:
> 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.
>

I also wonder if we should start calling these "next-level-cache"?

Acked-by: Balbir Singh <bsingharora@gmail.com>
Stewart Smith March 31, 2017, 7:01 a.m.
Oliver O'Halloran <oohall@gmail.com> writes:
> 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 <oohall@gmail.com>

Merged to master as of b265154139b59295f7f2138459606e797a12d9f5

Patch hide | download patch | download mbox

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);
 	}