linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 01/10] powerpc: Move ARCH_DLINFO out of uapi
@ 2016-08-17  5:39 Benjamin Herrenschmidt
  2016-08-17  5:39 ` [RFC PATCH 02/10] powerpc: Move {d, i, u}cache_bsize definitions to a common place Benjamin Herrenschmidt
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Benjamin Herrenschmidt @ 2016-08-17  5:39 UTC (permalink / raw)
  To: linuxppc-dev

It's an kernel private macro, it doesn't belong there

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/elf.h      | 22 ++++++++++++++++++++++
 arch/powerpc/include/uapi/asm/elf.h | 23 -----------------------
 2 files changed, 22 insertions(+), 23 deletions(-)

diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h
index ee46ffe..730c27e 100644
--- a/arch/powerpc/include/asm/elf.h
+++ b/arch/powerpc/include/asm/elf.h
@@ -136,4 +136,26 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
 
 #endif /* CONFIG_SPU_BASE */
 
+/*
+ * The requirements here are:
+ * - keep the final alignment of sp (sp & 0xf)
+ * - make sure the 32-bit value at the first 16 byte aligned position of
+ *   AUXV is greater than 16 for glibc compatibility.
+ *   AT_IGNOREPPC is used for that.
+ * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
+ *   even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
+ * update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes
+ */
+#define ARCH_DLINFO							\
+do {									\
+	/* Handle glibc compatibility. */				\
+	NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);			\
+	NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);			\
+	/* Cache size items */						\
+	NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize);			\
+	NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize);			\
+	NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize);			\
+	VDSO_AUX_ENT(AT_SYSINFO_EHDR, current->mm->context.vdso_base);	\
+} while (0)
+
 #endif /* _ASM_POWERPC_ELF_H */
diff --git a/arch/powerpc/include/uapi/asm/elf.h b/arch/powerpc/include/uapi/asm/elf.h
index 3a9e44c..b2c6fdd 100644
--- a/arch/powerpc/include/uapi/asm/elf.h
+++ b/arch/powerpc/include/uapi/asm/elf.h
@@ -162,29 +162,6 @@ typedef elf_vrreg_t elf_vrregset_t32[ELF_NVRREG32];
 typedef elf_fpreg_t elf_vsrreghalf_t32[ELF_NVSRHALFREG];
 #endif
 
-
-/*
- * The requirements here are:
- * - keep the final alignment of sp (sp & 0xf)
- * - make sure the 32-bit value at the first 16 byte aligned position of
- *   AUXV is greater than 16 for glibc compatibility.
- *   AT_IGNOREPPC is used for that.
- * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
- *   even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
- * update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes
- */
-#define ARCH_DLINFO							\
-do {									\
-	/* Handle glibc compatibility. */				\
-	NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);			\
-	NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);			\
-	/* Cache size items */						\
-	NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize);			\
-	NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize);			\
-	NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize);			\
-	VDSO_AUX_ENT(AT_SYSINFO_EHDR, current->mm->context.vdso_base);	\
-} while (0)
-
 /* PowerPC64 relocations defined by the ABIs */
 #define R_PPC64_NONE    R_PPC_NONE
 #define R_PPC64_ADDR32  R_PPC_ADDR32  /* 32bit absolute address.  */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 02/10] powerpc: Move {d, i, u}cache_bsize definitions to a common place
  2016-08-17  5:39 [RFC PATCH 01/10] powerpc: Move ARCH_DLINFO out of uapi Benjamin Herrenschmidt
@ 2016-08-17  5:39 ` Benjamin Herrenschmidt
  2016-08-17  5:39 ` [RFC PATCH 03/10] powerpc: A new cache shape aux vectors Benjamin Herrenschmidt
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Benjamin Herrenschmidt @ 2016-08-17  5:39 UTC (permalink / raw)
  To: linuxppc-dev

The variables are defined twice in setup_32.c and setup_64.c, do it
once in setup-common.c instead

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/kernel/setup-common.c | 9 +++++++++
 arch/powerpc/kernel/setup_32.c     | 8 --------
 arch/powerpc/kernel/setup_64.c     | 8 --------
 3 files changed, 9 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index dba265c..e0eeed4 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -87,6 +87,15 @@ EXPORT_SYMBOL(machine_id);
 int boot_cpuid = -1;
 EXPORT_SYMBOL_GPL(boot_cpuid);
 
+/*
+ * These are used in binfmt_elf.c to put aux entries on the stack
+ * for each elf executable being started.
+ */
+int dcache_bsize;
+int icache_bsize;
+int ucache_bsize;
+
+
 unsigned long klimit = (unsigned long) _end;
 
 /*
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 24ec3ea..3b81742 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -53,14 +53,6 @@ unsigned int DMA_MODE_READ;
 unsigned int DMA_MODE_WRITE;
 
 /*
- * These are used in binfmt_elf.c to put aux entries on the stack
- * for each elf executable being started.
- */
-int dcache_bsize;
-int icache_bsize;
-int ucache_bsize;
-
-/*
  * We're called here very early in the boot.
  *
  * Note that the kernel may be running at an address which is different
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 7ac8e6e..6263e0d 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -88,14 +88,6 @@ struct ppc64_caches ppc64_caches = {
 };
 EXPORT_SYMBOL_GPL(ppc64_caches);
 
-/*
- * These are used in binfmt_elf.c to put aux entries on the stack
- * for each elf executable being started.
- */
-int dcache_bsize;
-int icache_bsize;
-int ucache_bsize;
-
 #if defined(CONFIG_PPC_BOOK3E) && defined(CONFIG_SMP)
 void __init setup_tlb_core_data(void)
 {
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 03/10] powerpc: A new cache shape aux vectors
  2016-08-17  5:39 [RFC PATCH 01/10] powerpc: Move ARCH_DLINFO out of uapi Benjamin Herrenschmidt
  2016-08-17  5:39 ` [RFC PATCH 02/10] powerpc: Move {d, i, u}cache_bsize definitions to a common place Benjamin Herrenschmidt
@ 2016-08-17  5:39 ` Benjamin Herrenschmidt
  2016-08-17  5:39 ` [RFC PATCH 04/10] powerpc: Remove obsolete comment about patching instructions Benjamin Herrenschmidt
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Benjamin Herrenschmidt @ 2016-08-17  5:39 UTC (permalink / raw)
  To: linuxppc-dev

The definition is loosely based on sh and alpha, modified to
accomodate larger associativity and cache size for future-proofing.

We currently set all the values to -1 which indicates that the
information isn't available.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/elf.h         |  8 ++++++++
 arch/powerpc/include/uapi/asm/auxvec.h | 27 ++++++++++++++++++++++++++-
 arch/powerpc/kernel/setup-common.c     |  5 ++++-
 3 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h
index 730c27e..402605e 100644
--- a/arch/powerpc/include/asm/elf.h
+++ b/arch/powerpc/include/asm/elf.h
@@ -115,6 +115,10 @@ do {								\
 extern int dcache_bsize;
 extern int icache_bsize;
 extern int ucache_bsize;
+extern long il1cache_shape;
+extern long dl1cache_shape;
+extern long l2cache_shape;
+extern long l3cache_shape;
 
 /* vDSO has arch_setup_additional_pages */
 #define ARCH_HAS_SETUP_ADDITIONAL_PAGES
@@ -155,6 +159,10 @@ do {									\
 	NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize);			\
 	NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize);			\
 	NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize);			\
+	NEW_AUX_ENT(AT_L1I_CACHESHAPE, il1cache_shape);			\
+	NEW_AUX_ENT(AT_L1D_CACHESHAPE, dl1cache_shape);			\
+	NEW_AUX_ENT(AT_L2_CACHESHAPE, l2cache_shape);			\
+	NEW_AUX_ENT(AT_L3_CACHESHAPE, l3cache_shape);			\
 	VDSO_AUX_ENT(AT_SYSINFO_EHDR, current->mm->context.vdso_base);	\
 } while (0)
 
