xref: /kvm-unit-tests/s390x/diag288.c (revision 7b2e41767bb8caf91972ee32e4ca85ec630584e2)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Timer Event DIAG288 test
4  *
5  * Copyright (c) 2019 IBM Corp
6  *
7  * Authors:
8  *  Janosch Frank <frankja@linux.ibm.com>
9  */
10 
11 #include <libcflat.h>
12 #include <asm/asm-offsets.h>
13 #include <asm/interrupt.h>
14 
15 #define CODE_INIT	0
16 #define CODE_CHANGE	1
17 #define CODE_CANCEL	2
18 
19 #define ACTION_RESTART	0
20 
diag288(unsigned long code,unsigned long time,unsigned long action)21 static inline void diag288(unsigned long code, unsigned long time,
22 			   unsigned long action)
23 {
24 	register unsigned long fc asm("0") = code;
25 	register unsigned long tm asm("1") = time;
26 	register unsigned long ac asm("2") = action;
27 
28 	asm volatile("diag %0,%2,0x288"
29 		     : : "d" (fc), "d" (tm), "d" (ac));
30 }
31 
test_specs(void)32 static void test_specs(void)
33 {
34 	report_prefix_push("specification");
35 
36 	report_prefix_push("uneven");
37 	expect_pgm_int();
38 	asm volatile("diag 1,2,0x288");
39 	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
40 	report_prefix_pop();
41 
42 	report_prefix_push("unsupported action");
43 	expect_pgm_int();
44 	diag288(CODE_INIT, 15, 42);
45 	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
46 	report_prefix_pop();
47 
48 	report_prefix_push("unsupported function");
49 	expect_pgm_int();
50 	diag288(42, 15, ACTION_RESTART);
51 	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
52 	report_prefix_pop();
53 
54 	report_prefix_push("no init");
55 	expect_pgm_int();
56 	diag288(CODE_CANCEL, 15, ACTION_RESTART);
57 	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
58 	report_prefix_pop();
59 
60 	report_prefix_push("min timer");
61 	expect_pgm_int();
62 	diag288(CODE_INIT, 14, ACTION_RESTART);
63 	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
64 	report_prefix_pop();
65 
66 	report_prefix_pop();
67 }
68 
test_priv(void)69 static void test_priv(void)
70 {
71 	report_prefix_push("privileged");
72 	expect_pgm_int();
73 	enter_pstate();
74 	diag288(CODE_INIT, 15, ACTION_RESTART);
75 	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
76 	report_prefix_pop();
77 }
78 
test_bite(void)79 static void test_bite(void)
80 {
81 	uint64_t time;
82 
83 	/* If watchdog doesn't bite, the cpu timer does */
84 	asm volatile("stck %0" : "=Q" (time) : : "cc");
85 	time += (uint64_t)(16000 * 1000) << 12;
86 	asm volatile("sckc %0" : : "Q" (time));
87 	ctl_set_bit(0, CTL0_CLOCK_COMPARATOR);
88 	psw_mask_set_bits(PSW_MASK_EXT);
89 
90 	/* Arm watchdog */
91 	lowcore.restart_new_psw.mask = extract_psw_mask() & ~PSW_MASK_EXT;
92 	diag288(CODE_INIT, 15, ACTION_RESTART);
93 	asm volatile("		larl	%r0, 1f\n"
94 		     "		stg	%r0, 424\n"
95 		     "0:	nop\n"
96 		     "		j	0b\n"
97 		     "1:");
98 	report_pass("restart");
99 }
100 
main(void)101 int main(void)
102 {
103 	report_prefix_push("diag288");
104 	test_priv();
105 	test_specs();
106 	test_bite();
107 	return report_summary();
108 }
109