diff mbox

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

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

Commit Message

Janosch Frank March 20, 2018, 11:19 a.m. UTC
Short test of the vector, vector enhancement 1 and vector bcd
facility.

Signed-off-by: Janosch Frank <frankja@linux.vnet.ibm.com>
---
 lib/s390x/asm/arch_def.h |  18 +++++++
 s390x/Makefile           |   1 +
 s390x/unittests.cfg      |   3 ++
 s390x/vector.c           | 135 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 157 insertions(+)
 create mode 100644 s390x/vector.c

Comments

Thomas Huth March 23, 2018, 2:53 p.m. UTC | #1
On 20.03.2018 12:19, 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>
> ---
>  lib/s390x/asm/arch_def.h |  18 +++++++
>  s390x/Makefile           |   1 +
>  s390x/unittests.cfg      |   3 ++
>  s390x/vector.c           | 135 +++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 157 insertions(+)
>  create mode 100644 s390x/vector.c
> 
> diff --git a/lib/s390x/asm/arch_def.h b/lib/s390x/asm/arch_def.h
> index b67afac..99abe18 100644
> --- a/lib/s390x/asm/arch_def.h
> +++ b/lib/s390x/asm/arch_def.h
> @@ -183,6 +183,24 @@ static inline uint64_t stctg(int cr)
>  	return value;
>  }
>  
> +static inline void ctl_set_bit(int cr, unsigned int bit)
> +{
> +        uint64_t reg;
> +
> +	reg = stctg(cr);
> +	reg |= 1UL << bit;
> +	lctlg(cr, reg);
> +}
> +
> +static inline void ctl_clear_bit(int cr, unsigned int bit)
> +{
> +        uint64_t reg;
> +
> +	reg = stctg(cr);
> +	reg &= ~(1UL << bit);
> +	lctlg(cr, reg);
> +}
> +
>  static inline uint64_t extract_psw_mask(void)
>  {
>  	uint32_t mask_upper = 0, mask_lower = 0;
> diff --git a/s390x/Makefile b/s390x/Makefile
> index e04cad0..47013d1 100644
> --- a/s390x/Makefile
> +++ b/s390x/Makefile
> @@ -7,6 +7,7 @@ tests += $(TEST_DIR)/skey.elf
>  tests += $(TEST_DIR)/diag10.elf
>  tests += $(TEST_DIR)/pfmf.elf
>  tests += $(TEST_DIR)/cmm.elf
> +tests += $(TEST_DIR)/vector.elf
>  
>  all: directories test_cases
>  
> diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg
> index 367e970..2ea2bf9 100644
> --- a/s390x/unittests.cfg
> +++ b/s390x/unittests.cfg
> @@ -50,3 +50,6 @@ file = pfmf.elf
>  
>  [cmm]
>  file = cmm.elf
> +
> +[vector]
> +file = vector.elf
> diff --git a/s390x/vector.c b/s390x/vector.c
> new file mode 100644
> index 0000000..c6be541
> --- /dev/null
> +++ b/s390x/vector.c
> @@ -0,0 +1,135 @@
> +/*
> + * Tests vector instruction support
> + *
> + * Copyright 2018 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)));

If I get the code below right, one page (or even only a buffer of 512
bytes) should be enough here?

> +/* Fills all vector registers with data from addr */
> +static inline void vlm_all(unsigned long *addr)
> +{
> +	asm volatile(" .machine z13\n"
> +		     " vlm 0, 15, %[a]\n"
> +		     : : [a]  "Q" (*addr)
> +		     :	"v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8",
> +			"v9", "v10", "v11", "v12", "v13", "v14", "v15");

You're missing v0 in the clobber list.

> +	asm volatile(" .machine z13\n"
> +		     " vlm 16, 31, %[a]\n"
> +		     : : [a]  "Q" (*(addr+256/8))
> +		     :	"v16", "v17", "v18", "v19", "v20", "v21", "v22",
> +			"v23", "v24", "v25", "v26", "v27", "v28", "v29",
> +			"v30", "v31");
> +}
> +
> +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)
> +		     : "v0", "v1", "v2", "memory");
> +	report("adding 21", prm.c == 42);
> +}
> +
> +/* z14 vector extension test */
> +static void test_ext1_nand(void)
> +{
> +	bool has_vext = test_facility(134);
> +	static struct prm {
> +		__uint128_t a,b,c;
> +	} prm __attribute__((aligned(16)));
> +
> +	report_xfail("Vector extensions 1 available", !has_vext, has_vext);
> +	if (!has_vext)
> +		return;
> +
> +	memset(&prm.a, 0xff, 16);
> +	prm.b = prm.a;

Maybe also set prm.c = prm.a to be sure that it is initialized with a
non-zero value?

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

Does this make sense if you set both values again in the next line?
Maybe rather initialize prm.c here?

> +	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 */
> +		     " vst 2, %[v3]\n"
> +		     : [v3]  "=Q" (prm.c)
> +		     : [v1]  "Q" (prm.a), [v2]  "Q" (prm.b)
> +		     : "v0", "v1", "v2", "memory");
> +	report("bcd add 21", prm.c == 0x42c);
> +}
> +
> +static void init(void)
> +{
> +	/* Enable vector instructions */
> +	ctl_set_bit(0, 17);
> +
> +	/* Preset vector registers to 0xff */
> +	memset(pagebuf, 0xff, PAGE_SIZE);
> +	vlm_all((u64*)pagebuf);
> +}
> +
> +int main(void)
> +{
> +	bool has_vregs = test_facility(129);
> +
> +	report_prefix_push("vector");
> +	report_xfail("Basic vector facility available", !has_vregs, has_vregs);
> +	if (!has_vregs)
> +		goto done;
> +
> +	init();
> +	test_add();
> +	test_ext1_nand();
> +	test_bcd_add();
> +
> +done:
> +	report_prefix_pop();
> +	return report_summary();
> +}
> 

 Thomas
