xref: /kvm-unit-tests/s390x/sck.c (revision 5bf99cb38621d44b0a7d2204ecd9326b3209ab73)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Perform Set Clock tests
4  *
5  * Copyright IBM Corp. 2022
6  *
7  * Authors:
8  *  Nico Boehr <nrb@linux.ibm.com>
9  */
10 #include <libcflat.h>
11 #include <uv.h>
12 #include <asm/interrupt.h>
13 #include <asm/time.h>
14 
test_priv(void)15 static void test_priv(void)
16 {
17 	uint64_t time_to_set_privileged = 0xfacef00dcafe0000,
18 	    time_to_set_nonprivileged = 0xcafe0000,
19 	    time_verify;
20 	int cc;
21 
22 	report_prefix_push("privileged");
23 	cc = sck(&time_to_set_privileged);
24 	report(!cc, "set clock cc=%d", cc);
25 
26 	cc = stck(&time_verify);
27 	report(!cc, "store clock cc=%d", cc);
28 	report(time_verify > time_to_set_privileged,
29 	       "privileged set affected the clock");
30 	report_prefix_pop();
31 
32 	report_prefix_push("unprivileged");
33 	expect_pgm_int();
34 	enter_pstate();
35 	sck(&time_to_set_nonprivileged);
36 	leave_pstate();
37 	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
38 
39 	cc = stck(&time_verify);
40 	report(!cc, "store clock cc=%d", cc);
41 	report(time_verify > time_to_set_privileged,
42 	       "unprivileged set did not affect the clock");
43 	report_prefix_pop();
44 }
45 
test_align(void)46 static void test_align(void)
47 {
48 	const int align_to = 8;
49 	char unalign[sizeof(uint64_t) + align_to] __attribute__((aligned(8)));
50 
51 	report_prefix_push("Unaligned operand");
52 	for (int i = 1; i < align_to; i *= 2) {
53 		report_prefix_pushf("%d", i);
54 		expect_pgm_int();
55 		sck((uint64_t *)(unalign + i));
56 		check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
57 		report_prefix_pop();
58 	}
59 	report_prefix_pop();
60 }
61 
test_set(void)62 static void test_set(void)
63 {
64 	uint64_t start = 0, end = 0, time = 0xcafef00dbeef;
65 	const uint64_t ticks_per_ms = 1000 << 12, ms_to_wait = 5;
66 	int cc;
67 
68 	report_prefix_push("set");
69 
70 	cc = sck(&time);
71 	report(!cc, "set clock cc=%d", cc);
72 
73 	cc = stck(&start);
74 	report(!cc, "store start clock cc=%d", cc);
75 	report(start >= time, "start >= set value");
76 
77 	mdelay(ms_to_wait);
78 
79 	cc = stck(&end);
80 	report(!cc, "store end clock cc=%d", cc);
81 	report(end > time, "end > set value");
82 
83 	report(end - start > (ticks_per_ms * ms_to_wait), "Advances");
84 
85 	report_prefix_pop();
86 }
87 
main(void)88 int main(void)
89 {
90 	report_prefix_push("sck");
91 
92 	if (uv_os_is_guest()) {
93 		report_skip("Test unsupported under PV");
94 		goto out;
95 	}
96 
97 	test_align();
98 	test_set();
99 	test_priv();
100 
101 out:
102 	report_prefix_pop();
103 	return report_summary();
104 }
105