Commit 568e8c90 authored by Andre Przywara's avatar Andre Przywara Committed by Christoffer Dall
Browse files

KVM: arm/arm64: vgic-new: implement mapped IRQ handling



We now store the mapped hardware IRQ number in our struct, so we
don't need the irq_phys_map for the new VGIC.
Implement the hardware IRQ mapping on top of the reworked arch
timer interface.

Signed-off-by: default avatarAndre Przywara <andre.przywara@arm.com>
Reviewed-by: default avatarChristoffer Dall <christoffer.dall@linaro.org>
parent 03f0c94c
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -206,6 +206,11 @@ int kvm_vgic_hyp_init(void);

int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
			bool level);
int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid, unsigned int intid,
			       bool level);
int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq);
int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);

int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);

+53 −0
Original line number Diff line number Diff line
@@ -312,6 +312,47 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
}

int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid, unsigned int intid,
			       bool level)
{
	return vgic_update_irq_pending(kvm, cpuid, intid, level, true);
}

int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq)
{
	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);

	BUG_ON(!irq);

	spin_lock(&irq->irq_lock);

	irq->hw = true;
	irq->hwintid = phys_irq;

	spin_unlock(&irq->irq_lock);

	return 0;
}

int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq)
{
	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);

	BUG_ON(!irq);

	if (!vgic_initialized(vcpu->kvm))
		return -EAGAIN;

	spin_lock(&irq->irq_lock);

	irq->hw = false;
	irq->hwintid = 0;

	spin_unlock(&irq->irq_lock);

	return 0;
}

/**
 * vgic_prune_ap_list - Remove non-relevant interrupts from the list
 *
@@ -564,3 +605,15 @@ void vgic_kick_vcpus(struct kvm *kvm)
			kvm_vcpu_kick(vcpu);
	}
}

bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
{
	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
	bool map_is_active;

	spin_lock(&irq->irq_lock);
	map_is_active = irq->hw && irq->active;
	spin_unlock(&irq->irq_lock);

	return map_is_active;
}