1fa624cc2SJanosch Frank /* SPDX-License-Identifier: GPL-2.0-only */
265dc6515SJanosch Frank /*
365dc6515SJanosch Frank * Timer Event DIAG288 test
465dc6515SJanosch Frank *
565dc6515SJanosch Frank * Copyright (c) 2019 IBM Corp
665dc6515SJanosch Frank *
765dc6515SJanosch Frank * Authors:
865dc6515SJanosch Frank * Janosch Frank <frankja@linux.ibm.com>
965dc6515SJanosch Frank */
1065dc6515SJanosch Frank
1165dc6515SJanosch Frank #include <libcflat.h>
1265dc6515SJanosch Frank #include <asm/asm-offsets.h>
1365dc6515SJanosch Frank #include <asm/interrupt.h>
1465dc6515SJanosch Frank
1565dc6515SJanosch Frank #define CODE_INIT 0
1665dc6515SJanosch Frank #define CODE_CHANGE 1
1765dc6515SJanosch Frank #define CODE_CANCEL 2
1865dc6515SJanosch Frank
1965dc6515SJanosch Frank #define ACTION_RESTART 0
2065dc6515SJanosch Frank
diag288(unsigned long code,unsigned long time,unsigned long action)2165dc6515SJanosch Frank static inline void diag288(unsigned long code, unsigned long time,
2265dc6515SJanosch Frank unsigned long action)
2365dc6515SJanosch Frank {
2465dc6515SJanosch Frank register unsigned long fc asm("0") = code;
2565dc6515SJanosch Frank register unsigned long tm asm("1") = time;
2665dc6515SJanosch Frank register unsigned long ac asm("2") = action;
2765dc6515SJanosch Frank
2865dc6515SJanosch Frank asm volatile("diag %0,%2,0x288"
2965dc6515SJanosch Frank : : "d" (fc), "d" (tm), "d" (ac));
3065dc6515SJanosch Frank }
3165dc6515SJanosch Frank
test_specs(void)3265dc6515SJanosch Frank static void test_specs(void)
3365dc6515SJanosch Frank {
3465dc6515SJanosch Frank report_prefix_push("specification");
3565dc6515SJanosch Frank
3665dc6515SJanosch Frank report_prefix_push("uneven");
3765dc6515SJanosch Frank expect_pgm_int();
3865dc6515SJanosch Frank asm volatile("diag 1,2,0x288");
3965dc6515SJanosch Frank check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
4065dc6515SJanosch Frank report_prefix_pop();
4165dc6515SJanosch Frank
4265dc6515SJanosch Frank report_prefix_push("unsupported action");
4365dc6515SJanosch Frank expect_pgm_int();
4465dc6515SJanosch Frank diag288(CODE_INIT, 15, 42);
4565dc6515SJanosch Frank check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
4665dc6515SJanosch Frank report_prefix_pop();
4765dc6515SJanosch Frank
4865dc6515SJanosch Frank report_prefix_push("unsupported function");
4965dc6515SJanosch Frank expect_pgm_int();
5065dc6515SJanosch Frank diag288(42, 15, ACTION_RESTART);
5165dc6515SJanosch Frank check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
5265dc6515SJanosch Frank report_prefix_pop();
5365dc6515SJanosch Frank
5465dc6515SJanosch Frank report_prefix_push("no init");
5565dc6515SJanosch Frank expect_pgm_int();
5665dc6515SJanosch Frank diag288(CODE_CANCEL, 15, ACTION_RESTART);
5765dc6515SJanosch Frank check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
5865dc6515SJanosch Frank report_prefix_pop();
5965dc6515SJanosch Frank
6065dc6515SJanosch Frank report_prefix_push("min timer");
6165dc6515SJanosch Frank expect_pgm_int();
6265dc6515SJanosch Frank diag288(CODE_INIT, 14, ACTION_RESTART);
6365dc6515SJanosch Frank check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
6465dc6515SJanosch Frank report_prefix_pop();
6565dc6515SJanosch Frank
6665dc6515SJanosch Frank report_prefix_pop();
6765dc6515SJanosch Frank }
6865dc6515SJanosch Frank
test_priv(void)6965dc6515SJanosch Frank static void test_priv(void)
7065dc6515SJanosch Frank {
7165dc6515SJanosch Frank report_prefix_push("privileged");
7265dc6515SJanosch Frank expect_pgm_int();
7365dc6515SJanosch Frank enter_pstate();
7465dc6515SJanosch Frank diag288(CODE_INIT, 15, ACTION_RESTART);
7565dc6515SJanosch Frank check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
7665dc6515SJanosch Frank report_prefix_pop();
7765dc6515SJanosch Frank }
7865dc6515SJanosch Frank
test_bite(void)7965dc6515SJanosch Frank static void test_bite(void)
8065dc6515SJanosch Frank {
81*086985a3SClaudio Imbrenda uint64_t time;
8265dc6515SJanosch Frank
8365dc6515SJanosch Frank /* If watchdog doesn't bite, the cpu timer does */
8465dc6515SJanosch Frank asm volatile("stck %0" : "=Q" (time) : : "cc");
8565dc6515SJanosch Frank time += (uint64_t)(16000 * 1000) << 12;
8665dc6515SJanosch Frank asm volatile("sckc %0" : : "Q" (time));
871b2c0437SClaudio Imbrenda ctl_set_bit(0, CTL0_CLOCK_COMPARATOR);
88*086985a3SClaudio Imbrenda psw_mask_set_bits(PSW_MASK_EXT);
8965dc6515SJanosch Frank
9065dc6515SJanosch Frank /* Arm watchdog */
91cd719531SJanis Schoetterl-Glausch lowcore.restart_new_psw.mask = extract_psw_mask() & ~PSW_MASK_EXT;
9265dc6515SJanosch Frank diag288(CODE_INIT, 15, ACTION_RESTART);
9365dc6515SJanosch Frank asm volatile(" larl %r0, 1f\n"
9465dc6515SJanosch Frank " stg %r0, 424\n"
9565dc6515SJanosch Frank "0: nop\n"
9665dc6515SJanosch Frank " j 0b\n"
9765dc6515SJanosch Frank "1:");
985c3582f0SJanis Schoetterl-Glausch report_pass("restart");
9965dc6515SJanosch Frank }
10065dc6515SJanosch Frank
main(void)10165dc6515SJanosch Frank int main(void)
10265dc6515SJanosch Frank {
10365dc6515SJanosch Frank report_prefix_push("diag288");
10465dc6515SJanosch Frank test_priv();
10565dc6515SJanosch Frank test_specs();
10665dc6515SJanosch Frank test_bite();
10765dc6515SJanosch Frank return report_summary();
10865dc6515SJanosch Frank }
109