xref: /linux/tools/testing/selftests/kvm/include/aarch64/arch_timer.h (revision 64dd3b6a79f0907d36de481b0f15fab323a53e5a)
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 
timer_get_cntfrq(void)29 static inline uint32_t timer_get_cntfrq(void)
30 {
31 	return read_sysreg(cntfrq_el0);
32 }
33 
timer_get_cntct(enum arch_timer timer)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 
timer_set_cval(enum arch_timer timer,uint64_t cval)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 
timer_get_cval(enum arch_timer timer)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 
timer_set_tval(enum arch_timer timer,int32_t tval)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 
timer_get_tval(enum arch_timer timer)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 
timer_set_ctl(enum arch_timer timer,uint32_t ctl)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 
timer_get_ctl(enum arch_timer timer)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 
timer_set_next_cval_ms(enum arch_timer timer,uint32_t msec)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 
timer_set_next_tval_ms(enum arch_timer timer,uint32_t msec)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