[patch 1/1] powerpc: ppc EDAC ECC software scrubber

Dave Jiang djiang at mvista.com
Fri Mar 2 11:09:30 EST 2007


Implements the per arch atomic_scrub() function that EDAC uses for 
software ECC scrubbing. It scrubs 32bit chunks of memory by using the
PPC memory reservation instructions. It reads the memory location and
does a memory reservation. When it attempts to write back the same value
and thus "scrub" the memory, the operation fails if the memory is dirty.
It will continue to retry until it succeeds at "scrubbing".

Signed-off-by: Dave Jiang <djiang at mvista.com>

---

diff --git a/include/asm-powerpc/edac.h b/include/asm-powerpc/edac.h
new file mode 100644
index 0000000..0b7ac4d
--- /dev/null
+++ b/include/asm-powerpc/edac.h
@@ -0,0 +1,45 @@
+/*
+ * PPC EDAC common defs
+ *
+ * Author: Dave Jiang <djiang at mvista.com>
+ *
+ * (C) 2007 MontaVista Software
+ * This file may be distributed under the terms of the
+ * GNU General Public License Version 2.
+ */
+#ifndef ASM_EDAC_H
+#define ASM_EDAC_H
+/* ECC atomic, DMA, SMP and interrupt safe scrub function */
+
+/*
+ * This routine must provide a way to atomically read and then write
+ * back the value it reads to the same memory location in order to 
+ * "scrub" the memory. On x86 it is possible to do this in a single 
+ * instruction with the appropriate prefix. On PPC it is not possible
+ * because of the RISC instruction set. PPC instructions allow one to place 
+ * a reservation on the memory location during the read. And if the 
+ * location is dirtied by somebody else when the scrubber attempt the write, 
+ * the scrubber just have to try again.
+ */
+static __inline__ void atomic_scrub(void *va, u32 size)
+{
+    unsigned int *virt_addr = va;
+	unsigned int temp;
+    unsigned int i;
+
+    for (i = 0; i < size / 4; i++, virt_addr++) {
+        /* Very carefully read and write to memory atomically
+         * so we are interrupt, DMA and SMP safe.
+         */
+		__asm__ __volatile__ ("\n\
+				1:	lwarx	%0,0,%1\n\
+					stwcx.	%0,0,%1\n\
+					bne-	1b\n\
+					isync"
+					: "=&r"(temp)
+					: "r"(virt_addr)
+					: "cr0", "memory");
+	}
+}
+
+#endif



More information about the Linuxppc-dev mailing list