aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2016-08-16 10:03:02 -0400
committerChristoffer Dall <christoffer.dall@linaro.org>2016-08-17 06:23:47 -0400
commitcabdc5c59ab46a1ec5ea98c5ac4022111fbfd63a (patch)
tree42a9e42c4682c9c98131ad7ef61dfc9081db0664
parent674e70127069f3fd3c58fb0f94c60eb0f6567d78 (diff)
KVM: arm/arm64: timer: Workaround misconfigured timer interrupt
Similarily to f005bd7e3b84 ("clocksource/arm_arch_timer: Force per-CPU interrupt to be level-triggered"), make sure we can survive an interrupt that has been misconfigured as edge-triggered by forcing it to be level-triggered (active low is assumed, but the GIC doesn't really care whether this is high or low). Hopefully, the amount of shouting in the kernel log will convince the user to do something about their firmware. Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
-rw-r--r--virt/kvm/arm/arch_timer.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 4fde8c7dfcfe..77e6ccf14901 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -33,6 +33,7 @@
33static struct timecounter *timecounter; 33static struct timecounter *timecounter;
34static struct workqueue_struct *wqueue; 34static struct workqueue_struct *wqueue;
35static unsigned int host_vtimer_irq; 35static unsigned int host_vtimer_irq;
36static u32 host_vtimer_irq_flags;
36 37
37void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu) 38void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu)
38{ 39{
@@ -365,7 +366,7 @@ void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
365 366
366static void kvm_timer_init_interrupt(void *info) 367static void kvm_timer_init_interrupt(void *info)
367{ 368{
368 enable_percpu_irq(host_vtimer_irq, 0); 369 enable_percpu_irq(host_vtimer_irq, host_vtimer_irq_flags);
369} 370}
370 371
371int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value) 372int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
@@ -432,6 +433,14 @@ int kvm_timer_hyp_init(void)
432 } 433 }
433 host_vtimer_irq = info->virtual_irq; 434 host_vtimer_irq = info->virtual_irq;
434 435
436 host_vtimer_irq_flags = irq_get_trigger_type(host_vtimer_irq);
437 if (host_vtimer_irq_flags != IRQF_TRIGGER_HIGH &&
438 host_vtimer_irq_flags != IRQF_TRIGGER_LOW) {
439 kvm_err("Invalid trigger for IRQ%d, assuming level low\n",
440 host_vtimer_irq);
441 host_vtimer_irq_flags = IRQF_TRIGGER_LOW;
442 }
443
435 err = request_percpu_irq(host_vtimer_irq, kvm_arch_timer_handler, 444 err = request_percpu_irq(host_vtimer_irq, kvm_arch_timer_handler,
436 "kvm guest timer", kvm_get_running_vcpus()); 445 "kvm guest timer", kvm_get_running_vcpus());
437 if (err) { 446 if (err) {