linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] powerpc: fixup lwsync at runtime
@ 2008-06-26 15:30 Kumar Gala
  0 siblings, 0 replies; 9+ messages in thread
From: Kumar Gala @ 2008-06-26 15:30 UTC (permalink / raw)
  To: linuxppc-dev

To allow for a single kernel image on e500 v1/v2/mc we need to fixup lwsync
at runtime.  On e500v1/v2 lwsync causes an illop so we need to patch up
the code.  We default to 'sync' since that is always safe and if the cpu
is capable we will replace 'sync' with 'lwsync'.

We introduce CPU_FTR_LWSYNC as a way to determine at runtime if this is
needed.  This flag could be moved elsewhere since we dont really use it
for the normal CPU_FTR purpose.

Finally we only store the relative offset in the fixup section to keep it
as small as possible rather than using a full fixup_entry.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---

This patch is based on my powerpc-next tree, mpe's tree and my module
refactor patch.

- k

 arch/powerpc/kernel/module.c            |    6 ++++++
 arch/powerpc/kernel/setup_32.c          |    4 ++++
 arch/powerpc/kernel/setup_64.c          |    2 ++
 arch/powerpc/kernel/vdso.c              |   10 ++++++++++
 arch/powerpc/kernel/vdso32/vdso32.lds.S |    3 +++
 arch/powerpc/kernel/vdso64/vdso64.lds.S |    3 +++
 arch/powerpc/kernel/vmlinux.lds.S       |    6 ++++++
 arch/powerpc/lib/feature-fixups.c       |   16 ++++++++++++++++
 include/asm-powerpc/code-patching.h     |    3 ++-
 include/asm-powerpc/cputable.h          |   19 ++++++++++---------
 include/asm-powerpc/synch.h             |   27 ++++++++++++++++++++++-----
 11 files changed, 84 insertions(+), 15 deletions(-)

diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c
index 40dd52d..af07003 100644
--- a/arch/powerpc/kernel/module.c
+++ b/arch/powerpc/kernel/module.c
@@ -86,6 +86,12 @@ int module_finalize(const Elf_Ehdr *hdr,
 				  (void *)sect->sh_addr + sect->sh_size);
 #endif

+	sect = find_section(hdr, sechdrs, "__lwsync_fixup");
+	if (sect != NULL)
+		do_lwsync_fixups(cur_cpu_spec->cpu_features,
+				 (void *)sect->sh_addr,
+				 (void *)sect->sh_addr + sect->sh_size);
+
 	return 0;
 }

diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 9e83add..0109e7f 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -101,6 +101,10 @@ unsigned long __init early_init(unsigned long dt_ptr)
 			  PTRRELOC(&__start___ftr_fixup),
 			  PTRRELOC(&__stop___ftr_fixup));

+	do_lwsync_fixups(spec->cpu_features,
+			 PTRRELOC(&__start___lwsync_fixup),
+			 PTRRELOC(&__stop___lwsync_fixup));
+
 	return KERNELBASE + offset;
 }

diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 098fd96..04d8de9 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -363,6 +363,8 @@ void __init setup_system(void)
 			  &__start___ftr_fixup, &__stop___ftr_fixup);
 	do_feature_fixups(powerpc_firmware_features,
 			  &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
+	do_lwsync_fixups(cur_cpu_spec->cpu_features,
+			 &__start___lwsync_fixup, &__stop___lwsync_fixup);

 	/*
 	 * Unflatten the device-tree passed by prom_init or kexec
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index c21a626..32539b8 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -571,6 +571,11 @@ static __init int vdso_fixup_features(struct lib32_elfinfo *v32,
 	if (start64)
 		do_feature_fixups(powerpc_firmware_features,
 				  start64, start64 + size64);
+
+	start64 = find_section64(v64->hdr, "__lwsync_fixup", &size64);
+	if (start64)
+		do_lwsync_fixups(cur_cpu_spec->cpu_features,
+				 start64, start64 + size64);
 #endif /* CONFIG_PPC64 */

 	start32 = find_section32(v32->hdr, "__ftr_fixup", &size32);
@@ -585,6 +590,11 @@ static __init int vdso_fixup_features(struct lib32_elfinfo *v32,
 				  start32, start32 + size32);
 #endif /* CONFIG_PPC64 */

+	start32 = find_section32(v32->hdr, "__lwsync_fixup", &size32);
+	if (start32)
+		do_lwsync_fixups(cur_cpu_spec->cpu_features,
+				 start32, start32 + size32);
+
 	return 0;
 }

diff --git a/arch/powerpc/kernel/vdso32/vdso32.lds.S b/arch/powerpc/kernel/vdso32/vdso32.lds.S
index 2717935..be3b6a4 100644
--- a/arch/powerpc/kernel/vdso32/vdso32.lds.S
+++ b/arch/powerpc/kernel/vdso32/vdso32.lds.S
@@ -33,6 +33,9 @@ SECTIONS
 	. = ALIGN(8);
 	__ftr_fixup	: { *(__ftr_fixup) }

+	. = ALIGN(8);
+	__lwsync_fixup	: { *(__lwsync_fixup) }
+
 #ifdef CONFIG_PPC64
 	. = ALIGN(8);
 	__fw_ftr_fixup	: { *(__fw_ftr_fixup) }
diff --git a/arch/powerpc/kernel/vdso64/vdso64.lds.S b/arch/powerpc/kernel/vdso64/vdso64.lds.S
index e608d1b..d0b2526 100644
--- a/arch/powerpc/kernel/vdso64/vdso64.lds.S
+++ b/arch/powerpc/kernel/vdso64/vdso64.lds.S
@@ -35,6 +35,9 @@ SECTIONS
 	__ftr_fixup	: { *(__ftr_fixup) }

 	. = ALIGN(8);
