xref: /openbmc/linux/tools/testing/selftests/kvm/include/aarch64/arch_timer.h (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
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,uint32_t tval)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  
timer_set_ctl(enum arch_timer timer,uint32_t ctl)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  
timer_get_ctl(enum arch_timer timer)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  
timer_set_next_cval_ms(enum arch_timer timer,uint32_t msec)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  
timer_set_next_tval_ms(enum arch_timer timer,uint32_t msec)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