Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ff9c1143 authored by Marc Zyngier's avatar Marc Zyngier Committed by Christoffer Dall
Browse files

KVM: arm/arm64: GICv4: Handle MOVALL applied to a vPE



The current implementation of MOVALL doesn't allow us to call
into the core ITS code as we hold a number of spinlocks.

Let's try a method used in other parts of the code, were we copy
the intids of the candicate interrupts, and then do whatever
we need to do with them outside of the critical section.

This allows us to move the interrupts one by one, at the expense
of a bit of CPU time. Who cares? MOVALL is such a stupid command
anyway...

Reviewed-by: default avatarChristoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
Signed-off-by: default avatarChristoffer Dall <christoffer.dall@linaro.org>
parent fb0cada6
Loading
Loading
Loading
Loading
+10 −9
Original line number Original line Diff line number Diff line
@@ -1169,11 +1169,12 @@ static int vgic_its_cmd_handle_invall(struct kvm *kvm, struct vgic_its *its,
static int vgic_its_cmd_handle_movall(struct kvm *kvm, struct vgic_its *its,
static int vgic_its_cmd_handle_movall(struct kvm *kvm, struct vgic_its *its,
				      u64 *its_cmd)
				      u64 *its_cmd)
{
{
	struct vgic_dist *dist = &kvm->arch.vgic;
	u32 target1_addr = its_cmd_get_target_addr(its_cmd);
	u32 target1_addr = its_cmd_get_target_addr(its_cmd);
	u32 target2_addr = its_cmd_mask_field(its_cmd, 3, 16, 32);
	u32 target2_addr = its_cmd_mask_field(its_cmd, 3, 16, 32);
	struct kvm_vcpu *vcpu1, *vcpu2;
	struct kvm_vcpu *vcpu1, *vcpu2;
	struct vgic_irq *irq;
	struct vgic_irq *irq;
	u32 *intids;
	int irq_count, i;


	if (target1_addr >= atomic_read(&kvm->online_vcpus) ||
	if (target1_addr >= atomic_read(&kvm->online_vcpus) ||
	    target2_addr >= atomic_read(&kvm->online_vcpus))
	    target2_addr >= atomic_read(&kvm->online_vcpus))
@@ -1185,19 +1186,19 @@ static int vgic_its_cmd_handle_movall(struct kvm *kvm, struct vgic_its *its,
	vcpu1 = kvm_get_vcpu(kvm, target1_addr);
	vcpu1 = kvm_get_vcpu(kvm, target1_addr);
	vcpu2 = kvm_get_vcpu(kvm, target2_addr);
	vcpu2 = kvm_get_vcpu(kvm, target2_addr);


	spin_lock(&dist->lpi_list_lock);
	irq_count = vgic_copy_lpi_list(vcpu1, &intids);
	if (irq_count < 0)
		return irq_count;


	list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) {
	for (i = 0; i < irq_count; i++) {
		spin_lock(&irq->irq_lock);
		irq = vgic_get_irq(kvm, NULL, intids[i]);


		if (irq->target_vcpu == vcpu1)
		update_affinity(irq, vcpu2);
			irq->target_vcpu = vcpu2;


		spin_unlock(&irq->irq_lock);
		vgic_put_irq(kvm, irq);
	}
	}


	spin_unlock(&dist->lpi_list_lock);
	kfree(intids);

	return 0;
	return 0;
}
}