+	__lwsync_fixup	: { *(__lwsync_fixup) }
+
+	. = ALIGN(8);
 	__fw_ftr_fixup	: { *(__fw_ftr_fixup) }

 	/*
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 3c07811..6856f6c 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -127,6 +127,12 @@ SECTIONS
 		*(__ftr_fixup)
 		__stop___ftr_fixup = .;
 	}
+	. = ALIGN(8);
+	__lwsync_fixup : AT(ADDR(__lwsync_fixup) - LOAD_OFFSET) {
+		__start___lwsync_fixup = .;
+		*(__lwsync_fixup)
+		__stop___lwsync_fixup = .;
+	}
 #ifdef CONFIG_PPC64
 	. = ALIGN(8);
 	__fw_ftr_fixup : AT(ADDR(__fw_ftr_fixup) - LOAD_OFFSET) {
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
index 48e1ed8..ac5f5a1 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -110,6 +110,22 @@ void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end)
 	}
 }

+void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end)
+{
+	unsigned int *start, *end, *dest;
+
+	if (!(value & CPU_FTR_LWSYNC))
+		return ;
+
+	start = fixup_start;
+	end = fixup_end;
+
+	for (; start < end; start++) {
+		dest = (void *)start + *start;
+		patch_instruction(dest, PPC_LWSYNC_INSTR);
+	}
+}
+
 #ifdef CONFIG_FTR_FIXUP_SELFTEST

 #define check(x)	\
diff --git a/include/asm-powerpc/code-patching.h b/include/asm-powerpc/code-patching.h
index ef3a5d1..107d9b9 100644
--- a/include/asm-powerpc/code-patching.h
+++ b/include/asm-powerpc/code-patching.h
@@ -12,7 +12,8 @@

 #include <asm/types.h>

-#define PPC_NOP_INSTR	0x60000000
+#define PPC_NOP_INSTR		0x60000000
+#define PPC_LWSYNC_INSTR	0x7c2004ac

 /* Flags for create_branch:
  * "b"   == create_branch(addr, target, 0);
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
index becea99..f4ad060 100644
--- a/include/asm-powerpc/cputable.h
+++ b/include/asm-powerpc/cputable.h
@@ -153,6 +153,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
 #define CPU_FTR_UNIFIED_ID_CACHE	ASM_CONST(0x0000000001000000)
 #define CPU_FTR_SPE			ASM_CONST(0x0000000002000000)
 #define CPU_FTR_NEED_PAIRED_STWCX	ASM_CONST(0x0000000004000000)
+#define CPU_FTR_LWSYNC			ASM_CONST(0x0000000008000000)

 /*
  * Add the 64-bit processor unique features in the top half of the word;
@@ -354,37 +355,37 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
 	    CPU_FTR_NODSISRALIGN)
 #define CPU_FTRS_E500MC	(CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN | \
-	    CPU_FTR_L2CSR)
+	    CPU_FTR_L2CSR | CPU_FTR_LWSYNC)
 #define CPU_FTRS_GENERIC_32	(CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)

 /* 64-bit CPUs */
-#define CPU_FTRS_POWER3	(CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER3	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | CPU_FTR_PPC_LE)
-#define CPU_FTRS_RS64	(CPU_FTR_USE_TB | \
+#define CPU_FTRS_RS64	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | \
 	    CPU_FTR_MMCRA | CPU_FTR_CTRL)
-#define CPU_FTRS_POWER4	(CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER4	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_MMCRA)
-#define CPU_FTRS_PPC970	(CPU_FTR_USE_TB | \
+#define CPU_FTRS_PPC970	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA)
-#define CPU_FTRS_POWER5	(CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER5	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
 	    CPU_FTR_PURR)
-#define CPU_FTRS_POWER6 (CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER6 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
 	    CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
 	    CPU_FTR_DSCR)
-#define CPU_FTRS_CELL	(CPU_FTR_USE_TB | \
+#define CPU_FTRS_CELL	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_CELL_TB_BUG)
-#define CPU_FTRS_PA6T (CPU_FTR_USE_TB | \
+#define CPU_FTRS_PA6T (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \
 	    CPU_FTR_PURR | CPU_FTR_REAL_LE | CPU_FTR_NO_SLBIE_B)
diff --git a/include/asm-powerpc/synch.h b/include/asm-powerpc/synch.h
index 42a1ef5..4737c61 100644
--- a/include/asm-powerpc/synch.h
+++ b/include/asm-powerpc/synch.h
@@ -3,20 +3,37 @@
 #ifdef __KERNEL__

 #include <linux/stringify.h>
+#include <asm/feature-fixups.h>

-#if defined(__powerpc64__) || defined(CONFIG_PPC_E500MC)
-#define __SUBARCH_HAS_LWSYNC
-#endif
+#ifndef __ASSEMBLY__
+extern unsigned int __start___lwsync_fixup, __stop___lwsync_fixup;
+extern void do_lwsync_fixups(unsigned long value, void *fixup_start,
+			     void *fixup_end);
+#endif /* __ASSEMBLY__ */
+
+#define START_LWSYNC_SECTION(label)	label##1:
+#define MAKE_LWSYNC_SECTION_ENTRY(label, sect)		\
+label##4:						\
+	.pushsection sect,"a";				\
+	.align 2;					\
+label##5:					       	\
+	.long label##1b-label##5b;			\
+	.popsection;

-#ifdef __SUBARCH_HAS_LWSYNC
+#if defined(__powerpc64__)
 #    define LWSYNC	lwsync
+#elif defined(CONFIG_E500)
+#    define LWSYNC					\
+	START_LWSYNC_SECTION(97);			\
+	sync;						\
+	MAKE_LWSYNC_SECTION_ENTRY(97, __lwsync_fixup);
 #else
 #    define LWSYNC	sync
 #endif

 #ifdef CONFIG_SMP
 #define ISYNC_ON_SMP	"\n\tisync\n"
-#define LWSYNC_ON_SMP	__stringify(LWSYNC) "\n"
+#define LWSYNC_ON_SMP	stringify_in_c(LWSYNC) "\n"
 #else
 #define ISYNC_ON_SMP
 #define LWSYNC_ON_SMP
-- 
1.5.5.1

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

* [PATCH] powerpc: fixup lwsync at runtime
@ 2008-07-01  5:32 Kumar Gala
  2008-07-01  6:23 ` Benjamin Herrenschmidt
  2008-07-01  6:29 ` Michael Ellerman
  0 siblings, 2 replies; 9+ messages in thread
From: Kumar Gala @ 2008-07-01  5:32 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Paul Mackerras

To allow for a single kernel image on e500 v1/v2/mc we need to fixup lwsync
at runtime.  On e500v1/v2 lwsync causes an illop so we need to patch up
the code.  We default to 'sync' since that is always safe and if the cpu
is capable we will replace 'sync' with 'lwsync'.

We introduce CPU_FTR_LWSYNC as a way to determine at runtime if this is
needed.  This flag could be moved elsewhere since we dont really use it
for the normal CPU_FTR purpose.

Finally we only store the relative offset in the fixup section to keep it
as small as possible rather than using a full fixup_entry.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---

Rebased against latest powerpc-next tree.

- k

 arch/powerpc/kernel/module.c            |    6 ++++++
 arch/powerpc/kernel/setup_32.c          |    4 ++++
 arch/powerpc/kernel/setup_64.c          |    2 ++
 arch/powerpc/kernel/vdso.c              |   10 ++++++++++
 arch/powerpc/kernel/vdso32/vdso32.lds.S |    3 +++
 arch/powerpc/kernel/vdso64/vdso64.lds.S |    3 +++
 arch/powerpc/kernel/vmlinux.lds.S       |    6 ++++++
 arch/powerpc/lib/feature-fixups.c       |   16 ++++++++++++++++
 include/asm-powerpc/code-patching.h     |    3 ++-
 include/asm-powerpc/cputable.h          |   21 +++++++++++----------
 include/asm-powerpc/synch.h             |   27 ++++++++++++++++++++++-----
 11 files changed, 85 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c
