Commit | Line | Data |
---|---|---|
53e72406 MZ |
1 | /* |
2 | * Copyright (C) 2012 ARM Ltd. | |
3 | * Author: Marc Zyngier <marc.zyngier@arm.com> | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the GNU General Public License version 2 as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License | |
15 | * along with this program; if not, write to the Free Software | |
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
17 | */ | |
18 | ||
19 | #include <linux/cpu.h> | |
53e72406 MZ |
20 | #include <linux/kvm.h> |
21 | #include <linux/kvm_host.h> | |
22 | #include <linux/interrupt.h> | |
b452cb52 | 23 | #include <linux/irq.h> |
99a1db7a | 24 | #include <linux/uaccess.h> |
53e72406 | 25 | |
372b7c1b | 26 | #include <clocksource/arm_arch_timer.h> |
53e72406 | 27 | #include <asm/arch_timer.h> |
488f94d7 | 28 | #include <asm/kvm_hyp.h> |
53e72406 | 29 | |
7275acdf MZ |
30 | #include <kvm/arm_vgic.h> |
31 | #include <kvm/arm_arch_timer.h> | |
53e72406 | 32 | |
e21f0910 CD |
33 | #include "trace.h" |
34 | ||
53e72406 | 35 | static struct timecounter *timecounter; |
5ae7f87a | 36 | static unsigned int host_vtimer_irq; |
cabdc5c5 | 37 | static u32 host_vtimer_irq_flags; |
53e72406 | 38 | |
d60d8b64 CD |
39 | static DEFINE_STATIC_KEY_FALSE(has_gic_active_state); |
40 | ||
85e69ad7 CD |
41 | static const struct kvm_irq_level default_ptimer_irq = { |
42 | .irq = 30, | |
43 | .level = 1, | |
44 | }; | |
45 | ||
46 | static const struct kvm_irq_level default_vtimer_irq = { | |
47 | .irq = 27, | |
48 | .level = 1, | |
49 | }; | |
50 | ||
b103cc3f CD |
51 | static bool kvm_timer_irq_can_fire(struct arch_timer_context *timer_ctx); |
52 | static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level, | |
53 | struct arch_timer_context *timer_ctx); | |
1c88ab7e | 54 | static bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx); |
9b4a3004 | 55 | |
7b6b4631 | 56 | u64 kvm_phys_timer_read(void) |
53e72406 MZ |
57 | { |
58 | return timecounter->cc->read(timecounter->cc); | |
59 | } | |
60 | ||
d60d8b64 CD |
61 | static inline bool userspace_irqchip(struct kvm *kvm) |
62 | { | |
63 | return static_branch_unlikely(&userspace_irqchip_in_use) && | |
64 | unlikely(!irqchip_in_kernel(kvm)); | |
65 | } | |
66 | ||
8409a06f | 67 | static void soft_timer_start(struct hrtimer *hrt, u64 ns) |
53e72406 | 68 | { |
8409a06f | 69 | hrtimer_start(hrt, ktime_add_ns(ktime_get(), ns), |
53e72406 MZ |
70 | HRTIMER_MODE_ABS); |
71 | } | |
72 | ||
8409a06f | 73 | static void soft_timer_cancel(struct hrtimer *hrt, struct work_struct *work) |
53e72406 | 74 | { |
8409a06f | 75 | hrtimer_cancel(hrt); |
f2a2129e CD |
76 | if (work) |
77 | cancel_work_sync(work); | |
53e72406 MZ |
78 | } |
79 | ||
b103cc3f CD |
80 | static irqreturn_t kvm_arch_timer_handler(int irq, void *dev_id) |
81 | { | |
82 | struct kvm_vcpu *vcpu = *(struct kvm_vcpu **)dev_id; | |
83 | struct arch_timer_context *vtimer; | |
84 | ||
36e5cfd4 CD |
85 | /* |
86 | * We may see a timer interrupt after vcpu_put() has been called which | |
87 | * sets the CPU's vcpu pointer to NULL, because even though the timer | |
88 | * has been disabled in vtimer_save_state(), the hardware interrupt | |
89 | * signal may not have been retired from the interrupt controller yet. | |
90 | */ | |
91 | if (!vcpu) | |
92 | return IRQ_HANDLED; | |
b103cc3f | 93 | |
13e59ece CD |
94 | vtimer = vcpu_vtimer(vcpu); |
95 | if (kvm_timer_should_fire(vtimer)) | |
70450a9f | 96 | kvm_timer_update_irq(vcpu, true, vtimer); |
b103cc3f | 97 | |
d60d8b64 CD |
98 | if (userspace_irqchip(vcpu->kvm) && |
99 | !static_branch_unlikely(&has_gic_active_state)) | |
100 | disable_percpu_irq(host_vtimer_irq); | |
b103cc3f | 101 | |
53e72406 MZ |
102 | return IRQ_HANDLED; |
103 | } | |
104 | ||
1a748478 CD |
105 | /* |
106 | * Work function for handling the backup timer that we schedule when a vcpu is | |
107 | * no longer running, but had a timer programmed to fire in the future. | |
108 | */ | |
53e72406 MZ |
109 | static void kvm_timer_inject_irq_work(struct work_struct *work) |
110 | { | |
111 | struct kvm_vcpu *vcpu; | |
112 | ||
113 | vcpu = container_of(work, struct kvm_vcpu, arch.timer_cpu.expired); | |
1c5631c7 | 114 | |
1a748478 CD |
115 | /* |
116 | * If the vcpu is blocked we want to wake it up so that it will see | |
117 | * the timer has expired when entering the guest. | |
118 | */ | |
1b6502e5 | 119 | kvm_vcpu_wake_up(vcpu); |
53e72406 MZ |
120 | } |
121 | ||
9171fa2e | 122 | static u64 kvm_timer_compute_delta(struct arch_timer_context *timer_ctx) |
1c5631c7 | 123 | { |
a5a1d1c2 | 124 | u64 cval, now; |
1c5631c7 | 125 | |
9171fa2e JL |
126 | cval = timer_ctx->cnt_cval; |
127 | now = kvm_phys_timer_read() - timer_ctx->cntvoff; | |
1c5631c7 MZ |
128 | |
129 | if (now < cval) { | |
130 | u64 ns; | |
131 | ||
132 | ns = cyclecounter_cyc2ns(timecounter->cc, | |
133 | cval - now, | |
134 | timecounter->mask, | |
135 | &timecounter->frac); | |
136 | return ns; | |
137 | } | |
138 | ||
139 | return 0; | |
140 | } | |
141 | ||
fb280e97 JL |
142 | static bool kvm_timer_irq_can_fire(struct arch_timer_context *timer_ctx) |
143 | { | |
144 | return !(timer_ctx->cnt_ctl & ARCH_TIMER_CTRL_IT_MASK) && | |
145 | (timer_ctx->cnt_ctl & ARCH_TIMER_CTRL_ENABLE); | |
146 | } | |
147 | ||
148 | /* | |
149 | * Returns the earliest expiration time in ns among guest timers. | |
150 | * Note that it will return 0 if none of timers can fire. | |
151 | */ | |
152 | static u64 kvm_timer_earliest_exp(struct kvm_vcpu *vcpu) | |
153 | { | |
154 | u64 min_virt = ULLONG_MAX, min_phys = ULLONG_MAX; | |
155 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); | |
156 | struct arch_timer_context *ptimer = vcpu_ptimer(vcpu); | |
157 | ||
158 | if (kvm_timer_irq_can_fire(vtimer)) | |
159 | min_virt = kvm_timer_compute_delta(vtimer); | |
160 | ||
161 | if (kvm_timer_irq_can_fire(ptimer)) | |
162 | min_phys = kvm_timer_compute_delta(ptimer); | |
163 | ||
164 | /* If none of timers can fire, then return 0 */ | |
165 | if ((min_virt == ULLONG_MAX) && (min_phys == ULLONG_MAX)) | |
166 | return 0; | |
167 | ||
168 | return min(min_virt, min_phys); | |
169 | } | |
170 | ||
14d61fa9 | 171 | static enum hrtimer_restart kvm_bg_timer_expire(struct hrtimer *hrt) |
53e72406 MZ |
172 | { |
173 | struct arch_timer_cpu *timer; | |
1c5631c7 MZ |
174 | struct kvm_vcpu *vcpu; |
175 | u64 ns; | |
176 | ||
14d61fa9 | 177 | timer = container_of(hrt, struct arch_timer_cpu, bg_timer); |
1c5631c7 MZ |
178 | vcpu = container_of(timer, struct kvm_vcpu, arch.timer_cpu); |
179 | ||
180 | /* | |
181 | * Check that the timer has really expired from the guest's | |
182 | * PoV (NTP on the host may have forced it to expire | |
183 | * early). If we should have slept longer, restart it. | |
184 | */ | |
fb280e97 | 185 | ns = kvm_timer_earliest_exp(vcpu); |
1c5631c7 MZ |
186 | if (unlikely(ns)) { |
187 | hrtimer_forward_now(hrt, ns_to_ktime(ns)); | |
188 | return HRTIMER_RESTART; | |
189 | } | |
190 | ||
3706feac | 191 | schedule_work(&timer->expired); |
53e72406 MZ |
192 | return HRTIMER_NORESTART; |
193 | } | |
194 | ||
f2a2129e CD |
195 | static enum hrtimer_restart kvm_phys_timer_expire(struct hrtimer *hrt) |
196 | { | |
bbdd52cf CD |
197 | struct arch_timer_context *ptimer; |
198 | struct arch_timer_cpu *timer; | |
199 | struct kvm_vcpu *vcpu; | |
200 | u64 ns; | |
201 | ||
202 | timer = container_of(hrt, struct arch_timer_cpu, phys_timer); | |
203 | vcpu = container_of(timer, struct kvm_vcpu, arch.timer_cpu); | |
204 | ptimer = vcpu_ptimer(vcpu); | |
205 | ||
206 | /* | |
207 | * Check that the timer has really expired from the guest's | |
208 | * PoV (NTP on the host may have forced it to expire | |
209 | * early). If not ready, schedule for a later time. | |
210 | */ | |
211 | ns = kvm_timer_compute_delta(ptimer); | |
212 | if (unlikely(ns)) { | |
213 | hrtimer_forward_now(hrt, ns_to_ktime(ns)); | |
214 | return HRTIMER_RESTART; | |
215 | } | |
216 | ||
217 | kvm_timer_update_irq(vcpu, true, ptimer); | |
f2a2129e CD |
218 | return HRTIMER_NORESTART; |
219 | } | |
220 | ||
1c88ab7e | 221 | static bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx) |
1a748478 | 222 | { |
a5a1d1c2 | 223 | u64 cval, now; |
1a748478 | 224 | |
13e59ece CD |
225 | if (timer_ctx->loaded) { |
226 | u32 cnt_ctl; | |
227 | ||
228 | /* Only the virtual timer can be loaded so far */ | |
229 | cnt_ctl = read_sysreg_el0(cntv_ctl); | |
230 | return (cnt_ctl & ARCH_TIMER_CTRL_ENABLE) && | |
231 | (cnt_ctl & ARCH_TIMER_CTRL_IT_STAT) && | |
232 | !(cnt_ctl & ARCH_TIMER_CTRL_IT_MASK); | |
233 | } | |
234 | ||
9171fa2e | 235 | if (!kvm_timer_irq_can_fire(timer_ctx)) |
1a748478 CD |
236 | return false; |
237 | ||
9171fa2e JL |
238 | cval = timer_ctx->cnt_cval; |
239 | now = kvm_phys_timer_read() - timer_ctx->cntvoff; | |
1a748478 CD |
240 | |
241 | return cval <= now; | |
242 | } | |
243 | ||
1c88ab7e CD |
244 | bool kvm_timer_is_pending(struct kvm_vcpu *vcpu) |
245 | { | |
246 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); | |
247 | struct arch_timer_context *ptimer = vcpu_ptimer(vcpu); | |
248 | ||
13e59ece | 249 | if (kvm_timer_should_fire(vtimer)) |
1c88ab7e CD |
250 | return true; |
251 | ||
252 | return kvm_timer_should_fire(ptimer); | |
253 | } | |
254 | ||
d9e13977 AG |
255 | /* |
256 | * Reflect the timer output level into the kvm_run structure | |
257 | */ | |
258 | void kvm_timer_update_run(struct kvm_vcpu *vcpu) | |
259 | { | |
260 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); | |
261 | struct arch_timer_context *ptimer = vcpu_ptimer(vcpu); | |
262 | struct kvm_sync_regs *regs = &vcpu->run->s.regs; | |
263 | ||
d9e13977 AG |
264 | /* Populate the device bitmap with the timer states */ |
265 | regs->device_irq_level &= ~(KVM_ARM_DEV_EL1_VTIMER | | |
266 | KVM_ARM_DEV_EL1_PTIMER); | |
13e59ece | 267 | if (kvm_timer_should_fire(vtimer)) |
d9e13977 | 268 | regs->device_irq_level |= KVM_ARM_DEV_EL1_VTIMER; |
13e59ece | 269 | if (kvm_timer_should_fire(ptimer)) |
d9e13977 AG |
270 | regs->device_irq_level |= KVM_ARM_DEV_EL1_PTIMER; |
271 | } | |
272 | ||
9171fa2e JL |
273 | static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level, |
274 | struct arch_timer_context *timer_ctx) | |
4b4b4512 CD |
275 | { |
276 | int ret; | |
4b4b4512 | 277 | |
9171fa2e JL |
278 | timer_ctx->irq.level = new_level; |
279 | trace_kvm_timer_update_irq(vcpu->vcpu_id, timer_ctx->irq.irq, | |
280 | timer_ctx->irq.level); | |
11710dec | 281 | |
d60d8b64 | 282 | if (!userspace_irqchip(vcpu->kvm)) { |
d9e13977 AG |
283 | ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id, |
284 | timer_ctx->irq.irq, | |
cb3f0ad8 CD |
285 | timer_ctx->irq.level, |
286 | timer_ctx); | |
d9e13977 AG |
287 | WARN_ON(ret); |
288 | } | |
4b4b4512 CD |
289 | } |
290 | ||
cda93b7a | 291 | /* Schedule the background timer for the emulated timer. */ |
bbdd52cf | 292 | static void phys_timer_emulate(struct kvm_vcpu *vcpu) |
cda93b7a CD |
293 | { |
294 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | |
bbdd52cf | 295 | struct arch_timer_context *ptimer = vcpu_ptimer(vcpu); |
cda93b7a | 296 | |
bbdd52cf CD |
297 | /* |
298 | * If the timer can fire now we have just raised the IRQ line and we | |
299 | * don't need to have a soft timer scheduled for the future. If the | |
300 | * timer cannot fire at all, then we also don't need a soft timer. | |
301 | */ | |
302 | if (kvm_timer_should_fire(ptimer) || !kvm_timer_irq_can_fire(ptimer)) { | |
303 | soft_timer_cancel(&timer->phys_timer, NULL); | |
cda93b7a | 304 | return; |
bbdd52cf | 305 | } |
cda93b7a | 306 | |
bbdd52cf | 307 | soft_timer_start(&timer->phys_timer, kvm_timer_compute_delta(ptimer)); |
cda93b7a CD |
308 | } |
309 | ||
4b4b4512 | 310 | /* |
bbdd52cf CD |
311 | * Check if there was a change in the timer state, so that we should either |
312 | * raise or lower the line level to the GIC or schedule a background timer to | |
313 | * emulate the physical timer. | |
4b4b4512 | 314 | */ |
b22e7df2 | 315 | static void kvm_timer_update_state(struct kvm_vcpu *vcpu) |
4b4b4512 CD |
316 | { |
317 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | |
fbb4aeec | 318 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); |
58e0c973 | 319 | struct arch_timer_context *ptimer = vcpu_ptimer(vcpu); |
70450a9f | 320 | bool level; |
4b4b4512 | 321 | |
d9e13977 | 322 | if (unlikely(!timer->enabled)) |
b22e7df2 | 323 | return; |
4b4b4512 | 324 | |
70450a9f CD |
325 | /* |
326 | * The vtimer virtual interrupt is a 'mapped' interrupt, meaning part | |
327 | * of its lifecycle is offloaded to the hardware, and we therefore may | |
328 | * not have lowered the irq.level value before having to signal a new | |
329 | * interrupt, but have to signal an interrupt every time the level is | |
330 | * asserted. | |
331 | */ | |
332 | level = kvm_timer_should_fire(vtimer); | |
333 | kvm_timer_update_irq(vcpu, level, vtimer); | |
b3aff6cc | 334 | |
58e0c973 JL |
335 | if (kvm_timer_should_fire(ptimer) != ptimer->irq.level) |
336 | kvm_timer_update_irq(vcpu, !ptimer->irq.level, ptimer); | |
bbdd52cf CD |
337 | |
338 | phys_timer_emulate(vcpu); | |
4b4b4512 CD |
339 | } |
340 | ||
b103cc3f | 341 | static void vtimer_save_state(struct kvm_vcpu *vcpu) |
688c50aa CD |
342 | { |
343 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | |
344 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); | |
b103cc3f CD |
345 | unsigned long flags; |
346 | ||
347 | local_irq_save(flags); | |
348 | ||
349 | if (!vtimer->loaded) | |
350 | goto out; | |
688c50aa | 351 | |
d60d8b64 CD |
352 | if (timer->enabled) { |
353 | vtimer->cnt_ctl = read_sysreg_el0(cntv_ctl); | |
354 | vtimer->cnt_cval = read_sysreg_el0(cntv_cval); | |
355 | } | |
688c50aa CD |
356 | |
357 | /* Disable the virtual timer */ | |
358 | write_sysreg_el0(0, cntv_ctl); | |
36e5cfd4 | 359 | isb(); |
b103cc3f CD |
360 | |
361 | vtimer->loaded = false; | |
362 | out: | |
363 | local_irq_restore(flags); | |
688c50aa CD |
364 | } |
365 | ||
d35268da CD |
366 | /* |
367 | * Schedule the background timer before calling kvm_vcpu_block, so that this | |
368 | * thread is removed from its waitqueue and made runnable when there's a timer | |
369 | * interrupt to handle. | |
370 | */ | |
371 | void kvm_timer_schedule(struct kvm_vcpu *vcpu) | |
372 | { | |
373 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | |
9171fa2e | 374 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); |
fb280e97 | 375 | struct arch_timer_context *ptimer = vcpu_ptimer(vcpu); |
d35268da | 376 | |
b103cc3f CD |
377 | vtimer_save_state(vcpu); |
378 | ||
d35268da | 379 | /* |
fb280e97 | 380 | * No need to schedule a background timer if any guest timer has |
d35268da CD |
381 | * already expired, because kvm_vcpu_block will return before putting |
382 | * the thread to sleep. | |
383 | */ | |
fb280e97 | 384 | if (kvm_timer_should_fire(vtimer) || kvm_timer_should_fire(ptimer)) |
d35268da CD |
385 | return; |
386 | ||
387 | /* | |
fb280e97 | 388 | * If both timers are not capable of raising interrupts (disabled or |
d35268da CD |
389 | * masked), then there's no more work for us to do. |
390 | */ | |
fb280e97 | 391 | if (!kvm_timer_irq_can_fire(vtimer) && !kvm_timer_irq_can_fire(ptimer)) |
d35268da CD |
392 | return; |
393 | ||
fb280e97 JL |
394 | /* |
395 | * The guest timers have not yet expired, schedule a background timer. | |
396 | * Set the earliest expiration time among the guest timers. | |
397 | */ | |
14d61fa9 | 398 | soft_timer_start(&timer->bg_timer, kvm_timer_earliest_exp(vcpu)); |
d35268da CD |
399 | } |
400 | ||
b103cc3f | 401 | static void vtimer_restore_state(struct kvm_vcpu *vcpu) |
688c50aa CD |
402 | { |
403 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | |
404 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); | |
b103cc3f CD |
405 | unsigned long flags; |
406 | ||
407 | local_irq_save(flags); | |
408 | ||
409 | if (vtimer->loaded) | |
410 | goto out; | |
688c50aa CD |
411 | |
412 | if (timer->enabled) { | |
413 | write_sysreg_el0(vtimer->cnt_cval, cntv_cval); | |
414 | isb(); | |
415 | write_sysreg_el0(vtimer->cnt_ctl, cntv_ctl); | |
416 | } | |
b103cc3f CD |
417 | |
418 | vtimer->loaded = true; | |
419 | out: | |
420 | local_irq_restore(flags); | |
688c50aa CD |
421 | } |
422 | ||
d35268da CD |
423 | void kvm_timer_unschedule(struct kvm_vcpu *vcpu) |
424 | { | |
425 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | |
8409a06f | 426 | |
b103cc3f CD |
427 | vtimer_restore_state(vcpu); |
428 | ||
14d61fa9 | 429 | soft_timer_cancel(&timer->bg_timer, &timer->expired); |
d35268da CD |
430 | } |
431 | ||
688c50aa CD |
432 | static void set_cntvoff(u64 cntvoff) |
433 | { | |
434 | u32 low = lower_32_bits(cntvoff); | |
435 | u32 high = upper_32_bits(cntvoff); | |
436 | ||
437 | /* | |
438 | * Since kvm_call_hyp doesn't fully support the ARM PCS especially on | |
439 | * 32-bit systems, but rather passes register by register shifted one | |
440 | * place (we put the function address in r0/x0), we cannot simply pass | |
441 | * a 64-bit value as an argument, but have to split the value in two | |
442 | * 32-bit halves. | |
443 | */ | |
444 | kvm_call_hyp(__kvm_timer_set_cntvoff, low, high); | |
445 | } | |
446 | ||
d60d8b64 CD |
447 | static inline void set_vtimer_irq_phys_active(struct kvm_vcpu *vcpu, bool active) |
448 | { | |
449 | int r; | |
450 | r = irq_set_irqchip_state(host_vtimer_irq, IRQCHIP_STATE_ACTIVE, active); | |
451 | WARN_ON(r); | |
452 | } | |
453 | ||
454 | static void kvm_timer_vcpu_load_gic(struct kvm_vcpu *vcpu) | |
53e72406 | 455 | { |
fbb4aeec | 456 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); |
cff9211e | 457 | bool phys_active; |
53e72406 | 458 | |
d60d8b64 CD |
459 | if (irqchip_in_kernel(vcpu->kvm)) |
460 | phys_active = kvm_vgic_map_is_active(vcpu, vtimer->irq.irq); | |
461 | else | |
462 | phys_active = vtimer->irq.level; | |
463 | set_vtimer_irq_phys_active(vcpu, phys_active); | |
b103cc3f | 464 | } |
9b4a3004 | 465 | |
d60d8b64 | 466 | static void kvm_timer_vcpu_load_nogic(struct kvm_vcpu *vcpu) |
b103cc3f | 467 | { |
d60d8b64 CD |
468 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); |
469 | ||
470 | /* | |
471 | * When using a userspace irqchip with the architected timers and a | |
472 | * host interrupt controller that doesn't support an active state, we | |
473 | * must still prevent continuously exiting from the guest, and | |
474 | * therefore mask the physical interrupt by disabling it on the host | |
475 | * interrupt controller when the virtual level is high, such that the | |
476 | * guest can make forward progress. Once we detect the output level | |
477 | * being de-asserted, we unmask the interrupt again so that we exit | |
478 | * from the guest when the timer fires. | |
479 | */ | |
480 | if (vtimer->irq.level) | |
481 | disable_percpu_irq(host_vtimer_irq); | |
482 | else | |
483 | enable_percpu_irq(host_vtimer_irq, host_vtimer_irq_flags); | |
b103cc3f CD |
484 | } |
485 | ||
486 | void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu) | |
487 | { | |
488 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | |
489 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); | |
490 | ||
491 | if (unlikely(!timer->enabled)) | |
492 | return; | |
493 | ||
d60d8b64 CD |
494 | if (static_branch_likely(&has_gic_active_state)) |
495 | kvm_timer_vcpu_load_gic(vcpu); | |
b103cc3f | 496 | else |
d60d8b64 | 497 | kvm_timer_vcpu_load_nogic(vcpu); |
b103cc3f CD |
498 | |
499 | set_cntvoff(vtimer->cntvoff); | |
500 | ||
501 | vtimer_restore_state(vcpu); | |
502 | ||
bbdd52cf CD |
503 | /* Set the background timer for the physical timer emulation. */ |
504 | phys_timer_emulate(vcpu); | |
53e72406 MZ |
505 | } |
506 | ||
d9e13977 AG |
507 | bool kvm_timer_should_notify_user(struct kvm_vcpu *vcpu) |
508 | { | |
509 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); | |
510 | struct arch_timer_context *ptimer = vcpu_ptimer(vcpu); | |
511 | struct kvm_sync_regs *sregs = &vcpu->run->s.regs; | |
512 | bool vlevel, plevel; | |
513 | ||
514 | if (likely(irqchip_in_kernel(vcpu->kvm))) | |
515 | return false; | |
516 | ||
517 | vlevel = sregs->device_irq_level & KVM_ARM_DEV_EL1_VTIMER; | |
518 | plevel = sregs->device_irq_level & KVM_ARM_DEV_EL1_PTIMER; | |
519 | ||
13e59ece CD |
520 | return kvm_timer_should_fire(vtimer) != vlevel || |
521 | kvm_timer_should_fire(ptimer) != plevel; | |
d9e13977 AG |
522 | } |
523 | ||
b103cc3f CD |
524 | void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu) |
525 | { | |
526 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | |
688c50aa | 527 | |
b103cc3f CD |
528 | if (unlikely(!timer->enabled)) |
529 | return; | |
530 | ||
b103cc3f CD |
531 | vtimer_save_state(vcpu); |
532 | ||
bbdd52cf CD |
533 | /* |
534 | * Cancel the physical timer emulation, because the only case where we | |
535 | * need it after a vcpu_put is in the context of a sleeping VCPU, and | |
536 | * in that case we already factor in the deadline for the physical | |
537 | * timer when scheduling the bg_timer. | |
538 | * | |
539 | * In any case, we re-schedule the hrtimer for the physical timer when | |
540 | * coming back to the VCPU thread in kvm_timer_vcpu_load(). | |
541 | */ | |
542 | soft_timer_cancel(&timer->phys_timer, NULL); | |
543 | ||
b103cc3f CD |
544 | /* |
545 | * The kernel may decide to run userspace after calling vcpu_put, so | |
546 | * we reset cntvoff to 0 to ensure a consistent read between user | |
547 | * accesses to the virtual counter and kernel access to the physical | |
548 | * counter. | |
549 | */ | |
550 | set_cntvoff(0); | |
551 | } | |
552 | ||
4c60e360 CD |
553 | /* |
554 | * With a userspace irqchip we have to check if the guest de-asserted the | |
555 | * timer and if so, unmask the timer irq signal on the host interrupt | |
556 | * controller to ensure that we see future timer signals. | |
557 | */ | |
558 | static void unmask_vtimer_irq_user(struct kvm_vcpu *vcpu) | |
b103cc3f CD |
559 | { |
560 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); | |
561 | ||
d60d8b64 CD |
562 | if (!kvm_timer_should_fire(vtimer)) { |
563 | kvm_timer_update_irq(vcpu, false, vtimer); | |
564 | if (static_branch_likely(&has_gic_active_state)) | |
565 | set_vtimer_irq_phys_active(vcpu, false); | |
566 | else | |
567 | enable_percpu_irq(host_vtimer_irq, host_vtimer_irq_flags); | |
b103cc3f | 568 | } |
d9e13977 AG |
569 | } |
570 | ||
53e72406 MZ |
571 | void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu) |
572 | { | |
d60d8b64 CD |
573 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; |
574 | ||
575 | if (unlikely(!timer->enabled)) | |
576 | return; | |
577 | ||
578 | if (unlikely(!irqchip_in_kernel(vcpu->kvm))) | |
579 | unmask_vtimer_irq_user(vcpu); | |
53e72406 MZ |
580 | } |
581 | ||
85e69ad7 | 582 | int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu) |
5ae7f87a | 583 | { |
413aa807 | 584 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; |
fbb4aeec | 585 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); |
a91d1855 | 586 | struct arch_timer_context *ptimer = vcpu_ptimer(vcpu); |
5ae7f87a | 587 | |
4ad9e16a CD |
588 | /* |
589 | * The bits in CNTV_CTL are architecturally reset to UNKNOWN for ARMv8 | |
590 | * and to 0 for ARMv7. We provide an implementation that always | |
591 | * resets the timer to be disabled and unmasked and is compliant with | |
592 | * the ARMv7 architecture. | |
593 | */ | |
fbb4aeec | 594 | vtimer->cnt_ctl = 0; |
a91d1855 | 595 | ptimer->cnt_ctl = 0; |
4b4b4512 | 596 | kvm_timer_update_state(vcpu); |
4ad9e16a | 597 | |
413aa807 CD |
598 | if (timer->enabled && irqchip_in_kernel(vcpu->kvm)) |
599 | kvm_vgic_reset_mapped_irq(vcpu, vtimer->irq.irq); | |
600 | ||
41a54482 | 601 | return 0; |
5ae7f87a AP |
602 | } |
603 | ||
90de943a JL |
604 | /* Make the updates of cntvoff for all vtimer contexts atomic */ |
605 | static void update_vtimer_cntvoff(struct kvm_vcpu *vcpu, u64 cntvoff) | |
606 | { | |
607 | int i; | |
608 | struct kvm *kvm = vcpu->kvm; | |
609 | struct kvm_vcpu *tmp; | |
610 | ||
611 | mutex_lock(&kvm->lock); | |
612 | kvm_for_each_vcpu(i, tmp, kvm) | |
613 | vcpu_vtimer(tmp)->cntvoff = cntvoff; | |
614 | ||
615 | /* | |
616 | * When called from the vcpu create path, the CPU being created is not | |
617 | * included in the loop above, so we just set it here as well. | |
618 | */ | |
619 | vcpu_vtimer(vcpu)->cntvoff = cntvoff; | |
620 | mutex_unlock(&kvm->lock); | |
621 | } | |
622 | ||
53e72406 MZ |
623 | void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) |
624 | { | |
625 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | |
85e69ad7 CD |
626 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); |
627 | struct arch_timer_context *ptimer = vcpu_ptimer(vcpu); | |
53e72406 | 628 | |
90de943a JL |
629 | /* Synchronize cntvoff across all vtimers of a VM. */ |
630 | update_vtimer_cntvoff(vcpu, kvm_phys_timer_read()); | |
a91d1855 | 631 | vcpu_ptimer(vcpu)->cntvoff = 0; |
90de943a | 632 | |
53e72406 | 633 | INIT_WORK(&timer->expired, kvm_timer_inject_irq_work); |
14d61fa9 CD |
634 | hrtimer_init(&timer->bg_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); |
635 | timer->bg_timer.function = kvm_bg_timer_expire; | |
85e69ad7 | 636 | |
f2a2129e CD |
637 | hrtimer_init(&timer->phys_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); |
638 | timer->phys_timer.function = kvm_phys_timer_expire; | |
639 | ||
85e69ad7 CD |
640 | vtimer->irq.irq = default_vtimer_irq.irq; |
641 | ptimer->irq.irq = default_ptimer_irq.irq; | |
53e72406 MZ |
642 | } |
643 | ||
644 | static void kvm_timer_init_interrupt(void *info) | |
645 | { | |
cabdc5c5 | 646 | enable_percpu_irq(host_vtimer_irq, host_vtimer_irq_flags); |
53e72406 MZ |
647 | } |
648 | ||
39735a3a AP |
649 | int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value) |
650 | { | |
fbb4aeec | 651 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); |
5c5196da | 652 | struct arch_timer_context *ptimer = vcpu_ptimer(vcpu); |
39735a3a AP |
653 | |
654 | switch (regid) { | |
655 | case KVM_REG_ARM_TIMER_CTL: | |
5c5196da | 656 | vtimer->cnt_ctl = value & ~ARCH_TIMER_CTRL_IT_STAT; |
39735a3a AP |
657 | break; |
658 | case KVM_REG_ARM_TIMER_CNT: | |
90de943a | 659 | update_vtimer_cntvoff(vcpu, kvm_phys_timer_read() - value); |
39735a3a AP |
660 | break; |
661 | case KVM_REG_ARM_TIMER_CVAL: | |
fbb4aeec | 662 | vtimer->cnt_cval = value; |
39735a3a | 663 | break; |
5c5196da CD |
664 | case KVM_REG_ARM_PTIMER_CTL: |
665 | ptimer->cnt_ctl = value & ~ARCH_TIMER_CTRL_IT_STAT; | |
666 | break; | |
667 | case KVM_REG_ARM_PTIMER_CVAL: | |
668 | ptimer->cnt_cval = value; | |
669 | break; | |
670 | ||
39735a3a AP |
671 | default: |
672 | return -1; | |
673 | } | |
4b4b4512 CD |
674 | |
675 | kvm_timer_update_state(vcpu); | |
39735a3a AP |
676 | return 0; |
677 | } | |
678 | ||
5c5196da CD |
679 | static u64 read_timer_ctl(struct arch_timer_context *timer) |
680 | { | |
681 | /* | |
682 | * Set ISTATUS bit if it's expired. | |
683 | * Note that according to ARMv8 ARM Issue A.k, ISTATUS bit is | |
684 | * UNKNOWN when ENABLE bit is 0, so we chose to set ISTATUS bit | |
685 | * regardless of ENABLE bit for our implementation convenience. | |
686 | */ | |
687 | if (!kvm_timer_compute_delta(timer)) | |
688 | return timer->cnt_ctl | ARCH_TIMER_CTRL_IT_STAT; | |
689 | else | |
690 | return timer->cnt_ctl; | |
691 | } | |
692 | ||
39735a3a AP |
693 | u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid) |
694 | { | |
5c5196da | 695 | struct arch_timer_context *ptimer = vcpu_ptimer(vcpu); |
fbb4aeec | 696 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); |
39735a3a AP |
697 | |
698 | switch (regid) { | |
699 | case KVM_REG_ARM_TIMER_CTL: | |
5c5196da | 700 | return read_timer_ctl(vtimer); |
39735a3a | 701 | case KVM_REG_ARM_TIMER_CNT: |
90de943a | 702 | return kvm_phys_timer_read() - vtimer->cntvoff; |
39735a3a | 703 | case KVM_REG_ARM_TIMER_CVAL: |
fbb4aeec | 704 | return vtimer->cnt_cval; |
5c5196da CD |
705 | case KVM_REG_ARM_PTIMER_CTL: |
706 | return read_timer_ctl(ptimer); | |
707 | case KVM_REG_ARM_PTIMER_CVAL: | |
708 | return ptimer->cnt_cval; | |
709 | case KVM_REG_ARM_PTIMER_CNT: | |
710 | return kvm_phys_timer_read(); | |
39735a3a AP |
711 | } |
712 | return (u64)-1; | |
713 | } | |
53e72406 | 714 | |
b3c9950a | 715 | static int kvm_timer_starting_cpu(unsigned int cpu) |
53e72406 | 716 | { |
b3c9950a RC |
717 | kvm_timer_init_interrupt(NULL); |
718 | return 0; | |
53e72406 MZ |
719 | } |
720 | ||
b3c9950a RC |
721 | static int kvm_timer_dying_cpu(unsigned int cpu) |
722 | { | |
723 | disable_percpu_irq(host_vtimer_irq); | |
724 | return 0; | |
725 | } | |
53e72406 | 726 | |
f384dcfe | 727 | int kvm_timer_hyp_init(bool has_gic) |
53e72406 | 728 | { |
29c2d6ff | 729 | struct arch_timer_kvm_info *info; |
53e72406 MZ |
730 | int err; |
731 | ||
29c2d6ff JG |
732 | info = arch_timer_get_kvm_info(); |
733 | timecounter = &info->timecounter; | |
53e72406 | 734 | |
8e1a0476 CD |
735 | if (!timecounter->cc) { |
736 | kvm_err("kvm_arch_timer: uninitialized timecounter\n"); | |
737 | return -ENODEV; | |
738 | } | |
739 | ||
29c2d6ff JG |
740 | if (info->virtual_irq <= 0) { |
741 | kvm_err("kvm_arch_timer: invalid virtual timer IRQ: %d\n", | |
742 | info->virtual_irq); | |
53e72406 MZ |
743 | return -ENODEV; |
744 | } | |
29c2d6ff | 745 | host_vtimer_irq = info->virtual_irq; |
53e72406 | 746 | |
cabdc5c5 MZ |
747 | host_vtimer_irq_flags = irq_get_trigger_type(host_vtimer_irq); |
748 | if (host_vtimer_irq_flags != IRQF_TRIGGER_HIGH && | |
749 | host_vtimer_irq_flags != IRQF_TRIGGER_LOW) { | |
750 | kvm_err("Invalid trigger for IRQ%d, assuming level low\n", | |
751 | host_vtimer_irq); | |
752 | host_vtimer_irq_flags = IRQF_TRIGGER_LOW; | |
753 | } | |
754 | ||
29c2d6ff | 755 | err = request_percpu_irq(host_vtimer_irq, kvm_arch_timer_handler, |
53e72406 MZ |
756 | "kvm guest timer", kvm_get_running_vcpus()); |
757 | if (err) { | |
758 | kvm_err("kvm_arch_timer: can't request interrupt %d (%d)\n", | |
29c2d6ff | 759 | host_vtimer_irq, err); |
5d947a14 | 760 | return err; |
53e72406 MZ |
761 | } |
762 | ||
f384dcfe MZ |
763 | if (has_gic) { |
764 | err = irq_set_vcpu_affinity(host_vtimer_irq, | |
765 | kvm_get_running_vcpus()); | |
766 | if (err) { | |
767 | kvm_err("kvm_arch_timer: error setting vcpu affinity\n"); | |
768 | goto out_free_irq; | |
769 | } | |
d60d8b64 CD |
770 | |
771 | static_branch_enable(&has_gic_active_state); | |
40f4cba9 CD |
772 | } |
773 | ||
76600428 | 774 | kvm_debug("virtual timer IRQ%d\n", host_vtimer_irq); |
53e72406 | 775 | |
b3c9950a | 776 | cpuhp_setup_state(CPUHP_AP_KVM_ARM_TIMER_STARTING, |
73c1b41e | 777 | "kvm/arm/timer:starting", kvm_timer_starting_cpu, |
b3c9950a | 778 | kvm_timer_dying_cpu); |
40f4cba9 CD |
779 | return 0; |
780 | out_free_irq: | |
781 | free_percpu_irq(host_vtimer_irq, kvm_get_running_vcpus()); | |
53e72406 MZ |
782 | return err; |
783 | } | |
784 | ||
785 | void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu) | |
786 | { | |
787 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | |
fbb4aeec | 788 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); |
53e72406 | 789 | |
14d61fa9 | 790 | soft_timer_cancel(&timer->bg_timer, &timer->expired); |
f2a2129e | 791 | soft_timer_cancel(&timer->phys_timer, NULL); |
fbb4aeec | 792 | kvm_vgic_unmap_phys_irq(vcpu, vtimer->irq.irq); |
53e72406 MZ |
793 | } |
794 | ||
abcb851d | 795 | static bool timer_irqs_are_valid(struct kvm_vcpu *vcpu) |
99a1db7a | 796 | { |
99a1db7a | 797 | int vtimer_irq, ptimer_irq; |
abcb851d | 798 | int i, ret; |
99a1db7a | 799 | |
99a1db7a | 800 | vtimer_irq = vcpu_vtimer(vcpu)->irq.irq; |
abcb851d CD |
801 | ret = kvm_vgic_set_owner(vcpu, vtimer_irq, vcpu_vtimer(vcpu)); |
802 | if (ret) | |
803 | return false; | |
99a1db7a | 804 | |
abcb851d CD |
805 | ptimer_irq = vcpu_ptimer(vcpu)->irq.irq; |
806 | ret = kvm_vgic_set_owner(vcpu, ptimer_irq, vcpu_ptimer(vcpu)); | |
807 | if (ret) | |
99a1db7a CD |
808 | return false; |
809 | ||
abcb851d | 810 | kvm_for_each_vcpu(i, vcpu, vcpu->kvm) { |
99a1db7a CD |
811 | if (vcpu_vtimer(vcpu)->irq.irq != vtimer_irq || |
812 | vcpu_ptimer(vcpu)->irq.irq != ptimer_irq) | |
813 | return false; | |
814 | } | |
815 | ||
816 | return true; | |
817 | } | |
818 | ||
4c60e360 CD |
819 | bool kvm_arch_timer_get_input_level(int vintid) |
820 | { | |
821 | struct kvm_vcpu *vcpu = kvm_arm_get_running_vcpu(); | |
822 | struct arch_timer_context *timer; | |
823 | ||
824 | if (vintid == vcpu_vtimer(vcpu)->irq.irq) | |
825 | timer = vcpu_vtimer(vcpu); | |
826 | else | |
827 | BUG(); /* We only map the vtimer so far */ | |
828 | ||
4c60e360 CD |
829 | return kvm_timer_should_fire(timer); |
830 | } | |
831 | ||
41a54482 | 832 | int kvm_timer_enable(struct kvm_vcpu *vcpu) |
53e72406 | 833 | { |
41a54482 | 834 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; |
fbb4aeec | 835 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); |
41a54482 CD |
836 | int ret; |
837 | ||
838 | if (timer->enabled) | |
839 | return 0; | |
840 | ||
d9e13977 AG |
841 | /* Without a VGIC we do not map virtual IRQs to physical IRQs */ |
842 | if (!irqchip_in_kernel(vcpu->kvm)) | |
843 | goto no_vgic; | |
844 | ||
845 | if (!vgic_initialized(vcpu->kvm)) | |
846 | return -ENODEV; | |
847 | ||
abcb851d | 848 | if (!timer_irqs_are_valid(vcpu)) { |
99a1db7a CD |
849 | kvm_debug("incorrectly configured timer irqs\n"); |
850 | return -EINVAL; | |
851 | } | |
852 | ||
b6909a65 | 853 | ret = kvm_vgic_map_phys_irq(vcpu, host_vtimer_irq, vtimer->irq.irq, |
4c60e360 | 854 | kvm_arch_timer_get_input_level); |
41a54482 CD |
855 | if (ret) |
856 | return ret; | |
857 | ||
d9e13977 | 858 | no_vgic: |
4a2c4da1 | 859 | preempt_disable(); |
fd5ebf99 | 860 | timer->enabled = 1; |
0eb7c33c | 861 | kvm_timer_vcpu_load(vcpu); |
4a2c4da1 CD |
862 | preempt_enable(); |
863 | ||
41a54482 | 864 | return 0; |
05971120 | 865 | } |
53e72406 | 866 | |
488f94d7 JL |
867 | /* |
868 | * On VHE system, we only need to configure trap on physical timer and counter | |
869 | * accesses in EL0 and EL1 once, not for every world switch. | |
870 | * The host kernel runs at EL2 with HCR_EL2.TGE == 1, | |
871 | * and this makes those bits have no effect for the host kernel execution. | |
872 | */ | |
873 | void kvm_timer_init_vhe(void) | |
874 | { | |
875 | /* When HCR_EL2.E2H ==1, EL1PCEN and EL1PCTEN are shifted by 10 */ | |
876 | u32 cnthctl_shift = 10; | |
877 | u64 val; | |
878 | ||
879 | /* | |
880 | * Disallow physical timer access for the guest. | |
881 | * Physical counter access is allowed. | |
882 | */ | |
883 | val = read_sysreg(cnthctl_el2); | |
884 | val &= ~(CNTHCTL_EL1PCEN << cnthctl_shift); | |
885 | val |= (CNTHCTL_EL1PCTEN << cnthctl_shift); | |
886 | write_sysreg(val, cnthctl_el2); | |
887 | } | |
99a1db7a CD |
888 | |
889 | static void set_timer_irqs(struct kvm *kvm, int vtimer_irq, int ptimer_irq) | |
890 | { | |
891 | struct kvm_vcpu *vcpu; | |
892 | int i; | |
893 | ||
894 | kvm_for_each_vcpu(i, vcpu, kvm) { | |
895 | vcpu_vtimer(vcpu)->irq.irq = vtimer_irq; | |
896 | vcpu_ptimer(vcpu)->irq.irq = ptimer_irq; | |
897 | } | |
898 | } | |
899 | ||
900 | int kvm_arm_timer_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) | |
901 | { | |
902 | int __user *uaddr = (int __user *)(long)attr->addr; | |
903 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); | |
904 | struct arch_timer_context *ptimer = vcpu_ptimer(vcpu); | |
905 | int irq; | |
906 | ||
907 | if (!irqchip_in_kernel(vcpu->kvm)) | |
908 | return -EINVAL; | |
909 | ||
910 | if (get_user(irq, uaddr)) | |
911 | return -EFAULT; | |
912 | ||
913 | if (!(irq_is_ppi(irq))) | |
914 | return -EINVAL; | |
915 | ||
916 | if (vcpu->arch.timer_cpu.enabled) | |
917 | return -EBUSY; | |
918 | ||
919 | switch (attr->attr) { | |
920 | case KVM_ARM_VCPU_TIMER_IRQ_VTIMER: | |
921 | set_timer_irqs(vcpu->kvm, irq, ptimer->irq.irq); | |
922 | break; | |
923 | case KVM_ARM_VCPU_TIMER_IRQ_PTIMER: | |
924 | set_timer_irqs(vcpu->kvm, vtimer->irq.irq, irq); | |
925 | break; | |
926 | default: | |
927 | return -ENXIO; | |
928 | } | |
929 | ||
930 | return 0; | |
931 | } | |
932 | ||
933 | int kvm_arm_timer_get_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) | |
934 | { | |
935 | int __user *uaddr = (int __user *)(long)attr->addr; | |
936 | struct arch_timer_context *timer; | |
937 | int irq; | |
938 | ||
939 | switch (attr->attr) { | |
940 | case KVM_ARM_VCPU_TIMER_IRQ_VTIMER: | |
941 | timer = vcpu_vtimer(vcpu); | |
942 | break; | |
943 | case KVM_ARM_VCPU_TIMER_IRQ_PTIMER: | |
944 | timer = vcpu_ptimer(vcpu); | |
945 | break; | |
946 | default: | |
947 | return -ENXIO; | |
948 | } | |
949 | ||
950 | irq = timer->irq.irq; | |
951 | return put_user(irq, uaddr); | |
952 | } | |
953 | ||
954 | int kvm_arm_timer_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) | |
955 | { | |
956 | switch (attr->attr) { | |
957 | case KVM_ARM_VCPU_TIMER_IRQ_VTIMER: | |
958 | case KVM_ARM_VCPU_TIMER_IRQ_PTIMER: | |
959 | return 0; | |
960 | } | |
961 | ||
962 | return -ENXIO; | |
963 | } |