159 lines · c
1/* SPDX-License-Identifier: GPL-2.0 */2/*3 * ARM Generic Timer specific interface4 */5 6#ifndef SELFTEST_KVM_ARCH_TIMER_H7#define SELFTEST_KVM_ARCH_TIMER_H8 9#include "processor.h"10 11enum 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 29static inline uint32_t timer_get_cntfrq(void)30{31 return read_sysreg(cntfrq_el0);32}33 34static 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 51static 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 67static 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 82static inline void timer_set_tval(enum arch_timer timer, int32_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 98static inline int32_t timer_get_tval(enum arch_timer timer)99{100 isb();101 switch (timer) {102 case VIRTUAL:103 return read_sysreg(cntv_tval_el0);104 case PHYSICAL:105 return read_sysreg(cntp_tval_el0);106 default:107 GUEST_FAIL("Could not get timer %d\n", timer);108 }109 110 /* We should not reach here */111 return 0;112}113 114static inline void timer_set_ctl(enum arch_timer timer, uint32_t ctl)115{116 switch (timer) {117 case VIRTUAL:118 write_sysreg(ctl, cntv_ctl_el0);119 break;120 case PHYSICAL:121 write_sysreg(ctl, cntp_ctl_el0);122 break;123 default:124 GUEST_FAIL("Unexpected timer type = %u", timer);125 }126 127 isb();128}129 130static inline uint32_t timer_get_ctl(enum arch_timer timer)131{132 switch (timer) {133 case VIRTUAL:134 return read_sysreg(cntv_ctl_el0);135 case PHYSICAL:136 return read_sysreg(cntp_ctl_el0);137 default:138 GUEST_FAIL("Unexpected timer type = %u", timer);139 }140 141 /* We should not reach here */142 return 0;143}144 145static inline void timer_set_next_cval_ms(enum arch_timer timer, uint32_t msec)146{147 uint64_t now_ct = timer_get_cntct(timer);148 uint64_t next_ct = now_ct + msec_to_cycles(msec);149 150 timer_set_cval(timer, next_ct);151}152 153static inline void timer_set_next_tval_ms(enum arch_timer timer, uint32_t msec)154{155 timer_set_tval(timer, msec_to_cycles(msec));156}157 158#endif /* SELFTEST_KVM_ARCH_TIMER_H */159