index 40dd52d..af07003 100644
--- a/arch/powerpc/kernel/module.c
+++ b/arch/powerpc/kernel/module.c
@@ -86,6 +86,12 @@ int module_finalize(const Elf_Ehdr *hdr,
 				  (void *)sect->sh_addr + sect->sh_size);
 #endif

+	sect = find_section(hdr, sechdrs, "__lwsync_fixup");
+	if (sect != NULL)
+		do_lwsync_fixups(cur_cpu_spec->cpu_features,
+				 (void *)sect->sh_addr,
+				 (void *)sect->sh_addr + sect->sh_size);
+
 	return 0;
 }

diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 9e83add..0109e7f 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -101,6 +101,10 @@ unsigned long __init early_init(unsigned long dt_ptr)
 			  PTRRELOC(&__start___ftr_fixup),
 			  PTRRELOC(&__stop___ftr_fixup));

+	do_lwsync_fixups(spec->cpu_features,
+			 PTRRELOC(&__start___lwsync_fixup),
+			 PTRRELOC(&__stop___lwsync_fixup));
+
 	return KERNELBASE + offset;
 }

diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 098fd96..04d8de9 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -363,6 +363,8 @@ void __init setup_system(void)
 			  &__start___ftr_fixup, &__stop___ftr_fixup);
 	do_feature_fixups(powerpc_firmware_features,
 			  &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
+	do_lwsync_fixups(cur_cpu_spec->cpu_features,
+			 &__start___lwsync_fixup, &__stop___lwsync_fixup);

 	/*
 	 * Unflatten the device-tree passed by prom_init or kexec
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index ce245a8..f177c60 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -571,6 +571,11 @@ static __init int vdso_fixup_features(struct lib32_elfinfo *v32,
 	if (start64)
 		do_feature_fixups(powerpc_firmware_features,
 				  start64, start64 + size64);
+
+	start64 = find_section64(v64->hdr, "__lwsync_fixup", &size64);
+	if (start64)
+		do_lwsync_fixups(cur_cpu_spec->cpu_features,
+				 start64, start64 + size64);
 #endif /* CONFIG_PPC64 */

 	start32 = find_section32(v32->hdr, "__ftr_fixup", &size32);
@@ -585,6 +590,11 @@ static __init int vdso_fixup_features(struct lib32_elfinfo *v32,
 				  start32, start32 + size32);
 #endif /* CONFIG_PPC64 */

+	start32 = find_section32(v32->hdr, "__lwsync_fixup", &size32);
+	if (start32)
+		do_lwsync_fixups(cur_cpu_spec->cpu_features,
+				 start32, start32 + size32);
+
 	return 0;
 }

diff --git a/arch/powerpc/kernel/vdso32/vdso32.lds.S b/arch/powerpc/kernel/vdso32/vdso32.lds.S
index 2717935..be3b6a4 100644
--- a/arch/powerpc/kernel/vdso32/vdso32.lds.S
+++ b/arch/powerpc/kernel/vdso32/vdso32.lds.S
@@ -33,6 +33,9 @@ SECTIONS
 	. = ALIGN(8);
 	__ftr_fixup	: { *(__ftr_fixup) }

+	. = ALIGN(8);
+	__lwsync_fixup	: { *(__lwsync_fixup) }
+
 #ifdef CONFIG_PPC64
 	. = ALIGN(8);
 	__fw_ftr_fixup	: { *(__fw_ftr_fixup) }
diff --git a/arch/powerpc/kernel/vdso64/vdso64.lds.S b/arch/powerpc/kernel/vdso64/vdso64.lds.S
index e608d1b..d0b2526 100644
--- a/arch/powerpc/kernel/vdso64/vdso64.lds.S
+++ b/arch/powerpc/kernel/vdso64/vdso64.lds.S
@@ -35,6 +35,9 @@ SECTIONS
 	__ftr_fixup	: { *(__ftr_fixup) }

 	. = ALIGN(8);
+	__lwsync_fixup	: { *(__lwsync_fixup) }
+
+	. = ALIGN(8);
 	__fw_ftr_fixup	: { *(__fw_ftr_fixup) }

 	/*
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 3c07811..6856f6c 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -127,6 +127,12 @@ SECTIONS
 		*(__ftr_fixup)
 		__stop___ftr_fixup = .;
 	}
+	. = ALIGN(8);
+	__lwsync_fixup : AT(ADDR(__lwsync_fixup) - LOAD_OFFSET) {
+		__start___lwsync_fixup = .;
+		*(__lwsync_fixup)
+		__stop___lwsync_fixup = .;
+	}
 #ifdef CONFIG_PPC64
 	. = ALIGN(8);
 	__fw_ftr_fixup : AT(ADDR(__fw_ftr_fixup) - LOAD_OFFSET) {
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
index 48e1ed8..ac5f5a1 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -110,6 +110,22 @@ void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end)
 	}
 }

+void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end)
+{
+	unsigned int *start, *end, *dest;
+
+	if (!(value & CPU_FTR_LWSYNC))
+		return ;
+
+	start = fixup_start;
+	end = fixup_end;
+
+	for (; start < end; start++) {
+		dest = (void *)start + *start;
+		patch_instruction(dest, PPC_LWSYNC_INSTR);
+	}
+}
+
 #ifdef CONFIG_FTR_FIXUP_SELFTEST

 #define check(x)	\
diff --git a/include/asm-powerpc/code-patching.h b/include/asm-powerpc/code-patching.h
index ef3a5d1..107d9b9 100644
--- a/include/asm-powerpc/code-patching.h
+++ b/include/asm-powerpc/code-patching.h
@@ -12,7 +12,8 @@

 #include <asm/types.h>

-#define PPC_NOP_INSTR	0x60000000
+#define PPC_NOP_INSTR		0x60000000
+#define PPC_LWSYNC_INSTR	0x7c2004ac

 /* Flags for create_branch:
  * "b"   == create_branch(addr, target, 0);
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
index 4e4491c..3171ac9 100644
--- a/include/asm-powerpc/cputable.h
+++ b/include/asm-powerpc/cputable.h
@@ -156,6 +156,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
 #define CPU_FTR_UNIFIED_ID_CACHE	ASM_CONST(0x0000000001000000)
 #define CPU_FTR_SPE			ASM_CONST(0x0000000002000000)
 #define CPU_FTR_NEED_PAIRED_STWCX	ASM_CONST(0x0000000004000000)
+#define CPU_FTR_LWSYNC			ASM_CONST(0x0000000008000000)

 /*
  * Add the 64-bit processor unique features in the top half of the word;
@@ -369,43 +370,43 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
 	    CPU_FTR_NODSISRALIGN)
 #define CPU_FTRS_E500MC	(CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN | \
-	    CPU_FTR_L2CSR)
+	    CPU_FTR_L2CSR | CPU_FTR_LWSYNC)
 #define CPU_FTRS_GENERIC_32	(CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)

 /* 64-bit CPUs */
