[kvm-unit-tests PATCH] powerpc/emulator: Fix compilation with recent versions of GCC

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



New versions of GCC (e.g. version 11.2 from Fedora 34) refuse to compile
assembly with the lswx and lswi mnemonics in little endian mode since the
instruction is only allowed in big endian mode, thus emulator.c cannot be
compiled anymore. Re-arrange the tests a little bit to use hand-crafted
instructions in little endian mode to fix this issue. Additionally, the lswx
and lswi instructions generate an alignment exception with recent versions
of QEMU, too (see https://gitlab.com/qemu-project/qemu/-/commit/5817355ed0),
so we can turn the report_xfail() into proper report() statements now.

Signed-off-by: Thomas Huth <thuth@xxxxxxxxxx>
---
 powerpc/emulator.c | 69 +++++++++++++++++++++++++++-------------------
 1 file changed, 40 insertions(+), 29 deletions(-)

diff --git a/powerpc/emulator.c b/powerpc/emulator.c
index 147878e..65ae4b6 100644
--- a/powerpc/emulator.c
+++ b/powerpc/emulator.c
@@ -86,8 +86,25 @@ static void test_lswi(void)
 	for (i = 0; i < 128; i++)
 		addr[i] = 1 + i;
 
-	/* check incomplete register filling */
+#if  __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+
+	/*
+	 * lswi is supposed to cause an alignment exception in little endian
+	 * mode, but to be able to check this, we also have to specify the
+	 * opcode without mnemonic here since newer versions of GCC refuse
+	 * "lswi" when compiling in little endian mode.
+	 */
 	alignment = 0;
+	asm volatile ("mr r12,%[addr];"
+		      ".long 0x7d6c24aa;"       /* lswi r11,r12,4 */
+		      "std r11,0(%[regs]);"
+		       :: [addr] "r" (addr), [regs] "r" (regs)
+		       : "r11", "r12", "memory");
+	report(alignment, "alignment");
+
+#else
+
+	/* check incomplete register filling */
 	asm volatile ("li r12,-1;"
 		      "mr r11, r12;"
 		      "lswi r11, %[addr], %[len];"
@@ -99,19 +116,6 @@ static void test_lswi(void)
 		      [regs] "r" (regs)
 		      :
 		      "r11", "r12", "memory");
-
-#if  __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
-	/*
-	 * lswi is supposed to cause an alignment exception in little endian
-	 * mode, but QEMU does not support it. So in case we do not get an
-	 * exception, this is an expected failure and we run the other tests
-	 */
-	report_xfail(!alignment, alignment, "alignment");
-	if (alignment) {
-		report_prefix_pop();
-		return;
-	}
-#endif
 	report(regs[0] == 0x01020300 && regs[1] == (uint64_t)-1, "partial");
 
 	/* check NB = 0 ==> 32 bytes. */
@@ -191,6 +195,8 @@ static void test_lswi(void)
 	 */
 	report(regs[2] == (uint64_t)addr, "Don't overwrite Ra");
 
+#endif
+
 	report_prefix_pop();
 }
 
@@ -224,13 +230,29 @@ static void test_lswx(void)
 	report_prefix_push("lswx");
 
 	/* fill memory with sequence */
-
 	for (i = 0; i < 128; i++)
 		addr[i] = 1 + i;
 
-	/* check incomplete register filling */
+#if  __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
 
+	/*
+	 * lswx is supposed to cause an alignment exception in little endian
+	 * mode, but to be able to check this, we also have to specify the
+	 * opcode without mnemonic here since newer versions of GCC refuse
+	 * "lswx" when compiling in little endian mode.
+	 */
 	alignment = 0;
+	asm volatile ("mtxer %[len];"
+		      "mr r11,%[addr];"
+		      ".long 0x7d805c2a;"       /* lswx r12,0,r11 */
+		      "std r12,0(%[regs]);"
+		      :: [len]"r"(4), [addr]"r"(addr), [regs]"r"(regs)
+		      : "r11", "r12", "memory");
+	report(alignment, "alignment");
+
+#else
+
+	/* check incomplete register filling */
 	asm volatile ("mtxer %[len];"
 		      "li r12,-1;"
 		      "mr r11, r12;"
@@ -243,19 +265,6 @@ static void test_lswx(void)
 		      [regs] "r" (regs)
 		      :
 		      "xer", "r11", "r12", "memory");
-
-#if  __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
-	/*
-	 * lswx is supposed to cause an alignment exception in little endian
-	 * mode, but QEMU does not support it. So in case we do not get an
-	 * exception, this is an expected failure and we run the other tests
-	 */
-	report_xfail(!alignment, alignment, "alignment");
-	if (alignment) {
-		report_prefix_pop();
-		return;
-	}
-#endif
 	report(regs[0] == 0x01020300 && regs[1] == (uint64_t)-1, "partial");
 
 	/* check an old know bug: the number of bytes is used as
@@ -344,6 +353,8 @@ static void test_lswx(void)
 	 */
 	report(regs[1] == (uint64_t)addr, "Don't overwrite Rb");
 
+#endif
+
 	report_prefix_pop();
 }
 
-- 
2.27.0




[Index of Archives]     [KVM Development]     [KVM ARM]     [KVM ia64]     [Linux Virtualization]     [Linux USB Devel]     [Linux Video]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux