diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-10-23 18:32:29 +0900 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-10-23 18:32:29 +0900 |
commit | 2c44f4f03574a3754306b5a8a80b9ed38a795104 (patch) | |
tree | 31d132ab5fac5323c1da94d72f8c89f0b497204a /virt/kvm/arm/arch_timer.c | |
parent | 8a990fb47b4c93653745512eca7d2d210678e6c1 (diff) | |
parent | ad355e383d826e3506c3caaa0fe991fd112de47b (diff) |
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull KVM bugfixes from Paolo Bonzini:
"Bug fixes for ARM, mostly 4.3 regressions related to virtual interrupt
controller changes"
* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm:
arm/arm64: KVM: Fix disabled distributor operation
arm/arm64: KVM: Clear map->active on pend/active clear
arm/arm64: KVM: Fix arch timer behavior for disabled interrupts
KVM: arm: use GIC support unconditionally
KVM: arm/arm64: Fix memory leak if timer initialization fails
KVM: arm/arm64: Do not inject spurious interrupts
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); } /** |