-#define CPU_FTRS_POWER3	(CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER3	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | CPU_FTR_PPC_LE)
-#define CPU_FTRS_RS64	(CPU_FTR_USE_TB | \
+#define CPU_FTRS_RS64	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | \
 	    CPU_FTR_MMCRA | CPU_FTR_CTRL)
-#define CPU_FTRS_POWER4	(CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER4	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_MMCRA)
-#define CPU_FTRS_PPC970	(CPU_FTR_USE_TB | \
+#define CPU_FTRS_PPC970	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA)
-#define CPU_FTRS_POWER5	(CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER5	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
 	    CPU_FTR_PURR)
-#define CPU_FTRS_POWER6 (CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER6 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
 	    CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
 	    CPU_FTR_DSCR)
-#define CPU_FTRS_POWER7 (CPU_FTR_USE_TB | \
+#define CPU_FTRS_POWER7 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
 	    CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
 	    CPU_FTR_DSCR)
-#define CPU_FTRS_CELL	(CPU_FTR_USE_TB | \
+#define CPU_FTRS_CELL	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_CELL_TB_BUG)
-#define CPU_FTRS_PA6T (CPU_FTR_USE_TB | \
+#define CPU_FTRS_PA6T (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \
 	    CPU_FTR_PURR | CPU_FTR_REAL_LE | CPU_FTR_NO_SLBIE_B)
diff --git a/include/asm-powerpc/synch.h b/include/asm-powerpc/synch.h
index 42a1ef5..4737c61 100644
--- a/include/asm-powerpc/synch.h
+++ b/include/asm-powerpc/synch.h
@@ -3,20 +3,37 @@
 #ifdef __KERNEL__

 #include <linux/stringify.h>
+#include <asm/feature-fixups.h>

-#if defined(__powerpc64__) || defined(CONFIG_PPC_E500MC)
-#define __SUBARCH_HAS_LWSYNC
-#endif
+#ifndef __ASSEMBLY__
+extern unsigned int __start___lwsync_fixup, __stop___lwsync_fixup;
+extern void do_lwsync_fixups(unsigned long value, void *fixup_start,
+			     void *fixup_end);
+#endif /* __ASSEMBLY__ */
+
+#define START_LWSYNC_SECTION(label)	label##1:
+#define MAKE_LWSYNC_SECTION_ENTRY(label, sect)		\
+label##4:						\
+	.pushsection sect,"a";				\
+	.align 2;					\
+label##5:					       	\
+	.long label##1b-label##5b;			\
+	.popsection;

-#ifdef __SUBARCH_HAS_LWSYNC
+#if defined(__powerpc64__)
 #    define LWSYNC	lwsync
+#elif defined(CONFIG_E500)
+#    define LWSYNC					\
+	START_LWSYNC_SECTION(97);			\
+	sync;						\
+	MAKE_LWSYNC_SECTION_ENTRY(97, __lwsync_fixup);
 #else
 #    define LWSYNC	sync
 #endif

 #ifdef CONFIG_SMP
 #define ISYNC_ON_SMP	"\n\tisync\n"
-#define LWSYNC_ON_SMP	__stringify(LWSYNC) "\n"
+#define LWSYNC_ON_SMP	stringify_in_c(LWSYNC) "\n"
 #else
 #define ISYNC_ON_SMP
 #define LWSYNC_ON_SMP
-- 
1.5.5.1

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

* Re: [PATCH] powerpc: fixup lwsync at runtime
  2008-07-01  5:32 [PATCH] powerpc: fixup lwsync at runtime Kumar Gala
