aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/kvm/arm_arch_timer.h23
-rw-r--r--virt/kvm/arm/arch_timer.c295
-rw-r--r--virt/kvm/arm/trace.h105
3 files changed, 278 insertions, 145 deletions
diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
index 6d4a33a9c45a..05a18dd265b5 100644
--- a/include/kvm/arm_arch_timer.h
+++ b/include/kvm/arm_arch_timer.h
@@ -51,11 +51,24 @@ struct arch_timer_context {
51 /* Emulated Timer (may be unused) */ 51 /* Emulated Timer (may be unused) */
52 struct hrtimer hrtimer; 52 struct hrtimer hrtimer;
53 53
54 /*
55 * We have multiple paths which can save/restore the timer state onto
56 * the hardware, so we need some way of keeping track of where the
57 * latest state is.
58 */
59 bool loaded;
60
54 /* Duplicated state from arch_timer.c for convenience */ 61 /* Duplicated state from arch_timer.c for convenience */
55 u32 host_timer_irq; 62 u32 host_timer_irq;
56 u32 host_timer_irq_flags; 63 u32 host_timer_irq_flags;
57}; 64};
58 65
66struct timer_map {
67 struct arch_timer_context *direct_vtimer;
68 struct arch_timer_context *direct_ptimer;
69 struct arch_timer_context *emul_ptimer;
70};
71
59struct arch_timer_cpu { 72struct arch_timer_cpu {
60 struct arch_timer_context timers[NR_KVM_TIMERS]; 73 struct arch_timer_context timers[NR_KVM_TIMERS];
61 74
@@ -64,16 +77,6 @@ struct arch_timer_cpu {
64 77
65 /* Is the timer enabled */ 78 /* Is the timer enabled */
66 bool enabled; 79 bool enabled;
67
68 /*
69 * We have multiple paths which can save/restore the timer state
70 * onto the hardware, so we need some way of keeping track of
71 * where the latest state is.
72 *
73 * loaded == true: State is loaded on the hardware registers.
74 * loaded == false: State is stored in memory.
75 */
76 bool loaded;
77}; 80};
78 81
79int kvm_timer_hyp_init(bool); 82int kvm_timer_hyp_init(bool);
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 10c15151c87e..17f9de73cc8a 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -68,6 +68,21 @@ u64 kvm_phys_timer_read(void)
68 return timecounter->cc->read(timecounter->cc); 68 return timecounter->cc->read(timecounter->cc);
69} 69}
70 70
71static void get_timer_map(struct kvm_vcpu *vcpu, struct timer_map *map)
72{
73 if (has_vhe()) {
74 map->direct_vtimer = vcpu_vtimer(vcpu);
75 map->direct_ptimer = vcpu_ptimer(vcpu);
76 map->emul_ptimer = NULL;
77 } else {
78 map->direct_vtimer = vcpu_vtimer(vcpu);
79 map->direct_ptimer = NULL;
80 map->emul_ptimer = vcpu_ptimer(vcpu);
81 }
82
83 trace_kvm_get_timer_map(vcpu->vcpu_id, map);
84}
85
71static inline bool userspace_irqchip(struct kvm *kvm) 86static inline bool userspace_irqchip(struct kvm *kvm)
72{ 87{
73 return static_branch_unlikely(&userspace_irqchip_in_use) && 88 return static_branch_unlikely(&userspace_irqchip_in_use) &&
@@ -89,6 +104,7 @@ static irqreturn_t kvm_arch_timer_handler(int irq, void *dev_id)
89{ 104{
90 struct kvm_vcpu *vcpu = *(struct kvm_vcpu **)dev_id; 105 struct kvm_vcpu *vcpu = *(struct kvm_vcpu **)dev_id;
91 struct arch_timer_context *ctx; 106 struct arch_timer_context *ctx;
107 struct timer_map map;
92 108
93 /* 109 /*
94 * We may see a timer interrupt after vcpu_put() has been called which 110 * We may see a timer interrupt after vcpu_put() has been called which
@@ -99,10 +115,12 @@ static irqreturn_t kvm_arch_timer_handler(int irq, void *dev_id)
99 if (!vcpu) 115 if (!vcpu)
100 return IRQ_HANDLED; 116 return IRQ_HANDLED;
101 117
118 get_timer_map(vcpu, &map);
119
102 if (irq == host_vtimer_irq) 120 if (irq == host_vtimer_irq)
103 ctx = vcpu_vtimer(vcpu); 121 ctx = map.direct_vtimer;
104 else 122 else
105 ctx = vcpu_ptimer(vcpu); 123 ctx = map.direct_ptimer;
106 124
107 if (kvm_timer_should_fire(ctx)) 125 if (kvm_timer_should_fire(ctx))
108 kvm_timer_update_irq(vcpu, true, ctx); 126 kvm_timer_update_irq(vcpu, true, ctx);
@@ -136,7 +154,9 @@ static u64 kvm_timer_compute_delta(struct arch_timer_context *timer_ctx)
136 154
137static bool kvm_timer_irq_can_fire(struct arch_timer_context *timer_ctx) 155static bool kvm_timer_irq_can_fire(struct arch_timer_context *timer_ctx)
138{ 156{
139 return !(timer_ctx->cnt_ctl & ARCH_TIMER_CTRL_IT_MASK) && 157 WARN_ON(timer_ctx && timer_ctx->loaded);
158 return timer_ctx &&
159 !(timer_ctx->cnt_ctl & ARCH_TIMER_CTRL_IT_MASK) &&
140 (timer_ctx->cnt_ctl & ARCH_TIMER_CTRL_ENABLE); 160 (timer_ctx->cnt_ctl & ARCH_TIMER_CTRL_ENABLE);
141} 161}
142 162
@@ -146,21 +166,22 @@ static bool kvm_timer_irq_can_fire(struct arch_timer_context *timer_ctx)
146 */ 166 */
147static u64 kvm_timer_earliest_exp(struct kvm_vcpu *vcpu) 167static u64 kvm_timer_earliest_exp(struct kvm_vcpu *vcpu)
148{ 168{
149 u64 min_virt = ULLONG_MAX, min_phys = ULLONG_MAX; 169 u64 min_delta = ULLONG_MAX;
150 struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); 170 int i;
151 struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
152 171
153 if (kvm_timer_irq_can_fire(vtimer)) 172 for (i = 0; i < NR_KVM_TIMERS; i++) {
154 min_virt = kvm_timer_compute_delta(vtimer); 173 struct arch_timer_context *ctx = &vcpu->arch.timer_cpu.timers[i];
155 174
156 if (kvm_timer_irq_can_fire(ptimer)) 175 WARN(ctx->loaded, "timer %d loaded\n", i);
157 min_phys = kvm_timer_compute_delta(ptimer); 176 if (kvm_timer_irq_can_fire(ctx))
177 min_delta = min(min_delta, kvm_timer_compute_delta(ctx));
178 }
158 179
159 /* If none of timers can fire, then return 0 */ 180 /* If none of timers can fire, then return 0 */
160 if ((min_virt == ULLONG_MAX) && (min_phys == ULLONG_MAX)) 181 if (min_delta == ULLONG_MAX)
161 return 0; 182 return 0;
162 183
163 return min(min_virt, min_phys); 184 return min_delta;
164} 185}
165 186
166static enum hrtimer_restart kvm_bg_timer_expire(struct hrtimer *hrt) 187static enum hrtimer_restart kvm_bg_timer_expire(struct hrtimer *hrt)
@@ -187,37 +208,45 @@ static enum hrtimer_restart kvm_bg_timer_expire(struct hrtimer *hrt)
187 return HRTIMER_NORESTART; 208 return HRTIMER_NORESTART;
188} 209}
189 210
190static enum hrtimer_restart kvm_phys_timer_expire(struct hrtimer *hrt) 211static enum hrtimer_restart kvm_hrtimer_expire(struct hrtimer *hrt)
191{ 212{
192 struct arch_timer_context *ptimer; 213 struct arch_timer_context *ctx;
193 struct kvm_vcpu *vcpu; 214 struct kvm_vcpu *vcpu;
194 u64 ns; 215 u64 ns;
195 216
196 ptimer = container_of(hrt, struct arch_timer_context, hrtimer); 217 ctx = container_of(hrt, struct arch_timer_context, hrtimer);
197 vcpu = ptimer->vcpu; 218 vcpu = ctx->vcpu;
219
220 trace_kvm_timer_hrtimer_expire(ctx);
198 221
199 /* 222 /*
200 * Check that the timer has really expired from the guest's 223 * Check that the timer has really expired from the guest's
201 * PoV (NTP on the host may have forced it to expire 224 * PoV (NTP on the host may have forced it to expire
202 * early). If not ready, schedule for a later time. 225 * early). If not ready, schedule for a later time.
203 */ 226 */
204 ns = kvm_timer_compute_delta(ptimer); 227 ns = kvm_timer_compute_delta(ctx);
205 if (unlikely(ns)) { 228 if (unlikely(ns)) {
206 hrtimer_forward_now(hrt, ns_to_ktime(ns)); 229 hrtimer_forward_now(hrt, ns_to_ktime(ns));
207 return HRTIMER_RESTART; 230 return HRTIMER_RESTART;
208 } 231 }
209 232
210 kvm_timer_update_irq(vcpu, true, ptimer); 233 kvm_timer_update_irq(vcpu, true, ctx);
211 return HRTIMER_NORESTART; 234 return HRTIMER_NORESTART;
212} 235}
213 236
214static bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx) 237static bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx)
215{ 238{
216 struct arch_timer_cpu *timer = vcpu_timer(timer_ctx->vcpu); 239 struct arch_timer_cpu *timer;
217 enum kvm_arch_timers index = arch_timer_ctx_index(timer_ctx); 240 enum kvm_arch_timers index;
218 u64 cval, now; 241 u64 cval, now;