diff --git a/arch/powerpc/include/uapi/asm/auxvec.h b/arch/powerpc/include/uapi/asm/auxvec.h
index ce17d2c..b3861d8 100644
--- a/arch/powerpc/include/uapi/asm/auxvec.h
+++ b/arch/powerpc/include/uapi/asm/auxvec.h
@@ -16,6 +16,31 @@
  */
 #define AT_SYSINFO_EHDR		33
 
-#define AT_VECTOR_SIZE_ARCH 6 /* entries in ARCH_DLINFO */
+/* More complete cache descriptions than AT_[DIU]CACHEBSIZE.  If the
+   value is -1, then the cache doesn't exist or information isn't
+   availble.  Otherwise:
+
+      bit 0-9:	  Cache set-associativity 0 means fully associative.
+      bit 10-13:  Log2 of cacheline size.
+      bit 14-31:  Size of the entire cache >> 10.
+      bit 32-39:  [64-bit only] more bits for total cache size.
+      bit 40-63:  Reserved
+
+   If any of the fields is all 1's, then that field isn't available.
+
+    WARNING: The cache *line* size can be different from the cache *block*
+             size. The latter, represented by vectors 19,20,21, is the size
+	     used by the cache management instructions such as dcbz. The
+	     cache line size on the other hand is the real HW line size
+	     for a given cache level which might be different and should
+	     only be used for performance related tuning
+*/
+
+#define AT_L1I_CACHESHAPE	34
+#define AT_L1D_CACHESHAPE	35
+#define AT_L2_CACHESHAPE	36
+#define AT_L3_CACHESHAPE	37
+
+#define AT_VECTOR_SIZE_ARCH	10 /* entries in ARCH_DLINFO */
 
 #endif
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index e0eeed4..cfa2a06 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -94,7 +94,10 @@ EXPORT_SYMBOL_GPL(boot_cpuid);
 int dcache_bsize;
 int icache_bsize;
 int ucache_bsize;
-
+long il1cache_shape = -1;
+long dl1cache_shape = -1;
+long l2cache_shape = -1;
+long l3cache_shape = -1;
 
 unsigned long klimit = (unsigned long) _end;
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 04/10] powerpc: Remove obsolete comment about patching instructions
  2016-08-17  5:39 [RFC PATCH 01/10] powerpc: Move ARCH_DLINFO out of uapi Benjamin Herrenschmidt
  2016-08-17  5:39 ` [RFC PATCH 02/10] powerpc: Move {d, i, u}cache_bsize definitions to a common place Benjamin Herrenschmidt
  2016-08-17  5:39 ` [RFC PATCH 03/10] powerpc: A new cache shape aux vectors Benjamin Herrenschmidt
@ 2016-08-17  5:39 ` Benjamin Herrenschmidt
  2016-08-17  5:39 ` [RFC PATCH 05/10] powerpc/64: Fix naming of cache block vs. cache line Benjamin Herrenschmidt
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Benjamin Herrenschmidt @ 2016-08-17  5:39 UTC (permalink / raw)
  To: linuxppc-dev

We don't patch instructions based on the cache lines or block
sizes these days.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/kernel/setup_64.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 6263e0d..222bbb0 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -77,9 +77,6 @@
 int spinning_secondaries;
 u64 ppc64_pft_size;
 
-/* Pick defaults since we might want to patch instructions
- * before we've read this from the device tree.
- */
 struct ppc64_caches ppc64_caches = {
 	.dline_size = 0x40,
 	.log_dline_size = 6,
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 05/10] powerpc/64: Fix naming of cache block vs. cache line
  2016-08-17  5:39 [RFC PATCH 01/10] powerpc: Move ARCH_DLINFO out of uapi Benjamin Herrenschmidt
                   ` (2 preceding siblings ...)
  2016-08-17  5:39 ` [RFC PATCH 04/10] powerpc: Remove obsolete comment about patching instructions Benjamin Herrenschmidt
@ 2016-08-17  5:39 ` Benjamin Herrenschmidt
  2016-08-17  5:39 ` [RFC PATCH 06/10] powerpc/64: Retrieve number of L1 cache sets from device-tree Benjamin Herrenschmidt
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Benjamin Herrenschmidt @ 2016-08-17  5:39 UTC (permalink / raw)
  To: linuxppc-dev

In a number of places we called "cache line size" what is actually
the cache block size, which in the powerpc architecture, means the
effective size to use with cache management instructions (it can
be different from the actual cache line size).

We fix the naming across the board and properly retrieve both
pieces of information when available in the device-tree.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/cache.h   | 12 ++++---
 arch/powerpc/include/asm/page_64.h |  4 +--
 arch/powerpc/kernel/align.c        |  2 +-
 arch/powerpc/kernel/asm-offsets.c  | 12 +++----
 arch/powerpc/kernel/misc_64.S      | 28 ++++++++--------
 arch/powerpc/kernel/setup_64.c     | 65 +++++++++++++++++++++-----------------
 arch/powerpc/kernel/vdso.c         | 10 +++---
 arch/powerpc/lib/copypage_64.S     |  4 +--
 arch/powerpc/lib/string_64.S       |  6 ++--
 9 files changed, 75 insertions(+), 68 deletions(-)

diff --git a/arch/powerpc/include/asm/cache.h b/arch/powerpc/include/asm/cache.h
index ffbafbf..c74ebc2 100644
--- a/arch/powerpc/include/asm/cache.h
+++ b/arch/powerpc/include/asm/cache.h
@@ -30,12 +30,14 @@
 struct ppc64_caches {
 	u32	dsize;			/* L1 d-cache size */
 	u32	dline_size;		/* L1 d-cache line size	*/
-	u32	log_dline_size;
-	u32	dlines_per_page;
+	u32	dblock_size;		/* L1 d-cache block size */
+	u32	log_dblock_size;
+	u32	dblocks_per_page;
 	u32	isize;			/* L1 i-cache size */
-	u32	iline_size;		/* L1 i-cache line size	*/
-	u32	log_iline_size;
-	u32	ilines_per_page;
+	u32	iline_size;		/* L1 d-cache line size	*/
+	u32	iblock_size;		/* L1 i-cache block size */
+	u32	log_iblock_size;
+	u32	iblocks_per_page;
 };
 
 extern struct ppc64_caches ppc64_caches;
diff --git a/arch/powerpc/include/asm/page_64.h b/arch/powerpc/include/asm/page_64.h
index dd5f071..c50a666 100644
--- a/arch/powerpc/include/asm/page_64.h
+++ b/arch/powerpc/include/asm/page_64.h
@@ -47,14 +47,14 @@ static inline void clear_page(void *addr)
 	unsigned long iterations;
 	unsigned long onex, twox, fourx, eightx;
 
-	iterations = ppc64_caches.dlines_per_page / 8;
+	iterations = ppc64_caches.dblocks_per_page / 8;
 
 	/*
 	 * Some verisions of gcc use multiply instructions to
 	 * calculate the offsets so lets give it a hand to
 	 * do better.
 	 */
-	onex = ppc64_caches.dline_size;
+	onex = ppc64_caches.dblock_size;
 	twox = onex << 1;
 	fourx = onex << 2;
 	eightx = onex << 3;
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index 033f338..a617751 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -204,7 +204,7 @@ static int emulate_dcbz(struct pt_regs *regs, unsigned char __user *addr)
 	int i, size;
 
 #ifdef __powerpc64__
-	size = ppc64_caches.dline_size;
+	size = ppc64_caches.dblock_size;
 #else
 	size = L1_CACHE_BYTES;
 #endif
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index b89d14c..e2a881f 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -160,12 +160,12 @@ int main(void)
 	DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
 
 #ifdef CONFIG_PPC64
