1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright IBM Corp. 2021
4 *
5 * Specification exception interception test.
6 * Checks that specification exception interceptions occur as expected when
7 * specification exception interpretation is off/on.
8 */
9 #include <libcflat.h>
10 #include <stdlib.h>
11 #include <sclp.h>
12 #include <asm/page.h>
13 #include <asm/arch_def.h>
14 #include <alloc_page.h>
15 #include <sie.h>
16 #include <snippet.h>
17 #include <hardware.h>
18
19 static struct vm vm;
20 static bool strict;
21
setup_guest(void)22 static void setup_guest(void)
23 {
24 extern const char SNIPPET_NAME_START(c, spec_ex)[];
25 extern const char SNIPPET_NAME_END(c, spec_ex)[];
26
27 setup_vm();
28
29 snippet_setup_guest(&vm, false);
30 snippet_init(&vm, SNIPPET_NAME_START(c, spec_ex),
31 SNIPPET_LEN(c, spec_ex), SNIPPET_UNPACK_OFF);
32 }
33
reset_guest(void)34 static void reset_guest(void)
35 {
36 vm.sblk->gpsw = snippet_psw;
37 vm.sblk->icptcode = 0;
38 }
39
test_spec_ex_sie(void)40 static void test_spec_ex_sie(void)
41 {
42 const char *msg;
43
44 setup_guest();
45
46 report_prefix_push("SIE spec ex interpretation");
47 report_prefix_push("off");
48 reset_guest();
49 sie(&vm);
50 /* interpretation off -> initial exception must cause interception */
51 report(vm.sblk->icptcode == ICPT_PROGI
52 && vm.sblk->iprcc == PGM_INT_CODE_SPECIFICATION
53 && vm.sblk->gpsw.addr != 0xdeadbeee,
54 "Received specification exception intercept for initial exception");
55 report_prefix_pop();
56
57 report_prefix_push("on");
58 vm.sblk->ecb |= ECB_SPECI;
59 reset_guest();
60 sie(&vm);
61 /* interpretation on -> configuration dependent if initial exception causes
62 * interception, but invalid new program PSW must
63 */
64 report(vm.sblk->icptcode == ICPT_PROGI
65 && vm.sblk->iprcc == PGM_INT_CODE_SPECIFICATION,
66 "Received specification exception intercept");
67 msg = "Interpreted initial exception, intercepted invalid program new PSW exception";
68 if (strict)
69 report(vm.sblk->gpsw.addr == 0xdeadbeee, "%s", msg);
70 else if (vm.sblk->gpsw.addr == 0xdeadbeee)
71 report_info("%s", msg);
72 else
73 report_info("Did not interpret initial exception");
74 report_prefix_pop();
75 report_prefix_pop();
76 }
77
parse_strict(int argc,char ** argv)78 static bool parse_strict(int argc, char **argv)
79 {
80 uint16_t machine_id;
81 char *list;
82 bool ret;
83
84 if (argc < 1)
85 return false;
86 if (strcmp("--strict", argv[0]))
87 return false;
88
89 machine_id = get_machine_id();
90 if (argc < 2) {
91 printf("No argument to --strict, ignoring\n");
92 return false;
93 }
94 list = argv[1];
95 if (list[0] == '!') {
96 ret = true;
97 list++;
98 } else {
99 ret = false;
100 }
101 while (true) {
102 long input = 0;
103
104 if (strlen(list) == 0)
105 return ret;
106 input = strtol(list, &list, 16);
107 if (*list == ',')
108 list++;
109 else if (*list != '\0')
110 break;
111 if (input == machine_id)
112 return !ret;
113 }
114 printf("Invalid --strict argument \"%s\", ignoring\n", list);
115 return ret;
116 }
117
main(int argc,char ** argv)118 int main(int argc, char **argv)
119 {
120 strict = parse_strict(argc - 1, argv + 1);
121 if (!sclp_facilities.has_sief2) {
122 report_skip("SIEF2 facility unavailable");
123 goto out;
124 }
125
126 test_spec_ex_sie();
127 out:
128 return report_summary();
129 }
130