diff mbox

[kvm-unit-tests,8/8] s390x: Add vector tests

Message ID 1520942503-6163-9-git-send-email-frankja@linux.vnet.ibm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Janosch Frank March 13, 2018, 12:01 p.m. UTC
Short test of the vector, vector enhancement 1 and vector bcd
facility.

Signed-off-by: Janosch Frank <frankja@linux.vnet.ibm.com>
---
 s390x/Makefile      |   1 +
 s390x/unittests.cfg |   3 ++
 s390x/vector.c      | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 140 insertions(+)
 create mode 100644 s390x/vector.c

Comments

Thomas Huth March 14, 2018, 9:20 a.m. UTC | #1
On 13.03.2018 13:01, Janosch Frank wrote:
> Short test of the vector, vector enhancement 1 and vector bcd
> facility.
> 
> Signed-off-by: Janosch Frank <frankja@linux.vnet.ibm.com>
> ---
>  s390x/Makefile      |   1 +
>  s390x/unittests.cfg |   3 ++
>  s390x/vector.c      | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 140 insertions(+)
>  create mode 100644 s390x/vector.c
> 
> diff --git a/s390x/Makefile b/s390x/Makefile
> index d33e1d8..628f653 100644
> --- a/s390x/Makefile
> +++ b/s390x/Makefile
> @@ -8,6 +8,7 @@ tests += $(TEST_DIR)/diag10.elf
>  tests += $(TEST_DIR)/pfmf.elf
>  tests += $(TEST_DIR)/cmm.elf
>  tests += $(TEST_DIR)/gs.elf
> +tests += $(TEST_DIR)/vector.elf
>  
>  all: directories test_cases
>  
> diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg
> index 7f10d6b..97a16f5 100644
> --- a/s390x/unittests.cfg
> +++ b/s390x/unittests.cfg
> @@ -53,3 +53,6 @@ file = cmm.elf
>  
>  [gs]
>  file = gs.elf
> +
> +[vector]
> +file = vector.elf
> diff --git a/s390x/vector.c b/s390x/vector.c
> new file mode 100644
> index 0000000..a9de1bd
> --- /dev/null
> +++ b/s390x/vector.c
> @@ -0,0 +1,136 @@
> +/*
> + * Tests vector instruction support
> + *
> + * Copyright 2017 IBM Corp.
> + *
> + * Authors:
> + *    Janosch Frank <frankja@de.ibm.com>
> + *
> + * This code is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU Library General Public License version 2.
> + */
> +#include <libcflat.h>
> +#include <asm/page.h>
> +#include <asm/facility.h>
> +#include <asm/interrupt.h>
> +#include <asm-generic/barrier.h>
> +
> +static uint8_t pagebuf[PAGE_SIZE * 2] __attribute__((aligned(PAGE_SIZE * 2)));
> +
> +static inline void vstm(unsigned long *addr)
> +{
> +	asm volatile(" .machine z13\n"
> +		     " vstm 0, 15, %[a]\n"
> +		     : [a] "=Q" (*addr)
> +		     : : "memory");
> +	asm volatile(" .machine z13\n"
> +		     " vstm 16, 31, %[a]\n"
> +		     : [a]  "=Q" (*(addr+256/8))
> +		     : : "memory");
> +}

This inline function is apparently unused and thus could be removed.

