[PATCH v2] selftests/powerpc: Always test lmw and stmw

Subsystems: kernel selftest framework, the rest

STALE1951d

2 messages, 2 authors, 2021-06-16 · open the first message on its own page

[PATCH v2] selftests/powerpc: Always test lmw and stmw

From: Jordan Niethe <hidden>
Date: 2021-06-15 05:10:55

Load Multiple Word (lmw) and Store Multiple Word (stmw) will raise an
Alignment Exception:
  - Little Endian mode: always
  - Big Endian mode: address not word aligned

These conditions do not depend on cache inhibited memory. Test the
alignment handler emulation of these instructions regardless of if there
is cache inhibited memory available or not.

Commit dd3a44c06f7b ("selftests/powerpc: Only test lwm/stmw on big
endian") stopped testing lmw/stmw on little endian because newer
binutils (>= 2.36) will not assemble them in little endian mode. The
kernel still emulates these instructions in little endian mode so use
macros to generate them and test them.

Signed-off-by: Jordan Niethe <redacted>
---
v2: Use macros for lmw/stmw
---
 .../powerpc/alignment/alignment_handler.c     | 101 +++++++++++++++++-
 .../selftests/powerpc/include/instructions.h  |  10 ++
 2 files changed, 106 insertions(+), 5 deletions(-)
diff --git a/tools/testing/selftests/powerpc/alignment/alignment_handler.c b/tools/testing/selftests/powerpc/alignment/alignment_handler.c
index 33ee34fc0828..26878147f389 100644
--- a/tools/testing/selftests/powerpc/alignment/alignment_handler.c
+++ b/tools/testing/selftests/powerpc/alignment/alignment_handler.c
@@ -45,6 +45,7 @@
 #include <getopt.h>
 #include <setjmp.h>
 #include <signal.h>
+#include <errno.h>
 
 #include "utils.h"
 #include "instructions.h"
@@ -453,11 +454,6 @@ int test_alignment_handler_integer(void)
 	STORE_DFORM_TEST(stdu);
 	STORE_XFORM_TEST(stdux);
 
-#ifdef __BIG_ENDIAN__
-	LOAD_DFORM_TEST(lmw);
-	STORE_DFORM_TEST(stmw);
-#endif
-
 	return rc;
 }
 
@@ -602,6 +598,99 @@ int test_alignment_handler_fp_prefix(void)
 	return rc;
 }
 
+int test_alignment_handler_multiple(void)
+{
+	int offset, width, r, rc = 0;
+	void *src1, *dst1, *src2, *dst2;
+
+	rc = posix_memalign(&src1, bufsize, bufsize);
+	if (rc) {
+		printf("\n");
+		return rc;
+	}
+
+	rc = posix_memalign(&dst1, bufsize, bufsize);
+	if (rc) {
+		printf("\n");
+		free(src1);
+		return rc;
+	}
+
+	src2 = malloc(bufsize);
+	if (!src2) {
+		printf("\n");
+		free(src1);
+		free(dst1);
+		return -ENOMEM;
+	}
+
+	dst2 = malloc(bufsize);
+	if (!dst2) {
+		printf("\n");
+		free(src1);
+		free(dst1);
+		free(src2);
+		return -ENOMEM;
+	}
+
+	/* lmw */
+	width = 4;
+	printf("\tDoing lmw:\t");
+	for (offset = 0; offset < width; offset++) {
+		preload_data(src1, offset, width);
+		preload_data(src2, offset, width);
+
+		asm volatile(LMW(31, %0, 0)
+			     "std 31, 0(%1)"
+			     :: "r"(src1 + offset), "r"(dst1 + offset), "r"(0)
+			     : "memory", "r31");
+
+		memcpy(dst2 + offset, src1 + offset, width);
+
+		r = test_memcmp(dst1, dst2, width, offset, "test_lmw");
+		if (r && !debug) {
+			printf("FAILED: Wrong Data\n");
+			break;
+		}
+	}
+
+	if (!r)
+		printf("PASSED\n");
+	else
+		rc |= 1;
+
+	/* stmw */
+	width = 4;
+	printf("\tDoing stmw:\t");
+	for (offset = 0; offset < width; offset++) {
+		preload_data(src1, offset, width);
+		preload_data(src2, offset, width);
+
+		asm volatile("ld  31, 0(%0) ;"
+			     STMW(31, %1, 0)
+			     :: "r"(src1 + offset), "r"(dst1 + offset), "r"(0)
+			     : "memory", "r31");
+
+		memcpy(dst2 + offset, src1 + offset, width);
+
+		r = test_memcmp(dst1, dst2, width, offset, "test_stmw");
+		if (r && !debug) {
+			printf("FAILED: Wrong Data\n");
+			break;
+		}
+	}
+	if (!r)
+		printf("PASSED\n");
+	else
+		rc |= 1;
+
+	free(src1);
+	free(src2);
+	free(dst1);
+	free(dst2);
+	return rc;
+}
+
 void usage(char *prog)
 {
 	printf("Usage: %s [options] [path [offset]]\n", prog);
@@ -676,5 +765,7 @@ int main(int argc, char *argv[])
 			   "test_alignment_handler_fp_206");
 	rc |= test_harness(test_alignment_handler_fp_prefix,
 			   "test_alignment_handler_fp_prefix");