-	DEFINE(DCACHEL1LINESIZE, offsetof(struct ppc64_caches, dline_size));
-	DEFINE(DCACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_dline_size));
-	DEFINE(DCACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, dlines_per_page));
-	DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size));
-	DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size));
-	DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page));
+	DEFINE(DCACHEL1BLOCKSIZE, offsetof(struct ppc64_caches, dblock_size));
+	DEFINE(DCACHEL1LOGBLOCKSIZE, offsetof(struct ppc64_caches, log_dblock_size));
+	DEFINE(DCACHEL1BLOCKSPERPAGE, offsetof(struct ppc64_caches, dblocks_per_page));
+	DEFINE(ICACHEL1BLOCKSIZE, offsetof(struct ppc64_caches, iblock_size));
+	DEFINE(ICACHEL1LOGBLOCKSIZE, offsetof(struct ppc64_caches, log_iblock_size));
+	DEFINE(ICACHEL1BLOCKSPERPAGE, offsetof(struct ppc64_caches, iblocks_per_page));
 	/* paca */
 	DEFINE(PACA_SIZE, sizeof(struct paca_struct));
 	DEFINE(PACAPACAINDEX, offsetof(struct paca_struct, paca_index));
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index cb19515..70bc6f1 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -79,12 +79,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
  * each other.
  */
  	ld	r10,PPC64_CACHES@toc(r2)
-	lwz	r7,DCACHEL1LINESIZE(r10)/* Get cache line size */
+	lwz	r7,DCACHEL1BLOCKSIZE(r10)/* Get cache block size */
 	addi	r5,r7,-1
 	andc	r6,r3,r5		/* round low to line bdy */
 	subf	r8,r6,r4		/* compute length */
 	add	r8,r8,r5		/* ensure we get enough */
-	lwz	r9,DCACHEL1LOGLINESIZE(r10)	/* Get log-2 of cache line size */
+	lwz	r9,DCACHEL1LOGBLOCKSIZE(r10)	/* Get log-2 of cache block size */
 	srw.	r8,r8,r9		/* compute line count */
 	beqlr				/* nothing to do? */
 	mtctr	r8
@@ -95,12 +95,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
 
 /* Now invalidate the instruction cache */
 	
-	lwz	r7,ICACHEL1LINESIZE(r10)	/* Get Icache line size */
+	lwz	r7,ICACHEL1BLOCKSIZE(r10)	/* Get Icache block size */
 	addi	r5,r7,-1
 	andc	r6,r3,r5		/* round low to line bdy */
 	subf	r8,r6,r4		/* compute length */
 	add	r8,r8,r5
-	lwz	r9,ICACHEL1LOGLINESIZE(r10)	/* Get log-2 of Icache line size */
+	lwz	r9,ICACHEL1LOGBLOCKSIZE(r10)	/* Get log-2 of Icache block size */
 	srw.	r8,r8,r9		/* compute line count */
 	beqlr				/* nothing to do? */
 	mtctr	r8
@@ -125,12 +125,12 @@ _GLOBAL(flush_dcache_range)
  * Different systems have different cache line sizes
  */
  	ld	r10,PPC64_CACHES@toc(r2)
-	lwz	r7,DCACHEL1LINESIZE(r10)	/* Get dcache line size */
+	lwz	r7,DCACHEL1BLOCKSIZE(r10)	/* Get dcache block size */
 	addi	r5,r7,-1
 	andc	r6,r3,r5		/* round low to line bdy */
 	subf	r8,r6,r4		/* compute length */
 	add	r8,r8,r5		/* ensure we get enough */
-	lwz	r9,DCACHEL1LOGLINESIZE(r10)	/* Get log-2 of dcache line size */
+	lwz	r9,DCACHEL1LOGBLOCKSIZE(r10)	/* Get log-2 of dcache block size */
 	srw.	r8,r8,r9		/* compute line count */
 	beqlr				/* nothing to do? */
 	mtctr	r8
@@ -152,12 +152,12 @@ _GLOBAL(flush_dcache_range)
  */
 _GLOBAL(flush_dcache_phys_range)
  	ld	r10,PPC64_CACHES@toc(r2)
-	lwz	r7,DCACHEL1LINESIZE(r10)	/* Get dcache line size */
+	lwz	r7,DCACHEL1BLOCKSIZE(r10)	/* Get dcache block size */
 	addi	r5,r7,-1
 	andc	r6,r3,r5		/* round low to line bdy */
 	subf	r8,r6,r4		/* compute length */
 	add	r8,r8,r5		/* ensure we get enough */
-	lwz	r9,DCACHEL1LOGLINESIZE(r10)	/* Get log-2 of dcache line size */
+	lwz	r9,DCACHEL1LOGBLOCKSIZE(r10)	/* Get log-2 of dcache block size */
 	srw.	r8,r8,r9		/* compute line count */
 	beqlr				/* nothing to do? */
 	mfmsr	r5			/* Disable MMU Data Relocation */
@@ -180,12 +180,12 @@ _GLOBAL(flush_dcache_phys_range)
 
 _GLOBAL(flush_inval_dcache_range)
  	ld	r10,PPC64_CACHES@toc(r2)
-	lwz	r7,DCACHEL1LINESIZE(r10)	/* Get dcache line size */
+	lwz	r7,DCACHEL1BLOCKSIZE(r10)	/* Get dcache block size */
 	addi	r5,r7,-1
 	andc	r6,r3,r5		/* round low to line bdy */
 	subf	r8,r6,r4		/* compute length */
 	add	r8,r8,r5		/* ensure we get enough */
-	lwz	r9,DCACHEL1LOGLINESIZE(r10)/* Get log-2 of dcache line size */
+	lwz	r9,DCACHEL1LOGBLOCKSIZE(r10)/* Get log-2 of dcache block size */
 	srw.	r8,r8,r9		/* compute line count */
 	beqlr				/* nothing to do? */
 	sync
@@ -221,8 +221,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
 /* Flush the dcache */
  	ld	r7,PPC64_CACHES@toc(r2)
 	clrrdi	r3,r3,PAGE_SHIFT           	    /* Page align */
-	lwz	r4,DCACHEL1LINESPERPAGE(r7)	/* Get # dcache lines per page */
-	lwz	r5,DCACHEL1LINESIZE(r7)		/* Get dcache line size */
+	lwz	r4,DCACHEL1BLOCKSPERPAGE(r7)	/* Get # dcache blocks per page */
+	lwz	r5,DCACHEL1BLOCKSIZE(r7)	/* Get dcache block size */
 	mr	r6,r3
 	mtctr	r4
 0:	dcbst	0,r6
@@ -232,8 +232,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
 
 /* Now invalidate the icache */	
 
-	lwz	r4,ICACHEL1LINESPERPAGE(r7)	/* Get # icache lines per page */
-	lwz	r5,ICACHEL1LINESIZE(r7)		/* Get icache line size */
+	lwz	r4,ICACHEL1BLOCKSPERPAGE(r7)	/* Get # icache blocks per page */
+	lwz	r5,ICACHEL1BLOCKSIZE(r7)	/* Get icache block size */
 	mtctr	r4
 1:	icbi	0,r3
 	add	r3,r3,r5
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 222bbb0..e7e5c1b 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -78,10 +78,10 @@ int spinning_secondaries;
 u64 ppc64_pft_size;
 
 struct ppc64_caches ppc64_caches = {
-	.dline_size = 0x40,
-	.log_dline_size = 6,
-	.iline_size = 0x40,
-	.log_iline_size = 6
+	.dblock_size = 0x40,
+	.log_dblock_size = 6,
+	.iblock_size = 0x40,
+	.log_iblock_size = 6
 };
 EXPORT_SYMBOL_GPL(ppc64_caches);
 