> +static inline void vlm(unsigned long *addr)
> +{
> +	asm volatile(" .machine z13\n"
> +		     " vlm 0, 15, %[a]\n"
> +		     : : [a]  "Q" (*addr) : );
> +	asm volatile(" .machine z13\n"
> +		     " vlm 16, 31, %[a]\n"
> +		     : : [a]  "Q" (*(addr+256/8)) : );
> +}
> +
> +static void test_add(void)
> +{
> +	static struct prm {
> +		__uint128_t a,b,c;
> +	} prm __attribute__((aligned(16)));
> +
> +	prm.a = prm.b = 21;
> +
> +	asm volatile(" .machine z13\n"
> +		     " vl 0, %[v1]\n"
> +		     " vl 1, %[v2]\n"
> +		     " va 2, 0, 1, 4\n"
> +		     " vst 2, %[v3]\n"
> +		     : [v3]  "=Q" (prm.c)
> +		     : [v1]  "Q" (prm.a), [v2]  "Q" (prm.b)
> +		     : "memory");

Is it possible to specify the vector registers in the clobber list? ...
just in case the compiler also wants to use them on its own ...

> +	report("adding 21", prm.c == 42);
> +}
> +
> +/* z14 vector extension test */
> +static void test_ext1_nand(void)
> +{
> +	static struct prm {
> +		__uint128_t a,b,c;
> +	} prm __attribute__((aligned(16)));
> +
> +
> +	if (!test_facility(134))
> +		return;
> +
> +	memset(&prm.a, 0xff, 16);
> +	prm.b = prm.a;
> +
> +	asm volatile(" .machine z13\n"
> +		     " vl 0, %[v1]\n"
> +		     " vl 1, %[v2]\n"
> +		     " .byte 0xe7, 0x20, 0x10, 0x00, 0x00, 0x6e\n"

Please add a comment at the end of the line with the mnemonic of this
instruction ("vnn").

> +		     " vst 2, %[v3]\n"
> +		     : [v3]  "=Q" (prm.c)
> +		     : [v1]  "Q" (prm.a), [v2]  "Q" (prm.b)
> +		     : "memory");
> +	report("nand ff", !prm.c);
> +}
> +
> +/* z14 bcd extension test */
> +static void test_bcd_add(void)
> +{
> +	static struct prm {
> +		__uint128_t a,b,c;
> +	} prm __attribute__((aligned(16)));
> +
> +	if (!test_facility(135))
> +		return;
> +
> +	memset(&prm.a, 0x00, 16);
> +	prm.b = prm.a;
> +	prm.a = prm.b = 0b001000011100;
> +
> +	asm volatile(" .machine z13\n"
> +		     " vl 0, %[v1]\n"
> +		     " vl 1, %[v2]\n"
> +		     " .byte 0xe6, 0x20, 0x10, 0x01, 0x00, 0x71\n"

/* vap */

(off-topic: SIMD instructions for BCD arithmetics? WTF? Who needs such
stuff in the 21st century??)

> +		     " vst 2, %[v3]\n"
> +		     : [v3]  "=Q" (prm.c)
> +		     : [v1]  "Q" (prm.a), [v2]  "Q" (prm.b)
> +		     : "memory");
> +	report("bcd add 21", prm.c == 0x42c);
> +}
> +
> +static void init(void)
> +{
> +	/* Enable vector instructions */
> +	ctl_set_bit(0, 17);
> +}
> +
> +int main(void)
> +{
> +	unsigned long *addr = (u64*)pagebuf;
> +
> +	addr += PAGE_SIZE/8;

addr seems to be unused here?

> +	if (!test_facility(129)) {
> +		printf("basic vector facility not available");
> +		return 0;
> +	}
> +
> +	report_prefix_push("vector");
> +	memset(pagebuf, 0xff, PAGE_SIZE);

Maybe move that memset into the init() function?

> +	init();
> +	vlm((u64*)pagebuf);
> +	test_add();
> +	test_ext1_nand();
> +	test_bcd_add();
> +	report_prefix_pop();
> +	return report_summary();
> +}
> 

 Thomas


