diff options
author | Jike Song <jike.song@intel.com> | 2016-12-01 00:20:06 -0500 |
---|---|---|
committer | Alex Williamson <alex.williamson@redhat.com> | 2016-12-01 12:40:05 -0500 |
commit | ccd46dbae77dbf0d33f42e04b59536f108c395e8 (patch) | |
tree | 6857fe3d01f70509d63f656670a8f757d0b67c4e /drivers/vfio/vfio.c | |
parent | 22195cbd3451a75abaf30651a61cf85c89061327 (diff) |
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>
Diffstat (limited to 'drivers/vfio/vfio.c')
-rw-r--r-- | drivers/vfio/vfio.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 6cc2a9ffac10..9901c4671e2f 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c | |||
@@ -86,6 +86,8 @@ struct vfio_group { | |||
86 | struct mutex unbound_lock; | 86 | struct mutex unbound_lock; |
87 | atomic_t opened; | 87 | atomic_t opened; |
88 | bool noiommu; | 88 | bool noiommu; |
89 | struct kvm *kvm; | ||
90 | struct blocking_notifier_head notifier; | ||
89 | }; | 91 | }; |
90 | 92 | ||
91 | struct vfio_device { | 93 | struct vfio_device { |
@@ -339,6 +341,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group) | |||
339 | #ifdef CONFIG_VFIO_NOIOMMU | 341 | #ifdef CONFIG_VFIO_NOIOMMU |
340 | group->noiommu = (iommu_group_get_iommudata(iommu_group) == &noiommu); | 342 | group->noiommu = (iommu_group_get_iommudata(iommu_group) == &noiommu); |
341 | #endif | 343 | #endif |
344 | BLOCKING_INIT_NOTIFIER_HEAD(&group->notifier); | ||
342 | 345 | ||
343 | group->nb.notifier_call = vfio_iommu_group_notifier; | 346 | group->nb.notifier_call = vfio_iommu_group_notifier; |
344 | 347 | ||
@@ -1581,6 +1584,9 @@ static int vfio_group_fops_release(struct inode *inode, struct file *filep) | |||
1581 | 1584 | ||
1582 | filep->private_data = NULL; | 1585 | filep->private_data = NULL; |
1583 | 1586 | ||
1587 | /* Any user didn't unregister? */ | ||
1588 | WARN_ON(group->notifier.head); | ||
1589 | |||
1584 | vfio_group_try_dissolve_container(group); | 1590 | vfio_group_try_dissolve_container(group); |
1585 | 1591 | ||
1586 | atomic_dec(&group->opened); | 1592 | atomic_dec(&group->opened); |
@@ -2063,6 +2069,76 @@ static int vfio_unregister_iommu_notifier(struct vfio_group *group, | |||
2063 | return ret; | 2069 | return ret; |
2064 | } | 2070 | } |
2065 | 2071 | ||
2072 | void vfio_group_set_kvm(struct vfio_group *group, struct kvm *kvm) | ||
2073 | { | ||
2074 | group->kvm = kvm; | ||
2075 | blocking_notifier_call_chain(&group->notifier, | ||
2076 | VFIO_GROUP_NOTIFY_SET_KVM, kvm); | ||
2077 | } | ||
2078 | EXPORT_SYMBOL_GPL(vfio_group_set_kvm); | ||
2079 | |||
2080 | static int vfio_register_group_notifier(struct vfio_group *group, | ||
2081 | unsigned long *events, | ||
2082 | struct notifier_block *nb) | ||
2083 | { | ||
2084 | struct vfio_container *container; | ||
2085 | int ret; | ||
2086 | bool set_kvm = false; | ||
2087 | |||
2088 | if (*events & VFIO_GROUP_NOTIFY_SET_KVM) | ||
2089 | set_kvm = true; | ||
2090 | |||
2091 | /* clear known events */ | ||
2092 | *events &= ~VFIO_GROUP_NOTIFY_SET_KVM; | ||
2093 | |||
2094 | /* refuse to continue if still events remaining */ | ||
2095 | if (*events) | ||
2096 | return -EINVAL; | ||
2097 | |||
2098 | ret = vfio_group_add_container_user(group); | ||
2099 | if (ret) | ||
2100 | return -EINVAL; | ||
2101 | |||
2102 | container = group->container; | ||
2103 | down_read(&container->group_lock); | ||
2104 | |||
2105 | ret = blocking_notifier_chain_register(&group->notifier, nb); | ||
2106 | |||
2107 | /* | ||
2108 | * The attaching of kvm and vfio_group might already happen, so | ||
2109 | * here we replay once upon registration. | ||
2110 | */ | ||
2111 | if (!ret && set_kvm && group->kvm) | ||
2112 | blocking_notifier_call_chain(&group->notifier, | ||
2113 | VFIO_GROUP_NOTIFY_SET_KVM, group->kvm); | ||
2114 | |||
2115 | up_read(&container->group_lock); | ||
2116 | vfio_group_try_dissolve_container(group); | ||
2117 | |||
2118 | return ret; | ||
2119 | } | ||
2120 | |||
2121 | static int vfio_unregister_group_notifier(struct vfio_group *group, | ||
2122 | struct notifier_block *nb) | ||
2123 | { | ||
2124 | struct vfio_container *container; | ||
2125 | int ret; | ||
2126 | |||
2127 | ret = vfio_group_add_container_user(group); | ||
2128 | if (ret) | ||
2129 | return -EINVAL; | ||
2130 | |||
2131 | container = group->container; | ||
2132 | down_read(&container->group_lock); | ||
2133 | |||
2134 | ret = blocking_notifier_chain_unregister(&group->notifier, nb); | ||
2135 | |||
2136 | up_read(&container->group_lock); | ||
2137 | vfio_group_try_dissolve_container(group); | ||
2138 | |||
2139 | return ret; | ||
2140 | } | ||
2141 | |||
2066 | int vfio_register_notifier(struct device *dev, enum vfio_notify_type type, | 2142 | int vfio_register_notifier(struct device *dev, enum vfio_notify_type type, |
2067 | unsigned long *events, struct notifier_block *nb) | 2143 | unsigned long *events, struct notifier_block *nb) |
2068 | { | 2144 | { |
@@ -2080,6 +2156,9 @@ int vfio_register_notifier(struct device *dev, enum vfio_notify_type type, | |||
2080 | case VFIO_IOMMU_NOTIFY: | 2156 | case VFIO_IOMMU_NOTIFY: |
2081 | ret = vfio_register_iommu_notifier(group, events, nb); | 2157 | ret = vfio_register_iommu_notifier(group, events, nb); |
2082 | break; | 2158 | break; |
2159 | case VFIO_GROUP_NOTIFY: | ||
2160 | ret = vfio_register_group_notifier(group, events, nb); | ||
2161 | break; | ||
2083 | default: | 2162 | default: |
2084 | ret = -EINVAL; | 2163 | ret = -EINVAL; |
2085 | } | 2164 | } |
@@ -2106,6 +2185,9 @@ int vfio_unregister_notifier(struct device *dev, enum vfio_notify_type type, | |||
2106 | case VFIO_IOMMU_NOTIFY: | 2185 | case VFIO_IOMMU_NOTIFY: |
2107 | ret = vfio_unregister_iommu_notifier(group, nb); | 2186 | ret = vfio_unregister_iommu_notifier(group, nb); |
2108 | break; | 2187 | break; |
2188 | case VFIO_GROUP_NOTIFY: | ||
2189 | ret = vfio_unregister_group_notifier(group, nb); | ||
2190 | break; | ||
2109 | default: | 2191 | default: |
2110 | ret = -EINVAL; | 2192 | ret = -EINVAL; |
2111 | } | 2193 | } |