@ 2008-07-01  6:23 ` Benjamin Herrenschmidt
  2008-07-01  7:15   ` Benjamin Herrenschmidt
  2008-07-01  6:29 ` Michael Ellerman
  1 sibling, 1 reply; 9+ messages in thread
From: Benjamin Herrenschmidt @ 2008-07-01  6:23 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev, Paul Mackerras

On Tue, 2008-07-01 at 00:32 -0500, Kumar Gala wrote:
> To allow for a single kernel image on e500 v1/v2/mc we need to fixup lwsync
> at runtime.  On e500v1/v2 lwsync causes an illop so we need to patch up
> the code.  We default to 'sync' since that is always safe and if the cpu
> is capable we will replace 'sync' with 'lwsync'.
> 
> We introduce CPU_FTR_LWSYNC as a way to determine at runtime if this is
> needed.  This flag could be moved elsewhere since we dont really use it
> for the normal CPU_FTR purpose.
> 
> Finally we only store the relative offset in the fixup section to keep it
> as small as possible rather than using a full fixup_entry.
> 
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>

I'd rather have some more generic "alternatives" stuff but in the
meantime, Ack.

> ---
> 
> Rebased against latest powerpc-next tree.
> 
> - k
> 
>  arch/powerpc/kernel/module.c            |    6 ++++++
>  arch/powerpc/kernel/setup_32.c          |    4 ++++
>  arch/powerpc/kernel/setup_64.c          |    2 ++
>  arch/powerpc/kernel/vdso.c              |   10 ++++++++++
>  arch/powerpc/kernel/vdso32/vdso32.lds.S |    3 +++
>  arch/powerpc/kernel/vdso64/vdso64.lds.S |    3 +++
>  arch/powerpc/kernel/vmlinux.lds.S       |    6 ++++++
>  arch/powerpc/lib/feature-fixups.c       |   16 ++++++++++++++++
>  include/asm-powerpc/code-patching.h     |    3 ++-
>  include/asm-powerpc/cputable.h          |   21 +++++++++++----------
>  include/asm-powerpc/synch.h             |   27 ++++++++++++++++++++++-----
>  11 files changed, 85 insertions(+), 16 deletions(-)
> 
> diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c
> index 40dd52d..af07003 100644
> --- a/arch/powerpc/kernel/module.c
> +++ b/arch/powerpc/kernel/module.c
> @@ -86,6 +86,12 @@ int module_finalize(const Elf_Ehdr *hdr,
>  				  (void *)sect->sh_addr + sect->sh_size);
>  #endif
> 
> +	sect = find_section(hdr, sechdrs, "__lwsync_fixup");
> +	if (sect != NULL)
> +		do_lwsync_fixups(cur_cpu_spec->cpu_features,
> +				 (void *)sect->sh_addr,
> +				 (void *)sect->sh_addr + sect->sh_size);
> +
>  	return 0;
>  }
> 
> diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
> index 9e83add..0109e7f 100644
> --- a/arch/powerpc/kernel/setup_32.c
> +++ b/arch/powerpc/kernel/setup_32.c
> @@ -101,6 +101,10 @@ unsigned long __init early_init(unsigned long dt_ptr)
>  			  PTRRELOC(&__start___ftr_fixup),
>  			  PTRRELOC(&__stop___ftr_fixup));
> 
> +	do_lwsync_fixups(spec->cpu_features,
> +			 PTRRELOC(&__start___lwsync_fixup),
> +			 PTRRELOC(&__stop___lwsync_fixup));
> +
>  	return KERNELBASE + offset;
>  }
> 
> diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
> index 098fd96..04d8de9 100644
> --- a/arch/powerpc/kernel/setup_64.c
> +++ b/arch/powerpc/kernel/setup_64.c
> @@ -363,6 +363,8 @@ void __init setup_system(void)
>  			  &__start___ftr_fixup, &__stop___ftr_fixup);
>  	do_feature_fixups(powerpc_firmware_features,
>  			  &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
> +	do_lwsync_fixups(cur_cpu_spec->cpu_features,
> +			 &__start___lwsync_fixup, &__stop___lwsync_fixup);
> 
>  	/*
>  	 * Unflatten the device-tree passed by prom_init or kexec
> diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
> index ce245a8..f177c60 100644
> --- a/arch/powerpc/kernel/vdso.c
> +++ b/arch/powerpc/kernel/vdso.c
> @@ -571,6 +571,11 @@ static __init int vdso_fixup_features(struct lib32_elfinfo *v32,
>  	if (start64)
>  		do_feature_fixups(powerpc_firmware_features,
>  				  start64, start64 + size64);
> +
> +	start64 = find_section64(v64->hdr, "__lwsync_fixup", &size64);
> +	if (start64)
> +		do_lwsync_fixups(cur_cpu_spec->cpu_features,
> +				 start64, start64 + size64);
>  #endif /* CONFIG_PPC64 */
> 
>  	start32 = find_section32(v32->hdr, "__ftr_fixup", &size32);
> @@ -585,6 +590,11 @@ static __init int vdso_fixup_features(struct lib32_elfinfo *v32,
>  				  start32, start32 + size32);
>  #endif /* CONFIG_PPC64 */
> 
> +	start32 = find_section32(v32->hdr, "__lwsync_fixup", &size32);
> +	if (start32)
> +		do_lwsync_fixups(cur_cpu_spec->cpu_features,
> +				 start32, start32 + size32);
> +
>  	return 0;
>  }
> 
> diff --git a/arch/powerpc/kernel/vdso32/vdso32.lds.S b/arch/powerpc/kernel/vdso32/vdso32.lds.S
> index 2717935..be3b6a4 100644
> --- a/arch/powerpc/kernel/vdso32/vdso32.lds.S
> +++ b/arch/powerpc/kernel/vdso32/vdso32.lds.S
> @@ -33,6 +33,9 @@ SECTIONS
>  	. = ALIGN(8);
>  	__ftr_fixup	: { *(__ftr_fixup) }
> 
> +	. = ALIGN(8);
> +	__lwsync_fixup	: { *(__lwsync_fixup) }
> +
>  #ifdef CONFIG_PPC64
>  	. = ALIGN(8);
>  	__fw_ftr_fixup	: { *(__fw_ftr_fixup) }
> diff --git a/arch/powerpc/kernel/vdso64/vdso64.lds.S b/arch/powerpc/kernel/vdso64/vdso64.lds.S
> index e608d1b..d0b2526 100644
> --- a/arch/powerpc/kernel/vdso64/vdso64.lds.S
> +++ b/arch/powerpc/kernel/vdso64/vdso64.lds.S
> @@ -35,6 +35,9 @@ SECTIONS
>  	__ftr_fixup	: { *(__ftr_fixup) }
> 
>  	. = ALIGN(8);
> +	__lwsync_fixup	: { *(__lwsync_fixup) }
> +
> +	. = ALIGN(8);
>  	__fw_ftr_fixup	: { *(__fw_ftr_fixup) }
> 
>  	/*
> diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
> index 3c07811..6856f6c 100644
> --- a/arch/powerpc/kernel/vmlinux.lds.S
> +++ b/arch/powerpc/kernel/vmlinux.lds.S
> @@ -127,6 +127,12 @@ SECTIONS
>  		*(__ftr_fixup)
>  		__stop___ftr_fixup = .;
>  	}
> +	. = ALIGN(8);
> +	__lwsync_fixup : AT(ADDR(__lwsync_fixup) - LOAD_OFFSET) {
> +		__start___lwsync_fixup = .;
> +		*(__lwsync_fixup)
> +		__stop___lwsync_fixup = .;
> +	}
>  #ifdef CONFIG_PPC64
>  	. = ALIGN(8);
>  	__fw_ftr_fixup : AT(ADDR(__fw_ftr_fixup) - LOAD_OFFSET) {
> diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
> index 48e1ed8..ac5f5a1 100644
> --- a/arch/powerpc/lib/feature-fixups.c
> +++ b/arch/powerpc/lib/feature-fixups.c
> @@ -110,6 +110,22 @@ void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end)
>  	}
>  }
> 
> +void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end)
> +{
> +	unsigned int *start, *end, *dest;
> +
> +	if (!(value & CPU_FTR_LWSYNC))
> +		return ;
> +
> +	start = fixup_start;
> +	end = fixup_end;
> +
> +	for (; start < end; start++) {
> +		dest = (void *)start + *start;
> +		patch_instruction(dest, PPC_LWSYNC_INSTR);
> +	}
> +}
> +
>  #ifdef CONFIG_FTR_FIXUP_SELFTEST
> 
>  #define check(x)	\
> diff --git a/include/asm-powerpc/code-patching.h b/include/asm-powerpc/code-patching.h
> index ef3a5d1..107d9b9 100644
> --- a/include/asm-powerpc/code-patching.h
> +++ b/include/asm-powerpc/code-patching.h
> @@ -12,7 +12,8 @@
> 
>  #include <asm/types.h>
> 
> -#define PPC_NOP_INSTR	0x60000000
> +#define PPC_NOP_INSTR		0x60000000
> +#define PPC_LWSYNC_INSTR	0x7c2004ac
> 
>  /* Flags for create_branch:
>   * "b"   == create_branch(addr, target, 0);
> diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
> index 4e4491c..3171ac9 100644
> --- a/include/asm-powerpc/cputable.h
> +++ b/include/asm-powerpc/cputable.h
> @@ -156,6 +156,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
>  #define CPU_FTR_UNIFIED_ID_CACHE	ASM_CONST(0x0000000001000000)
>  #define CPU_FTR_SPE			ASM_CONST(0x0000000002000000)
>  #define CPU_FTR_NEED_PAIRED_STWCX	ASM_CONST(0x0000000004000000)
> +#define CPU_FTR_LWSYNC			ASM_CONST(0x0000000008000000)
> 
>  /*
>   * Add the 64-bit processor unique features in the top half of the word;
> @@ -369,43 +370,43 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
>  	    CPU_FTR_NODSISRALIGN)
>  #define CPU_FTRS_E500MC	(CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
>  	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN | \
> -	    CPU_FTR_L2CSR)
> +	    CPU_FTR_L2CSR | CPU_FTR_LWSYNC)
>  #define CPU_FTRS_GENERIC_32	(CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
> 
>  /* 64-bit CPUs */
> -#define CPU_FTRS_POWER3	(CPU_FTR_USE_TB | \
> +#define CPU_FTRS_POWER3	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
>  	    CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | CPU_FTR_PPC_LE)
> -#define CPU_FTRS_RS64	(CPU_FTR_USE_TB | \
> +#define CPU_FTRS_RS64	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
>  	    CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | \
>  	    CPU_FTR_MMCRA | CPU_FTR_CTRL)
> -#define CPU_FTRS_POWER4	(CPU_FTR_USE_TB | \
> +#define CPU_FTRS_POWER4	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
>  	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
>  	    CPU_FTR_MMCRA)
> -#define CPU_FTRS_PPC970	(CPU_FTR_USE_TB | \
> +#define CPU_FTRS_PPC970	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
>  	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
>  	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA)
> -#define CPU_FTRS_POWER5	(CPU_FTR_USE_TB | \
> +#define CPU_FTRS_POWER5	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
>  	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
>  	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
>  	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
>  	    CPU_FTR_PURR)
> -#define CPU_FTRS_POWER6 (CPU_FTR_USE_TB | \
> +#define CPU_FTRS_POWER6 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
>  	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
>  	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
>  	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
>  	    CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
>  	    CPU_FTR_DSCR)
> -#define CPU_FTRS_POWER7 (CPU_FTR_USE_TB | \
> +#define CPU_FTRS_POWER7 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
>  	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
>  	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
>  	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
>  	    CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
>  	    CPU_FTR_DSCR)
> -#define CPU_FTRS_CELL	(CPU_FTR_USE_TB | \
> +#define CPU_FTRS_CELL	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
>  	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
>  	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
>  	    CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_CELL_TB_BUG)
> -#define CPU_FTRS_PA6T (CPU_FTR_USE_TB | \
> +#define CPU_FTRS_PA6T (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
>  	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
>  	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \
>  	    CPU_FTR_PURR | CPU_FTR_REAL_LE | CPU_FTR_NO_SLBIE_B)
> diff --git a/include/asm-powerpc/synch.h b/include/asm-powerpc/synch.h
> index 42a1ef5..4737c61 100644
> --- a/include/asm-powerpc/synch.h
> +++ b/include/asm-powerpc/synch.h
> @@ -3,20 +3,37 @@
>  #ifdef __KERNEL__
> 
>  #include <linux/stringify.h>
> +#include <asm/feature-fixups.h>
> 
> -#if defined(__powerpc64__) || defined(CONFIG_PPC_E500MC)
> -#define __SUBARCH_HAS_LWSYNC
> -#endif
> +#ifndef __ASSEMBLY__
> +extern unsigned int __start___lwsync_fixup, __stop___lwsync_fixup;
> +extern void do_lwsync_fixups(unsigned long value, void *fixup_start,
> +			     void *fixup_end);
> +#endif /* __ASSEMBLY__ */
> +
> +#define START_LWSYNC_SECTION(label)	label##1:
> +#define MAKE_LWSYNC_SECTION_ENTRY(label, sect)		\
> +label##4:						\
> +	.pushsection sect,"a";				\
> +	.align 2;					\
> +label##5:					       	\
> +	.long label##1b-label##5b;			\
> +	.popsection;
> 
> -#ifdef __SUBARCH_HAS_LWSYNC
> +#if defined(__powerpc64__)
>  #    define LWSYNC	lwsync
> +#elif defined(CONFIG_E500)
> +#    define LWSYNC					\
> +	START_LWSYNC_SECTION(97);			\
> +	sync;						\
> +	MAKE_LWSYNC_SECTION_ENTRY(97, __lwsync_fixup);
>  #else
>  #    define LWSYNC	sync
>  #endif
> 
>  #ifdef CONFIG_SMP
>  #define ISYNC_ON_SMP	"\n\tisync\n"
> -#define LWSYNC_ON_SMP	__stringify(LWSYNC) "\n"
> +#define LWSYNC_ON_SMP	stringify_in_c(LWSYNC) "\n"
>  #else
>  #define ISYNC_ON_SMP
>  #define LWSYNC_ON_SMP

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

* Re: [PATCH] powerpc: fixup lwsync at runtime
  2008-07-01  5:32 [PATCH] powerpc: fixup lwsync at runtime Kumar Gala
  2008-07-01  6:23 ` Benjamin Herrenschmidt
