diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2015-10-21 17:46:56 +0200 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2015-10-21 17:46:56 +0200 |
commit | ad355e383d826e3506c3caaa0fe991fd112de47b (patch) | |
tree | 1f1da23f174f30a2cb1b7d8c2e8b8ace1fd00032 /virt/kvm/arm/arch_timer.c | |
parent | b10d92a54dac25a6152f1aa1ffc95c12908035ce (diff) | |
parent | 0d997491f814c87310a6ad7be30a9049c7150489 (diff) |
Merge tag 'kvm-arm-for-v4.3-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into kvm-master
A late round of KVM/ARM fixes for v4.3-rc7, fixing:
- A bug where level-triggered interrupts lowered from userspace
are still routed to the guest
- A memory leak an a failed initialization path
- A build error under certain configurations
- Several timer bugs introduced with moving the timer to the active
state handling instead of the masking trick.
Diffstat (limited to 'virt/kvm/arm/arch_timer.c')
-rw-r--r-- | virt/kvm/arm/arch_timer.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c index 48c6e1ac6827..b9d3a32cbc04 100644 --- a/virt/kvm/arm/arch_timer.c +++ b/virt/kvm/arm/arch_timer.c @@ -137,6 +137,8 @@ bool kvm_timer_should_fire(struct kvm_vcpu *vcpu) void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu) { struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; + bool phys_active; + int ret; /* * We're about to run this vcpu again, so there is no need to @@ -151,6 +153,23 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu) */ if (kvm_timer_should_fire(vcpu)) kvm_timer_inject_irq(vcpu); + + /* + * We keep track of whether the edge-triggered interrupt has been + * signalled to the vgic/guest, and if so, we mask the interrupt and + * the physical distributor to prevent the timer from raising a + * physical interrupt whenever we run a guest, preventing forward + * VCPU progress. + */ + if (kvm_vgic_get_phys_irq_active(timer->map)) + phys_active = true; + else + phys_active = false; + + ret = irq_set_irqchip_state(timer->map->irq, + IRQCHIP_STATE_ACTIVE, + phys_active); + WARN_ON(ret); } /** |