PS:
In case you've got some spare cycles, here's an idea for a future test:
Check whether the contents of all vector registers are preserved
correctly during migration. See run_migration in scripts/arch-run.bash
and powerpc/sprs.c for an example how this can be done automatically
with kvm-unit-tests.
Janosch Frank March 14, 2018, 9:34 a.m. UTC | #2
On 14.03.2018 10:20, Thomas Huth wrote:
> On 13.03.2018 13:01, Janosch Frank wrote:
>> Short test of the vector, vector enhancement 1 and vector bcd
>> facility.
>>
>> Signed-off-by: Janosch Frank <frankja@linux.vnet.ibm.com>
>> ---
>>  s390x/Makefile      |   1 +
>>  s390x/unittests.cfg |   3 ++
>>  s390x/vector.c      | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 140 insertions(+)
>>  create mode 100644 s390x/vector.c
>>
>> diff --git a/s390x/Makefile b/s390x/Makefile
>> index d33e1d8..628f653 100644
>> --- a/s390x/Makefile
>> +++ b/s390x/Makefile
>> @@ -8,6 +8,7 @@ tests += $(TEST_DIR)/diag10.elf
>>  tests += $(TEST_DIR)/pfmf.elf
>>  tests += $(TEST_DIR)/cmm.elf
>>  tests += $(TEST_DIR)/gs.elf
>> +tests += $(TEST_DIR)/vector.elf
>>  
>>  all: directories test_cases
>>  
>> diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg
>> index 7f10d6b..97a16f5 100644
>> --- a/s390x/unittests.cfg
>> +++ b/s390x/unittests.cfg
>> @@ -53,3 +53,6 @@ file = cmm.elf
>>  
>>  [gs]
>>  file = gs.elf
>> +
>> +[vector]
>> +file = vector.elf
>> diff --git a/s390x/vector.c b/s390x/vector.c
>> new file mode 100644
>> index 0000000..a9de1bd
>> --- /dev/null
>> +++ b/s390x/vector.c
>> @@ -0,0 +1,136 @@
>> +/*
>> + * Tests vector instruction support
>> + *
>> + * Copyright 2017 IBM Corp.
>> + *
>> + * Authors:
>> + *    Janosch Frank <frankja@de.ibm.com>
>> + *
>> + * This code is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU Library General Public License version 2.
>> + */
>> +#include <libcflat.h>
>> +#include <asm/page.h>
>> +#include <asm/facility.h>
>> +#include <asm/interrupt.h>
>> +#include <asm-generic/barrier.h>
>> +
>> +static uint8_t pagebuf[PAGE_SIZE * 2] __attribute__((aligned(PAGE_SIZE * 2)));
>> +
>> +static inline void vstm(unsigned long *addr)
>> +{
>> +	asm volatile(" .machine z13\n"
>> +		     " vstm 0, 15, %[a]\n"
>> +		     : [a] "=Q" (*addr)
>> +		     : : "memory");
>> +	asm volatile(" .machine z13\n"
>> +		     " vstm 16, 31, %[a]\n"
>> +		     : [a]  "=Q" (*(addr+256/8))
>> +		     : : "memory");
>> +}
> 
> This inline function is apparently unused and thus could be removed.

There used to be a dump_regs() function for debugging that needed vstm,
will remove.

