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