xref: /kvm-unit-tests/s390x/spec_ex-sie.c (revision 4c8a99ca02252d4a2bee43f4558fe47ce5ab7ec0)
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 extern const char SNIPPET_NAME_START(c, spec_ex)[];
21 extern const char SNIPPET_NAME_END(c, spec_ex)[];
22 static bool strict;
23 
24 static void setup_guest(void)
25 {
26 	char *guest;
27 	int binary_size = SNIPPET_LEN(c, spec_ex);
28 
29 	setup_vm();
30 	guest = alloc_pages(8);
31 	memcpy(guest, SNIPPET_NAME_START(c, spec_ex), binary_size);
32 	sie_guest_create(&vm, (uint64_t) guest, HPAGE_SIZE);
33 }
34 
35 static void reset_guest(void)
36 {
37 	vm.sblk->gpsw = snippet_psw;
38 	vm.sblk->icptcode = 0;
39 }
40 
41 static void test_spec_ex_sie(void)
42 {
43 	const char *msg;
44 
45 	setup_guest();
46 
47 	report_prefix_push("SIE spec ex interpretation");
48 	report_prefix_push("off");
49 	reset_guest();
50 	sie(&vm);
51 	/* interpretation off -> initial exception must cause interception */
52 	report(vm.sblk->icptcode == ICPT_PROGI
53 	       && vm.sblk->iprcc == PGM_INT_CODE_SPECIFICATION
54 	       && vm.sblk->gpsw.addr != 0xdeadbeee,
55 	       "Received specification exception intercept for initial exception");
56 	report_prefix_pop();
57 
58 	report_prefix_push("on");
59 	vm.sblk->ecb |= ECB_SPECI;
60 	reset_guest();
61 	sie(&vm);
62 	/* interpretation on -> configuration dependent if initial exception causes
63 	 * interception, but invalid new program PSW must
64 	 */
65 	report(vm.sblk->icptcode == ICPT_PROGI
66 	       && vm.sblk->iprcc == PGM_INT_CODE_SPECIFICATION,
67 	       "Received specification exception intercept");
68 	msg = "Interpreted initial exception, intercepted invalid program new PSW exception";
69 	if (strict)
70 		report(vm.sblk->gpsw.addr == 0xdeadbeee, "%s", msg);
71 	else if (vm.sblk->gpsw.addr == 0xdeadbeee)
72 		report_info("%s", msg);
73 	else
74 		report_info("Did not interpret initial exception");
75 	report_prefix_pop();
76 	report_prefix_pop();
77 }
78 
79 static bool parse_strict(int argc, char **argv)
80 {
81 	uint16_t machine_id;
82 	char *list;
83 	bool ret;
84 
85 	if (argc < 1)
86 		return false;
87 	if (strcmp("--strict", argv[0]))
88 		return false;
89 
90 	machine_id = get_machine_id();
91 	if (argc < 2) {
92 		printf("No argument to --strict, ignoring\n");
93 		return false;
94 	}
95 	list = argv[1];
96 	if (list[0] == '!') {
97 		ret = true;
98 		list++;
99 	} else {
100 		ret = false;
101 	}
102 	while (true) {
103 		long input = 0;
104 
105 		if (strlen(list) == 0)
106 			return ret;
107 		input = strtol(list, &list, 16);
108 		if (*list == ',')
109 			list++;
110 		else if (*list != '\0')
111 			break;
112 		if (input == machine_id)
113 			return !ret;
114 	}
115 	printf("Invalid --strict argument \"%s\", ignoring\n", list);
116 	return ret;
117 }
118 
119 int main(int argc, char **argv)
120 {
121 	strict = parse_strict(argc - 1, argv + 1);
122 	if (!sclp_facilities.has_sief2) {
123 		report_skip("SIEF2 facility unavailable");
124 		goto out;
125 	}
126 
127 	test_spec_ex_sie();
128 out:
129 	return report_summary();
130 }
131