summaryrefslogtreecommitdiff
path: root/virt/kvm/arm/arch_timer.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-10-23 18:32:29 +0900
committerLinus Torvalds <torvalds@linux-foundation.org>2015-10-23 18:32:29 +0900
commit2c44f4f03574a3754306b5a8a80b9ed38a795104 (patch)
tree31d132ab5fac5323c1da94d72f8c89f0b497204a /virt/kvm/arm/arch_timer.c
parent8a990fb47b4c93653745512eca7d2d210678e6c1 (diff)
parentad355e383d826e3506c3caaa0fe991fd112de47b (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.c19
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);
}
/**