All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thomas Huth <thuth@redhat.com>
To: kvm@vger.kernel.org, lvivier@redhat.com
Cc: kvm-ppc@vger.kernel.org, pbonzini@redhat.com, drjones@redhat.com
Subject: [kvm-unit-tests PATCH] powerpc: Add emulator test for the lswi instruction
Date: Wed, 13 Apr 2016 21:31:26 +0200	[thread overview]
Message-ID: <1460575886-12569-1-git-send-email-thuth@redhat.com> (raw)

This test checks some special cases of the lswi instruction. Test
works fine on real hardware, but in QEMU, this reveals a bug with
the final "don't overwrite RA" test (RA gets destroyed since the
check in QEMU is still wrong).
The code is based on the lswx test by Laurent Vivier.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 powerpc/emulator.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 128 insertions(+)

diff --git a/powerpc/emulator.c b/powerpc/emulator.c
index 3696d83..f6ffe21 100644
--- a/powerpc/emulator.c
+++ b/powerpc/emulator.c
@@ -71,6 +71,133 @@ static void test_64bit(void)
 	report_prefix_pop();
 }
 
+/**
+ * Test 'Load String Word Immediate' instruction
+ */
+static void test_lswi(void)
+{
+	int i;
+	char addr[128];
+	uint64_t regs[32];
+
+	report_prefix_push("lswi");
+
+	/* fill memory with sequence */
+	for (i = 0; i < 128; i++)
+		addr[i] = 1 + i;
+
+	/* check incomplete register filling */
+	alignment = 0;
+	asm volatile ("li r12,-1;"
+		      "mr r11, r12;"
+		      "lswi r11, %[addr], %[len];"
+		      "std r11, 0*8(%[regs]);"
+		      "std r12, 1*8(%[regs]);"
+		      ::
+		      [len] "i" (3),
+		      [addr] "b" (addr),
+		      [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("partial", regs[0] == 0x01020300 && regs[1] == (uint64_t)-1);
+
+	/* check NB = 0 ==> 32 bytes. */
+	asm volatile ("li r19,-1;"
+		      "mr r11, r19; mr r12, r19; mr r13, r19;"
+		      "mr r14, r19; mr r15, r19; mr r16, r19;"
+		      "mr r17, r19; mr r18, r19;"
+		      "lswi r11, %[addr], %[len];"
+		      "std r11, 0*8(%[regs]);"
+		      "std r12, 1*8(%[regs]);"
+		      "std r13, 2*8(%[regs]);"
+		      "std r14, 3*8(%[regs]);"
+		      "std r15, 4*8(%[regs]);"
+		      "std r16, 5*8(%[regs]);"
+		      "std r17, 6*8(%[regs]);"
+		      "std r18, 7*8(%[regs]);"
+		      "std r19, 8*8(%[regs]);"
+		      ::
+		      [len] "i" (0),
+		      [addr] "b" (addr),
+		      [regs] "r" (regs)
+		      :
+		      /* as 32 is the number of bytes,
+		       * we should modify 32/4 = 8 regs, from r11 to r18
+		       * We check r19 is unmodified by filling it with 1s
+		       * before the instruction.
+		       */
+		      "r11", "r12", "r13", "r14", "r15", "r16", "r17",
+		      "r18", "r19", "memory");
+
+	report("length", regs[0] == 0x01020304 && regs[1] == 0x05060708 &&
+			 regs[2] == 0x090a0b0c && regs[3] == 0x0d0e0f10 &&
+			 regs[4] == 0x11121314 && regs[5] == 0x15161718 &&
+			 regs[6] == 0x191a1b1c && regs[7] == 0x1d1e1f20 &&
+			 regs[8] == (uint64_t)-1);
+
+	/* check wrap around to r0 */
+	asm volatile ("li r31,-1;"
+		      "mr r0, r31;"
+		      "lswi r31, %[addr], %[len];"
+		      "std r31, 0*8(%[regs]);"
+		      "std r0, 1*8(%[regs]);"
+		      ::
+		      [len] "i" (8),
+		      [addr] "b" (addr),
+		      [regs] "r" (regs)
+		      :
+		      /* modify two registers from r31, wrap around to r0 */
+		      "r31", "r0", "memory");
+
+	report("wrap around to r0", regs[0] == 0x01020304 &&
+			            regs[1] == 0x05060708);
+
+	/* check wrap around doesn't break RA */
+	asm volatile ("mr r28,r1\n"
+		      "mr r29,r2\n"
+		      "li r31,-1\n"
+		      "mr r2,r31\n"
+		      "mr r0,r31\n"
+		      "mr r1, %[addr]\n"
+		      ".long 0x7fe184aa\n"       /* lswi r31, r1, 16 */
+		      "std r31, 0*8(%[regs])\n"
+		      "std r0, 1*8(%[regs])\n"
+		      "std r1, 2*8(%[regs])\n"
+		      "std r2, 3*8(%[regs])\n"
+		      "mr r1,r28\n"
+		      "mr r2,r29\n"
+		      ::
+		      [addr] "r" (addr),
+		      [regs] "r" (regs)
+		      :
+		      /* loading four registers from r31 wraps around to r2,
+		       * r1 is saved to r29, as adding it to the clobber
+		       * list doesn't protect it
+		       */
+		      "r31", "r0", "r28", "r29", "memory");
+
+	/* doc says it is invalid, real proc stops when it comes to
+	 * overwrite the register.
+	 * In all the cases, the register must stay untouched
+	 */
+	report("Don't overwrite RA", regs[2] == (uint64_t)addr);
+
+	report_prefix_pop();
+}
+
 /*
  * lswx: Load String Word Indexed X-form
  *
@@ -234,6 +361,7 @@ int main(int argc, char **argv)
 
 	test_64bit();
 	test_illegal();
+	test_lswi();
 	test_lswx();
 
 	report_prefix_pop();
-- 
1.8.3.1


WARNING: multiple messages have this Message-ID (diff)
From: Thomas Huth <thuth@redhat.com>
To: kvm@vger.kernel.org, lvivier@redhat.com
Cc: kvm-ppc@vger.kernel.org, pbonzini@redhat.com, drjones@redhat.com
Subject: [kvm-unit-tests PATCH] powerpc: Add emulator test for the lswi instruction
Date: Wed, 13 Apr 2016 19:31:26 +0000	[thread overview]
Message-ID: <1460575886-12569-1-git-send-email-thuth@redhat.com> (raw)

This test checks some special cases of the lswi instruction. Test
works fine on real hardware, but in QEMU, this reveals a bug with
the final "don't overwrite RA" test (RA gets destroyed since the
check in QEMU is still wrong).
The code is based on the lswx test by Laurent Vivier.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 powerpc/emulator.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 128 insertions(+)

diff --git a/powerpc/emulator.c b/powerpc/emulator.c
index 3696d83..f6ffe21 100644
--- a/powerpc/emulator.c
+++ b/powerpc/emulator.c
@@ -71,6 +71,133 @@ static void test_64bit(void)
 	report_prefix_pop();
 }
 
+/**
+ * Test 'Load String Word Immediate' instruction
+ */
+static void test_lswi(void)
+{
+	int i;
+	char addr[128];
+	uint64_t regs[32];
+
+	report_prefix_push("lswi");
+
+	/* fill memory with sequence */
+	for (i = 0; i < 128; i++)
+		addr[i] = 1 + i;
+
+	/* check incomplete register filling */
+	alignment = 0;
+	asm volatile ("li r12,-1;"
+		      "mr r11, r12;"
+		      "lswi r11, %[addr], %[len];"
+		      "std r11, 0*8(%[regs]);"
+		      "std r12, 1*8(%[regs]);"
+		      ::
+		      [len] "i" (3),
+		      [addr] "b" (addr),
+		      [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("partial", regs[0] = 0x01020300 && regs[1] = (uint64_t)-1);
+
+	/* check NB = 0 => 32 bytes. */
+	asm volatile ("li r19,-1;"
+		      "mr r11, r19; mr r12, r19; mr r13, r19;"
+		      "mr r14, r19; mr r15, r19; mr r16, r19;"
+		      "mr r17, r19; mr r18, r19;"
+		      "lswi r11, %[addr], %[len];"
+		      "std r11, 0*8(%[regs]);"
+		      "std r12, 1*8(%[regs]);"
+		      "std r13, 2*8(%[regs]);"
+		      "std r14, 3*8(%[regs]);"
+		      "std r15, 4*8(%[regs]);"
+		      "std r16, 5*8(%[regs]);"
+		      "std r17, 6*8(%[regs]);"
+		      "std r18, 7*8(%[regs]);"
+		      "std r19, 8*8(%[regs]);"
+		      ::
+		      [len] "i" (0),
+		      [addr] "b" (addr),
+		      [regs] "r" (regs)
+		      :
+		      /* as 32 is the number of bytes,
+		       * we should modify 32/4 = 8 regs, from r11 to r18
+		       * We check r19 is unmodified by filling it with 1s
+		       * before the instruction.
+		       */
+		      "r11", "r12", "r13", "r14", "r15", "r16", "r17",
+		      "r18", "r19", "memory");
+
+	report("length", regs[0] = 0x01020304 && regs[1] = 0x05060708 &&
+			 regs[2] = 0x090a0b0c && regs[3] = 0x0d0e0f10 &&
+			 regs[4] = 0x11121314 && regs[5] = 0x15161718 &&
+			 regs[6] = 0x191a1b1c && regs[7] = 0x1d1e1f20 &&
+			 regs[8] = (uint64_t)-1);
+
+	/* check wrap around to r0 */
+	asm volatile ("li r31,-1;"
+		      "mr r0, r31;"
+		      "lswi r31, %[addr], %[len];"
+		      "std r31, 0*8(%[regs]);"
+		      "std r0, 1*8(%[regs]);"
+		      ::
+		      [len] "i" (8),
+		      [addr] "b" (addr),
+		      [regs] "r" (regs)
+		      :
+		      /* modify two registers from r31, wrap around to r0 */
+		      "r31", "r0", "memory");
+
+	report("wrap around to r0", regs[0] = 0x01020304 &&
+			            regs[1] = 0x05060708);
+
+	/* check wrap around doesn't break RA */
+	asm volatile ("mr r28,r1\n"
+		      "mr r29,r2\n"
+		      "li r31,-1\n"
+		      "mr r2,r31\n"
+		      "mr r0,r31\n"
+		      "mr r1, %[addr]\n"
+		      ".long 0x7fe184aa\n"       /* lswi r31, r1, 16 */
+		      "std r31, 0*8(%[regs])\n"
+		      "std r0, 1*8(%[regs])\n"
+		      "std r1, 2*8(%[regs])\n"
+		      "std r2, 3*8(%[regs])\n"
+		      "mr r1,r28\n"
+		      "mr r2,r29\n"
+		      ::
+		      [addr] "r" (addr),
+		      [regs] "r" (regs)
+		      :
+		      /* loading four registers from r31 wraps around to r2,
+		       * r1 is saved to r29, as adding it to the clobber
+		       * list doesn't protect it
+		       */
+		      "r31", "r0", "r28", "r29", "memory");
+
+	/* doc says it is invalid, real proc stops when it comes to
+	 * overwrite the register.
+	 * In all the cases, the register must stay untouched
+	 */
+	report("Don't overwrite RA", regs[2] = (uint64_t)addr);
+
+	report_prefix_pop();
+}
+
 /*
  * lswx: Load String Word Indexed X-form
  *
@@ -234,6 +361,7 @@ int main(int argc, char **argv)
 
 	test_64bit();
 	test_illegal();
+	test_lswi();
 	test_lswx();
 
 	report_prefix_pop();
-- 
1.8.3.1


             reply	other threads:[~2016-04-13 19:31 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-13 19:31 Thomas Huth [this message]
2016-04-13 19:31 ` [kvm-unit-tests PATCH] powerpc: Add emulator test for the lswi instruction Thomas Huth
2016-04-14 11:02 ` Thomas Huth
2016-04-14 11:02   ` Thomas Huth

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1460575886-12569-1-git-send-email-thuth@redhat.com \
    --to=thuth@redhat.com \
    --cc=drjones@redhat.com \
    --cc=kvm-ppc@vger.kernel.org \
    --cc=kvm@vger.kernel.org \
    --cc=lvivier@redhat.com \
    --cc=pbonzini@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.