aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoffer Dall <cdall@kernel.org>2018-03-05 05:36:38 -0500
committerMarc Zyngier <marc.zyngier@arm.com>2018-03-14 14:29:14 -0400
commit413aa807ae39fed7e387c175d2d0ae9fcf6c0c9d (patch)
treeb1a6f9ebd348103896f0e9c153d37341475f5b67
parente21a4f3a930cda6e4902cb5b3213365e5ff3ce7c (diff)
KVM: arm/arm64: Reset mapped IRQs on VM reset
We currently don't allow resetting mapped IRQs from userspace, because their state is controlled by the hardware. But we do need to reset the state when the VM is reset, so we provide a function for the 'owner' of the mapped interrupt to reset the interrupt state. Currently only the timer uses mapped interrupts, so we call this function from the timer reset logic. Cc: stable@vger.kernel.org Fixes: 4c60e360d6df ("KVM: arm/arm64: Provide a get_input_level for the arch timer") Signed-off-by: Christoffer Dall <cdall@kernel.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
-rw-r--r--include/kvm/arm_vgic.h1
-rw-r--r--virt/kvm/arm/arch_timer.c4
-rw-r--r--virt/kvm/arm/vgic/vgic.c26
3 files changed, 31 insertions, 0 deletions
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index cdbd142ca7f2..02924ae2527e 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -360,6 +360,7 @@ void kvm_vgic_put(struct kvm_vcpu *vcpu);
360bool kvm_vcpu_has_pending_irqs(struct kvm_vcpu *vcpu); 360bool kvm_vcpu_has_pending_irqs(struct kvm_vcpu *vcpu);
361void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu); 361void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
362void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu); 362void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
363void kvm_vgic_reset_mapped_irq(struct kvm_vcpu *vcpu, u32 vintid);
363 364
364void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg); 365void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
365 366
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 70f4c30918eb..3945021510a9 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -581,6 +581,7 @@ void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu)
581 581
582int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu) 582int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu)
583{ 583{
584 struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
584 struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); 585 struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
585 struct arch_timer_context *ptimer = vcpu_ptimer(vcpu); 586 struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
586 587
@@ -594,6 +595,9 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu)
594 ptimer->cnt_ctl = 0; 595 ptimer->cnt_ctl = 0;
595 kvm_timer_update_state(vcpu); 596 kvm_timer_update_state(vcpu);
596 597
598 if (timer->enabled && irqchip_in_kernel(vcpu->kvm))
599 kvm_vgic_reset_mapped_irq(vcpu, vtimer->irq.irq);
600
597 return 0; 601 return 0;
598} 602}
599 603
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index c7c5ef190afa..0001858a2c23 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -495,6 +495,32 @@ int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, unsigned int host_irq,
495 return ret; 495 return ret;
496} 496}
497 497
498/**
499 * kvm_vgic_reset_mapped_irq - Reset a mapped IRQ
500 * @vcpu: The VCPU pointer
501 * @vintid: The INTID of the interrupt
502 *
503 * Reset the active and pending states of a mapped interrupt. Kernel
504 * subsystems injecting mapped interrupts should reset their interrupt lines
505 * when we are doing a reset of the VM.
506 */
507void kvm_vgic_reset_mapped_irq(struct kvm_vcpu *vcpu, u32 vintid)
508{
509 struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
510 unsigned long flags;
511
512 if (!irq->hw)
513 goto out;
514
515 spin_lock_irqsave(&irq->irq_lock, flags);
516 irq->active = false;
517 irq->pending_latch = false;
518 irq->line_level = false;
519 spin_unlock_irqrestore(&irq->irq_lock, flags);
520out:
521 vgic_put_irq(vcpu->kvm, irq);
522}
523
498int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int vintid) 524int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int vintid)
499{ 525{
500 struct vgic_irq *irq; 526 struct vgic_irq *irq;