Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

vfio: support notifier chain in vfio_group

Beyond vfio_iommu events, users might also be interested in
vfio_group events. For example, if a vfio_group is used along
with Qemu/KVM, whenever kvm pointer is set to/cleared from the
vfio_group, users could be notified.

Currently only VFIO_GROUP_NOTIFY_SET_KVM supported.

Cc: Kirti Wankhede <kwankhede@nvidia.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Xiao Guangrong <guangrong.xiao@linux.intel.com>
Signed-off-by: Jike Song <jike.song@intel.com>
[aw: remove use of new typedef]
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>

authored by

Jike Song and committed by
Alex Williamson
ccd46dba 22195cbd

+89
+82
drivers/vfio/vfio.c
··· 86 86 struct mutex unbound_lock; 87 87 atomic_t opened; 88 88 bool noiommu; 89 + struct kvm *kvm; 90 + struct blocking_notifier_head notifier; 89 91 }; 90 92 91 93 struct vfio_device { ··· 341 339 #ifdef CONFIG_VFIO_NOIOMMU 342 340 group->noiommu = (iommu_group_get_iommudata(iommu_group) == &noiommu); 343 341 #endif 342 + BLOCKING_INIT_NOTIFIER_HEAD(&group->notifier); 344 343 345 344 group->nb.notifier_call = vfio_iommu_group_notifier; 346 345 ··· 1584 1581 1585 1582 filep->private_data = NULL; 1586 1583 1584 + /* Any user didn't unregister? */ 1585 + WARN_ON(group->notifier.head); 1586 + 1587 1587 vfio_group_try_dissolve_container(group); 1588 1588 1589 1589 atomic_dec(&group->opened); ··· 2069 2063 return ret; 2070 2064 } 2071 2065 2066 + void vfio_group_set_kvm(struct vfio_group *group, struct kvm *kvm) 2067 + { 2068 + group->kvm = kvm; 2069 + blocking_notifier_call_chain(&group->notifier, 2070 + VFIO_GROUP_NOTIFY_SET_KVM, kvm); 2071 + } 2072 + EXPORT_SYMBOL_GPL(vfio_group_set_kvm); 2073 + 2074 + static int vfio_register_group_notifier(struct vfio_group *group, 2075 + unsigned long *events, 2076 + struct notifier_block *nb) 2077 + { 2078 + struct vfio_container *container; 2079 + int ret; 2080 + bool set_kvm = false; 2081 + 2082 + if (*events & VFIO_GROUP_NOTIFY_SET_KVM) 2083 + set_kvm = true; 2084 + 2085 + /* clear known events */ 2086 + *events &= ~VFIO_GROUP_NOTIFY_SET_KVM; 2087 + 2088 + /* refuse to continue if still events remaining */ 2089 + if (*events) 2090 + return -EINVAL; 2091 + 2092 + ret = vfio_group_add_container_user(group); 2093 + if (ret) 2094 + return -EINVAL; 2095 + 2096 + container = group->container; 2097 + down_read(&container->group_lock); 2098 + 2099 + ret = blocking_notifier_chain_register(&group->notifier, nb); 2100 + 2101 + /* 2102 + * The attaching of kvm and vfio_group might already happen, so 2103 + * here we replay once upon registration. 2104 + */ 2105 + if (!ret && set_kvm && group->kvm) 2106 + blocking_notifier_call_chain(&group->notifier, 2107 + VFIO_GROUP_NOTIFY_SET_KVM, group->kvm); 2108 + 2109 + up_read(&container->group_lock); 2110 + vfio_group_try_dissolve_container(group); 2111 + 2112 + return ret; 2113 + } 2114 + 2115 + static int vfio_unregister_group_notifier(struct vfio_group *group, 2116 + struct notifier_block *nb) 2117 + { 2118 + struct vfio_container *container; 2119 + int ret; 2120 + 2121 + ret = vfio_group_add_container_user(group); 2122 + if (ret) 2123 + return -EINVAL; 2124 + 2125 + container = group->container; 2126 + down_read(&container->group_lock); 2127 + 2128 + ret = blocking_notifier_chain_unregister(&group->notifier, nb); 2129 + 2130 + up_read(&container->group_lock); 2131 + vfio_group_try_dissolve_container(group); 2132 + 2133 + return ret; 2134 + } 2135 + 2072 2136 int vfio_register_notifier(struct device *dev, enum vfio_notify_type type, 2073 2137 unsigned long *events, struct notifier_block *nb) 2074 2138 { ··· 2155 2079 switch (type) { 2156 2080 case VFIO_IOMMU_NOTIFY: 2157 2081 ret = vfio_register_iommu_notifier(group, events, nb); 2082 + break; 2083 + case VFIO_GROUP_NOTIFY: 2084 + ret = vfio_register_group_notifier(group, events, nb); 2158 2085 break; 2159 2086 default: 2160 2087 ret = -EINVAL; ··· 2184 2105 switch (type) { 2185 2106 case VFIO_IOMMU_NOTIFY: 2186 2107 ret = vfio_unregister_iommu_notifier(group, nb); 2108 + break; 2109 + case VFIO_GROUP_NOTIFY: 2110 + ret = vfio_unregister_group_notifier(group, nb); 2187 2111 break; 2188 2112 default: 2189 2113 ret = -EINVAL;
+7
include/linux/vfio.h
··· 111 111 /* each type has independent events */ 112 112 enum vfio_notify_type { 113 113 VFIO_IOMMU_NOTIFY = 0, 114 + VFIO_GROUP_NOTIFY = 1, 114 115 }; 115 116 116 117 /* events for VFIO_IOMMU_NOTIFY */ 117 118 #define VFIO_IOMMU_NOTIFY_DMA_UNMAP BIT(0) 119 + 120 + /* events for VFIO_GROUP_NOTIFY */ 121 + #define VFIO_GROUP_NOTIFY_SET_KVM BIT(0) 118 122 119 123 extern int vfio_register_notifier(struct device *dev, 120 124 enum vfio_notify_type type, ··· 127 123 extern int vfio_unregister_notifier(struct device *dev, 128 124 enum vfio_notify_type type, 129 125 struct notifier_block *nb); 126 + 127 + struct kvm; 128 + extern void vfio_group_set_kvm(struct vfio_group *group, struct kvm *kvm); 130 129 131 130 /* 132 131 * Sub-module helpers