aboutsummaryrefslogtreecommitdiffstats
path: root/virt/kvm
diff options
context:
space:
mode:
authorChristoffer Dall <christoffer.dall@linaro.org>2013-11-15 23:51:31 -0500
committerChristoffer Dall <christoffer.dall@linaro.org>2013-12-21 13:01:44 -0500
commitcbd333a4bfd0d93bba36d46a0e4e7979228873a6 (patch)
tree700a2000d496cbca1a5d12b6ec04195be91f92fb /virt/kvm
parentc07a0191ef2de1f9510f12d1f88e3b0b5cd8d66f (diff)
KVM: arm-vgic: Support unqueueing of LRs to the dist
To properly access the VGIC state from user space it is very unpractical to have to loop through all the LRs in all register access functions. Instead, support moving all pending state from LRs to the distributor, but leave active state LRs alone. Note that to accurately present the active and pending state to VCPUs reading these distributor registers from a live VM, we would have to stop all other VPUs than the calling VCPU and ask each CPU to unqueue their LR state onto the distributor and add fields to track active state on the distributor side as well. We don't have any users of such functionality yet and there are other inaccuracies of the GIC emulation, so don't provide accurate synchronized access to this state just yet. However, when the time comes, having this function should help. Acked-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Diffstat (limited to 'virt/kvm')
-rw-r--r--virt/kvm/arm/vgic.c88
1 files changed, 83 insertions, 5 deletions
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 88599b585362..d08ba28e729a 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -589,6 +589,80 @@ static bool handle_mmio_sgi_reg(struct kvm_vcpu *vcpu,
589 return false; 589 return false;
590} 590}
591 591
592#define LR_CPUID(lr) \
593 (((lr) & GICH_LR_PHYSID_CPUID) >> GICH_LR_PHYSID_CPUID_SHIFT)
594#define LR_IRQID(lr) \
595 ((lr) & GICH_LR_VIRTUALID)
596
597static void vgic_retire_lr(int lr_nr, int irq, struct vgic_cpu *vgic_cpu)
598{
599 clear_bit(lr_nr, vgic_cpu->lr_used);
600 vgic_cpu->vgic_lr[lr_nr] &= ~GICH_LR_STATE;
601 vgic_cpu->vgic_irq_lr_map[irq] = LR_EMPTY;
602}
603
604/**
605 * vgic_unqueue_irqs - move pending IRQs from LRs to the distributor
606 * @vgic_cpu: Pointer to the vgic_cpu struct holding the LRs
607 *
608 * Move any pending IRQs that have already been assigned to LRs back to the
609 * emulated distributor state so that the complete emulated state can be read
610 * from the main emulation structures without investigating the LRs.
611 *
612 * Note that IRQs in the active state in the LRs get their pending state moved
613 * to the distributor but the active state stays in the LRs, because we don't
614 * track the active state on the distributor side.
615 */
616static void vgic_unqueue_irqs(struct kvm_vcpu *vcpu)
617{
618 struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
619 struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
620 int vcpu_id = vcpu->vcpu_id;
621 int i, irq, source_cpu;
622 u32 *lr;
623
624 for_each_set_bit(i, vgic_cpu->lr_used, vgic_cpu->nr_lr) {
625 lr = &vgic_cpu->vgic_lr[i];
626 irq = LR_IRQID(*lr);
627 source_cpu = LR_CPUID(*lr);
628
629 /*
630 * There are three options for the state bits:
631 *
632 * 01: pending
633 * 10: active
634 * 11: pending and active
635 *
636 * If the LR holds only an active interrupt (not pending) then
637 * just leave it alone.
638 */
639 if ((*lr & GICH_LR_STATE) == GICH_LR_ACTIVE_BIT)
640 continue;
641
642 /*
643 * Reestablish the pending state on the distributor and the
644 * CPU interface. It may have already been pending, but that
645 * is fine, then we are only setting a few bits that were
646 * already set.
647 */
648 vgic_dist_irq_set(vcpu, irq);
649 if (irq < VGIC_NR_SGIS)
650 dist->irq_sgi_sources[vcpu_id][irq] |= 1 << source_cpu;
651 *lr &= ~GICH_LR_PENDING_BIT;
652
653 /*
654 * If there's no state left on the LR (it could still be
655 * active), then the LR does not hold any useful info and can
656 * be marked as free for other use.
657 */
658 if (!(*lr & GICH_LR_STATE))
659 vgic_retire_lr(i, irq, vgic_cpu);
660
661 /* Finally update the VGIC state. */
662 vgic_update_state(vcpu->kvm);
663 }
664}
665
592static bool handle_mmio_sgi_clear(struct kvm_vcpu *vcpu, 666static bool handle_mmio_sgi_clear(struct kvm_vcpu *vcpu,
593 struct kvm_exit_mmio *mmio, 667 struct kvm_exit_mmio *mmio,
594 phys_addr_t offset) 668 phys_addr_t offset)
@@ -848,8 +922,6 @@ static void vgic_update_state(struct kvm *kvm)
848 } 922 }
849} 923}
850 924
851#define LR_CPUID(lr) \
852 (((lr) & GICH_LR_PHYSID_CPUID) >> GICH_LR_PHYSID_CPUID_SHIFT)
853#define MK_LR_PEND(src, irq) \ 925#define MK_LR_PEND(src, irq) \
854 (GICH_LR_PENDING_BIT | ((src) << GICH_LR_PHYSID_CPUID_SHIFT) | (irq)) 926 (GICH_LR_PENDING_BIT | ((src) << GICH_LR_PHYSID_CPUID_SHIFT) | (irq))
855 927
@@ -871,9 +943,7 @@ static void vgic_retire_disabled_irqs(struct kvm_vcpu *vcpu)
871 int irq = vgic_cpu->vgic_lr[lr] & GICH_LR_VIRTUALID; 943 int irq = vgic_cpu->vgic_lr[lr] & GICH_LR_VIRTUALID;
872 944
873 if (!vgic_irq_is_enabled(vcpu, irq)) { 945 if (!vgic_irq_is_enabled(vcpu, irq)) {
874 vgic_cpu->vgic_irq_lr_map[irq] = LR_EMPTY; 946 vgic_retire_lr(lr, irq, vgic_cpu);
875 clear_bit(lr, vgic_cpu->lr_used);
876 vgic_cpu->vgic_lr[lr] &= ~GICH_LR_STATE;
877 if (vgic_irq_is_active(vcpu, irq)) 947 if (vgic_irq_is_active(vcpu, irq))
878 vgic_irq_clear_active(vcpu, irq); 948 vgic_irq_clear_active(vcpu, irq);
879 } 949 }
@@ -1675,6 +1745,14 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
1675 } 1745 }
1676 } 1746 }
1677 1747
1748 /*
1749 * Move all pending IRQs from the LRs on all VCPUs so the pending
1750 * state can be properly represented in the register state accessible
1751 * through this API.
1752 */
1753 kvm_for_each_vcpu(c, tmp_vcpu, dev->kvm)
1754 vgic_unqueue_irqs(tmp_vcpu);
1755
1678 offset -= r->base; 1756 offset -= r->base;
1679 r->handle_mmio(vcpu, &mmio, offset); 1757 r->handle_mmio(vcpu, &mmio, offset);
1680 1758