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