Hi Dmytro, On 8/5/22 21:39, Dmytro Maluka wrote: > Currently irq mask notifiers are used only internally in the x86 code > for PIT emulation. However they are not really arch specific. We are > going to use them in the generic irqfd code, for postponing resampler > irqfd notification until the interrupt is unmasked. So move the > implementation of mask notifiers to the generic code, to allow irqfd to > register its mask notifiers. > > Note that calling mask notifiers via calling kvm_fire_mask_notifiers() > is still implemented for x86 only, so registering mask notifiers on > other architectures will have no effect for now. > > Signed-off-by: Dmytro Maluka <dmy@xxxxxxxxxxxx> Reviewed-by: Eric Auger <eric.auger@xxxxxxxxxx> Eric > --- > arch/x86/include/asm/kvm_host.h | 16 ---------------- > arch/x86/kvm/irq_comm.c | 33 --------------------------------- > arch/x86/kvm/x86.c | 1 - > include/linux/kvm_host.h | 15 +++++++++++++++ > virt/kvm/eventfd.c | 33 +++++++++++++++++++++++++++++++++ > virt/kvm/kvm_main.c | 1 + > 6 files changed, 49 insertions(+), 50 deletions(-) > > diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h > index 9217bd6cf0d1..dc76617f11c1 100644 > --- a/arch/x86/include/asm/kvm_host.h > +++ b/arch/x86/include/asm/kvm_host.h > @@ -1198,9 +1198,6 @@ struct kvm_arch { > > struct kvm_xen_hvm_config xen_hvm_config; > > - /* reads protected by irq_srcu, writes by irq_lock */ > - struct hlist_head mask_notifier_list; > - > struct kvm_hv hyperv; > struct kvm_xen xen; > > @@ -1688,19 +1685,6 @@ int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3); > int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa, > const void *val, int bytes); > > -struct kvm_irq_mask_notifier { > - void (*func)(struct kvm_irq_mask_notifier *kimn, bool masked); > - int irq; > - struct hlist_node link; > -}; > - > -void kvm_register_irq_mask_notifier(struct kvm *kvm, int irq, > - struct kvm_irq_mask_notifier *kimn); > -void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq, > - struct kvm_irq_mask_notifier *kimn); > -void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin, > - bool mask); > - > extern bool tdp_enabled; > > u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu); > diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c > index 0687162c4f22..f27e4c9c403e 100644 > --- a/arch/x86/kvm/irq_comm.c > +++ b/arch/x86/kvm/irq_comm.c > @@ -234,39 +234,6 @@ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id) > mutex_unlock(&kvm->irq_lock); > } > > -void kvm_register_irq_mask_notifier(struct kvm *kvm, int irq, > - struct kvm_irq_mask_notifier *kimn) > -{ > - mutex_lock(&kvm->irq_lock); > - kimn->irq = irq; > - hlist_add_head_rcu(&kimn->link, &kvm->arch.mask_notifier_list); > - mutex_unlock(&kvm->irq_lock); > -} > - > -void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq, > - struct kvm_irq_mask_notifier *kimn) > -{ > - mutex_lock(&kvm->irq_lock); > - hlist_del_rcu(&kimn->link); > - mutex_unlock(&kvm->irq_lock); > - synchronize_srcu(&kvm->irq_srcu); > -} > - > -void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin, > - bool mask) > -{ > - struct kvm_irq_mask_notifier *kimn; > - int idx, gsi; > - > - idx = srcu_read_lock(&kvm->irq_srcu); > - gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin); > - if (gsi != -1) > - hlist_for_each_entry_rcu(kimn, &kvm->arch.mask_notifier_list, link) > - if (kimn->irq == gsi) > - kimn->func(kimn, mask); > - srcu_read_unlock(&kvm->irq_srcu, idx); > -} > - > bool kvm_arch_can_set_irq_routing(struct kvm *kvm) > { > return irqchip_in_kernel(kvm); > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index e5fa335a4ea7..a0a776f5c42f 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -11818,7 +11818,6 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) > if (ret) > goto out_page_track; > > - INIT_HLIST_HEAD(&kvm->arch.mask_notifier_list); > INIT_LIST_HEAD(&kvm->arch.assigned_dev_head); > atomic_set(&kvm->arch.noncoherent_dma_count, 0); > > diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h > index 90a45ef7203b..dd5f14e31996 100644 > --- a/include/linux/kvm_host.h > +++ b/include/linux/kvm_host.h > @@ -760,7 +760,10 @@ struct kvm { > struct kvm_irq_routing_table __rcu *irq_routing; > #endif > #ifdef CONFIG_HAVE_KVM_IRQFD > + /* reads protected by irq_srcu, writes by irq_lock */ > struct hlist_head irq_ack_notifier_list; > + /* reads protected by irq_srcu, writes by irq_lock */ > + struct hlist_head irq_mask_notifier_list; > #endif > > #if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER) > @@ -1581,6 +1584,12 @@ struct kvm_irq_ack_notifier { > void (*irq_acked)(struct kvm_irq_ack_notifier *kian); > }; > > +struct kvm_irq_mask_notifier { > + void (*func)(struct kvm_irq_mask_notifier *kimn, bool masked); > + int irq; > + struct hlist_node link; > +}; > + > int kvm_irq_map_gsi(struct kvm *kvm, > struct kvm_kernel_irq_routing_entry *entries, int gsi); > int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned irqchip, unsigned pin); > @@ -1599,6 +1608,12 @@ void kvm_register_irq_ack_notifier(struct kvm *kvm, > struct kvm_irq_ack_notifier *kian); > void kvm_unregister_irq_ack_notifier(struct kvm *kvm, > struct kvm_irq_ack_notifier *kian); > +void kvm_register_irq_mask_notifier(struct kvm *kvm, int irq, > + struct kvm_irq_mask_notifier *kimn); > +void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq, > + struct kvm_irq_mask_notifier *kimn); > +void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin, > + bool mask); > int kvm_request_irq_source_id(struct kvm *kvm); > void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id); > bool kvm_arch_irqfd_allowed(struct kvm *kvm, struct kvm_irqfd *args); > diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c > index 2a3ed401ce46..39403d9fbdcc 100644 > --- a/virt/kvm/eventfd.c > +++ b/virt/kvm/eventfd.c > @@ -518,6 +518,39 @@ void kvm_unregister_irq_ack_notifier(struct kvm *kvm, > synchronize_srcu(&kvm->irq_srcu); > kvm_arch_post_irq_ack_notifier_list_update(kvm); > } > + > +void kvm_register_irq_mask_notifier(struct kvm *kvm, int irq, > + struct kvm_irq_mask_notifier *kimn) > +{ > + mutex_lock(&kvm->irq_lock); > + kimn->irq = irq; > + hlist_add_head_rcu(&kimn->link, &kvm->irq_mask_notifier_list); > + mutex_unlock(&kvm->irq_lock); > +} > + > +void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq, > + struct kvm_irq_mask_notifier *kimn) > +{ > + mutex_lock(&kvm->irq_lock); > + hlist_del_rcu(&kimn->link); > + mutex_unlock(&kvm->irq_lock); > + synchronize_srcu(&kvm->irq_srcu); > +} > + > +void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin, > + bool mask) > +{ > + struct kvm_irq_mask_notifier *kimn; > + int idx, gsi; > + > + idx = srcu_read_lock(&kvm->irq_srcu); > + gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin); > + if (gsi != -1) > + hlist_for_each_entry_rcu(kimn, &kvm->irq_mask_notifier_list, link) > + if (kimn->irq == gsi) > + kimn->func(kimn, mask); > + srcu_read_unlock(&kvm->irq_srcu, idx); > +} > #endif > > void > diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c > index a49df8988cd6..5ca7fb0b8257 100644 > --- a/virt/kvm/kvm_main.c > +++ b/virt/kvm/kvm_main.c > @@ -1144,6 +1144,7 @@ static struct kvm *kvm_create_vm(unsigned long type) > > #ifdef CONFIG_HAVE_KVM_IRQFD > INIT_HLIST_HEAD(&kvm->irq_ack_notifier_list); > + INIT_HLIST_HEAD(&kvm->irq_mask_notifier_list); > #endif > > r = kvm_init_mmu_notifier(kvm);