0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef __CLKSOURCE_HYPERV_TIMER_H
0014 #define __CLKSOURCE_HYPERV_TIMER_H
0015
0016 #include <linux/clocksource.h>
0017 #include <linux/math64.h>
0018 #include <asm/mshyperv.h>
0019
0020 #define HV_MAX_MAX_DELTA_TICKS 0xffffffff
0021 #define HV_MIN_DELTA_TICKS 1
0022
0023 #ifdef CONFIG_HYPERV_TIMER
0024
0025
0026 extern int hv_stimer_alloc(bool have_percpu_irqs);
0027 extern int hv_stimer_cleanup(unsigned int cpu);
0028 extern void hv_stimer_legacy_init(unsigned int cpu, int sint);
0029 extern void hv_stimer_legacy_cleanup(unsigned int cpu);
0030 extern void hv_stimer_global_cleanup(void);
0031 extern void hv_stimer0_isr(void);
0032
0033 extern void hv_init_clocksource(void);
0034
0035 extern struct ms_hyperv_tsc_page *hv_get_tsc_page(void);
0036
0037 static inline notrace u64
0038 hv_read_tsc_page_tsc(const struct ms_hyperv_tsc_page *tsc_pg, u64 *cur_tsc)
0039 {
0040 u64 scale, offset;
0041 u32 sequence;
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059 do {
0060 sequence = READ_ONCE(tsc_pg->tsc_sequence);
0061 if (!sequence)
0062 return U64_MAX;
0063
0064
0065
0066
0067 smp_rmb();
0068
0069 scale = READ_ONCE(tsc_pg->tsc_scale);
0070 offset = READ_ONCE(tsc_pg->tsc_offset);
0071 *cur_tsc = hv_get_raw_timer();
0072
0073
0074
0075
0076
0077 smp_rmb();
0078
0079 } while (READ_ONCE(tsc_pg->tsc_sequence) != sequence);
0080
0081 return mul_u64_u64_shr(*cur_tsc, scale, 64) + offset;
0082 }
0083
0084 static inline notrace u64
0085 hv_read_tsc_page(const struct ms_hyperv_tsc_page *tsc_pg)
0086 {
0087 u64 cur_tsc;
0088
0089 return hv_read_tsc_page_tsc(tsc_pg, &cur_tsc);
0090 }
0091
0092 #else
0093 static inline struct ms_hyperv_tsc_page *hv_get_tsc_page(void)
0094 {
0095 return NULL;
0096 }
0097
0098 static inline u64 hv_read_tsc_page_tsc(const struct ms_hyperv_tsc_page *tsc_pg,
0099 u64 *cur_tsc)
0100 {
0101 return U64_MAX;
0102 }
0103
0104 static inline int hv_stimer_cleanup(unsigned int cpu) { return 0; }
0105 static inline void hv_stimer_legacy_init(unsigned int cpu, int sint) {}
0106 static inline void hv_stimer_legacy_cleanup(unsigned int cpu) {}
0107 static inline void hv_stimer_global_cleanup(void) {}
0108 static inline void hv_stimer0_isr(void) {}
0109
0110 #endif
0111
0112 #endif