@@ -86,6 +86,8 @@ struct vfio_group {
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 {
@@ -339,6 +341,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
339
341
#ifdef CONFIG_VFIO_NOIOMMU
340
342
group -> noiommu = (iommu_group_get_iommudata (iommu_group ) == & noiommu );
341
343
#endif
344
+ BLOCKING_INIT_NOTIFIER_HEAD (& group -> notifier );
342
345
343
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
1585
filep -> private_data = NULL ;
1583
1586
1587
+ /* Any user didn't unregister? */
1588
+ WARN_ON (group -> notifier .head );
1589
+
1584
1590
vfio_group_try_dissolve_container (group );
1585
1591
1586
1592
atomic_dec (& group -> opened );
@@ -2063,6 +2069,76 @@ static int vfio_unregister_iommu_notifier(struct vfio_group *group,
2063
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
2142
int vfio_register_notifier (struct device * dev , enum vfio_notify_type type ,
2067
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
2156
case VFIO_IOMMU_NOTIFY :
2081
2157
ret = vfio_register_iommu_notifier (group , events , nb );
2082
2158
break ;
2159
+ case VFIO_GROUP_NOTIFY :
2160
+ ret = vfio_register_group_notifier (group , events , nb );
2161
+ break ;
2083
2162
default :
2084
2163
ret = - EINVAL ;
2085
2164
}
@@ -2106,6 +2185,9 @@ int vfio_unregister_notifier(struct device *dev, enum vfio_notify_type type,
2106
2185
case VFIO_IOMMU_NOTIFY :
2107
2186
ret = vfio_unregister_iommu_notifier (group , nb );
2108
2187
break ;
2188
+ case VFIO_GROUP_NOTIFY :
2189
+ ret = vfio_unregister_group_notifier (group , nb );
2190
+ break ;
2109
2191
default :
2110
2192
ret = - EINVAL ;
2111
2193
}
0 commit comments