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 mask, 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 mask = extract_psw_mask(); 89 mask |= PSW_MASK_EXT; 90 load_psw_mask(mask); 91 92 /* Arm watchdog */ 93 lowcore.restart_new_psw.mask = extract_psw_mask() & ~PSW_MASK_EXT; 94 diag288(CODE_INIT, 15, ACTION_RESTART); 95 asm volatile(" larl %r0, 1f\n" 96 " stg %r0, 424\n" 97 "0: nop\n" 98 " j 0b\n" 99 "1:"); 100 report_pass("restart"); 101 } 102 103 int main(void) 104 { 105 report_prefix_push("diag288"); 106 test_priv(); 107 test_specs(); 108 test_bite(); 109 return report_summary(); 110 } 111