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