diff mbox

Patch

diff --git a/lib/s390x/asm/arch_def.h b/lib/s390x/asm/arch_def.h
index b67afac..99abe18 100644
--- a/lib/s390x/asm/arch_def.h
+++ b/lib/s390x/asm/arch_def.h
@@ -183,6 +183,24 @@  static inline uint64_t stctg(int cr)
 	return value;
 }
 
+static inline void ctl_set_bit(int cr, unsigned int bit)
+{
+        uint64_t reg;
+
+	reg = stctg(cr);
+	reg |= 1UL << bit;
+	lctlg(cr, reg);
+}
+
+static inline void ctl_clear_bit(int cr, unsigned int bit)
+{
+        uint64_t reg;
+
+	reg = stctg(cr);
+	reg &= ~(1UL << bit);
+	lctlg(cr, reg);
+}
+
 static inline uint64_t extract_psw_mask(void)
 {
 	uint32_t mask_upper = 0, mask_lower = 0;
diff --git a/s390x/Makefile b/s390x/Makefile
index e04cad0..47013d1 100644
--- a/s390x/Makefile
+++ b/s390x/Makefile
@@ -7,6 +7,7 @@  tests += $(TEST_DIR)/skey.elf
 tests += $(TEST_DIR)/diag10.elf
 tests += $(TEST_DIR)/pfmf.elf
 tests += $(TEST_DIR)/cmm.elf
+tests += $(TEST_DIR)/vector.elf
 
 all: directories test_cases
 
diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg
index 367e970..2ea2bf9 100644
--- a/s390x/unittests.cfg
+++ b/s390x/unittests.cfg
@@ -50,3 +50,6 @@  file = pfmf.elf
 
 [cmm]
 file = cmm.elf
+
+[vector]
+file = vector.elf
diff --git a/s390x/vector.c b/s390x/vector.c
new file mode 100644
index 0000000..c6be541
--- /dev/null
+++ b/s390x/vector.c
@@ -0,0 +1,135 @@ 
+/*
+ * Tests vector instruction support
+ *
+ * Copyright 2018 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)));
+
+/* Fills all vector registers with data from addr */
+static inline void vlm_all(unsigned long *addr)
+{
+	asm volatile(" .machine z13\n"
+		     " vlm 0, 15, %[a]\n"
+		     : : [a]  "Q" (*addr)
+		     :	"v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8",
+			"v9", "v10", "v11", "v12", "v13", "v14", "v15");
+	asm volatile(" .machine z13\n"
+		     " vlm 16, 31, %[a]\n"
+		     : : [a]  "Q" (*(addr+256/8))
+		     :	"v16", "v17", "v18", "v19", "v20", "v21", "v22",
+			"v23", "v24", "v25", "v26", "v27", "v28", "v29",
+			"v30", "v31");
+}
+
+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)
+		     : "v0", "v1", "v2", "memory");
+	report("adding 21", prm.c == 42);
+}
+
+/* z14 vector extension test */
+static void test_ext1_nand(void)
+{
+	bool has_vext = test_facility(134);
+	static struct prm {
+		__uint128_t a,b,c;
+	} prm __attribute__((aligned(16)));
+
+	report_xfail("Vector extensions 1 available", !has_vext, has_vext);
+	if (!has_vext)
+		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" /* vnn */
+		     " vst 2, %[v3]\n"
+		     : [v3]  "=Q" (prm.c)
+		     : [v1]  "Q" (prm.a), [v2]  "Q" (prm.b)
+		     : "v0", "v1", "v2", "memory");
+	report("nand ff", !prm.c);
+}
+
+/* z14 bcd extension test */
+static void test_bcd_add(void)
+{
+	bool has_bcd = test_facility(135);
+	static struct prm {
+		__uint128_t a,b,c;
+	} prm __attribute__((aligned(16)));
+
+	report_xfail("Vector BCD extensions available", !has_bcd, has_bcd);
+	if (!has_bcd)
+		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 */
+		     " vst 2, %[v3]\n"
+		     : [v3]  "=Q" (prm.c)
+		     : [v1]  "Q" (prm.a), [v2]  "Q" (prm.b)
+		     : "v0", "v1", "v2", "memory");
+	report("bcd add 21", prm.c == 0x42c);
+}
+
+static void init(void)
+{
+	/* Enable vector instructions */
+	ctl_set_bit(0, 17);
+
+	/* Preset vector registers to 0xff */
+	memset(pagebuf, 0xff, PAGE_SIZE);
+	vlm_all((u64*)pagebuf);
+}
+
+int main(void)
+{
+	bool has_vregs = test_facility(129);
+
+	report_prefix_push("vector");
+	report_xfail("Basic vector facility available", !has_vregs, has_vregs);
+	if (!has_vregs)
+		goto done;
+
+	init();
+	test_add();
+	test_ext1_nand();
+	test_bcd_add();
+
+done:
+	report_prefix_pop();
+	return report_summary();
+}