> 
>> +static inline void vlm(unsigned long *addr)
>> +{
>> +	asm volatile(" .machine z13\n"
>> +		     " vlm 0, 15, %[a]\n"
>> +		     : : [a]  "Q" (*addr) : );
>> +	asm volatile(" .machine z13\n"
>> +		     " vlm 16, 31, %[a]\n"
>> +		     : : [a]  "Q" (*(addr+256/8)) : );
>> +}
>> +
>> +static void test_add(void)
>> +{
>> +	static struct prm {
>> +		__uint128_t a,b,c;
>> +	} prm __attribute__((aligned(16)));
>> +
>> +	prm.a = prm.b = 21;
>> +
>> +	asm volatile(" .machine z13\n"
>> +		     " vl 0, %[v1]\n"
>> +		     " vl 1, %[v2]\n"
>> +		     " va 2, 0, 1, 4\n"
>> +		     " vst 2, %[v3]\n"
>> +		     : [v3]  "=Q" (prm.c)
>> +		     : [v1]  "Q" (prm.a), [v2]  "Q" (prm.b)
>> +		     : "memory");
> 
> Is it possible to specify the vector registers in the clobber list? ...
> just in case the compiler also wants to use them on its own ...

I'll have to talk to the compiler guys again for a lot of this inline
assembly code. Using instructions, that are not yet known to the
libraries and gcc is not that easy. They'll probably have some ideas on
how to make this nicer.

> 
>> +	report("adding 21", prm.c == 42);
>> +}
>> +
>> +/* z14 vector extension test */
>> +static void test_ext1_nand(void)
>> +{
>> +	static struct prm {
>> +		__uint128_t a,b,c;
>> +	} prm __attribute__((aligned(16)));
>> +
>> +
>> +	if (!test_facility(134))
>> +		return;
>> +
>> +	memset(&prm.a, 0xff, 16);
>> +	prm.b = prm.a;
>> +
>> +	asm volatile(" .machine z13\n"
>> +		     " vl 0, %[v1]\n"
>> +		     " vl 1, %[v2]\n"
>> +		     " .byte 0xe7, 0x20, 0x10, 0x00, 0x00, 0x6e\n"
> 
> Please add a comment at the end of the line with the mnemonic of this
> instruction ("vnn").

Sure

> 
>> +		     " vst 2, %[v3]\n"
>> +		     : [v3]  "=Q" (prm.c)
>> +		     : [v1]  "Q" (prm.a), [v2]  "Q" (prm.b)
>> +		     : "memory");
>> +	report("nand ff", !prm.c);
>> +}
>> +
>> +/* z14 bcd extension test */
>> +static void test_bcd_add(void)
>> +{
>> +	static struct prm {
>> +		__uint128_t a,b,c;
>> +	} prm __attribute__((aligned(16)));
>> +
>> +	if (!test_facility(135))
>> +		return;
>> +
>> +	memset(&prm.a, 0x00, 16);
>> +	prm.b = prm.a;
>> +	prm.a = prm.b = 0b001000011100;
>> +
>> +	asm volatile(" .machine z13\n"
>> +		     " vl 0, %[v1]\n"
>> +		     " vl 1, %[v2]\n"
>> +		     " .byte 0xe6, 0x20, 0x10, 0x01, 0x00, 0x71\n"
> 
> /* vap */
> 
> (off-topic: SIMD instructions for BCD arithmetics? WTF? Who needs such
> stuff in the 21st century??)

Welcome to IBM Z
I had a quick search but couldn't find the reason behind this facility
in my documents anymore.

> 
>> +		     " vst 2, %[v3]\n"
>> +		     : [v3]  "=Q" (prm.c)
>> +		     : [v1]  "Q" (prm.a), [v2]  "Q" (prm.b)
>> +		     : "memory");
>> +	report("bcd add 21", prm.c == 0x42c);
>> +}
>> +
>> +static void init(void)
>> +{
>> +	/* Enable vector instructions */
>> +	ctl_set_bit(0, 17);
>> +}
>> +
>> +int main(void)
>> +{
>> +	unsigned long *addr = (u64*)pagebuf;
>> +
>> +	addr += PAGE_SIZE/8;
> 
> addr seems to be unused here?

Once again the dump_regs() leftover.

> 
>> +	if (!test_facility(129)) {
>> +		printf("basic vector facility not available");
>> +		return 0;
>> +	}
>> +
>> +	report_prefix_push("vector");
>> +	memset(pagebuf, 0xff, PAGE_SIZE);
> 
> Maybe move that memset into the init() function?

Sure

> 
>> +	init();
>> +	vlm((u64*)pagebuf);
>> +	test_add();
>> +	test_ext1_nand();
>> +	test_bcd_add();
>> +	report_prefix_pop();
>> +	return report_summary();
>> +}
>>
> 
>  Thomas
> 
> 
> PS:
> In case you've got some spare cycles, here's an idea for a future test:
> Check whether the contents of all vector registers are preserved
> correctly during migration. See run_migration in scripts/arch-run.bash
> and powerpc/sprs.c for an example how this can be done automatically
> with kvm-unit-tests.
> 

Yep, this is on my list for skeys, gs and essa (cmm), but it will come
when I find time for it. Thanks for the pointer.
diff mbox

Patch

diff --git a/s390x/Makefile b/s390x/Makefile
index d33e1d8..628f653 100644
--- a/s390x/Makefile
+++ b/s390x/Makefile
@@ -8,6 +8,7 @@  tests += $(TEST_DIR)/diag10.elf
 tests += $(TEST_DIR)/pfmf.elf
 tests += $(TEST_DIR)/cmm.elf
 tests += $(TEST_DIR)/gs.elf
+tests += $(TEST_DIR)/vector.elf
 
 all: directories test_cases
 
diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg
index 7f10d6b..97a16f5 100644
--- a/s390x/unittests.cfg
+++ b/s390x/unittests.cfg
@@ -53,3 +53,6 @@  file = cmm.elf
 
 [gs]
 file = gs.elf
