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 struct lowcore *lc = (struct lowcore *)0x0; 16 17 #define CODE_INIT 0 18 #define CODE_CHANGE 1 19 #define CODE_CANCEL 2 20 21 #define ACTION_RESTART 0 22 23 static inline void diag288(unsigned long code, unsigned long time, 24 unsigned long action) 25 { 26 register unsigned long fc asm("0") = code; 27 register unsigned long tm asm("1") = time; 28 register unsigned long ac asm("2") = action; 29 30 asm volatile("diag %0,%2,0x288" 31 : : "d" (fc), "d" (tm), "d" (ac)); 32 } 33 34 static void test_specs(void) 35 { 36 report_prefix_push("specification"); 37 38 report_prefix_push("uneven"); 39 expect_pgm_int(); 40 asm volatile("diag 1,2,0x288"); 41 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 42 report_prefix_pop(); 43 44 report_prefix_push("unsupported action"); 45 expect_pgm_int(); 46 diag288(CODE_INIT, 15, 42); 47 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 48 report_prefix_pop(); 49 50 report_prefix_push("unsupported function"); 51 expect_pgm_int(); 52 diag288(42, 15, ACTION_RESTART); 53 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 54 report_prefix_pop(); 55 56 report_prefix_push("no init"); 57 expect_pgm_int(); 58 diag288(CODE_CANCEL, 15, ACTION_RESTART); 59 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 60 report_prefix_pop(); 61 62 report_prefix_push("min timer"); 63 expect_pgm_int(); 64 diag288(CODE_INIT, 14, ACTION_RESTART); 65 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 66 report_prefix_pop(); 67 68 report_prefix_pop(); 69 } 70 71 static void test_priv(void) 72 { 73 report_prefix_push("privileged"); 74 expect_pgm_int(); 75 enter_pstate(); 76 diag288(CODE_INIT, 15, ACTION_RESTART); 77 check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION); 78 report_prefix_pop(); 79 } 80 81 static void test_bite(void) 82 { 83 uint64_t mask, time; 84 85 /* If watchdog doesn't bite, the cpu timer does */ 86 asm volatile("stck %0" : "=Q" (time) : : "cc"); 87 time += (uint64_t)(16000 * 1000) << 12; 88 asm volatile("sckc %0" : : "Q" (time)); 89 ctl_set_bit(0, CTL0_CLOCK_COMPARATOR); 90 mask = extract_psw_mask(); 91 mask |= PSW_MASK_EXT; 92 load_psw_mask(mask); 93 94 /* Arm watchdog */ 95 lc->restart_new_psw.mask = extract_psw_mask() & ~PSW_MASK_EXT; 96 diag288(CODE_INIT, 15, ACTION_RESTART); 97 asm volatile(" larl %r0, 1f\n" 98 " stg %r0, 424\n" 99 "0: nop\n" 100 " j 0b\n" 101 "1:"); 102 report_pass("restart"); 103 } 104 105 int main(void) 106 { 107 report_prefix_push("diag288"); 108 test_priv(); 109 test_specs(); 110 test_bite(); 111 return report_summary(); 112 } 113