@ 2008-07-01  6:29 ` Michael Ellerman
  2008-07-01 14:48   ` Kumar Gala
  1 sibling, 1 reply; 9+ messages in thread
From: Michael Ellerman @ 2008-07-01  6:29 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev, Paul Mackerras

[-- Attachment #1: Type: text/plain, Size: 4013 bytes --]

On Tue, 2008-07-01 at 00:32 -0500, Kumar Gala wrote:
> To allow for a single kernel image on e500 v1/v2/mc we need to fixup lwsync
> at runtime.  On e500v1/v2 lwsync causes an illop so we need to patch up
> the code.  We default to 'sync' since that is always safe and if the cpu
> is capable we will replace 'sync' with 'lwsync'.
> 
> We introduce CPU_FTR_LWSYNC as a way to determine at runtime if this is
> needed.  This flag could be moved elsewhere since we dont really use it
> for the normal CPU_FTR purpose.
> 
> Finally we only store the relative offset in the fixup section to keep it
> as small as possible rather than using a full fixup_entry.

How many entries are we talking? I guess it's not much bother to have a
separate section.

> diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
> index 9e83add..0109e7f 100644
> --- a/arch/powerpc/kernel/setup_32.c
> +++ b/arch/powerpc/kernel/setup_32.c
> @@ -101,6 +101,10 @@ unsigned long __init early_init(unsigned long dt_ptr)
>  			  PTRRELOC(&__start___ftr_fixup),
>  			  PTRRELOC(&__stop___ftr_fixup));
> 
> +	do_lwsync_fixups(spec->cpu_features,
> +			 PTRRELOC(&__start___lwsync_fixup),
> +			 PTRRELOC(&__stop___lwsync_fixup));
> +

This could be changed to use cur_cpu_spec->cpu_features, and then all
the call sites would be passing that, which would mean
do_lwsync_fixups() could just check cur_cpu_spec->cpu_features directly.

> diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
> index 48e1ed8..ac5f5a1 100644
> --- a/arch/powerpc/lib/feature-fixups.c
> +++ b/arch/powerpc/lib/feature-fixups.c
> @@ -110,6 +110,22 @@ void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end)
>  	}
>  }
> 
> +void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end)
> +{
> +	unsigned int *start, *end, *dest;
> +
> +	if (!(value & CPU_FTR_LWSYNC))
> +		return ;
> +
> +	start = fixup_start;
> +	end = fixup_end;
> +
> +	for (; start < end; start++) {
> +		dest = (void *)start + *start;
> +		patch_instruction(dest, PPC_LWSYNC_INSTR);
> +	}
> +}
> +
>  #ifdef CONFIG_FTR_FIXUP_SELFTEST

