Commit | Line | Data |
---|---|---|
45051539 | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
53e72406 MZ |
2 | /* |
3 | * Copyright (C) 2012 ARM Ltd. | |
4 | * Author: Marc Zyngier <marc.zyngier@arm.com> | |
53e72406 MZ |
5 | */ |
6 | ||
7 | #ifndef __ASM_ARM_KVM_ARCH_TIMER_H | |
8 | #define __ASM_ARM_KVM_ARCH_TIMER_H | |
9 | ||
10 | #include <linux/clocksource.h> | |
11 | #include <linux/hrtimer.h> | |
53e72406 | 12 | |
84135d3d AP |
13 | enum kvm_arch_timers { |
14 | TIMER_PTIMER, | |
15 | TIMER_VTIMER, | |
81dc9504 MZ |
16 | NR_KVM_EL0_TIMERS, |
17 | TIMER_HVTIMER = NR_KVM_EL0_TIMERS, | |
18 | TIMER_HPTIMER, | |
84135d3d AP |
19 | NR_KVM_TIMERS |
20 | }; | |
21 | ||
22 | enum kvm_arch_timer_regs { | |
23 | TIMER_REG_CNT, | |
24 | TIMER_REG_CVAL, | |
25 | TIMER_REG_TVAL, | |
26 | TIMER_REG_CTL, | |
81dc9504 | 27 | TIMER_REG_VOFF, |
84135d3d AP |
28 | }; |
29 | ||
47053904 MZ |
30 | struct arch_timer_offset { |
31 | /* | |
32 | * If set, pointer to one of the offsets in the kvm's offset | |
33 | * structure. If NULL, assume a zero offset. | |
34 | */ | |
35 | u64 *vm_offset; | |
1e0eec09 MZ |
36 | /* |
37 | * If set, pointer to one of the offsets in the vcpu's sysreg | |
38 | * array. If NULL, assume a zero offset. | |
39 | */ | |
40 | u64 *vcpu_offset; | |
47053904 MZ |
41 | }; |
42 | ||
43 | struct arch_timer_vm_data { | |
44 | /* Offset applied to the virtual timer/counter */ | |
45 | u64 voffset; | |
2b4825a8 MZ |
46 | /* Offset applied to the physical timer/counter */ |
47 | u64 poffset; | |
8a5eb2d2 | 48 | |
8a5eb2d2 MZ |
49 | /* The PPI for each timer, global to the VM */ |
50 | u8 ppi[NR_KVM_TIMERS]; | |
47053904 MZ |
51 | }; |
52 | ||
fbb4aeec | 53 | struct arch_timer_context { |
e604dd5d CD |
54 | struct kvm_vcpu *vcpu; |
55 | ||
e604dd5d CD |
56 | /* Emulated Timer (may be unused) */ |
57 | struct hrtimer hrtimer; | |
0d0ae656 | 58 | u64 ns_frac; |
9e01dc76 | 59 | |
47053904 MZ |
60 | /* Offset for this counter/timer */ |
61 | struct arch_timer_offset offset; | |
bee038a6 CD |
62 | /* |
63 | * We have multiple paths which can save/restore the timer state onto | |
64 | * the hardware, so we need some way of keeping track of where the | |
65 | * latest state is. | |
66 | */ | |
67 | bool loaded; | |
68 | ||
8a5eb2d2 MZ |
69 | /* Output level of the timer IRQ */ |
70 | struct { | |
71 | bool level; | |
72 | } irq; | |
73 | ||
9e01dc76 CD |
74 | /* Duplicated state from arch_timer.c for convenience */ |
75 | u32 host_timer_irq; | |
fbb4aeec | 76 | }; |
53e72406 | 77 | |
bee038a6 CD |
78 | struct timer_map { |
79 | struct arch_timer_context *direct_vtimer; | |
80 | struct arch_timer_context *direct_ptimer; | |
81dc9504 | 81 | struct arch_timer_context *emul_vtimer; |
bee038a6 CD |
82 | struct arch_timer_context *emul_ptimer; |
83 | }; | |
84 | ||
94046732 MZ |
85 | void get_timer_map(struct kvm_vcpu *vcpu, struct timer_map *map); |
86 | ||
fbb4aeec | 87 | struct arch_timer_cpu { |
e604dd5d | 88 | struct arch_timer_context timers[NR_KVM_TIMERS]; |
53e72406 MZ |
89 | |
90 | /* Background timer used when the guest is not running */ | |
14d61fa9 | 91 | struct hrtimer bg_timer; |
53e72406 | 92 | |
41a54482 CD |
93 | /* Is the timer enabled */ |
94 | bool enabled; | |
53e72406 MZ |
95 | }; |
96 | ||
8d20bd63 | 97 | int __init kvm_timer_hyp_init(bool has_gic); |
41a54482 | 98 | int kvm_timer_enable(struct kvm_vcpu *vcpu); |
3d4b2a4c | 99 | void kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu); |
53e72406 | 100 | void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu); |
3c5ff0c6 | 101 | void kvm_timer_sync_user(struct kvm_vcpu *vcpu); |
d9e13977 AG |
102 | bool kvm_timer_should_notify_user(struct kvm_vcpu *vcpu); |
103 | void kvm_timer_update_run(struct kvm_vcpu *vcpu); | |
53e72406 | 104 | void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu); |
1df08ba0 | 105 | |
8a5eb2d2 MZ |
106 | void kvm_timer_init_vm(struct kvm *kvm); |
107 | ||
1df08ba0 AB |
108 | u64 kvm_arm_timer_get_reg(struct kvm_vcpu *, u64 regid); |
109 | int kvm_arm_timer_set_reg(struct kvm_vcpu *, u64 regid, u64 value); | |
110 | ||
99a1db7a CD |
111 | int kvm_arm_timer_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr); |
112 | int kvm_arm_timer_get_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr); | |
113 | int kvm_arm_timer_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr); | |
114 | ||
7b6b4631 JL |
115 | u64 kvm_phys_timer_read(void); |
116 | ||
b103cc3f | 117 | void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu); |
9b4a3004 MZ |
118 | void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu); |
119 | ||
488f94d7 | 120 | void kvm_timer_init_vhe(void); |
fbb4aeec | 121 | |
e604dd5d CD |
122 | #define vcpu_timer(v) (&(v)->arch.timer_cpu) |
123 | #define vcpu_get_timer(v,t) (&vcpu_timer(v)->timers[(t)]) | |
124 | #define vcpu_vtimer(v) (&(v)->arch.timer_cpu.timers[TIMER_VTIMER]) | |
125 | #define vcpu_ptimer(v) (&(v)->arch.timer_cpu.timers[TIMER_PTIMER]) | |
81dc9504 MZ |
126 | #define vcpu_hvtimer(v) (&(v)->arch.timer_cpu.timers[TIMER_HVTIMER]) |
127 | #define vcpu_hptimer(v) (&(v)->arch.timer_cpu.timers[TIMER_HPTIMER]) | |
84135d3d | 128 | |
9e01dc76 CD |
129 | #define arch_timer_ctx_index(ctx) ((ctx) - vcpu_timer((ctx)->vcpu)->timers) |
130 | ||
8a5eb2d2 MZ |
131 | #define timer_vm_data(ctx) (&(ctx)->vcpu->kvm->arch.timer_data) |
132 | #define timer_irq(ctx) (timer_vm_data(ctx)->ppi[arch_timer_ctx_index(ctx)]) | |
33c54946 | 133 | |
84135d3d AP |
134 | u64 kvm_arm_timer_read_sysreg(struct kvm_vcpu *vcpu, |
135 | enum kvm_arch_timers tmr, | |
136 | enum kvm_arch_timer_regs treg); | |
137 | void kvm_arm_timer_write_sysreg(struct kvm_vcpu *vcpu, | |
138 | enum kvm_arch_timers tmr, | |
139 | enum kvm_arch_timer_regs treg, | |
140 | u64 val); | |
b103cc3f | 141 | |
41ce82f6 MZ |
142 | /* Needed for tracing */ |
143 | u32 timer_get_ctl(struct arch_timer_context *ctxt); | |
144 | u64 timer_get_cval(struct arch_timer_context *ctxt); | |
145 | ||
466d27e4 MZ |
146 | /* CPU HP callbacks */ |
147 | void kvm_timer_cpu_up(void); | |
148 | void kvm_timer_cpu_down(void); | |
149 | ||
94046732 MZ |
150 | static inline bool has_cntpoff(void) |
151 | { | |
152 | return (has_vhe() && cpus_have_final_cap(ARM64_HAS_ECV_CNTPOFF)); | |
153 | } | |
154 | ||
53e72406 | 155 | #endif |