@@ -404,59 +404,66 @@ void __init initialize_cache_info(void)
 		 * d-cache and i-cache sizes... -Peter
 		 */
 		if (num_cpus == 1) {
-			const __be32 *sizep, *lsizep;
-			u32 size, lsize;
+			const __be32 *sizep, *lsizep, *bsizep;
+			u32 size, lsize, bsize;
 
 			size = 0;
-			lsize = cur_cpu_spec->dcache_bsize;
+			lsize = bsize = cur_cpu_spec->dcache_bsize;
 			sizep = of_get_property(np, "d-cache-size", NULL);
 			if (sizep != NULL)
 				size = be32_to_cpu(*sizep);
-			lsizep = of_get_property(np, "d-cache-block-size",
+			bsizep = of_get_property(np, "d-cache-block-size",
 						 NULL);
-			/* fallback if block size missing */
-			if (lsizep == NULL)
-				lsizep = of_get_property(np,
-							 "d-cache-line-size",
-							 NULL);
+			lsizep = of_get_property(np, "d-cache-line-size",
+						 NULL);
+			if (bsizep == NULL)
+				bsizep = lsizep;
 			if (lsizep != NULL)
 				lsize = be32_to_cpu(*lsizep);
-			if (sizep == NULL || lsizep == NULL)
+			if (bsizep != NULL)
+				bsize = be32_to_cpu(*bsizep);
+			if (sizep == NULL || bsizep == NULL || lsizep == NULL)
 				DBG("Argh, can't find dcache properties ! "
-				    "sizep: %p, lsizep: %p\n", sizep, lsizep);
+				    "sizep: %p, bsizep: %p, lsizep: %p\n",
+				    sizep, bsizep, lsizep);
 
 			ppc64_caches.dsize = size;
 			ppc64_caches.dline_size = lsize;
-			ppc64_caches.log_dline_size = __ilog2(lsize);
-			ppc64_caches.dlines_per_page = PAGE_SIZE / lsize;
+			ppc64_caches.dblock_size = bsize;
+			ppc64_caches.log_dblock_size = __ilog2(bsize);
+			ppc64_caches.dblocks_per_page = PAGE_SIZE / bsize;
 
 			size = 0;
-			lsize = cur_cpu_spec->icache_bsize;
+			lsize = bsize = cur_cpu_spec->icache_bsize;
 			sizep = of_get_property(np, "i-cache-size", NULL);
 			if (sizep != NULL)
 				size = be32_to_cpu(*sizep);
-			lsizep = of_get_property(np, "i-cache-block-size",
+			bsizep = of_get_property(np, "i-cache-block-size",
+						 NULL);
+			lsizep = of_get_property(np, "i-cache-line-size",
 						 NULL);
-			if (lsizep == NULL)
-				lsizep = of_get_property(np,
-							 "i-cache-line-size",
-							 NULL);
+			if (bsizep == NULL)
+				bsizep = lsizep;
 			if (lsizep != NULL)
 				lsize = be32_to_cpu(*lsizep);
-			if (sizep == NULL || lsizep == NULL)
+			if (bsizep != NULL)
+				bsize = be32_to_cpu(*bsizep);
+			if (sizep == NULL || bsizep == NULL || lsizep == NULL)
 				DBG("Argh, can't find icache properties ! "
-				    "sizep: %p, lsizep: %p\n", sizep, lsizep);
+				    "sizep: %p, bsizep: %p, lsizep: %p\n",
+				    sizep, bsizep, lsizep);
 
 			ppc64_caches.isize = size;
 			ppc64_caches.iline_size = lsize;
-			ppc64_caches.log_iline_size = __ilog2(lsize);
-			ppc64_caches.ilines_per_page = PAGE_SIZE / lsize;
+			ppc64_caches.iblock_size = bsize;
+			ppc64_caches.log_iblock_size = __ilog2(bsize);
+			ppc64_caches.iblocks_per_page = PAGE_SIZE / bsize;
 		}
 	}
 
 	/* For use by binfmt_elf */
-	dcache_bsize = ppc64_caches.dline_size;
-	icache_bsize = ppc64_caches.iline_size;
+	dcache_bsize = ppc64_caches.dblock_size;
+	icache_bsize = ppc64_caches.iblock_size;
 
 	DBG(" <- initialize_cache_info()\n");
 }
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index 4111d30..9c0a857 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -740,12 +740,10 @@ static int __init vdso_init(void)
 	vdso_data->dcache_line_size = ppc64_caches.dline_size;
 	vdso_data->icache_size = ppc64_caches.isize;
 	vdso_data->icache_line_size = ppc64_caches.iline_size;
-
-	/* XXXOJN: Blocks should be added to ppc64_caches and used instead */
-	vdso_data->dcache_block_size = ppc64_caches.dline_size;
-	vdso_data->icache_block_size = ppc64_caches.iline_size;
-	vdso_data->dcache_log_block_size = ppc64_caches.log_dline_size;
-	vdso_data->icache_log_block_size = ppc64_caches.log_iline_size;
+	vdso_data->dcache_block_size = ppc64_caches.dblock_size;
+	vdso_data->icache_block_size = ppc64_caches.iblock_size;
+	vdso_data->dcache_log_block_size = ppc64_caches.log_dblock_size;
+	vdso_data->icache_log_block_size = ppc64_caches.log_iblock_size;
 
 	/*
 	 * Calculate the size of the 64 bits vDSO
diff --git a/arch/powerpc/lib/copypage_64.S b/arch/powerpc/lib/copypage_64.S
index a3c4dc4..0c3bd46 100644
--- a/arch/powerpc/lib/copypage_64.S
+++ b/arch/powerpc/lib/copypage_64.S
@@ -25,8 +25,8 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_VMX_COPY)
 	ori	r5,r5,PAGE_SIZE@l
 BEGIN_FTR_SECTION
 	ld      r10,PPC64_CACHES@toc(r2)
-	lwz	r11,DCACHEL1LOGLINESIZE(r10)	/* log2 of cache line size */
-	lwz     r12,DCACHEL1LINESIZE(r10)	/* get cache line size */
+	lwz	r11,DCACHEL1LOGBLOCKSIZE(r10)	/* log2 of cache block size */
+	lwz     r12,DCACHEL1BLOCKSIZE(r10)	/* get cache block size */
 	li	r9,0
 	srd	r8,r5,r11
 
diff --git a/arch/powerpc/lib/string_64.S b/arch/powerpc/lib/string_64.S
index 7bd9549..9907379 100644
--- a/arch/powerpc/lib/string_64.S
+++ b/arch/powerpc/lib/string_64.S
@@ -159,9 +159,9 @@ err2;	std	r0,0(r3)
 	addi	r3,r3,8
 	addi	r4,r4,-8
 
-	/* Destination is 16 byte aligned, need to get it cacheline aligned */
-11:	lwz	r7,DCACHEL1LOGLINESIZE(r5)
-	lwz	r9,DCACHEL1LINESIZE(r5)
+	/* Destination is 16 byte aligned, need to get it cache block aligned */
+11:	lwz	r7,DCACHEL1LOGBLOCKSIZE(r5)
+	lwz	r9,DCACHEL1BLOCKSIZE(r5)
 
 	/*
 	 * With worst case alignment the long clear loop takes a minimum
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 06/10] powerpc/64: Retrieve number of L1 cache sets from device-tree
  2016-08-17  5:39 [RFC PATCH 01/10] powerpc: Move ARCH_DLINFO out of uapi Benjamin Herrenschmidt
                   ` (3 preceding siblings ...)
  2016-08-17  5:39 ` [RFC PATCH 05/10] powerpc/64: Fix naming of cache block vs. cache line Benjamin Herrenschmidt
@ 2016-08-17  5:39 ` Benjamin Herrenschmidt
  2016-08-17  5:39 ` [RFC PATCH 07/10] powerpc/64: Build L1 cache shape info for userspace Benjamin Herrenschmidt
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Benjamin Herrenschmidt @ 2016-08-17  5:39 UTC (permalink / raw)
  To: linuxppc-dev

It will be used to calculate the associativity

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/cache.h |  2 ++
 arch/powerpc/kernel/setup_64.c   | 27 +++++++++++++++++++++++++--
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/include/asm/cache.h b/arch/powerpc/include/asm/cache.h
index c74ebc2..ceb1244 100644
--- a/arch/powerpc/include/asm/cache.h
+++ b/arch/powerpc/include/asm/cache.h
@@ -33,11 +33,13 @@ struct ppc64_caches {
 	u32	dblock_size;		/* L1 d-cache block size */
 	u32	log_dblock_size;
 	u32	dblocks_per_page;
