xref: /kvm-unit-tests/s390x/spec_ex-sie.c (revision d1e2a8e2d0d5856f1a6ce23ea3f044a1532eab40)
149934b5aSJanis Schoetterl-Glausch // SPDX-License-Identifier: GPL-2.0-only
249934b5aSJanis Schoetterl-Glausch /*
349934b5aSJanis Schoetterl-Glausch  * Copyright IBM Corp. 2021
449934b5aSJanis Schoetterl-Glausch  *
549934b5aSJanis Schoetterl-Glausch  * Specification exception interception test.
649934b5aSJanis Schoetterl-Glausch  * Checks that specification exception interceptions occur as expected when
749934b5aSJanis Schoetterl-Glausch  * specification exception interpretation is off/on.
849934b5aSJanis Schoetterl-Glausch  */
949934b5aSJanis Schoetterl-Glausch #include <libcflat.h>
10d05bf604SJanis Schoetterl-Glausch #include <stdlib.h>
1149934b5aSJanis Schoetterl-Glausch #include <sclp.h>
1249934b5aSJanis Schoetterl-Glausch #include <asm/page.h>
1349934b5aSJanis Schoetterl-Glausch #include <asm/arch_def.h>
1449934b5aSJanis Schoetterl-Glausch #include <alloc_page.h>
1549934b5aSJanis Schoetterl-Glausch #include <sie.h>
1649934b5aSJanis Schoetterl-Glausch #include <snippet.h>
17d05bf604SJanis Schoetterl-Glausch #include <hardware.h>
1849934b5aSJanis Schoetterl-Glausch 
1949934b5aSJanis Schoetterl-Glausch static struct vm vm;
20d05bf604SJanis Schoetterl-Glausch static bool strict;
2149934b5aSJanis Schoetterl-Glausch 
setup_guest(void)2249934b5aSJanis Schoetterl-Glausch static void setup_guest(void)
2349934b5aSJanis Schoetterl-Glausch {
24*be76de4dSNico Boehr 	extern const char SNIPPET_NAME_START(c, spec_ex)[];
25*be76de4dSNico Boehr 	extern const char SNIPPET_NAME_END(c, spec_ex)[];
2649934b5aSJanis Schoetterl-Glausch 
2749934b5aSJanis Schoetterl-Glausch 	setup_vm();
28*be76de4dSNico Boehr 
29*be76de4dSNico Boehr 	snippet_setup_guest(&vm, false);
30*be76de4dSNico Boehr 	snippet_init(&vm, SNIPPET_NAME_START(c, spec_ex),
31*be76de4dSNico Boehr 		     SNIPPET_LEN(c, spec_ex), SNIPPET_UNPACK_OFF);
3249934b5aSJanis Schoetterl-Glausch }
3349934b5aSJanis Schoetterl-Glausch 
reset_guest(void)3449934b5aSJanis Schoetterl-Glausch static void reset_guest(void)
3549934b5aSJanis Schoetterl-Glausch {
3649934b5aSJanis Schoetterl-Glausch 	vm.sblk->gpsw = snippet_psw;
3749934b5aSJanis Schoetterl-Glausch 	vm.sblk->icptcode = 0;
3849934b5aSJanis Schoetterl-Glausch }
3949934b5aSJanis Schoetterl-Glausch 
test_spec_ex_sie(void)4049934b5aSJanis Schoetterl-Glausch static void test_spec_ex_sie(void)
4149934b5aSJanis Schoetterl-Glausch {
42d05bf604SJanis Schoetterl-Glausch 	const char *msg;
43d05bf604SJanis Schoetterl-Glausch 
4449934b5aSJanis Schoetterl-Glausch 	setup_guest();
4549934b5aSJanis Schoetterl-Glausch 
4649934b5aSJanis Schoetterl-Glausch 	report_prefix_push("SIE spec ex interpretation");
4749934b5aSJanis Schoetterl-Glausch 	report_prefix_push("off");
4849934b5aSJanis Schoetterl-Glausch 	reset_guest();
4949934b5aSJanis Schoetterl-Glausch 	sie(&vm);
5049934b5aSJanis Schoetterl-Glausch 	/* interpretation off -> initial exception must cause interception */
5149934b5aSJanis Schoetterl-Glausch 	report(vm.sblk->icptcode == ICPT_PROGI
5249934b5aSJanis Schoetterl-Glausch 	       && vm.sblk->iprcc == PGM_INT_CODE_SPECIFICATION
5349934b5aSJanis Schoetterl-Glausch 	       && vm.sblk->gpsw.addr != 0xdeadbeee,
5449934b5aSJanis Schoetterl-Glausch 	       "Received specification exception intercept for initial exception");
5549934b5aSJanis Schoetterl-Glausch 	report_prefix_pop();
5649934b5aSJanis Schoetterl-Glausch 
5749934b5aSJanis Schoetterl-Glausch 	report_prefix_push("on");
5849934b5aSJanis Schoetterl-Glausch 	vm.sblk->ecb |= ECB_SPECI;
5949934b5aSJanis Schoetterl-Glausch 	reset_guest();
6049934b5aSJanis Schoetterl-Glausch 	sie(&vm);
6149934b5aSJanis Schoetterl-Glausch 	/* interpretation on -> configuration dependent if initial exception causes
6249934b5aSJanis Schoetterl-Glausch 	 * interception, but invalid new program PSW must
6349934b5aSJanis Schoetterl-Glausch 	 */
6449934b5aSJanis Schoetterl-Glausch 	report(vm.sblk->icptcode == ICPT_PROGI
6549934b5aSJanis Schoetterl-Glausch 	       && vm.sblk->iprcc == PGM_INT_CODE_SPECIFICATION,
6649934b5aSJanis Schoetterl-Glausch 	       "Received specification exception intercept");
67d05bf604SJanis Schoetterl-Glausch 	msg = "Interpreted initial exception, intercepted invalid program new PSW exception";
68d05bf604SJanis Schoetterl-Glausch 	if (strict)
69d05bf604SJanis Schoetterl-Glausch 		report(vm.sblk->gpsw.addr == 0xdeadbeee, "%s", msg);
70d05bf604SJanis Schoetterl-Glausch 	else if (vm.sblk->gpsw.addr == 0xdeadbeee)
71d05bf604SJanis Schoetterl-Glausch 		report_info("%s", msg);
7249934b5aSJanis Schoetterl-Glausch 	else
7349934b5aSJanis Schoetterl-Glausch 		report_info("Did not interpret initial exception");
7449934b5aSJanis Schoetterl-Glausch 	report_prefix_pop();
7549934b5aSJanis Schoetterl-Glausch 	report_prefix_pop();
7649934b5aSJanis Schoetterl-Glausch }
7749934b5aSJanis Schoetterl-Glausch 
parse_strict(int argc,char ** argv)78d05bf604SJanis Schoetterl-Glausch static bool parse_strict(int argc, char **argv)
79d05bf604SJanis Schoetterl-Glausch {
80d05bf604SJanis Schoetterl-Glausch 	uint16_t machine_id;
81d05bf604SJanis Schoetterl-Glausch 	char *list;
82d05bf604SJanis Schoetterl-Glausch 	bool ret;
83d05bf604SJanis Schoetterl-Glausch 
84d05bf604SJanis Schoetterl-Glausch 	if (argc < 1)
85d05bf604SJanis Schoetterl-Glausch 		return false;
86d05bf604SJanis Schoetterl-Glausch 	if (strcmp("--strict", argv[0]))
87d05bf604SJanis Schoetterl-Glausch 		return false;
88d05bf604SJanis Schoetterl-Glausch 
89d05bf604SJanis Schoetterl-Glausch 	machine_id = get_machine_id();
90d05bf604SJanis Schoetterl-Glausch 	if (argc < 2) {
91d05bf604SJanis Schoetterl-Glausch 		printf("No argument to --strict, ignoring\n");
92d05bf604SJanis Schoetterl-Glausch 		return false;
93d05bf604SJanis Schoetterl-Glausch 	}
94d05bf604SJanis Schoetterl-Glausch 	list = argv[1];
95d05bf604SJanis Schoetterl-Glausch 	if (list[0] == '!') {
96d05bf604SJanis Schoetterl-Glausch 		ret = true;
97d05bf604SJanis Schoetterl-Glausch 		list++;
98d05bf604SJanis Schoetterl-Glausch 	} else {
99d05bf604SJanis Schoetterl-Glausch 		ret = false;
100d05bf604SJanis Schoetterl-Glausch 	}
101d05bf604SJanis Schoetterl-Glausch 	while (true) {
102d05bf604SJanis Schoetterl-Glausch 		long input = 0;
103d05bf604SJanis Schoetterl-Glausch 
104d05bf604SJanis Schoetterl-Glausch 		if (strlen(list) == 0)
105d05bf604SJanis Schoetterl-Glausch 			return ret;
106d05bf604SJanis Schoetterl-Glausch 		input = strtol(list, &list, 16);
107d05bf604SJanis Schoetterl-Glausch 		if (*list == ',')
108d05bf604SJanis Schoetterl-Glausch 			list++;
109d05bf604SJanis Schoetterl-Glausch 		else if (*list != '\0')
110d05bf604SJanis Schoetterl-Glausch 			break;
111d05bf604SJanis Schoetterl-Glausch 		if (input == machine_id)
112d05bf604SJanis Schoetterl-Glausch 			return !ret;
113d05bf604SJanis Schoetterl-Glausch 	}
114d05bf604SJanis Schoetterl-Glausch 	printf("Invalid --strict argument \"%s\", ignoring\n", list);
115d05bf604SJanis Schoetterl-Glausch 	return ret;
116d05bf604SJanis Schoetterl-Glausch }
117d05bf604SJanis Schoetterl-Glausch 
main(int argc,char ** argv)11849934b5aSJanis Schoetterl-Glausch int main(int argc, char **argv)
11949934b5aSJanis Schoetterl-Glausch {
120d05bf604SJanis Schoetterl-Glausch 	strict = parse_strict(argc - 1, argv + 1);
12149934b5aSJanis Schoetterl-Glausch 	if (!sclp_facilities.has_sief2) {
12249934b5aSJanis Schoetterl-Glausch 		report_skip("SIEF2 facility unavailable");
12349934b5aSJanis Schoetterl-Glausch 		goto out;
12449934b5aSJanis Schoetterl-Glausch 	}
12549934b5aSJanis Schoetterl-Glausch 
12649934b5aSJanis Schoetterl-Glausch 	test_spec_ex_sie();
12749934b5aSJanis Schoetterl-Glausch out:
12849934b5aSJanis Schoetterl-Glausch 	return report_summary();
12949934b5aSJanis Schoetterl-Glausch }
130