1 /* 2 * Timer Event DIAG288 test 3 * 4 * Copyright (c) 2019 IBM Corp 5 * 6 * Authors: 7 * Janosch Frank <frankja@linux.ibm.com> 8 * 9 * This code is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU Library General Public License version 2. 11 */ 12 13 #include <libcflat.h> 14 #include <asm/asm-offsets.h> 15 #include <asm/interrupt.h> 16 17 struct lowcore *lc = (struct lowcore *)0x0; 18 19 #define CODE_INIT 0 20 #define CODE_CHANGE 1 21 #define CODE_CANCEL 2 22 23 #define ACTION_RESTART 0 24 25 static inline void diag288(unsigned long code, unsigned long time, 26 unsigned long action) 27 { 28 register unsigned long fc asm("0") = code; 29 register unsigned long tm asm("1") = time; 30 register unsigned long ac asm("2") = action; 31 32 asm volatile("diag %0,%2,0x288" 33 : : "d" (fc), "d" (tm), "d" (ac)); 34 } 35 36 static void test_specs(void) 37 { 38 report_prefix_push("specification"); 39 40 report_prefix_push("uneven"); 41 expect_pgm_int(); 42 asm volatile("diag 1,2,0x288"); 43 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 44 report_prefix_pop(); 45 46 report_prefix_push("unsupported action"); 47 expect_pgm_int(); 48 diag288(CODE_INIT, 15, 42); 49 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 50 report_prefix_pop(); 51 52 report_prefix_push("unsupported function"); 53 expect_pgm_int(); 54 diag288(42, 15, ACTION_RESTART); 55 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 56 report_prefix_pop(); 57 58 report_prefix_push("no init"); 59 expect_pgm_int(); 60 diag288(CODE_CANCEL, 15, ACTION_RESTART); 61 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 62 report_prefix_pop(); 63 64 report_prefix_push("min timer"); 65 expect_pgm_int(); 66 diag288(CODE_INIT, 14, ACTION_RESTART); 67 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 68 report_prefix_pop(); 69 70 report_prefix_pop(); 71 } 72 73 static void test_priv(void) 74 { 75 report_prefix_push("privileged"); 76 expect_pgm_int(); 77 enter_pstate(); 78 diag288(CODE_INIT, 15, ACTION_RESTART); 79 check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION); 80 report_prefix_pop(); 81 } 82 83 static void test_bite(void) 84 { 85 uint64_t mask, time; 86 87 /* If watchdog doesn't bite, the cpu timer does */ 88 asm volatile("stck %0" : "=Q" (time) : : "cc"); 89 time += (uint64_t)(16000 * 1000) << 12; 90 asm volatile("sckc %0" : : "Q" (time)); 91 ctl_set_bit(0, 11); 92 mask = extract_psw_mask(); 93 mask |= PSW_MASK_EXT; 94 load_psw_mask(mask); 95 96 /* Arm watchdog */ 97 lc->restart_new_psw.mask = extract_psw_mask() & ~PSW_MASK_EXT; 98 diag288(CODE_INIT, 15, ACTION_RESTART); 99 asm volatile(" larl %r0, 1f\n" 100 " stg %r0, 424\n" 101 "0: nop\n" 102 " j 0b\n" 103 "1:"); 104 report("restart", true); 105 } 106 107 int main(void) 108 { 109 report_prefix_push("diag288"); 110 test_priv(); 111 test_specs(); 112 test_bite(); 113 return report_summary(); 114 } 115