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