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