xref: /kvm-unit-tests/s390x/selftest.c (revision dfc1fec2fbde04ad607e1aed560cf7059350c70f)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (c) 2017 Red Hat Inc
4  *
5  * Authors:
6  *  Thomas Huth <thuth@redhat.com>
7  *  David Hildenbrand <david@redhat.com>
8  */
9 #include <libcflat.h>
10 #include <util.h>
11 #include <alloc.h>
12 #include <asm/interrupt.h>
13 #include <asm/barrier.h>
14 #include <asm/pgtable.h>
15 
16 static void test_fp(void)
17 {
18 	double a = 3.0;
19 	double b = 2.0;
20 	double c;
21 
22 	asm volatile(
23 		"	ddb %1, %2\n"
24 		"	std %1, %0\n"
25 		: "=m" (c) : "f" (a), "m" (b));
26 
27 	report(c == 1.5, "3.0/2.0 == 1.5");
28 }
29 
30 static void test_pgm_int(void)
31 {
32 	expect_pgm_int();
33 	asm volatile("	.insn e,0x0000"); /* used for SW breakpoints in QEMU */
34 	check_pgm_int_code(PGM_INT_CODE_OPERATION);
35 
36 	expect_pgm_int();
37 	asm volatile("	stg %0,0(%0)\n" : : "a"(-1L));
38 	check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
39 }
40 
41 static void test_malloc(void)
42 {
43 	int *tmp, *tmp2;
44 
45 	report_prefix_push("malloc");
46 
47 	report_prefix_push("ptr_0");
48 	tmp = malloc(sizeof(int));
49 	report((uintptr_t)tmp & 0xf000000000000000ul, "allocated memory");
50 	*tmp = 123456789;
51 	mb();
52 	report(*tmp == 123456789, "wrote allocated memory");
53 	report_prefix_pop();
54 
55 	report_prefix_push("ptr_1");
56 	tmp2 = malloc(sizeof(int));
57 	report((uintptr_t)tmp2 & 0xf000000000000000ul,
58 	       "allocated memory");
59 	*tmp2 = 123456789;
60 	mb();
61 	report((*tmp2 == 123456789), "wrote allocated memory");
62 	report_prefix_pop();
63 
64 	report(tmp != tmp2, "allocated memory addresses differ");
65 
66 	expect_pgm_int();
67 	disable_dat();
68 	*tmp = 987654321;
69 	enable_dat();
70 	check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
71 
72 	free(tmp);
73 	free(tmp2);
74 	report_prefix_pop();
75 }
76 
77 static void test_psw_mask(void)
78 {
79 	uint64_t expected_key = 0xf;
80 	struct psw test_psw = PSW(0, 0);
81 
82 	report_prefix_push("PSW mask");
83 	test_psw.mask = PSW_MASK_DAT;
84 	report(test_psw.dat, "DAT matches expected=0x%016lx actual=0x%016lx", PSW_MASK_DAT, test_psw.mask);
85 
86 	test_psw.mask = PSW_MASK_IO;
87 	report(test_psw.io, "IO matches expected=0x%016lx actual=0x%016lx", PSW_MASK_IO, test_psw.mask);
88 
89 	test_psw.mask = PSW_MASK_EXT;
90 	report(test_psw.ext, "EXT matches expected=0x%016lx actual=0x%016lx", PSW_MASK_EXT, test_psw.mask);
91 
92 	test_psw.mask = expected_key << (63 - 11);
93 	report(test_psw.key == expected_key, "PSW Key matches expected=0x%lx actual=0x%x", expected_key, test_psw.key);
94 
95 	test_psw.mask = 1UL << (63 - 13);
96 	report(test_psw.mchk, "MCHK matches");
97 
98 	test_psw.mask = PSW_MASK_WAIT;
99 	report(test_psw.wait, "Wait matches expected=0x%016lx actual=0x%016lx", PSW_MASK_WAIT, test_psw.mask);
100 
101 	test_psw.mask = PSW_MASK_PSTATE;
102 	report(test_psw.pstate, "Pstate matches expected=0x%016lx actual=0x%016lx", PSW_MASK_PSTATE, test_psw.mask);
103 
104 	test_psw.mask = PSW_MASK_64;
105 	report(test_psw.ea && test_psw.ba, "BA/EA matches expected=0x%016lx actual=0x%016lx", PSW_MASK_64, test_psw.mask);
106 
107 	report_prefix_pop();
108 }
109 
110 int main(int argc, char**argv)
111 {
112 	report_prefix_push("selftest");
113 
114 	report_pass("true");
115 	report(argc == 3, "argc == 3");
116 	report(!strcmp(argv[0], "s390x/selftest.elf"), "argv[0] == PROGNAME");
117 	report(!strcmp(argv[1], "test"), "argv[1] == test");
118 	report(!strcmp(argv[2], "123"), "argv[2] == 123");
119 
120 	setup_vm();
121 
122 	test_fp();
123 	test_pgm_int();
124 	test_malloc();
125 	test_psw_mask();
126 
127 	return report_summary();
128 }
129