+	u32	dsets;
 	u32	isize;			/* L1 i-cache size */
 	u32	iline_size;		/* L1 d-cache line size	*/
 	u32	iblock_size;		/* L1 i-cache block size */
 	u32	log_iblock_size;
 	u32	iblocks_per_page;
+	u32	isets;
 };
 
 extern struct ppc64_caches ppc64_caches;
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index e7e5c1b..d36b6f4 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -404,14 +404,18 @@ void __init initialize_cache_info(void)
 		 * d-cache and i-cache sizes... -Peter
 		 */
 		if (num_cpus == 1) {
-			const __be32 *sizep, *lsizep, *bsizep;
-			u32 size, lsize, bsize;
+			const __be32 *sizep, *lsizep, *bsizep, *setsp;
+			u32 size, lsize, bsize, sets;
 
 			size = 0;
+			sets = -1u;
 			lsize = bsize = cur_cpu_spec->dcache_bsize;
 			sizep = of_get_property(np, "d-cache-size", NULL);
 			if (sizep != NULL)
 				size = be32_to_cpu(*sizep);
+			setsp = of_get_property(np, "d-cache-sets", NULL);
+			if (setsp != NULL)
+				sets = be32_to_cpu(*setsp);
 			bsizep = of_get_property(np, "d-cache-block-size",
 						 NULL);
 			lsizep = of_get_property(np, "d-cache-line-size",
@@ -427,17 +431,31 @@ void __init initialize_cache_info(void)
 				    "sizep: %p, bsizep: %p, lsizep: %p\n",
 				    sizep, bsizep, lsizep);
 
+			/* OF is weird .. it represents fully associative caches
+			 * as "1 way" which doesn't make much sense and doesn't
+			 * leave room for direct mapped. We'll assume that 0
+			 * in OF means direct mapped for that reason.
+			 */
+			if (sets == 1)
+				sets = 0;
+			else if (sets == 0)
+				sets = 1;
 			ppc64_caches.dsize = size;
+			ppc64_caches.dsets = sets;
 			ppc64_caches.dline_size = lsize;
 			ppc64_caches.dblock_size = bsize;
 			ppc64_caches.log_dblock_size = __ilog2(bsize);
 			ppc64_caches.dblocks_per_page = PAGE_SIZE / bsize;
 
 			size = 0;
+			sets = -1u;
 			lsize = bsize = cur_cpu_spec->icache_bsize;
 			sizep = of_get_property(np, "i-cache-size", NULL);
 			if (sizep != NULL)
 				size = be32_to_cpu(*sizep);
+			setsp = of_get_property(np, "i-cache-sets", NULL);
+			if (setsp != NULL)
+				sets = be32_to_cpu(*setsp);
 			bsizep = of_get_property(np, "i-cache-block-size",
 						 NULL);
 			lsizep = of_get_property(np, "i-cache-line-size",
@@ -453,7 +471,12 @@ void __init initialize_cache_info(void)
 				    "sizep: %p, bsizep: %p, lsizep: %p\n",
 				    sizep, bsizep, lsizep);
 
+			if (sets == 1)
+				sets = 0;
+			else if (sets == 0)
+				sets = 1;
 			ppc64_caches.isize = size;
+			ppc64_caches.isets = sets;
 			ppc64_caches.iline_size = lsize;
 			ppc64_caches.iblock_size = bsize;
 			ppc64_caches.log_iblock_size = __ilog2(bsize);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 07/10] powerpc/64: Build L1 cache shape info for userspace
  2016-08-17  5:39 [RFC PATCH 01/10] powerpc: Move ARCH_DLINFO out of uapi Benjamin Herrenschmidt
                   ` (4 preceding siblings ...)
  2016-08-17  5:39 ` [RFC PATCH 06/10] powerpc/64: Retrieve number of L1 cache sets from device-tree Benjamin Herrenschmidt
@ 2016-08-17  5:39 ` Benjamin Herrenschmidt
  2016-08-17  5:39 ` [RFC PATCH 08/10] powerpc/64: Clean up ppc64_caches using a struct per cache Benjamin Herrenschmidt
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Benjamin Herrenschmidt @ 2016-08-17  5:39 UTC (permalink / raw)
  To: linuxppc-dev

Now that we have all the necessary information available we can
build the L1 cache shape info to be passed down to userspace via
the ELF AUX vectors.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/kernel/setup_64.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index d36b6f4..2079e2e 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -382,6 +382,34 @@ void smp_release_cpus(void)
 }
 #endif /* CONFIG_SMP || CONFIG_KEXEC */
 
+static long format_cache_shape(u32 size, u32 sets, u32 lsize)
+{
+	long result = 0;
+	u32 log2size = __ilog2(lsize);
+	u32 ways;
+
+	if (size == 0 || sets == 0)
+		return -1;
+	if (sets == 1)
+		ways = 0;
+	else
+		ways = size / (lsize * sets);
+	if (ways < 0x2ff)
+		result |= ways;
+	else
+		result |= 0x2ff;
+	if (log2size < 0xf)
+		result |= (log2size << 10);
+	else
+		result |= 0x3c00;
+	if (size >= 1024)
+		result |= (size >> 10) << 14;
+	else
+		result |= 0xfffffc000ul;
+
+	return result;
+}
+
 /*
  * Initialize some remaining members of the ppc64_caches and systemcfg
  * structures
@@ -487,6 +515,12 @@ void __init initialize_cache_info(void)
 	/* For use by binfmt_elf */
 	dcache_bsize = ppc64_caches.dblock_size;
 	icache_bsize = ppc64_caches.iblock_size;
+	il1cache_shape = format_cache_shape(ppc64_caches.isize,
+					    ppc64_caches.isets,
+					    ppc64_caches.iline_size);
+	dl1cache_shape = format_cache_shape(ppc64_caches.dsize,
+					    ppc64_caches.dsets,
+					    ppc64_caches.dline_size);
 
 	DBG(" <- initialize_cache_info()\n");
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 08/10] powerpc/64: Clean up ppc64_caches using a struct per cache
  2016-08-17  5:39 [RFC PATCH 01/10] powerpc: Move ARCH_DLINFO out of uapi Benjamin Herrenschmidt
                   ` (5 preceding siblings ...)
  2016-08-17  5:39 ` [RFC PATCH 07/10] powerpc/64: Build L1 cache shape info for userspace Benjamin Herrenschmidt
