1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * ARM Generic Timer specific interface 4 */ 5 6 #ifndef SELFTEST_KVM_ARCH_TIMER_H 7 #define SELFTEST_KVM_ARCH_TIMER_H 8 9 #include "processor.h" 10 11 enum arch_timer { 12 VIRTUAL, 13 PHYSICAL, 14 }; 15 16 #define CTL_ENABLE (1 << 0) 17 #define CTL_IMASK (1 << 1) 18 #define CTL_ISTATUS (1 << 2) 19 20 #define msec_to_cycles(msec) \ 21 (timer_get_cntfrq() * (uint64_t)(msec) / 1000) 22 23 #define usec_to_cycles(usec) \ 24 (timer_get_cntfrq() * (uint64_t)(usec) / 1000000) 25 26 #define cycles_to_usec(cycles) \ 27 ((uint64_t)(cycles) * 1000000 / timer_get_cntfrq()) 28 29 static inline uint32_t timer_get_cntfrq(void) 30 { 31 return read_sysreg(cntfrq_el0); 32 } 33 34 static inline uint64_t timer_get_cntct(enum arch_timer timer) 35 { 36 isb(); 37 38 switch (timer) { 39 case VIRTUAL: 40 return read_sysreg(cntvct_el0); 41 case PHYSICAL: 42 return read_sysreg(cntpct_el0); 43 default: 44 GUEST_FAIL("Unexpected timer type = %u", timer); 45 } 46 47 /* We should not reach here */ 48 return 0; 49 } 50 51 static inline void timer_set_cval(enum arch_timer timer, uint64_t cval) 52 { 53 switch (timer) { 54 case VIRTUAL: 55 write_sysreg(cval, cntv_cval_el0); 56 break; 57 case PHYSICAL: 58 write_sysreg(cval, cntp_cval_el0); 59 break; 60 default: 61 GUEST_FAIL("Unexpected timer type = %u", timer); 62 } 63 64 isb(); 65 } 66 67 static inline uint64_t timer_get_cval(enum arch_timer timer) 68 { 69 switch (timer) { 70 case VIRTUAL: 71 return read_sysreg(cntv_cval_el0); 72 case PHYSICAL: 73 return read_sysreg(cntp_cval_el0); 74 default: 75 GUEST_FAIL("Unexpected timer type = %u", timer); 76 } 77 78 /* We should not reach here */ 79 return 0; 80 } 81 82 static inline void timer_set_tval(enum arch_timer timer, uint32_t tval) 83 { 84 switch (timer) { 85 case VIRTUAL: 86 write_sysreg(tval, cntv_tval_el0); 87 break; 88 case PHYSICAL: 89 write_sysreg(tval, cntp_tval_el0); 90 break; 91 default: 92 GUEST_FAIL("Unexpected timer type = %u", timer); 93 } 94 95 isb(); 96 } 97 98 static inline void timer_set_ctl(enum arch_timer timer, uint32_t ctl) 99 { 100 switch (timer) { 101 case VIRTUAL: 102 write_sysreg(ctl, cntv_ctl_el0); 103 break; 104 case PHYSICAL: 105 write_sysreg(ctl, cntp_ctl_el0); 106 break; 107 default: 108 GUEST_FAIL("Unexpected timer type = %u", timer); 109 } 110 111 isb(); 112 } 113 114 static inline uint32_t timer_get_ctl(enum arch_timer timer) 115 { 116 switch (timer) { 117 case VIRTUAL: 118 return read_sysreg(cntv_ctl_el0); 119 case PHYSICAL: 120 return read_sysreg(cntp_ctl_el0); 121 default: 122 GUEST_FAIL("Unexpected timer type = %u", timer); 123 } 124 125 /* We should not reach here */ 126 return 0; 127 } 128 129 static inline void timer_set_next_cval_ms(enum arch_timer timer, uint32_t msec) 130 { 131 uint64_t now_ct = timer_get_cntct(timer); 132 uint64_t next_ct = now_ct + msec_to_cycles(msec); 133 134 timer_set_cval(timer, next_ct); 135 } 136 137 static inline void timer_set_next_tval_ms(enum arch_timer timer, uint32_t msec) 138 { 139 timer_set_tval(timer, msec_to_cycles(msec)); 140 } 141 142 #endif /* SELFTEST_KVM_ARCH_TIMER_H */ 143