From 5bdba9a6a023bcc8dbb6416a194b753804f69aae Mon Sep 17 00:00:00 2001
From: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
Date: Mon, 8 Jun 2020 12:01:34 -0300
Subject: [PATCH] pmem: Fix data cache flush on ppc64
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The dcbst instruction doesn't flush a cache block correctly because it
doesn't mark that block as clean on Power 9, see Manual "POWER9
Processor User’s Manual" page 66.
Replace dcbst with dcbf in order to fix this issue. This change requires
to replace lwsync with a hwsync too in order to cover for the usage of
dcbf.

Adopt the best practices according to the POWER ISA 3.1.

Fix bug #4843.

Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
---
 src/libpmem/ppc64/.cstyleignore      |  1 +
 src/libpmem/ppc64/platform_generic.c | 30 ++++++++++++++++++++--------
 2 files changed, 23 insertions(+), 8 deletions(-)
 create mode 100644 src/libpmem/ppc64/.cstyleignore

diff --git a/src/libpmem/ppc64/.cstyleignore b/src/libpmem/ppc64/.cstyleignore
new file mode 100644
index 000000000..81bcd74b5
--- /dev/null
+++ b/src/libpmem/ppc64/.cstyleignore
@@ -0,0 +1 @@
+platform_generic.c
diff --git a/src/libpmem/ppc64/platform_generic.c b/src/libpmem/ppc64/platform_generic.c
index 57a1edb22..f05eb2888 100644
--- a/src/libpmem/ppc64/platform_generic.c
+++ b/src/libpmem/ppc64/platform_generic.c
@@ -39,17 +39,29 @@
 #include "pmem.h"
 #include "os.h"
 
+/*
+ * Older assemblers versions do not support the latest versions of L, e.g.
+ * Binutils 2.34.
+ * Workaround this by using longs.
+ */
+#define __SYNC(l) ".long (0x7c0004AC | ((" #l ") << 21))"
+#define __DCBF(ra, rb, l) ".long (0x7c0000AC | ((" #l ") << 21)" \
+	" | ((" #ra ") << 16) | ((" #rb ") << 11))"
+
 static void
 ppc_predrain_fence(void)
 {
 	LOG(15, NULL);
 
 	/*
-	 * Force a memory barrier to flush out all cache lines
+	 * Force a memory barrier to flush out all cache lines.
+	 * Uses a heavyweight sync in order to guarantee the memory ordering
+	 * even with a data cache flush.
+	 * According to the POWER ISA 3.1, phwsync (aka. sync (L=4)) is treated
+	 * as a hwsync by processors compatible with previous versions of the
+	 * POWER ISA.
 	 */
-	asm volatile(
-		"lwsync"
-		: : : "memory");
+	asm volatile(__SYNC(4) : : : "memory");
 }
 
 static void
@@ -63,10 +75,12 @@ ppc_flush(const void *addr, size_t size)
 	/* round down the address */
 	uptr &= ~(CACHELINE_SIZE - 1);
 	while (uptr < end) {
-		/* issue a dcbst instruction for the cache line */
-		asm volatile(
-			"dcbst 0,%0"
-			: :"r"(uptr) : "memory");
+		/*
+		 * Flush the data cache block.
+		 * According to the POWER ISA 3.1, dcbstps (aka. dcbf (L=6))
+		 * behaves as dcbf (L=0) on previous processors.
+		 */
+		asm volatile(__DCBF(0, %0, 6) : :"r"(uptr) : "memory");
 
 		uptr += CACHELINE_SIZE;
 	}
-- 
GitLab