@ 2016-08-17  5:39 ` Benjamin Herrenschmidt
  2016-08-17  5:39 ` [RFC PATCH 09/10] powerpc/64: Add L2 and L3 cache shape info Benjamin Herrenschmidt
  2016-08-17  5:39 ` [RFC PATCH 10/10] powerpc/64: Hard code cache geometry on POWER8 Benjamin Herrenschmidt
  8 siblings, 0 replies; 10+ messages in thread
From: Benjamin Herrenschmidt @ 2016-08-17  5:39 UTC (permalink / raw)
  To: linuxppc-dev

We have two set of identical struct members for the I and D sides
and mostly identical bunches of code to parse the device-tree to
populate them. Instead make a ppc_cache_info structure with one
copy for I and one for D

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/cache.h   |  24 ++---
 arch/powerpc/include/asm/page_64.h |   4 +-
 arch/powerpc/kernel/align.c        |   2 +-
 arch/powerpc/kernel/asm-offsets.c  |  12 +--
 arch/powerpc/kernel/setup_64.c     | 197 +++++++++++++++++--------------------
 arch/powerpc/kernel/vdso.c         |  16 +--
 6 files changed, 121 insertions(+), 134 deletions(-)

diff --git a/arch/powerpc/include/asm/cache.h b/arch/powerpc/include/asm/cache.h
index ceb1244..ceb7376 100644
--- a/arch/powerpc/include/asm/cache.h
+++ b/arch/powerpc/include/asm/cache.h
@@ -27,19 +27,19 @@
 #define	SMP_CACHE_BYTES		L1_CACHE_BYTES
 
 #if defined(__powerpc64__) && !defined(__ASSEMBLY__)
+
+struct ppc_cache_info {
+	u32 size;
+	u32 line_size;
+	u32 block_size;	/* L1 only */
+	u32 log_block_size;
+	u32 blocks_per_page;
+	u32 sets;
+};
+
 struct ppc64_caches {
-	u32	dsize;			/* L1 d-cache size */
-	u32	dline_size;		/* L1 d-cache line size	*/
-	u32	dblock_size;		/* L1 d-cache block size */
-	u32	log_dblock_size;
-	u32	dblocks_per_page;
-	u32	dsets;
-	u32	isize;			/* L1 i-cache size */
-	u32	iline_size;		/* L1 d-cache line size	*/
-	u32	iblock_size;		/* L1 i-cache block size */
-	u32	log_iblock_size;
-	u32	iblocks_per_page;
-	u32	isets;
+	struct ppc_cache_info l1d;
+	struct ppc_cache_info l1i;
 };
 
 extern struct ppc64_caches ppc64_caches;
diff --git a/arch/powerpc/include/asm/page_64.h b/arch/powerpc/include/asm/page_64.h
index c50a666..3e83d2a 100644
--- a/arch/powerpc/include/asm/page_64.h
+++ b/arch/powerpc/include/asm/page_64.h
@@ -47,14 +47,14 @@ static inline void clear_page(void *addr)
 	unsigned long iterations;
 	unsigned long onex, twox, fourx, eightx;
 
-	iterations = ppc64_caches.dblocks_per_page / 8;
+	iterations = ppc64_caches.l1d.blocks_per_page / 8;
 
 	/*
 	 * Some verisions of gcc use multiply instructions to
 	 * calculate the offsets so lets give it a hand to
 	 * do better.
 	 */
-	onex = ppc64_caches.dblock_size;
+	onex = ppc64_caches.l1d.block_size;
 	twox = onex << 1;
 	fourx = onex << 2;
 	eightx = onex << 3;
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index a617751..7806211 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -204,7 +204,7 @@ static int emulate_dcbz(struct pt_regs *regs, unsigned char __user *addr)
 	int i, size;
 
 #ifdef __powerpc64__
-	size = ppc64_caches.dblock_size;
+	size = ppc64_caches.l1d.block_size;
 #else
 	size = L1_CACHE_BYTES;
 #endif
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index e2a881f..100261b 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -160,12 +160,12 @@ int main(void)
 	DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
 
 #ifdef CONFIG_PPC64
-	DEFINE(DCACHEL1BLOCKSIZE, offsetof(struct ppc64_caches, dblock_size));
-	DEFINE(DCACHEL1LOGBLOCKSIZE, offsetof(struct ppc64_caches, log_dblock_size));
-	DEFINE(DCACHEL1BLOCKSPERPAGE, offsetof(struct ppc64_caches, dblocks_per_page));
-	DEFINE(ICACHEL1BLOCKSIZE, offsetof(struct ppc64_caches, iblock_size));
-	DEFINE(ICACHEL1LOGBLOCKSIZE, offsetof(struct ppc64_caches, log_iblock_size));
-	DEFINE(ICACHEL1BLOCKSPERPAGE, offsetof(struct ppc64_caches, iblocks_per_page));
+	DEFINE(DCACHEL1BLOCKSIZE, offsetof(struct ppc64_caches, l1d.block_size));
+	DEFINE(DCACHEL1LOGBLOCKSIZE, offsetof(struct ppc64_caches, l1d.log_block_size));
+	DEFINE(DCACHEL1BLOCKSPERPAGE, offsetof(struct ppc64_caches, l1d.blocks_per_page));
+	DEFINE(ICACHEL1BLOCKSIZE, offsetof(struct ppc64_caches, l1i.block_size));
+	DEFINE(ICACHEL1LOGBLOCKSIZE, offsetof(struct ppc64_caches, l1i.log_block_size));
+	DEFINE(ICACHEL1BLOCKSPERPAGE, offsetof(struct ppc64_caches, l1i.blocks_per_page));
 	/* paca */
 	DEFINE(PACA_SIZE, sizeof(struct paca_struct));
 	DEFINE(PACAPACAINDEX, offsetof(struct paca_struct, paca_index));
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 2079e2e..80a20b9 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -78,10 +78,14 @@ int spinning_secondaries;
 u64 ppc64_pft_size;
 
 struct ppc64_caches ppc64_caches = {
-	.dblock_size = 0x40,
-	.log_dblock_size = 6,
-	.iblock_size = 0x40,
-	.log_iblock_size = 6
+	.l1d = {
+		.block_size = 0x40,
+		.log_block_size = 6,
+	},
+	.l1i = {
+		.block_size = 0x40,
+		.log_block_size = 6
+	},
 };
 EXPORT_SYMBOL_GPL(ppc64_caches);
 
@@ -382,18 +386,18 @@ void smp_release_cpus(void)
 }
 #endif /* CONFIG_SMP || CONFIG_KEXEC */
 
-static long format_cache_shape(u32 size, u32 sets, u32 lsize)
+static long format_cache_shape(struct ppc_cache_info *info)
 {
 	long result = 0;
-	u32 log2size = __ilog2(lsize);
+	u32 log2size = __ilog2(info->line_size);
 	u32 ways;
 
-	if (size == 0 || sets == 0)
+	if (info->size == 0 || info->sets == 0)
 		return -1;
-	if (sets == 1)
+	if (info->sets == 1)
 		ways = 0;
 	else
-		ways = size / (lsize * sets);
+		ways = info->size / (info->line_size * info->sets);
 	if (ways < 0x2ff)
 		result |= ways;
 	else
@@ -402,8 +406,8 @@ static long format_cache_shape(u32 size, u32 sets, u32 lsize)
 		result |= (log2size << 10);
 	else
 		result |= 0x3c00;
-	if (size >= 1024)
-		result |= (size >> 10) << 14;
+	if (info->size >= 1024)
+		result |= (info->size >> 10) << 14;
 	else
 		result |= 0xfffffc000ul;
 
@@ -417,110 +421,93 @@ static long format_cache_shape(u32 size, u32 sets, u32 lsize)
  * cache informations about the CPU that will be used by cache flush
  * routines and/or provided to userland
  */
+
+static bool __init parse_cache_info(struct device_node *np,
+				    bool icache,
+				    struct ppc_cache_info *info)
+{
+	static const char *ipropnames[] __initdata = {
+		"i-cache-size",
+		"i-cache-sets",
+		"i-cache-block-size",
+		"i-cache-line-size",
+	};
+	static const char *dpropnames[] __initdata = {
+		"d-cache-size",
+		"d-cache-sets",
+		"d-cache-block-size",
+		"d-cache-line-size",
+	};
+	const char **propnames = icache ? ipropnames : dpropnames;
+	const __be32 *sizep, *lsizep, *bsizep, *setsp;
+	u32 size, lsize, bsize, sets;
+	bool success = true;
+
+	size = 0;
+	sets = -1u;
+	lsize = bsize = cur_cpu_spec->dcache_bsize;
+	sizep = of_get_property(np, propnames[0], NULL);
+	if (sizep != NULL)
+		size = be32_to_cpu(*sizep);
+	setsp = of_get_property(np, propnames[1], NULL);
+	if (setsp != NULL)
+		sets = be32_to_cpu(*setsp);
+	bsizep = of_get_property(np, propnames[2], NULL);
+	lsizep = of_get_property(np, propnames[3], NULL);
+	if (bsizep == NULL)
+		bsizep = lsizep;
+	if (lsizep != NULL)
+		lsize = be32_to_cpu(*lsizep);
+	if (bsizep != NULL)
+		bsize = be32_to_cpu(*bsizep);
+	if (sizep == NULL || bsizep == NULL || lsizep == NULL)
+		success = false;
+
+	/* OF is weird .. it represents fully associative caches
+	 * as "1 way" which doesn't make much sense and doesn't
+	 * leave room for direct mapped. We'll assume that 0
+	 * in OF means direct mapped for that reason.
+	 */
+	if (sets == 1)
+		sets = 0;
+	else if (sets == 0)
+		sets = 1;
+
+	info->size = size;
+	info->sets = sets;
+	info->line_size = lsize;
+	info->block_size = bsize;
+	info->log_block_size = __ilog2(bsize);
+	info->blocks_per_page = PAGE_SIZE / bsize;
+
+	return success;
+}
+
 void __init initialize_cache_info(void)
 {
 	struct device_node *np;
-	unsigned long num_cpus = 0;
 
 	DBG(" -> initialize_cache_info()\n");
 
-	for_each_node_by_type(np, "cpu") {
-		num_cpus += 1;
+	np  = of_find_node_by_type(NULL, "cpu");
 
-		/*
-		 * We're assuming *all* of the CPUs have the same
-		 * d-cache and i-cache sizes... -Peter
-		 */
-		if (num_cpus == 1) {
-			const __be32 *sizep, *lsizep, *bsizep, *setsp;
-			u32 size, lsize, bsize, sets;
-
-			size = 0;
-			sets = -1u;
-			lsize = bsize = cur_cpu_spec->dcache_bsize;
-			sizep = of_get_property(np, "d-cache-size", NULL);
-			if (sizep != NULL)
-				size = be32_to_cpu(*sizep);
-			setsp = of_get_property(np, "d-cache-sets", NULL);
-			if (setsp != NULL)
-				sets = be32_to_cpu(*setsp);
-			bsizep = of_get_property(np, "d-cache-block-size",
-						 NULL);
-			lsizep = of_get_property(np, "d-cache-line-size",
-						 NULL);
-			if (bsizep == NULL)
-				bsizep = lsizep;
-			if (lsizep != NULL)
-				lsize = be32_to_cpu(*lsizep);
-			if (bsizep != NULL)
-				bsize = be32_to_cpu(*bsizep);
-			if (sizep == NULL || bsizep == NULL || lsizep == NULL)
-				DBG("Argh, can't find dcache properties ! "
-				    "sizep: %p, bsizep: %p, lsizep: %p\n",
-				    sizep, bsizep, lsizep);
-
-			/* OF is weird .. it represents fully associative caches
-			 * as "1 way" which doesn't make much sense and doesn't
-			 * leave room for direct mapped. We'll assume that 0
-			 * in OF means direct mapped for that reason.
-			 */
-			if (sets == 1)
-				sets = 0;
-			else if (sets == 0)
-				sets = 1;
-			ppc64_caches.dsize = size;
-			ppc64_caches.dsets = sets;
-			ppc64_caches.dline_size = lsize;
-			ppc64_caches.dblock_size = bsize;
-			ppc64_caches.log_dblock_size = __ilog2(bsize);
-			ppc64_caches.dblocks_per_page = PAGE_SIZE / bsize;
-
-			size = 0;
-			sets = -1u;
-			lsize = bsize = cur_cpu_spec->icache_bsize;
-			sizep = of_get_property(np, "i-cache-size", NULL);
-			if (sizep != NULL)
-				size = be32_to_cpu(*sizep);
-			setsp = of_get_property(np, "i-cache-sets", NULL);
-			if (setsp != NULL)
-				sets = be32_to_cpu(*setsp);
-			bsizep = of_get_property(np, "i-cache-block-size",
-						 NULL);
-			lsizep = of_get_property(np, "i-cache-line-size",
-						 NULL);
-			if (bsizep == NULL)
-				bsizep = lsizep;
-			if (lsizep != NULL)
-				lsize = be32_to_cpu(*lsizep);
-			if (bsizep != NULL)
-				bsize = be32_to_cpu(*bsizep);
-			if (sizep == NULL || bsizep == NULL || lsizep == NULL)
-				DBG("Argh, can't find icache properties ! "
-				    "sizep: %p, bsizep: %p, lsizep: %p\n",
-				    sizep, bsizep, lsizep);
-
-			if (sets == 1)
-				sets = 0;
-			else if (sets == 0)
-				sets = 1;
-			ppc64_caches.isize = size;
-			ppc64_caches.isets = sets;
-			ppc64_caches.iline_size = lsize;
-			ppc64_caches.iblock_size = bsize;
-			ppc64_caches.log_iblock_size = __ilog2(bsize);
-			ppc64_caches.iblocks_per_page = PAGE_SIZE / bsize;
-		}
+	/*
+	 * We're assuming *all* of the CPUs have the same
+	 * d-cache and i-cache sizes... -Peter
+	 */
+	if (np) {
+		if (!parse_cache_info(np, false, &ppc64_caches.l1d))
+			DBG("Argh, can't find dcache properties !\n");
+
+		if (!parse_cache_info(np, true, &ppc64_caches.l1i))
+			DBG("Argh, can't find icache properties !\n");
 	}
 
 	/* For use by binfmt_elf */
-	dcache_bsize = ppc64_caches.dblock_size;
-	icache_bsize = ppc64_caches.iblock_size;
-	il1cache_shape = format_cache_shape(ppc64_caches.isize,
-					    ppc64_caches.isets,
-					    ppc64_caches.iline_size);
-	dl1cache_shape = format_cache_shape(ppc64_caches.dsize,
-					    ppc64_caches.dsets,
-					    ppc64_caches.dline_size);
+	dcache_bsize = ppc64_caches.l1d.block_size;
+	icache_bsize = ppc64_caches.l1i.block_size;
+	dl1cache_shape = format_cache_shape(&ppc64_caches.l1d);
+	il1cache_shape = format_cache_shape(&ppc64_caches.l1i);
 
 	DBG(" <- initialize_cache_info()\n");
 }
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index 9c0a857..22b01a3 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -736,14 +736,14 @@ static int __init vdso_init(void)
 	if (firmware_has_feature(FW_FEATURE_LPAR))
 		vdso_data->platform |= 1;
 	vdso_data->physicalMemorySize = memblock_phys_mem_size();
-	vdso_data->dcache_size = ppc64_caches.dsize;
-	vdso_data->dcache_line_size = ppc64_caches.dline_size;
-	vdso_data->icache_size = ppc64_caches.isize;
-	vdso_data->icache_line_size = ppc64_caches.iline_size;
-	vdso_data->dcache_block_size = ppc64_caches.dblock_size;
-	vdso_data->icache_block_size = ppc64_caches.iblock_size;
-	vdso_data->dcache_log_block_size = ppc64_caches.log_dblock_size;
-	vdso_data->icache_log_block_size = ppc64_caches.log_iblock_size;
+	vdso_data->dcache_size = ppc64_caches.l1d.size;
+	vdso_data->dcache_line_size = ppc64_caches.l1d.line_size;
+	vdso_data->icache_size = ppc64_caches.l1i.size;
+	vdso_data->icache_line_size = ppc64_caches.l1i.line_size;
+	vdso_data->dcache_block_size = ppc64_caches.l1d.block_size;
+	vdso_data->icache_block_size = ppc64_caches.l1i.block_size;
+	vdso_data->dcache_log_block_size = ppc64_caches.l1d.log_block_size;
+	vdso_data->icache_log_block_size = ppc64_caches.l1i.log_block_size;
 
 	/*
 	 * Calculate the size of the 64 bits vDSO
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 09/10] powerpc/64: Add L2 and L3 cache shape info
  2016-08-17  5:39 [RFC PATCH 01/10] powerpc: Move ARCH_DLINFO out of uapi Benjamin Herrenschmidt
                   ` (6 preceding siblings ...)
  2016-08-17  5:39 ` [RFC PATCH 08/10] powerpc/64: Clean up ppc64_caches using a struct per cache Benjamin Herrenschmidt
@ 2016-08-17  5:39 ` Benjamin Herrenschmidt
  2016-08-17  5:39 ` [RFC PATCH 10/10] powerpc/64: Hard code cache geometry on POWER8 Benjamin Herrenschmidt
  8 siblings, 0 replies; 10+ messages in thread
From: Benjamin Herrenschmidt @ 2016-08-17  5:39 UTC (permalink / raw)
  To: linuxppc-dev

Retrieved from device-tree when available

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/cache.h |  2 ++
 arch/powerpc/kernel/setup_64.c   | 27 ++++++++++++++++++++++-----
 2 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/include/asm/cache.h b/arch/powerpc/include/asm/cache.h
index ceb7376..3987bd9 100644
--- a/arch/powerpc/include/asm/cache.h
+++ b/arch/powerpc/include/asm/cache.h
@@ -40,6 +40,8 @@ struct ppc_cache_info {
 struct ppc64_caches {
 	struct ppc_cache_info l1d;
 	struct ppc_cache_info l1i;
+	struct ppc_cache_info l2;
+	struct ppc_cache_info l3;
 };
 
 extern struct ppc64_caches ppc64_caches;
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 80a20b9..78d28ca 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -485,22 +485,37 @@ static bool __init parse_cache_info(struct device_node *np,
 
 void __init initialize_cache_info(void)
 {
-	struct device_node *np;
+	struct device_node *cpu, *l2, *l3 = NULL;
 
 	DBG(" -> initialize_cache_info()\n");
 
-	np  = of_find_node_by_type(NULL, "cpu");
+	cpu = of_find_node_by_type(NULL, "cpu");
 
 	/*
 	 * We're assuming *all* of the CPUs have the same
 	 * d-cache and i-cache sizes... -Peter
 	 */
-	if (np) {
-		if (!parse_cache_info(np, false, &ppc64_caches.l1d))
+	if (cpu) {
+		if (!parse_cache_info(cpu, false, &ppc64_caches.l1d))
 			DBG("Argh, can't find dcache properties !\n");
 
-		if (!parse_cache_info(np, true, &ppc64_caches.l1i))
+		if (!parse_cache_info(cpu, true, &ppc64_caches.l1i))
 			DBG("Argh, can't find icache properties !\n");
+
+		/* Try to find the L2 and L3 if any. Assume they are
+		 * unified and use the D-side properties
+		 */
+		l2 = of_find_next_cache_node(cpu);
+		of_node_put(cpu);
+		if (l2) {
+			parse_cache_info(l2, false, &ppc64_caches.l2);
+			l3 = of_find_next_cache_node(l2);
+			of_node_put(l2);
+		}
+		if (l3) {
+			parse_cache_info(l3, false, &ppc64_caches.l3);
+			of_node_put(l3);
+		}
 	}
 
 	/* For use by binfmt_elf */
@@ -508,6 +523,8 @@ void __init initialize_cache_info(void)
 	icache_bsize = ppc64_caches.l1i.block_size;
 	dl1cache_shape = format_cache_shape(&ppc64_caches.l1d);
 	il1cache_shape = format_cache_shape(&ppc64_caches.l1i);
+	l2cache_shape = format_cache_shape(&ppc64_caches.l2);
+	l3cache_shape = format_cache_shape(&ppc64_caches.l3);
 
 	DBG(" <- initialize_cache_info()\n");
 }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 10/10] powerpc/64: Hard code cache geometry on POWER8
  2016-08-17  5:39 [RFC PATCH 01/10] powerpc: Move ARCH_DLINFO out of uapi Benjamin Herrenschmidt
                   ` (7 preceding siblings ...)
  2016-08-17  5:39 ` [RFC PATCH 09/10] powerpc/64: Add L2 and L3 cache shape info Benjamin Herrenschmidt
@ 2016-08-17  5:39 ` Benjamin Herrenschmidt
  8 siblings, 0 replies; 10+ messages in thread