+
+[vector]
+file = vector.elf
diff --git a/s390x/vector.c b/s390x/vector.c
new file mode 100644
index 0000000..a9de1bd
--- /dev/null
+++ b/s390x/vector.c
@@ -0,0 +1,136 @@ 
+/*
+ * Tests vector instruction support
+ *
+ * Copyright 2017 IBM Corp.
+ *
+ * Authors:
+ *    Janosch Frank <frankja@de.ibm.com>
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License version 2.
+ */
+#include <libcflat.h>
+#include <asm/page.h>
+#include <asm/facility.h>
+#include <asm/interrupt.h>
+#include <asm-generic/barrier.h>
+
+static uint8_t pagebuf[PAGE_SIZE * 2] __attribute__((aligned(PAGE_SIZE * 2)));
+
+static inline void vstm(unsigned long *addr)
+{
+	asm volatile(" .machine z13\n"
+		     " vstm 0, 15, %[a]\n"
+		     : [a] "=Q" (*addr)
+		     : : "memory");
+	asm volatile(" .machine z13\n"
+		     " vstm 16, 31, %[a]\n"
+		     : [a]  "=Q" (*(addr+256/8))
+		     : : "memory");
+}
+
+static inline void vlm(unsigned long *addr)
+{
+	asm volatile(" .machine z13\n"
+		     " vlm 0, 15, %[a]\n"
+		     : : [a]  "Q" (*addr) : );
+	asm volatile(" .machine z13\n"
+		     " vlm 16, 31, %[a]\n"
+		     : : [a]  "Q" (*(addr+256/8)) : );
+}
+
+static void test_add(void)
+{
+	static struct prm {
+		__uint128_t a,b,c;
+	} prm __attribute__((aligned(16)));
+
+	prm.a = prm.b = 21;
+
+	asm volatile(" .machine z13\n"
+		     " vl 0, %[v1]\n"
+		     " vl 1, %[v2]\n"
+		     " va 2, 0, 1, 4\n"
+		     " vst 2, %[v3]\n"
+		     : [v3]  "=Q" (prm.c)
+		     : [v1]  "Q" (prm.a), [v2]  "Q" (prm.b)
+		     : "memory");
+	report("adding 21", prm.c == 42);
+}
+
+/* z14 vector extension test */
+static void test_ext1_nand(void)
+{
+	static struct prm {
+		__uint128_t a,b,c;
+	} prm __attribute__((aligned(16)));
+
+
+	if (!test_facility(134))
+		return;
+
+	memset(&prm.a, 0xff, 16);
+	prm.b = prm.a;
+
+	asm volatile(" .machine z13\n"
+		     " vl 0, %[v1]\n"
+		     " vl 1, %[v2]\n"
+		     " .byte 0xe7, 0x20, 0x10, 0x00, 0x00, 0x6e\n"
+		     " vst 2, %[v3]\n"
+		     : [v3]  "=Q" (prm.c)
+		     : [v1]  "Q" (prm.a), [v2]  "Q" (prm.b)
+		     : "memory");
+	report("nand ff", !prm.c);
+}
+
+/* z14 bcd extension test */
+static void test_bcd_add(void)
+{
+	static struct prm {
+		__uint128_t a,b,c;
+	} prm __attribute__((aligned(16)));
+
+	if (!test_facility(135))
+		return;
+
+	memset(&prm.a, 0x00, 16);
+	prm.b = prm.a;
+	prm.a = prm.b = 0b001000011100;
+
+	asm volatile(" .machine z13\n"
+		     " vl 0, %[v1]\n"
+		     " vl 1, %[v2]\n"
+		     " .byte 0xe6, 0x20, 0x10, 0x01, 0x00, 0x71\n"
+		     " vst 2, %[v3]\n"
+		     : [v3]  "=Q" (prm.c)
+		     : [v1]  "Q" (prm.a), [v2]  "Q" (prm.b)
+		     : "memory");
+	report("bcd add 21", prm.c == 0x42c);
+}
+
+static void init(void)
+{
+	/* Enable vector instructions */
+	ctl_set_bit(0, 17);
+}
+
+int main(void)
+{
+	unsigned long *addr = (u64*)pagebuf;
+
+	addr += PAGE_SIZE/8;
+	if (!test_facility(129)) {
+		printf("basic vector facility not available");
+		return 0;
+	}
+
+	report_prefix_push("vector");
+	memset(pagebuf, 0xff, PAGE_SIZE);
+	init();
+	vlm((u64*)pagebuf);
+	test_add();
+	test_ext1_nand();
+	test_bcd_add();
+	report_prefix_pop();
+	return report_summary();
+}