From: wanghaibin wanghaibin.wang@huawei.com
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: wanghaibin wanghaibin.wang@huawei.com Signed-off-by: Zenghui Yu yuzenghui@huawei.com Signed-off-by: Kunkun Jiang jiangkunkun@huawei.com Signed-off-by: Dongxu Sun sundongxu3@huawei.com --- arch/arm64/kvm/vgic/vgic-irqfd.c | 18 ++++++++++++++++++ include/kvm/arm_vgic.h | 2 ++ 2 files changed, 20 insertions(+)
diff --git a/arch/arm64/kvm/vgic/vgic-irqfd.c b/arch/arm64/kvm/vgic/vgic-irqfd.c index 39b86a60b957..78f508408ac9 100644 --- a/arch/arm64/kvm/vgic/vgic-irqfd.c +++ b/arch/arm64/kvm/vgic/vgic-irqfd.c @@ -119,6 +119,21 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, return vgic_its_inject_msi(kvm, &msi); }
+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); +} + /** * kvm_arch_set_irq_inatomic: fast-path for irqfd injection */ @@ -136,6 +151,9 @@ int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e, if (!vgic_has_its(kvm)) break;
+ if (!kvm_arch_set_irq_bypass(e, kvm)) + return 0; + kvm_populate_msi(e, &msi); return vgic_its_inject_cached_translation(kvm, &msi); } diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index fa02ab5ef144..a690527f041d 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h @@ -497,4 +497,6 @@ 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 /* __KVM_ARM_VGIC_H */