Commit 3a95fc61 authored by wanghaibin's avatar wanghaibin Committed by Dongxu Sun
Browse files

KVM: arm64: sdev: Support virq bypass by INT/VSYNC command

virt inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8UROS


CVE: NA

--------------------------------

We already have the set_irqchip_state() callback which will issue
INT/VSYNC commands on the physical side when the handled IRQ is
forwarded to vcpu.  It was intended to be used to handle the guest
INT command targeting a VLPI.

Let's reuse this hack to set the virtio-pci function's VLPI pending,
instead of directly writing message data into GITS_TRANSLATER, which
should only be treated as the Message Address of PCI devices.

Signed-off-by: default avatarwanghaibin <wanghaibin.wang@huawei.com>
Signed-off-by: default avatarZenghui Yu <yuzenghui@huawei.com>
Signed-off-by: default avatarKunkun Jiang <jiangkunkun@huawei.com>
Signed-off-by: default avatarDongxu Sun <sundongxu3@huawei.com>
parent e25e2fd4
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -121,6 +121,23 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
	return vgic_its_inject_msi(kvm, &msi);
}

#ifdef CONFIG_VIRT_PLAT_DEV
static int kvm_arch_set_irq_bypass(struct kvm_kernel_irq_routing_entry *e,
				  struct kvm *kvm)
{
	struct kire_data *cache = &e->cache;

	/*
	 * FIXME: is there any race against the irqfd_update(),
	 * where the cache data will be updated?
	 */
	if (!cache->valid)
		return -EWOULDBLOCK;

	return shadow_dev_virq_bypass_inject(kvm, e);
}
#endif

/**
 * kvm_arch_set_irq_inatomic: fast-path for irqfd injection
 */
@@ -138,6 +155,10 @@ int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,
		if (!vgic_has_its(kvm))
			break;

#ifdef CONFIG_VIRT_PLAT_DEV
		if (!kvm_arch_set_irq_bypass(e, kvm))
			return 0;
#endif
		kvm_populate_msi(e, &msi);
		return vgic_its_inject_cached_translation(kvm, &msi);
	}
+3 −0
Original line number Diff line number Diff line
@@ -466,6 +466,9 @@ int kvm_shadow_dev_create(struct kvm *kvm, struct kvm_master_dev_info *mdi);
void kvm_shadow_dev_delete(struct kvm *kvm, u32 devid);
void kvm_shadow_dev_delete_all(struct kvm *kvm);
struct shadow_dev *kvm_shadow_dev_get(struct kvm *kvm, struct kvm_msi *msi);

int shadow_dev_virq_bypass_inject(struct kvm *kvm,
				  struct kvm_kernel_irq_routing_entry *e);
#endif

#endif /* __KVM_ARM_VGIC_H */