xref: /kvm-unit-tests/s390x/vector.c (revision 90016cc56bd072042e7e2926c59a0146c10a4d32)
1 /*
2  * Tests vector instruction support
3  *
4  * Copyright 2018 IBM Corp.
5  *
6  * Authors:
7  *    Janosch Frank <frankja@de.ibm.com>
8  *
9  * This code is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Library General Public License version 2.
11  */
12 #include <libcflat.h>
13 #include <asm/page.h>
14 #include <asm/facility.h>
15 #include <asm/interrupt.h>
16 #include <asm-generic/barrier.h>
17 
18 static uint8_t pagebuf[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
19 
20 /* Fills all vector registers with data from addr */
21 static inline void vlm_all(unsigned long *addr)
22 {
23 	asm volatile(" .machine z13\n"
24 		     " vlm 0, 15, %[a]\n"
25 		     : : [a]  "Q" (*addr)
26 		     :	"v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8",
27 			"v9", "v10", "v11", "v12", "v13", "v14", "v15");
28 	asm volatile(" .machine z13\n"
29 		     " vlm 16, 31, %[a]\n"
30 		     : : [a]  "Q" (*(addr+256/8))
31 		     :	"v16", "v17", "v18", "v19", "v20", "v21", "v22",
32 			"v23", "v24", "v25", "v26", "v27", "v28", "v29",
33 			"v30", "v31");
34 }
35 
36 static void test_add(void)
37 {
38 	static struct prm {
39 		__uint128_t a,b,c;
40 	} prm __attribute__((aligned(16)));
41 
42 	prm.a = prm.b = prm.c = 21;
43 
44 	asm volatile(" .machine z13\n"
45 		     " vl 0, %[v1]\n"
46 		     " vl 1, %[v2]\n"
47 		     " va 2, 0, 1, 4\n"
48 		     " vst 2, %[v3]\n"
49 		     : [v3]  "=Q" (prm.c)
50 		     : [v1]  "Q" (prm.a), [v2]  "Q" (prm.b)
51 		     : "v0", "v1", "v2", "memory");
52 	report("adding 21", prm.c == 42);
53 }
54 
55 /* z14 vector extension test */
56 static void test_ext1_nand(void)
57 {
58 	bool has_vext = test_facility(134);
59 	static struct prm {
60 		__uint128_t a,b,c;
61 	} prm __attribute__((aligned(16)));
62 
63 	if (!has_vext) {
64 		report_skip("Vector extensions 1 is not available");
65 		return;
66 	}
67 
68 	memset(&prm, 0xff, sizeof(prm));
69 
70 	asm volatile(" .machine z13\n"
71 		     " vl 0, %[v1]\n"
72 		     " vl 1, %[v2]\n"
73 		     " .byte 0xe7, 0x20, 0x10, 0x00, 0x00, 0x6e\n" /* vnn */
74 		     " vst 2, %[v3]\n"
75 		     : [v3]  "=Q" (prm.c)
76 		     : [v1]  "Q" (prm.a), [v2]  "Q" (prm.b)
77 		     : "v0", "v1", "v2", "memory");
78 	report("nand ff", !prm.c);
79 }
80 
81 /* z14 bcd extension test */
82 static void test_bcd_add(void)
83 {
84 	bool has_bcd = test_facility(135);
85 	static struct prm {
86 		__uint128_t a,b,c;
87 	} prm __attribute__((aligned(16)));
88 
89 	if (!has_bcd) {
90 		report_skip("Vector BCD extensions is not available");
91 		return;
92 	}
93 
94 	prm.c = 0;
95 	prm.a = prm.b = 0b001000011100;
96 
97 	asm volatile(" .machine z13\n"
98 		     " vl 0, %[v1]\n"
99 		     " vl 1, %[v2]\n"
100 		     " .byte 0xe6, 0x20, 0x10, 0x01, 0x00, 0x71\n" /* vap */
101 		     " vst 2, %[v3]\n"
102 		     : [v3]  "=Q" (prm.c)
103 		     : [v1]  "Q" (prm.a), [v2]  "Q" (prm.b)
104 		     : "v0", "v1", "v2", "memory");
105 	report("bcd add 21", prm.c == 0x42c);
106 }
107 
108 static void init(void)
109 {
110 	/* Enable vector instructions */
111 	ctl_set_bit(0, 17);
112 
113 	/* Preset vector registers to 0xff */
114 	memset(pagebuf, 0xff, PAGE_SIZE);
115 	vlm_all((u64*)pagebuf);
116 }
117 
118 int main(void)
119 {
120 	bool has_vregs = test_facility(129);
121 
122 	report_prefix_push("vector");
123 	if (!has_vregs) {
124 		report_skip("Basic vector facility is not available");
125 		goto done;
126 	}
127 
128 	init();
129 	test_add();
130 	test_ext1_nand();
131 	test_bcd_add();
132 
133 done:
134 	report_prefix_pop();
135 	return report_summary();
136 }
137