...

No tests? :)

> diff --git a/include/asm-powerpc/synch.h b/include/asm-powerpc/synch.h
> index 42a1ef5..4737c61 100644
> --- a/include/asm-powerpc/synch.h
> +++ b/include/asm-powerpc/synch.h
> @@ -3,20 +3,37 @@
>  #ifdef __KERNEL__
> 
>  #include <linux/stringify.h>
> +#include <asm/feature-fixups.h>
> 
> -#if defined(__powerpc64__) || defined(CONFIG_PPC_E500MC)
> -#define __SUBARCH_HAS_LWSYNC
> -#endif
> +#ifndef __ASSEMBLY__
> +extern unsigned int __start___lwsync_fixup, __stop___lwsync_fixup;
> +extern void do_lwsync_fixups(unsigned long value, void *fixup_start,
> +			     void *fixup_end);
> +#endif /* __ASSEMBLY__ */
> +
> +#define START_LWSYNC_SECTION(label)	label##1:
> +#define MAKE_LWSYNC_SECTION_ENTRY(label, sect)		\
> +label##4:						\
> +	.pushsection sect,"a";				\
> +	.align 2;					\
> +label##5:					       	\
> +	.long label##1b-label##5b;			\
> +	.popsection;

I'd rather this was in feature-fixups.h, seeing as I just moved all the
feature-fixup related macros in there :)

It might make more sense to use label##2 and label##3.

> 
> -#ifdef __SUBARCH_HAS_LWSYNC
> +#if defined(__powerpc64__)
>  #    define LWSYNC	lwsync
> +#elif defined(CONFIG_E500)
> +#    define LWSYNC					\
> +	START_LWSYNC_SECTION(97);			\
> +	sync;						\
> +	MAKE_LWSYNC_SECTION_ENTRY(97, __lwsync_fixup);
>  #else
>  #    define LWSYNC	sync
>  #endif

Using 97 means you can't nest an LWSYNC inside a feature or firmware
feature section, if you use say 96 then nesting should work.

cheers

-- 
Michael Ellerman
OzLabs, IBM Australia Development Lab

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

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

* Re: [PATCH] powerpc: fixup lwsync at runtime
  2008-07-01  6:23 ` Benjamin Herrenschmidt
@ 2008-07-01  7:15   ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 9+ messages in thread
From: Benjamin Herrenschmidt @ 2008-07-01  7:15 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev, Paul Mackerras

On Tue, 2008-07-01 at 16:23 +1000, Benjamin Herrenschmidt wrote:
> On Tue, 2008-07-01 at 00:32 -0500, Kumar Gala wrote:
> > To allow for a single kernel image on e500 v1/v2/mc we need to fixup lwsync
> > at runtime.  On e500v1/v2 lwsync causes an illop so we need to patch up
> > the code.  We default to 'sync' since that is always safe and if the cpu
> > is capable we will replace 'sync' with 'lwsync'.
> > 
> > We introduce CPU_FTR_LWSYNC as a way to determine at runtime if this is
> > needed.  This flag could be moved elsewhere since we dont really use it
> > for the normal CPU_FTR purpose.
> > 
> > Finally we only store the relative offset in the fixup section to keep it
> > as small as possible rather than using a full fixup_entry.
> > 
> > Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> 
> I'd rather have some more generic "alternatives" stuff but in the
> meantime, Ack.

Hrm... minus mpe's comments...

Cheers,
Ben.

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

* Re: [PATCH] powerpc: fixup lwsync at runtime
  2008-07-01  6:29 ` Michael Ellerman
@ 2008-07-01 14:48   ` Kumar Gala
  2008-07-02  9:34     ` Michael Ellerman
  0 siblings, 1 reply; 9+ messages in thread
From: Kumar Gala @ 2008-07-01 14:48 UTC (permalink / raw)
  To: michael; +Cc: linuxppc-dev, Paul Mackerras


On Jul 1, 2008, at 1:29 AM, Michael Ellerman wrote:

> On Tue, 2008-07-01 at 00:32 -0500, Kumar Gala wrote:
>> To allow for a single kernel image on e500 v1/v2/mc we need to  
>> fixup lwsync
>> at runtime.  On e500v1/v2 lwsync causes an illop so we need to  
>> patch up
>> the code.  We default to 'sync' since that is always safe and if  
>> the cpu
>> is capable we will replace 'sync' with 'lwsync'.
>>
>> We introduce CPU_FTR_LWSYNC as a way to determine at runtime if  
>> this is
>> needed.  This flag could be moved elsewhere since we dont really  
>> use it
>> for the normal CPU_FTR purpose.
>>
>> Finally we only store the relative offset in the fixup section to  
>> keep it
>> as small as possible rather than using a full fixup_entry.
>
> How many entries are we talking? I guess it's not much bother to  
> have a
> separate section.

On the order of 1000 entries for an SMP build.

>> diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/ 
>> setup_32.c
>> index 9e83add..0109e7f 100644
>> --- a/arch/powerpc/kernel/setup_32.c
>> +++ b/arch/powerpc/kernel/setup_32.c
>> @@ -101,6 +101,10 @@ unsigned long __init early_init(unsigned long  
>> dt_ptr)
>> 			  PTRRELOC(&__start___ftr_fixup),
>> 			  PTRRELOC(&__stop___ftr_fixup));
>>
>> +	do_lwsync_fixups(spec->cpu_features,
>> +			 PTRRELOC(&__start___lwsync_fixup),
>> +			 PTRRELOC(&__stop___lwsync_fixup));
>> +
>
> This could be changed to use cur_cpu_spec->cpu_features, and then all
> the call sites would be passing that, which would mean
> do_lwsync_fixups() could just check cur_cpu_spec->cpu_features  
> directly.

cur_cpu_spec and spec at this point arent the same thing.

will post a new version w/fixes.

- k

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

