xref: /kvm-unit-tests/s390x/diag288.c (revision 7b2e41767bb8caf91972ee32e4ca85ec630584e2)
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