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 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 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 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 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 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