xref: /kvm-unit-tests/s390x/spec_ex-sie.c (revision d1e2a8e2d0d5856f1a6ce23ea3f044a1532eab40)
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