powerpc/476: Software workaround to fix dcr read/write sequencing.

From: Dave Kleikamp <sha...@linux.vnet.ibm.com>

Copy the register containing the dcr address to a spr before mfdcrx or
mtdcrx instruction.  SPRN_SPRG_WSCRATCH_CRIT seems safe enough to use
as a dummy register, as it is only otherwise used by critical interrupts,
and we don't care if what we write is overwritten.

Ideally, would only do this when CPU_FTR_476_DD1_1 is set, but I'm not
getting the feature macros working in inlined assembler.  The dummy store
is pretty cheap though, so I'm doing it unconditionally for 47x.

Signed-off-by: Dave Kleikamp <sha...@linux.vnet.ibm.com>
---

 arch/powerpc/include/asm/dcr-native.h |   24 ++++++++++++++++++++++--
 1 files changed, 22 insertions(+), 2 deletions(-)


diff --git a/arch/powerpc/include/asm/dcr-native.h 
b/arch/powerpc/include/asm/dcr-native.h
index 7d2e623..768ce50 100644
--- a/arch/powerpc/include/asm/dcr-native.h
+++ b/arch/powerpc/include/asm/dcr-native.h
@@ -50,14 +50,34 @@ extern unsigned int __mfdcr(unsigned int reg);
 static inline unsigned int mfdcrx(unsigned int reg)
 {
        unsigned int ret;
-       asm volatile(".long 0x7c000206 | (%0 << 21) | (%1 << 16)"
+       asm volatile(
+#ifdef CONFIG_PPC_47x
+               /*
+                * Workaround: move reg to an spr prior to mfdcrx instruction
+                */
+                    /* __stringify(BEGIN_FTR_SECTION) */
+                    "mtspr "__stringify(SPRN_SPRG_WSCRATCH_CRIT)",%1;"
+                    /* __stringify(END_FTR_SECTION_IFSET(CPU_FTR_476_DD1_1)) */
+#endif
+                    ".long 0x7c000206 | (%0 << 21) | (%1 << 16)"
                     : "=r" (ret) : "r" (reg));
        return ret;
 }
 
 static inline void mtdcrx(unsigned int reg, unsigned int val)
 {
-       asm volatile(".long 0x7c000306 | (%0 << 21) | (%1 << 16)"
+       asm volatile(
+#ifdef CONFIG_PPC_47x
+               /*
+                * Workaround: move reg to an spr prior to mtdcrx instruction.
+                * (Would love to get the FTR_SECTION macros working for
+                * inlined assembler -- shaggy)
+                */
+                    /* __stringify(BEGIN_FTR_SECTION) */
+                    "mtspr "__stringify(SPRN_SPRG_WSCRATCH_CRIT)",%1;"
+                    /* __stringify(END_FTR_SECTION_IFSET(CPU_FTR_476_DD1_1)) */
+#endif
+                    ".long 0x7c000306 | (%0 << 21) | (%1 << 16)"
                     : : "r" (val), "r" (reg));
 }
 

-- 
Dave Kleikamp
IBM Linux Technology Center
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to