xref: /kvm-unit-tests/s390x/stfle-sie.c (revision 1f08a91a41402b0e032ecce8ed1b5952cbfca0ea)
1*708ec6dbSNina Schoetterl-Glausch /* SPDX-License-Identifier: GPL-2.0-only */
2*708ec6dbSNina Schoetterl-Glausch /*
3*708ec6dbSNina Schoetterl-Glausch  * Copyright IBM Corp. 2023
4*708ec6dbSNina Schoetterl-Glausch  *
5*708ec6dbSNina Schoetterl-Glausch  * SIE with STLFE interpretive execution facilities test.
6*708ec6dbSNina Schoetterl-Glausch  */
7*708ec6dbSNina Schoetterl-Glausch #include <libcflat.h>
8*708ec6dbSNina Schoetterl-Glausch #include <stdlib.h>
9*708ec6dbSNina Schoetterl-Glausch #include <asm/facility.h>
10*708ec6dbSNina Schoetterl-Glausch #include <asm/time.h>
11*708ec6dbSNina Schoetterl-Glausch #include <snippet.h>
12*708ec6dbSNina Schoetterl-Glausch #include <snippet-exit.h>
13*708ec6dbSNina Schoetterl-Glausch #include <alloc_page.h>
14*708ec6dbSNina Schoetterl-Glausch #include <sclp.h>
15*708ec6dbSNina Schoetterl-Glausch #include <rand.h>
16*708ec6dbSNina Schoetterl-Glausch 
17*708ec6dbSNina Schoetterl-Glausch static struct vm vm;
18*708ec6dbSNina Schoetterl-Glausch static uint64_t (*fac)[PAGE_SIZE / sizeof(uint64_t)];
19*708ec6dbSNina Schoetterl-Glausch static prng_state prng_s;
20*708ec6dbSNina Schoetterl-Glausch 
setup_guest(void)21*708ec6dbSNina Schoetterl-Glausch static void setup_guest(void)
22*708ec6dbSNina Schoetterl-Glausch {
23*708ec6dbSNina Schoetterl-Glausch 	extern const char SNIPPET_NAME_START(c, stfle)[];
24*708ec6dbSNina Schoetterl-Glausch 	extern const char SNIPPET_NAME_END(c, stfle)[];
25*708ec6dbSNina Schoetterl-Glausch 
26*708ec6dbSNina Schoetterl-Glausch 	setup_vm();
27*708ec6dbSNina Schoetterl-Glausch 	fac = alloc_pages_flags(0, AREA_DMA31);
28*708ec6dbSNina Schoetterl-Glausch 
29*708ec6dbSNina Schoetterl-Glausch 	snippet_setup_guest(&vm, false);
30*708ec6dbSNina Schoetterl-Glausch 	snippet_init(&vm, SNIPPET_NAME_START(c, stfle),
31*708ec6dbSNina Schoetterl-Glausch 		     SNIPPET_LEN(c, stfle), SNIPPET_UNPACK_OFF);
32*708ec6dbSNina Schoetterl-Glausch }
33*708ec6dbSNina Schoetterl-Glausch 
34*708ec6dbSNina Schoetterl-Glausch struct guest_stfle_res {
35*708ec6dbSNina Schoetterl-Glausch 	uint16_t len;
36*708ec6dbSNina Schoetterl-Glausch 	unsigned char *mem;
37*708ec6dbSNina Schoetterl-Glausch };
38*708ec6dbSNina Schoetterl-Glausch 
run_guest(void)39*708ec6dbSNina Schoetterl-Glausch static struct guest_stfle_res run_guest(void)
40*708ec6dbSNina Schoetterl-Glausch {
41*708ec6dbSNina Schoetterl-Glausch 	struct guest_stfle_res res;
42*708ec6dbSNina Schoetterl-Glausch 	uint64_t guest_stfle_addr;
43*708ec6dbSNina Schoetterl-Glausch 	uint64_t reg;
44*708ec6dbSNina Schoetterl-Glausch 
45*708ec6dbSNina Schoetterl-Glausch 	sie(&vm);
46*708ec6dbSNina Schoetterl-Glausch 	assert(snippet_is_force_exit_value(&vm));
47*708ec6dbSNina Schoetterl-Glausch 	guest_stfle_addr = snippet_get_force_exit_value(&vm);
48*708ec6dbSNina Schoetterl-Glausch 	res.mem = &vm.guest_mem[guest_stfle_addr];
49*708ec6dbSNina Schoetterl-Glausch 	memcpy(&reg, res.mem, sizeof(reg));
50*708ec6dbSNina Schoetterl-Glausch 	res.len = (reg & 0xff) + 1;
51*708ec6dbSNina Schoetterl-Glausch 	res.mem += sizeof(reg);
52*708ec6dbSNina Schoetterl-Glausch 	return res;
53*708ec6dbSNina Schoetterl-Glausch }
54*708ec6dbSNina Schoetterl-Glausch 
test_stfle_format_0(void)55*708ec6dbSNina Schoetterl-Glausch static void test_stfle_format_0(void)
56*708ec6dbSNina Schoetterl-Glausch {
57*708ec6dbSNina Schoetterl-Glausch 	struct guest_stfle_res res;
58*708ec6dbSNina Schoetterl-Glausch 
59*708ec6dbSNina Schoetterl-Glausch 	report_prefix_push("format-0");
60*708ec6dbSNina Schoetterl-Glausch 	for (int j = 0; j < stfle_size(); j++)
61*708ec6dbSNina Schoetterl-Glausch 		WRITE_ONCE((*fac)[j], prng64(&prng_s));
62*708ec6dbSNina Schoetterl-Glausch 	vm.sblk->fac = (uint32_t)(uint64_t)fac;
63*708ec6dbSNina Schoetterl-Glausch 	res = run_guest();
64*708ec6dbSNina Schoetterl-Glausch 	report(res.len == stfle_size(), "stfle len correct");
65*708ec6dbSNina Schoetterl-Glausch 	report(!memcmp(*fac, res.mem, res.len * sizeof(uint64_t)),
66*708ec6dbSNina Schoetterl-Glausch 	       "Guest facility list as specified");
67*708ec6dbSNina Schoetterl-Glausch 	report_prefix_pop();
68*708ec6dbSNina Schoetterl-Glausch }
69*708ec6dbSNina Schoetterl-Glausch 
70*708ec6dbSNina Schoetterl-Glausch struct args {
71*708ec6dbSNina Schoetterl-Glausch 	uint64_t seed;
72*708ec6dbSNina Schoetterl-Glausch };
73*708ec6dbSNina Schoetterl-Glausch 
parse_uint64_t(const char * arg,uint64_t * out)74*708ec6dbSNina Schoetterl-Glausch static bool parse_uint64_t(const char *arg, uint64_t *out)
75*708ec6dbSNina Schoetterl-Glausch {
76*708ec6dbSNina Schoetterl-Glausch 	char *end;
77*708ec6dbSNina Schoetterl-Glausch 	uint64_t num;
78*708ec6dbSNina Schoetterl-Glausch 
79*708ec6dbSNina Schoetterl-Glausch 	if (arg[0] == '\0')
80*708ec6dbSNina Schoetterl-Glausch 		return false;
81*708ec6dbSNina Schoetterl-Glausch 	num = strtoul(arg, &end, 0);
82*708ec6dbSNina Schoetterl-Glausch 	if (end[0] != '\0')
83*708ec6dbSNina Schoetterl-Glausch 		return false;
84*708ec6dbSNina Schoetterl-Glausch 	*out = num;
85*708ec6dbSNina Schoetterl-Glausch 	return true;
86*708ec6dbSNina Schoetterl-Glausch }
87*708ec6dbSNina Schoetterl-Glausch 
parse_args(int argc,char ** argv)88*708ec6dbSNina Schoetterl-Glausch static struct args parse_args(int argc, char **argv)
89*708ec6dbSNina Schoetterl-Glausch {
90*708ec6dbSNina Schoetterl-Glausch 	struct args args;
91*708ec6dbSNina Schoetterl-Glausch 	const char *flag;
92*708ec6dbSNina Schoetterl-Glausch 	unsigned int i;
93*708ec6dbSNina Schoetterl-Glausch 	uint64_t arg;
94*708ec6dbSNina Schoetterl-Glausch 	bool has_arg;
95*708ec6dbSNina Schoetterl-Glausch 
96*708ec6dbSNina Schoetterl-Glausch 	stck(&args.seed);
97*708ec6dbSNina Schoetterl-Glausch 
98*708ec6dbSNina Schoetterl-Glausch 	for (i = 1; i < argc; i++) {
99*708ec6dbSNina Schoetterl-Glausch 		if (i + 1 < argc)
100*708ec6dbSNina Schoetterl-Glausch 			has_arg = parse_uint64_t(argv[i + 1], &arg);
101*708ec6dbSNina Schoetterl-Glausch 		else
102*708ec6dbSNina Schoetterl-Glausch 			has_arg = false;
103*708ec6dbSNina Schoetterl-Glausch 
104*708ec6dbSNina Schoetterl-Glausch 		flag = "--seed";
105*708ec6dbSNina Schoetterl-Glausch 		if (!strcmp(flag, argv[i])) {
106*708ec6dbSNina Schoetterl-Glausch 			if (!has_arg)
107*708ec6dbSNina Schoetterl-Glausch 				report_abort("%s needs an uint64_t parameter", flag);
108*708ec6dbSNina Schoetterl-Glausch 			args.seed = arg;
109*708ec6dbSNina Schoetterl-Glausch 			++i;
110*708ec6dbSNina Schoetterl-Glausch 			continue;
111*708ec6dbSNina Schoetterl-Glausch 		}
112*708ec6dbSNina Schoetterl-Glausch 		report_abort("Unsupported parameter '%s'",
113*708ec6dbSNina Schoetterl-Glausch 			     argv[i]);
114*708ec6dbSNina Schoetterl-Glausch 	}
115*708ec6dbSNina Schoetterl-Glausch 
116*708ec6dbSNina Schoetterl-Glausch 	return args;
117*708ec6dbSNina Schoetterl-Glausch }
118*708ec6dbSNina Schoetterl-Glausch 
main(int argc,char ** argv)119*708ec6dbSNina Schoetterl-Glausch int main(int argc, char **argv)
120*708ec6dbSNina Schoetterl-Glausch {
121*708ec6dbSNina Schoetterl-Glausch 	struct args args = parse_args(argc, argv);
122*708ec6dbSNina Schoetterl-Glausch 	bool run_format_0 = test_facility(7);
123*708ec6dbSNina Schoetterl-Glausch 
124*708ec6dbSNina Schoetterl-Glausch 	if (!sclp_facilities.has_sief2) {
125*708ec6dbSNina Schoetterl-Glausch 		report_skip("SIEF2 facility unavailable");
126*708ec6dbSNina Schoetterl-Glausch 		goto out;
127*708ec6dbSNina Schoetterl-Glausch 	}
128*708ec6dbSNina Schoetterl-Glausch 	if (!run_format_0)
129*708ec6dbSNina Schoetterl-Glausch 		report_skip("STFLE facility not available");
130*708ec6dbSNina Schoetterl-Glausch 
131*708ec6dbSNina Schoetterl-Glausch 	report_info("PRNG seed: 0x%lx", args.seed);
132*708ec6dbSNina Schoetterl-Glausch 	prng_s = prng_init(args.seed);
133*708ec6dbSNina Schoetterl-Glausch 	setup_guest();
134*708ec6dbSNina Schoetterl-Glausch 	if (run_format_0)
135*708ec6dbSNina Schoetterl-Glausch 		test_stfle_format_0();
136*708ec6dbSNina Schoetterl-Glausch out:
137*708ec6dbSNina Schoetterl-Glausch 	return report_summary();
138*708ec6dbSNina Schoetterl-Glausch }
139