* Re: [PATCH] powerpc: fixup lwsync at runtime
  2008-07-01 14:48   ` Kumar Gala
@ 2008-07-02  9:34     ` Michael Ellerman
  2008-07-02 15:57       ` Kumar Gala
  0 siblings, 1 reply; 9+ messages in thread
From: Michael Ellerman @ 2008-07-02  9:34 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev, Paul Mackerras

[-- Attachment #1: Type: text/plain, Size: 2001 bytes --]

On Tue, 2008-07-01 at 09:48 -0500, Kumar Gala wrote:
> On Jul 1, 2008, at 1:29 AM, Michael Ellerman wrote:

> >> diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/ 
> >> setup_32.c
> >> index 9e83add..0109e7f 100644
> >> --- a/arch/powerpc/kernel/setup_32.c
> >> +++ b/arch/powerpc/kernel/setup_32.c
> >> @@ -101,6 +101,10 @@ unsigned long __init early_init(unsigned long  
> >> dt_ptr)
> >> 			  PTRRELOC(&__start___ftr_fixup),
> >> 			  PTRRELOC(&__stop___ftr_fixup));
> >>
> >> +	do_lwsync_fixups(spec->cpu_features,
> >> +			 PTRRELOC(&__start___lwsync_fixup),
> >> +			 PTRRELOC(&__stop___lwsync_fixup));
> >> +
> >
> > This could be changed to use cur_cpu_spec->cpu_features, and then all
> > the call sites would be passing that, which would mean
> > do_lwsync_fixups() could just check cur_cpu_spec->cpu_features  
> > directly.
> 
> cur_cpu_spec and spec at this point arent the same thing.

Aren't they? I must be missing something:

struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr)
{
        struct cpu_spec *s = cpu_specs;
        struct cpu_spec *t = &the_cpu_spec;
        int i;

        for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++)
                if ((pvr & s->pvr_mask) == s->pvr_value) {
			...
                        *t = *s;
                        *PTRRELOC(&cur_cpu_spec) = &the_cpu_spec;
			...
                        return s;

then:

unsigned long __init early_init(unsigned long dt_ptr)
{
	...
	spec = identify_cpu(offset, mfspr(SPRN_PVR));

        do_feature_fixups(spec->cpu_features,
                          PTRRELOC(&__start___ftr_fixup),
                          PTRRELOC(&__stop___ftr_fixup));
}


cheers

-- 
Michael Ellerman
OzLabs, IBM Australia Development Lab

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

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

* Re: [PATCH] powerpc: fixup lwsync at runtime
  2008-07-02  9:34     ` Michael Ellerman
@ 2008-07-02 15:57       ` Kumar Gala
  2008-07-03  5:55         ` Michael Ellerman
  0 siblings, 1 reply; 9+ messages in thread
From: Kumar Gala @ 2008-07-02 15:57 UTC (permalink / raw)
  To: michael; +Cc: linuxppc-dev, Paul Mackerras


On Jul 2, 2008, at 4:34 AM, Michael Ellerman wrote:

> On Tue, 2008-07-01 at 09:48 -0500, Kumar Gala wrote:
>> On Jul 1, 2008, at 1:29 AM, Michael Ellerman wrote:
>
>>>> diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/
>>>> setup_32.c
>>>> index 9e83add..0109e7f 100644
>>>> --- a/arch/powerpc/kernel/setup_32.c
>>>> +++ b/arch/powerpc/kernel/setup_32.c
>>>> @@ -101,6 +101,10 @@ unsigned long __init early_init(unsigned long
>>>> dt_ptr)
>>>> 			  PTRRELOC(&__start___ftr_fixup),
>>>> 			  PTRRELOC(&__stop___ftr_fixup));
>>>>
>>>> +	do_lwsync_fixups(spec->cpu_features,
>>>> +			 PTRRELOC(&__start___lwsync_fixup),
>>>> +			 PTRRELOC(&__stop___lwsync_fixup));
>>>> +
>>>
>>> This could be changed to use cur_cpu_spec->cpu_features, and then  
>>> all
>>> the call sites would be passing that, which would mean
>>> do_lwsync_fixups() could just check cur_cpu_spec->cpu_features
>>> directly.
>>
>> cur_cpu_spec and spec at this point arent the same thing.
>
> Aren't they? I must be missing something:

There is an issue with how ppc32 classic gets here and relocation.  If  
I change the call to:

         do_lwsync_fixups(cur_cpu_spec->cpu_features,
                          PTRRELOC(&__start___lwsync_fixup),
                          PTRRELOC(&__stop___lwsync_fixup));

I can't boot on a 6xx based machine anymore.

- k

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

* Re: [PATCH] powerpc: fixup lwsync at runtime
  2008-07-02 15:57       ` Kumar Gala
@ 2008-07-03  5:55         ` Michael Ellerman
  0 siblings, 0 replies; 9+ messages in thread
From: Michael Ellerman @ 2008-07-03  5:55 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev, Paul Mackerras

[-- Attachment #1: Type: text/plain, Size: 1859 bytes --]

On Wed, 2008-07-02 at 10:57 -0500, Kumar Gala wrote:
> On Jul 2, 2008, at 4:34 AM, Michael Ellerman wrote:
> 
> > On Tue, 2008-07-01 at 09:48 -0500, Kumar Gala wrote:
> >> On Jul 1, 2008, at 1:29 AM, Michael Ellerman wrote:
> >
> >>>> diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/
> >>>> setup_32.c
> >>>> index 9e83add..0109e7f 100644
> >>>> --- a/arch/powerpc/kernel/setup_32.c
> >>>> +++ b/arch/powerpc/kernel/setup_32.c
> >>>> @@ -101,6 +101,10 @@ unsigned long __init early_init(unsigned long
> >>>> dt_ptr)
> >>>> 			  PTRRELOC(&__start___ftr_fixup),
> >>>> 			  PTRRELOC(&__stop___ftr_fixup));
> >>>>
> >>>> +	do_lwsync_fixups(spec->cpu_features,
> >>>> +			 PTRRELOC(&__start___lwsync_fixup),
> >>>> +			 PTRRELOC(&__stop___lwsync_fixup));
> >>>> +
> >>>
> >>> This could be changed to use cur_cpu_spec->cpu_features, and then  
> >>> all
> >>> the call sites would be passing that, which would mean
> >>> do_lwsync_fixups() could just check cur_cpu_spec->cpu_features
> >>> directly.
> >>
> >> cur_cpu_spec and spec at this point arent the same thing.
> >
> > Aren't they? I must be missing something:
> 
> There is an issue with how ppc32 classic gets here and relocation.  If  
> I change the call to:
> 
>          do_lwsync_fixups(cur_cpu_spec->cpu_features,
>                           PTRRELOC(&__start___lwsync_fixup),
>                           PTRRELOC(&__stop___lwsync_fixup));
> 
> I can't boot on a 6xx based machine anymore.

OK, I guess it needs a PTRRELOC(), but it's not that important, don't
worry about it.

cheers

-- 
Michael Ellerman
OzLabs, IBM Australia Development Lab

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

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

end of thread, other threads:[~2008-07-03  5:55 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-07-01  5:32 [PATCH] powerpc: fixup lwsync at runtime Kumar Gala
2008-07-01  6:23 ` Benjamin Herrenschmidt
2008-07-01  7:15   ` Benjamin Herrenschmidt
2008-07-01  6:29 ` Michael Ellerman
2008-07-01 14:48   ` Kumar Gala
2008-07-02  9:34     ` Michael Ellerman
2008-07-02 15:57       ` Kumar Gala
2008-07-03  5:55         ` Michael Ellerman
  -- strict thread matches above, loose matches on Subject: below --
2008-06-26 15:30 Kumar Gala

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).