From: Benjamin Herrenschmidt @ 2016-08-17  5:39 UTC (permalink / raw)
  To: linuxppc-dev

All shipping firmware versions have it wrong in the device-tree

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/kernel/setup_64.c | 52 +++++++++++++++++++++++++++++++++++++++---
 1 file changed, 49 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 78d28ca..1243062 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -255,7 +255,7 @@ static void cpu_ready_for_interrupts(void)
 
 void __init early_setup(unsigned long dt_ptr)
 {
-	static __initdata struct paca_struct boot_paca;
+	static struct paca_struct boot_paca __initdata ;
 
 	/* -------- printk is _NOT_ safe to use here ! ------- */
 
@@ -483,13 +483,59 @@ static bool __init parse_cache_info(struct device_node *np,
 	return success;
 }
 
+static void __init populate_p8_cache_info(void)
+{
+	static const struct ppc_cache_info p8_l1i __initconst  = {
+		.size = 0x8000,
+		.line_size = 128,
+		.block_size = 128,
+		.log_block_size = 7,
+		.blocks_per_page = PAGE_SIZE / 128,
+		.sets = 32
+	};
+	static const struct ppc_cache_info p8_l1d __initconst  = {
+		.size = 0x10000,
+		.line_size = 128,
+		.block_size = 128,
+		.log_block_size = 7,
+		.blocks_per_page = PAGE_SIZE / 128,
+		.sets = 64
+	};
+	static const struct ppc_cache_info p8_l2 __initconst  = {
+		.size = 0x80000,
+		.line_size = 128,
+		.sets = 512
+	};
+	static const struct ppc_cache_info p8_l3 __initconst  = {
+		.size = 0x800000,
+		.line_size = 128,
+		.sets = 8192
+	};
+	ppc64_caches.l1i = p8_l1i;
+	ppc64_caches.l1d = p8_l1d;
+	ppc64_caches.l2 = p8_l2;
+	ppc64_caches.l3 = p8_l3;
+}
+
 void __init initialize_cache_info(void)
 {
-	struct device_node *cpu, *l2, *l3 = NULL;
+	struct device_node *cpu = NULL, *l2, *l3 = NULL;
+	u32 pvr;
 
 	DBG(" -> initialize_cache_info()\n");
 
-	cpu = of_find_node_by_type(NULL, "cpu");
+	/*
+	 * All shipping POWER8 machines have a firmware bug that
+	 * puts incorrect information in the device-tree. This will
+	 * be (hopefully) fixed for future chips but for now hard
+	 * code the values if we are running on one of these
+	 */
+	pvr = PVR_VER(mfspr(SPRN_PVR));
+	if (pvr == PVR_POWER8 || pvr == PVR_POWER8E ||
+	    pvr == PVR_POWER8NVL)
+		populate_p8_cache_info();
+	else
+		cpu = of_find_node_by_type(NULL, "cpu");
 
 	/*
 	 * We're assuming *all* of the CPUs have the same
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2016-08-17  5:43 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-08-17  5:39 [RFC PATCH 01/10] powerpc: Move ARCH_DLINFO out of uapi Benjamin Herrenschmidt
2016-08-17  5:39 ` [RFC PATCH 02/10] powerpc: Move {d, i, u}cache_bsize definitions to a common place Benjamin Herrenschmidt
2016-08-17  5:39 ` [RFC PATCH 03/10] powerpc: A new cache shape aux vectors Benjamin Herrenschmidt
2016-08-17  5:39 ` [RFC PATCH 04/10] powerpc: Remove obsolete comment about patching instructions Benjamin Herrenschmidt
2016-08-17  5:39 ` [RFC PATCH 05/10] powerpc/64: Fix naming of cache block vs. cache line Benjamin Herrenschmidt
2016-08-17  5:39 ` [RFC PATCH 06/10] powerpc/64: Retrieve number of L1 cache sets from device-tree Benjamin Herrenschmidt
2016-08-17  5:39 ` [RFC PATCH 07/10] powerpc/64: Build L1 cache shape info for userspace Benjamin Herrenschmidt
2016-08-17  5:39 ` [RFC PATCH 08/10] powerpc/64: Clean up ppc64_caches using a struct per cache Benjamin Herrenschmidt
2016-08-17  5:39 ` [RFC PATCH 09/10] powerpc/64: Add L2 and L3 cache shape info Benjamin Herrenschmidt
2016-08-17  5:39 ` [RFC PATCH 10/10] powerpc/64: Hard code cache geometry on POWER8 Benjamin Herrenschmidt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).