+	rc |= test_harness(test_alignment_handler_multiple,
+			   "test_alignment_handler_multiple");
 	return rc;
 }
diff --git a/tools/testing/selftests/powerpc/include/instructions.h b/tools/testing/selftests/powerpc/include/instructions.h
index 4efa6314bd96..60605e2bbd3c 100644
--- a/tools/testing/selftests/powerpc/include/instructions.h
+++ b/tools/testing/selftests/powerpc/include/instructions.h
@@ -143,4 +143,14 @@ static inline int paste_last(void *i)
 #define PSTXV0(s, a, r, d)		PREFIX_8LS(0xd8000000, s, a, r, d)
 #define PSTXV1(s, a, r, d)		PREFIX_8LS(0xdc000000, s, a, r, d)
 
+/* Load and Store Multiple Instructions */
+#define LMW(t, a, d)			stringify_in_c(.long (46 << 26) |		\
+						       __PPC_RT(t) |			\
+						       __PPC_RA(a) |			\
+						       ((d) & 0xffff);\n)
+#define STMW(t, a, d)			stringify_in_c(.long (47 << 26) |		\
+						       __PPC_RT(t) |			\
+						       __PPC_RA(a) |			\
+						       ((d) & 0xffff);\n)
+
 #endif /* _SELFTESTS_POWERPC_INSTRUCTIONS_H */
-- 
2.25.1

Re: [PATCH v2] selftests/powerpc: Always test lmw and stmw

From: Michael Ellerman <mpe@ellerman.id.au>
Date: 2021-06-16 01:06:32

Jordan Niethe [off-list ref] writes:
Load Multiple Word (lmw) and Store Multiple Word (stmw) will raise an
Alignment Exception:
  - Little Endian mode: always
  - Big Endian mode: address not word aligned

These conditions do not depend on cache inhibited memory. Test the
alignment handler emulation of these instructions regardless of if there
is cache inhibited memory available or not.

Commit dd3a44c06f7b ("selftests/powerpc: Only test lwm/stmw on big
endian") stopped testing lmw/stmw on little endian because newer
binutils (>= 2.36) will not assemble them in little endian mode. The
kernel still emulates these instructions in little endian mode so use
macros to generate them and test them.

Signed-off-by: Jordan Niethe <redacted>
---
v2: Use macros for lmw/stmw
---
 .../powerpc/alignment/alignment_handler.c     | 101 +++++++++++++++++-
 .../selftests/powerpc/include/instructions.h  |  10 ++
 2 files changed, 106 insertions(+), 5 deletions(-)
Fails for me on BE?

test: test_alignment_handler_multiple
tags: git_version:v5.13-rc5-2025-g31e45305e351
        Doing lmw:      FAILED: Wrong Data
        Doing stmw:     FAILED: Wrong Data
failure: test_alignment_handler_multiple

cheers
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help