[PATCH] powerpc/kernel: Fix L1D_SIZE to a non-zero value on missing cache nodes

Madhavan Srinivasan maddy at linux.vnet.ibm.com
Thu Jan 18 06:03:36 AEDT 2018


parse_cache_info() parse device tree to detect various [i/d] cache properties.
But if no cache nodes found in device tree, these properties are set to zero
as default in init_cache_info().

Having a zero value could cause a infinite loop in rfi_flush_callback() since
l1d_size is used to determine the lid_flush_set parameter which is used as
the upper bounce in L1D cache flush loop. So default the l1d_size to 64K if
it is zero.

Fixes: aa8a5e0062ac9 ('powerpc/64s: Add support for RFI flush of L1-D cache')
Signed-off-by: Madhavan Srinivasan <maddy at linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/setup.h |  2 ++
 arch/powerpc/kernel/setup_64.c   | 16 ++++++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h
index 469b7fdc9be4..12954bf2d3fe 100644
--- a/arch/powerpc/include/asm/setup.h
+++ b/arch/powerpc/include/asm/setup.h
@@ -41,6 +41,8 @@ static inline void pseries_little_endian_exceptions(void) {}
 
 void rfi_flush_enable(bool enable);
 
+#define DEFAULT_L1D_SIZE	(1024 * 64)
+
 /* These are bit flags */
 enum l1d_flush_type {
 	L1D_FLUSH_NONE		= 0x1,
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 491be4179ddd..7a3077a2cd5c 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -856,6 +856,22 @@ static void init_fallback_flush(void)
 	int cpu;
 
 	l1d_size = ppc64_caches.l1d.size;
+
+	/*
+	 * If there is no cache node in cpus/ device tree,
+	 * l1d_size could be zero. This in turn make l1d_flush_sets as
+	 * zero, which will be an issue in RFI_FLUSH_CALLBACK.
+	 *
+	 * RFI_FLUSH_CALLBACK use the l1d_flush_sets value as upper bounce
+	 * (loaded in CTR) and loop with a `bdnz` instruction. If the CTR
+	 * happen to zero, instruction (as per definition) will decrement
+	 * CTR first and then compare. So we end up in a really big
+	 * loop (becos of negative value in CTR). Avoid this by defaulting
+	 * to a sane value (64kb).
+	 */
+	if (!l1d_size)
+		l1d_size = DEFAULT_L1D_SIZE;
+
 	limit = min(safe_stack_limit(), ppc64_rma_size);
 
 	/*
-- 
2.7.4



More information about the Linuxppc-dev mailing list