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, 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 98 static 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 114 static 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 130 static 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 145 static 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 153 static 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