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