Skip to content

Commit ccd46db

Browse files
l1viathanawilliam
authored andcommitted
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 <[email protected]> Cc: Paolo Bonzini <[email protected]> Cc: Xiao Guangrong <[email protected]> Signed-off-by: Jike Song <[email protected]> [aw: remove use of new typedef] Signed-off-by: Alex Williamson <[email protected]>
1 parent 22195cb commit ccd46db

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed

drivers/vfio/vfio.c

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ struct vfio_group {
8686
struct mutex unbound_lock;
8787
atomic_t opened;
8888
bool noiommu;
89+
struct kvm *kvm;
90+
struct blocking_notifier_head notifier;
8991
};
9092

9193
struct vfio_device {
@@ -339,6 +341,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
339341
#ifdef CONFIG_VFIO_NOIOMMU
340342
group->noiommu = (iommu_group_get_iommudata(iommu_group) == &noiommu);
341343
#endif
344+
BLOCKING_INIT_NOTIFIER_HEAD(&group->notifier);
342345

343346
group->nb.notifier_call = vfio_iommu_group_notifier;
344347

@@ -1581,6 +1584,9 @@ static int vfio_group_fops_release(struct inode *inode, struct file *filep)
15811584

15821585
filep->private_data = NULL;
15831586

1587+
/* Any user didn't unregister? */
1588+
WARN_ON(group->notifier.head);
1589+
15841590
vfio_group_try_dissolve_container(group);
15851591

15861592
atomic_dec(&group->opened);
@@ -2063,6 +2069,76 @@ static int vfio_unregister_iommu_notifier(struct vfio_group *group,
20632069
return ret;
20642070
}
20652071

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+
20662142
int vfio_register_notifier(struct device *dev, enum vfio_notify_type type,
20672143
unsigned long *events, struct notifier_block *nb)
20682144
{
@@ -2080,6 +2156,9 @@ int vfio_register_notifier(struct device *dev, enum vfio_notify_type type,
20802156
case VFIO_IOMMU_NOTIFY:
20812157
ret = vfio_register_iommu_notifier(group, events, nb);
20822158
break;
2159+
case VFIO_GROUP_NOTIFY:
2160+
ret = vfio_register_group_notifier(group, events, nb);
2161+
break;
20832162
default:
20842163
ret = -EINVAL;
20852164
}
@@ -2106,6 +2185,9 @@ int vfio_unregister_notifier(struct device *dev, enum vfio_notify_type type,
21062185
case VFIO_IOMMU_NOTIFY:
21072186
ret = vfio_unregister_iommu_notifier(group, nb);
21082187
break;
2188+
case VFIO_GROUP_NOTIFY:
2189+
ret = vfio_unregister_group_notifier(group, nb);
2190+
break;
21092191
default:
21102192
ret = -EINVAL;
21112193
}

include/linux/vfio.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,15 @@ extern int vfio_unpin_pages(struct device *dev, unsigned long *user_pfn,
111111
/* each type has independent events */
112112
enum vfio_notify_type {
113113
VFIO_IOMMU_NOTIFY = 0,
114+
VFIO_GROUP_NOTIFY = 1,
114115
};
115116

116117
/* events for VFIO_IOMMU_NOTIFY */
117118
#define VFIO_IOMMU_NOTIFY_DMA_UNMAP BIT(0)
118119

120+
/* events for VFIO_GROUP_NOTIFY */
121+
#define VFIO_GROUP_NOTIFY_SET_KVM BIT(0)
122+
119123
extern int vfio_register_notifier(struct device *dev,
120124
enum vfio_notify_type type,
121125
unsigned long *required_events,
@@ -124,6 +128,9 @@ extern int vfio_unregister_notifier(struct device *dev,
124128
enum vfio_notify_type type,
125129
struct notifier_block *nb);
126130

131+
struct kvm;
132+
extern void vfio_group_set_kvm(struct vfio_group *group, struct kvm *kvm);
133+
127134
/*
128135
* Sub-module helpers
129136
*/

0 commit comments

Comments
 (0)