Commit 3ed0dc03 authored by Oliver Upton's avatar Oliver Upton
Browse files

Merge branch 'kvm-arm64/misc' into kvmarm/next



* kvm-arm64/misc:
  : Miscellaneous fixes/cleanups for KVM/arm64
  :
  :  - Avoid GICv4 vLPI configuration when confronted with user error
  :
  :  - Only attempt vLPI configuration when the target routing is an MSI
  :
  :  - Document ordering requirements to avoid aforementioned user error
  KVM: arm64: Tear down vGIC on failed vCPU creation
  KVM: arm64: Document ordering requirements for irqbypass
  KVM: arm64: vgic-v4: Fall back to software irqbypass if LPI not found
  KVM: arm64: vgic-v4: Only WARN for HW IRQ mismatch when unmapping vLPI
  KVM: arm64: vgic-v4: Only attempt vLPI mapping for actual MSIs

Signed-off-by: default avatarOliver Upton <oliver.upton@linux.dev>
parents 80e54e84 250f2536
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -126,7 +126,8 @@ KVM_DEV_ARM_VGIC_GRP_ITS_REGS
ITS Restore Sequence:
---------------------

The following ordering must be followed when restoring the GIC and the ITS:
The following ordering must be followed when restoring the GIC, ITS, and
KVM_IRQFD assignments:

a) restore all guest memory and create vcpus
b) restore all redistributors
@@ -139,6 +140,8 @@ d) restore the ITS in the following order:
     3. Load the ITS table data (KVM_DEV_ARM_ITS_RESTORE_TABLES)
     4. Restore GITS_CTLR

e) restore KVM_IRQFD assignments for MSIs

Then vcpus can be started.

ITS Table ABI REV0:
+17 −1
Original line number Diff line number Diff line
@@ -466,7 +466,11 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
	if (err)
		return err;

	return kvm_share_hyp(vcpu, vcpu + 1);
	err = kvm_share_hyp(vcpu, vcpu + 1);
	if (err)
		kvm_vgic_vcpu_destroy(vcpu);

	return err;
}

void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
@@ -2714,6 +2718,14 @@ int kvm_arch_irq_bypass_add_producer(struct irq_bypass_consumer *cons,
{
	struct kvm_kernel_irqfd *irqfd =
		container_of(cons, struct kvm_kernel_irqfd, consumer);
	struct kvm_kernel_irq_routing_entry *irq_entry = &irqfd->irq_entry;

	/*
	 * The only thing we have a chance of directly-injecting is LPIs. Maybe
	 * one day...
	 */
	if (irq_entry->type != KVM_IRQ_ROUTING_MSI)
		return 0;

	return kvm_vgic_v4_set_forwarding(irqfd->kvm, prod->irq,
					  &irqfd->irq_entry);
@@ -2723,6 +2735,10 @@ void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,
{
	struct kvm_kernel_irqfd *irqfd =
		container_of(cons, struct kvm_kernel_irqfd, consumer);
	struct kvm_kernel_irq_routing_entry *irq_entry = &irqfd->irq_entry;

	if (irq_entry->type != KVM_IRQ_ROUTING_MSI)
		return;

	kvm_vgic_v4_unset_forwarding(irqfd->kvm, prod->irq,
				     &irqfd->irq_entry);
+11 −6
Original line number Diff line number Diff line
@@ -415,7 +415,7 @@ int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int virq,
	struct vgic_irq *irq;
	struct its_vlpi_map map;
	unsigned long flags;
	int ret;
	int ret = 0;

	if (!vgic_supports_direct_msis(kvm))
		return 0;
@@ -430,10 +430,15 @@ int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int virq,

	mutex_lock(&its->its_lock);

	/* Perform the actual DevID/EventID -> LPI translation. */
	ret = vgic_its_resolve_lpi(kvm, its, irq_entry->msi.devid,
				   irq_entry->msi.data, &irq);
	if (ret)
	/*
	 * Perform the actual DevID/EventID -> LPI translation.
	 *
	 * Silently exit if translation fails as the guest (or userspace!) has
	 * managed to do something stupid. Emulated LPI injection will still
	 * work if the guest figures itself out at a later time.
	 */
	if (vgic_its_resolve_lpi(kvm, its, irq_entry->msi.devid,
				 irq_entry->msi.data, &irq))
		goto out;

	/* Silently exit if the vLPI is already mapped */
@@ -512,7 +517,7 @@ int kvm_vgic_v4_unset_forwarding(struct kvm *kvm, int virq,
	if (ret)
		goto out;

	WARN_ON(!(irq->hw && irq->host_irq == virq));
	WARN_ON(irq->hw && irq->host_irq != virq);
	if (irq->hw) {
		atomic_dec(&irq->target_vcpu->arch.vgic_cpu.vgic_v3.its_vpe.vlpi_count);
		irq->hw = false;