xref: /kvm-unit-tests/s390x/spec_ex.c (revision d1e2a8e2d0d5856f1a6ce23ea3f044a1532eab40)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright IBM Corp. 2021, 2022
4  *
5  * Specification exception test.
6  * Tests that specification exceptions occur when expected.
7  * This includes specification exceptions occurring during transactional execution
8  * as these result in another interruption code (the transactional-execution-aborted
9  * bit is set).
10  *
11  * Can be extended by adding triggers to spec_ex_triggers, see comments below.
12  */
13 #include <stdlib.h>
14 #include <htmintrin.h>
15 #include <libcflat.h>
16 #include <bitops.h>
17 #include <asm/barrier.h>
18 #include <asm/interrupt.h>
19 #include <asm/facility.h>
20 
21 /* toggled to signal occurrence of invalid psw fixup */
22 static bool invalid_psw_expected;
23 static struct psw expected_psw;
24 static struct psw invalid_psw;
25 static struct psw fixup_psw;
26 
27 /*
28  * The standard program exception handler cannot deal with invalid old PSWs,
29  * especially not invalid instruction addresses, as in that case one cannot
30  * find the instruction following the faulting one from the old PSW.
31  * The PSW to return to is set by load_psw.
32  */
fixup_invalid_psw(struct stack_frame_int * stack)33 static void fixup_invalid_psw(struct stack_frame_int *stack)
34 {
35 	assert_msg(invalid_psw_expected,
36 		   "Unexpected invalid PSW during program interrupt fixup: %#lx %#lx",
37 		   lowcore.pgm_old_psw.mask, lowcore.pgm_old_psw.addr);
38 	/* signal occurrence of invalid psw fixup */
39 	invalid_psw_expected = false;
40 	invalid_psw = lowcore.pgm_old_psw;
41 	lowcore.pgm_old_psw = fixup_psw;
42 }
43 
44 /*
45  * Load possibly invalid psw, but setup fixup_psw before,
46  * so that fixup_invalid_psw() can bring us back onto the right track.
47  * Also acts as compiler barrier, -> none required in expect/check_invalid_psw
48  */
load_psw(struct psw psw)49 static void load_psw(struct psw psw)
50 {
51 	uint64_t scratch;
52 
53 	/*
54 	 * The fixup psw is the current psw with the instruction address replaced
55 	 * by the address of the nop following the instruction loading the new psw.
56 	 */
57 	fixup_psw.mask = extract_psw_mask();
58 	asm volatile ( "larl	%[scratch],0f\n"
59 		"	stg	%[scratch],%[fixup_addr]\n"
60 		"	lpswe	%[psw]\n"
61 		"0:	nop\n"
62 		: [scratch] "=&d" (scratch),
63 		  [fixup_addr] "=&T" (fixup_psw.addr)
64 		: [psw] "Q" (psw)
65 		: "cc", "memory"
66 	);
67 }
68 
load_short_psw(struct short_psw psw)69 static void load_short_psw(struct short_psw psw)
70 {
71 	uint64_t scratch;
72 
73 	fixup_psw.mask = extract_psw_mask();
74 	asm volatile ( "larl	%[scratch],0f\n"
75 		"	stg	%[scratch],%[fixup_addr]\n"
76 		"	lpsw	%[psw]\n"
77 		"0:	nop\n"
78 		: [scratch] "=&d" (scratch),
79 		  [fixup_addr] "=&T" (fixup_psw.addr)
80 		: [psw] "Q" (psw)
81 		: "cc", "memory"
82 	);
83 }
84 
expect_invalid_psw(struct psw psw)85 static void expect_invalid_psw(struct psw psw)
86 {
87 	expected_psw = psw;
88 	invalid_psw_expected = true;
89 }
90 
clear_invalid_psw(void)91 static void clear_invalid_psw(void)
92 {
93 	expected_psw = PSW(0, 0);
94 	invalid_psw_expected = false;
95 }
96 
check_invalid_psw(void)97 static int check_invalid_psw(void)
98 {
99 	/* Since the fixup sets this to false we check for false here. */
100 	if (!invalid_psw_expected) {
101 		/*
102 		 * Early exception recognition: pgm_int_id == 0.
103 		 * Late exception recognition: psw address has been
104 		 *	incremented by pgm_int_id (unpredictable value)
105 		 */
106 		if (expected_psw.mask == invalid_psw.mask &&
107 		    expected_psw.addr == invalid_psw.addr - lowcore.pgm_int_id)
108 			return 0;
109 		report_fail("Wrong invalid PSW");
110 	} else {
111 		report_fail("Expected exception due to invalid PSW");
112 	}
113 	return 1;
114 }
115 
116 /* For normal PSWs bit 12 has to be 0 to be a valid PSW*/
psw_bit_12_is_1(void)117 static int psw_bit_12_is_1(void)
118 {
119 	struct psw invalid = PSW(BIT(63 - 12), 0x00000000deadbeee);
120 
121 	expect_invalid_psw(invalid);
122 	load_psw(invalid);
123 	return check_invalid_psw();
124 }
125 
126 extern char misaligned_code_pre[];
127 asm (  ".balign	2\n"
128 "misaligned_code_pre:\n"
129 "	. = . + 1\n"
130 "	larl	%r0,0\n"
131 "	br	%r1\n"
132 );
133 
psw_odd_address(void)134 static int psw_odd_address(void)
135 {
136 	struct psw odd = PSW_WITH_CUR_MASK(((uint64_t)&misaligned_code_pre) + 1);
137 	uint64_t executed_addr;
138 
139 	expect_invalid_psw(odd);
140 	fixup_psw.mask = extract_psw_mask();
141 	asm volatile ( "xgr	%%r0,%%r0\n"
142 		"	larl	%%r1,0f\n"
143 		"	stg	%%r1,%[fixup_addr]\n"
144 		"	lpswe	%[odd_psw]\n"
145 		"0:	lgr	%[executed_addr],%%r0\n"
146 	: [fixup_addr] "=&T" (fixup_psw.addr),
147 	  [executed_addr] "=d" (executed_addr)
148 	: [odd_psw] "Q" (odd)
149 	: "cc", "%r0", "%r1", "memory" /* Compiler barrier like in load_psw */
150 	);
151 
152 	if (!executed_addr) {
153 		return check_invalid_psw();
154 	} else {
155 		assert(executed_addr == odd.addr);
156 		clear_invalid_psw();
157 		report_fail("did not execute unaligned instructions");
158 		return 1;
159 	}
160 }
161 
162 /* A short PSW needs to have bit 12 set to be valid. */
short_psw_bit_12_is_0(void)163 static int short_psw_bit_12_is_0(void)
164 {
165 	struct psw invalid = PSW(BIT(63 - 12), 0x00000000deadbeee);
166 	struct short_psw short_invalid = {
167 		.mask = 0x0,
168 		.addr = 0xdeadbeee
169 	};
170 
171 	expect_invalid_psw(invalid);
172 	load_short_psw(short_invalid);
173 	/*
174 	 * lpsw may optionally check bit 12 before loading the new psw
175 	 * -> cannot check the expected invalid psw like with lpswe
176 	 */
177 	return 0;
178 }
179 
odd_ex_target(void)180 static int odd_ex_target(void)
181 {
182 	uint64_t pre_target_addr;
183 	int to = 0, from = 0x0dd;
184 
185 	asm volatile ( ".pushsection .text.ex_odd\n"
186 		"	.balign	2\n"
187 		"pre_odd_ex_target%=:\n"
188 		"	. = . + 1\n"
189 		"	lr	%[to],%[from]\n"
190 		"	.popsection\n"
191 
192 		"	larl	%[pre_target_addr],pre_odd_ex_target%=\n"
193 		"	ex	0,1(%[pre_target_addr])\n"
194 		: [pre_target_addr] "=&a" (pre_target_addr),
195 		  [to] "+d" (to)
196 		: [from] "d" (from)
197 	);
198 
199 	assert((pre_target_addr + 1) & 1);
200 	report(to != from, "did not perform ex with odd target");
201 	return 0;
202 }
203 
bad_alignment_lqp(void)204 static int bad_alignment_lqp(void)
205 {
206 	uint32_t words[5] __attribute__((aligned(16)));
207 	uint32_t (*bad_aligned)[4] = (uint32_t (*)[4])&words[1];
208 
209 	/* LOAD PAIR FROM QUADWORD (LPQ) requires quadword alignment */
210 	asm volatile ("lpq %%r6,%[bad]"
211 		      : : [bad] "T" (*bad_aligned)
212 		      : "%r6", "%r7"
213 	);
214 	return 0;
215 }
216 
bad_alignment_lrl(void)217 static int bad_alignment_lrl(void)
218 {
219 	uint64_t r;
220 
221 	asm volatile ( ".pushsection .rodata\n"
222 		"	.balign	4\n"
223 		"	. = . + 2\n"
224 		"0:	.fill	4\n"
225 		"	.popsection\n"
226 
227 		"	lrl	%0,0b\n"
228 		: "=d" (r)
229 	);
230 	return 0;
231 }
232 
not_even(void)233 static int not_even(void)
234 {
235 	uint64_t quad[2] __attribute__((aligned(16))) = {0};
236 
237 	asm volatile (".insn	rxy,0xe3000000008f,%%r7,%[quad]" /* lpq %%r7,%[quad] */
238 		      : : [quad] "T" (quad)
239 		      : "%r7", "%r8"
240 	);
241 	return 0;
242 }
243 
244 /*
245  * Harness for specification exception testing.
246  * func only triggers exception, reporting is taken care of automatically.
247  * If a trigger is transactable it will also be executed during a transaction.
248  */
249 struct spec_ex_trigger {
250 	const char *name;
251 	int (*func)(void);
252 	bool transactable;
253 	void (*fixup)(struct stack_frame_int *stack);
254 };
255 
256 /* List of all tests to execute */
257 static const struct spec_ex_trigger spec_ex_triggers[] = {
258 	{ "psw_bit_12_is_1", &psw_bit_12_is_1, false, &fixup_invalid_psw },
259 	{ "short_psw_bit_12_is_0", &short_psw_bit_12_is_0, false, &fixup_invalid_psw },
260 	{ "psw_odd_address", &psw_odd_address, false, &fixup_invalid_psw },
261 	{ "odd_ex_target", &odd_ex_target, true, NULL },
262 	{ "bad_alignment_lqp", &bad_alignment_lqp, true, NULL },
263 	{ "bad_alignment_lrl", &bad_alignment_lrl, true, NULL },
264 	{ "not_even", &not_even, true, NULL },
265 	{ NULL, NULL, false, NULL },
266 };
267 
test_spec_ex(const struct spec_ex_trigger * trigger)268 static void test_spec_ex(const struct spec_ex_trigger *trigger)
269 {
270 	int rc;
271 
272 	expect_pgm_int();
273 	register_pgm_cleanup_func(trigger->fixup);
274 	rc = trigger->func();
275 	register_pgm_cleanup_func(NULL);
276 	/* test failed, nothing to be done, reporting responsibility of trigger */
277 	if (rc)
278 		return;
279 	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
280 }
281 
282 #define TRANSACTION_COMPLETED 4
283 #define TRANSACTION_MAX_RETRIES 5
284 
285 /*
286  * NULL must not be passed to __builtin_tbegin via variable, only constant,
287  * forbid diagnose from being NULL at all to keep things simple
288  */
289 static int __attribute__((nonnull))
with_transaction(int (* trigger)(void),struct __htm_tdb * diagnose)290 with_transaction(int (*trigger)(void), struct __htm_tdb *diagnose)
291 {
292 	int cc;
293 
294 	cc = __builtin_tbegin(diagnose);
295 	/*
296 	 * Everything between tbegin and tend is part of the transaction,
297 	 * which either completes in its entirety or does not have any effect.
298 	 * If the transaction fails, execution is reset to this point with another
299 	 * condition code indicating why the transaction failed.
300 	 */
301 	if (cc == _HTM_TBEGIN_STARTED) {
302 		/*
303 		 * return code is meaningless: transaction needs to complete
304 		 * in order to return and completion indicates a test failure
305 		 */
306 		trigger();
307 		__builtin_tend();
308 		return TRANSACTION_COMPLETED;
309 	} else {
310 		return cc;
311 	}
312 }
313 
retry_transaction(const struct spec_ex_trigger * trigger,unsigned int max_retries,struct __htm_tdb * tdb,uint16_t expected_pgm)314 static int retry_transaction(const struct spec_ex_trigger *trigger, unsigned int max_retries,
315 			     struct __htm_tdb *tdb, uint16_t expected_pgm)
316 {
317 	int trans_result, i;
318 	uint16_t pgm;
319 
320 	for (i = 0; i < max_retries; i++) {
321 		expect_pgm_int();
322 		trans_result = with_transaction(trigger->func, tdb);
323 		if (trans_result == _HTM_TBEGIN_TRANSIENT) {
324 			mb();
325 			pgm = lowcore.pgm_int_code;
326 			if (pgm == expected_pgm)
327 				return 0;
328 			else if (pgm == 0)
329 				/*
330 				 * Transaction failed for unknown reason but not because
331 				 * of an unexpected program exception. Give it another
332 				 * go so that hopefully it reaches the triggering instruction.
333 				 */
334 				continue;
335 		}
336 		return trans_result;
337 	}
338 	return TRANSACTION_MAX_RETRIES;
339 }
340 
341 struct args {
342 	uint64_t max_retries;
343 	bool diagnose;
344 };
345 
test_spec_ex_trans(struct args * args,const struct spec_ex_trigger * trigger)346 static void test_spec_ex_trans(struct args *args, const struct spec_ex_trigger *trigger)
347 {
348 	const uint16_t expected_pgm = PGM_INT_CODE_SPECIFICATION |
349 				      PGM_INT_CODE_TX_ABORTED_EVENT;
350 	union {
351 		struct __htm_tdb tdb;
352 		uint64_t dwords[sizeof(struct __htm_tdb) / sizeof(uint64_t)];
353 	} diag;
354 	unsigned int i;
355 	int trans_result;
356 
357 	if (!test_facility(73)) {
358 		report_skip("transactional-execution facility not installed");
359 		return;
360 	}
361 	ctl_set_bit(0, CTL0_TRANSACT_EX_CTL); /* enable transactional-exec */
362 
363 	register_pgm_cleanup_func(trigger->fixup);
364 	trans_result = retry_transaction(trigger, args->max_retries, &diag.tdb, expected_pgm);
365 	register_pgm_cleanup_func(NULL);
366 	switch (trans_result) {
367 	case 0:
368 		report_pass("Program interrupt: expected(%d) == received(%d)",
369 			    expected_pgm, expected_pgm);
370 		break;
371 	case _HTM_TBEGIN_INDETERMINATE:
372 	case _HTM_TBEGIN_PERSISTENT:
373 		report_info("transaction failed with cc %d", trans_result);
374 		report_info("transaction abort code: %llu", diag.tdb.abort_code);
375 		if (args->diagnose)
376 			for (i = 0; i < 32; i++)
377 				report_info("diag+%03d: %016lx", i * 8, diag.dwords[i]);
378 		break;
379 	case _HTM_TBEGIN_TRANSIENT:
380 		report_fail("Program interrupt: expected(%d) == received(%d)",
381 			    expected_pgm, clear_pgm_int());
382 		break;
383 	case TRANSACTION_COMPLETED:
384 		report_fail("Transaction completed without exception");
385 		break;
386 	case TRANSACTION_MAX_RETRIES:
387 		report_skip("Transaction retried %lu times with transient failures, giving up",
388 			    args->max_retries);
389 		break;
390 	default:
391 		report_fail("Invalid transaction result");
392 		break;
393 	}
394 
395 	ctl_clear_bit(0, CTL0_TRANSACT_EX_CTL);
396 }
397 
parse_unsigned(const char * arg,unsigned int * out)398 static bool parse_unsigned(const char *arg, unsigned int *out)
399 {
400 	char *end;
401 	long num;
402 
403 	if (arg[0] == '\0')
404 		return false;
405 	num = strtol(arg, &end, 10);
406 	if (end[0] != '\0' || num < 0)
407 		return false;
408 	*out = num;
409 	return true;
410 }
411 
parse_args(int argc,char ** argv)412 static struct args parse_args(int argc, char **argv)
413 {
414 	struct args args = {
415 		.max_retries = 20,
416 		.diagnose = false
417 	};
418 	unsigned int i, arg;
419 	bool has_arg;
420 	const char *flag;
421 
422 	for (i = 1; i < argc; i++) {
423 		if (i + 1 < argc)
424 			has_arg = parse_unsigned(argv[i + 1], &arg);
425 		else
426 			has_arg = false;
427 
428 		flag = "--max-retries";
429 		if (!strcmp(flag, argv[i])) {
430 			if (!has_arg)
431 				report_abort("%s needs a positive parameter", flag);
432 			args.max_retries = arg;
433 			++i;
434 			continue;
435 		}
436 		if (!strcmp("--diagnose", argv[i])) {
437 			args.diagnose = true;
438 			continue;
439 		}
440 		if (!strcmp("--no-diagnose", argv[i])) {
441 			args.diagnose = false;
442 			continue;
443 		}
444 		report_abort("Unsupported parameter '%s'",
445 			     argv[i]);
446 	}
447 
448 	return args;
449 }
450 
main(int argc,char ** argv)451 int main(int argc, char **argv)
452 {
453 	unsigned int i;
454 
455 	struct args args = parse_args(argc, argv);
456 
457 	report_prefix_push("specification exception");
458 	for (i = 0; spec_ex_triggers[i].name; i++) {
459 		report_prefix_push(spec_ex_triggers[i].name);
460 		test_spec_ex(&spec_ex_triggers[i]);
461 		report_prefix_pop();
462 	}
463 	report_prefix_pop();
464 
465 	report_prefix_push("specification exception during transaction");
466 	for (i = 0; spec_ex_triggers[i].name; i++) {
467 		if (spec_ex_triggers[i].transactable) {
468 			report_prefix_push(spec_ex_triggers[i].name);
469 			test_spec_ex_trans(&args, &spec_ex_triggers[i]);
470 			report_prefix_pop();
471 		}
472 	}
473 	report_prefix_pop();
474 
475 	return report_summary();
476 }
477