1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2ec53500fSAlex Williamson /*
3ec53500fSAlex Williamson * VFIO-KVM bridge pseudo device
4ec53500fSAlex Williamson *
5ec53500fSAlex Williamson * Copyright (C) 2013 Red Hat, Inc. All rights reserved.
6ec53500fSAlex Williamson * Author: Alex Williamson <alex.williamson@redhat.com>
7ec53500fSAlex Williamson */
8ec53500fSAlex Williamson
9ec53500fSAlex Williamson #include <linux/errno.h>
10ec53500fSAlex Williamson #include <linux/file.h>
11ec53500fSAlex Williamson #include <linux/kvm_host.h>
12ec53500fSAlex Williamson #include <linux/list.h>
13ec53500fSAlex Williamson #include <linux/module.h>
14ec53500fSAlex Williamson #include <linux/mutex.h>
15ec53500fSAlex Williamson #include <linux/slab.h>
16ec53500fSAlex Williamson #include <linux/uaccess.h>
17ec53500fSAlex Williamson #include <linux/vfio.h>
183c3c29fdSPaolo Bonzini #include "vfio.h"
19ec53500fSAlex Williamson
20121f80baSAlexey Kardashevskiy #ifdef CONFIG_SPAPR_TCE_IOMMU
21121f80baSAlexey Kardashevskiy #include <asm/kvm_ppc.h>
22121f80baSAlexey Kardashevskiy #endif
23121f80baSAlexey Kardashevskiy
242f99073aSYi Liu struct kvm_vfio_file {
25ec53500fSAlex Williamson struct list_head node;
26d55d9e7aSJason Gunthorpe struct file *file;
27819da99aSJason Gunthorpe #ifdef CONFIG_SPAPR_TCE_IOMMU
28819da99aSJason Gunthorpe struct iommu_group *iommu_group;
29819da99aSJason Gunthorpe #endif
30ec53500fSAlex Williamson };
31ec53500fSAlex Williamson
32ec53500fSAlex Williamson struct kvm_vfio {
332f99073aSYi Liu struct list_head file_list;
34ec53500fSAlex Williamson struct mutex lock;
35e0f0bbc5SAlex Williamson bool noncoherent;
36ec53500fSAlex Williamson };
37ec53500fSAlex Williamson
kvm_vfio_file_set_kvm(struct file * file,struct kvm * kvm)38ba70a89fSJason Gunthorpe static void kvm_vfio_file_set_kvm(struct file *file, struct kvm *kvm)
392fc1bec1SJike Song {
40ba70a89fSJason Gunthorpe void (*fn)(struct file *file, struct kvm *kvm);
412fc1bec1SJike Song
42ba70a89fSJason Gunthorpe fn = symbol_get(vfio_file_set_kvm);
432fc1bec1SJike Song if (!fn)
442fc1bec1SJike Song return;
452fc1bec1SJike Song
46ba70a89fSJason Gunthorpe fn(file, kvm);
472fc1bec1SJike Song
48ba70a89fSJason Gunthorpe symbol_put(vfio_file_set_kvm);
492fc1bec1SJike Song }
502fc1bec1SJike Song
kvm_vfio_file_enforced_coherent(struct file * file)51a905ad04SJason Gunthorpe static bool kvm_vfio_file_enforced_coherent(struct file *file)
529d830d47SAlex Williamson {
53a905ad04SJason Gunthorpe bool (*fn)(struct file *file);
54a905ad04SJason Gunthorpe bool ret;
559d830d47SAlex Williamson
56a905ad04SJason Gunthorpe fn = symbol_get(vfio_file_enforced_coherent);
579d830d47SAlex Williamson if (!fn)
589d830d47SAlex Williamson return false;
599d830d47SAlex Williamson
60a905ad04SJason Gunthorpe ret = fn(file);
619d830d47SAlex Williamson
62a905ad04SJason Gunthorpe symbol_put(vfio_file_enforced_coherent);
639d830d47SAlex Williamson
64a905ad04SJason Gunthorpe return ret;
659d830d47SAlex Williamson }
669d830d47SAlex Williamson
kvm_vfio_file_is_valid(struct file * file)67b1a59be8SYi Liu static bool kvm_vfio_file_is_valid(struct file *file)
684b22ef04SJason Gunthorpe {
694b22ef04SJason Gunthorpe bool (*fn)(struct file *file);
704b22ef04SJason Gunthorpe bool ret;
714b22ef04SJason Gunthorpe
72b1a59be8SYi Liu fn = symbol_get(vfio_file_is_valid);
734b22ef04SJason Gunthorpe if (!fn)
744b22ef04SJason Gunthorpe return false;
754b22ef04SJason Gunthorpe
764b22ef04SJason Gunthorpe ret = fn(file);
774b22ef04SJason Gunthorpe
78b1a59be8SYi Liu symbol_put(vfio_file_is_valid);
794b22ef04SJason Gunthorpe
804b22ef04SJason Gunthorpe return ret;
814b22ef04SJason Gunthorpe }
824b22ef04SJason Gunthorpe
834b22ef04SJason Gunthorpe #ifdef CONFIG_SPAPR_TCE_IOMMU
kvm_vfio_file_iommu_group(struct file * file)8450d63b5bSJason Gunthorpe static struct iommu_group *kvm_vfio_file_iommu_group(struct file *file)
85121f80baSAlexey Kardashevskiy {
8650d63b5bSJason Gunthorpe struct iommu_group *(*fn)(struct file *file);
8750d63b5bSJason Gunthorpe struct iommu_group *ret;
88121f80baSAlexey Kardashevskiy
8950d63b5bSJason Gunthorpe fn = symbol_get(vfio_file_iommu_group);
90121f80baSAlexey Kardashevskiy if (!fn)
91121f80baSAlexey Kardashevskiy return NULL;
92121f80baSAlexey Kardashevskiy
9350d63b5bSJason Gunthorpe ret = fn(file);
9450d63b5bSJason Gunthorpe
9550d63b5bSJason Gunthorpe symbol_put(vfio_file_iommu_group);
9650d63b5bSJason Gunthorpe
9750d63b5bSJason Gunthorpe return ret;
98121f80baSAlexey Kardashevskiy }
99121f80baSAlexey Kardashevskiy
kvm_spapr_tce_release_vfio_group(struct kvm * kvm,struct kvm_vfio_file * kvf)100121f80baSAlexey Kardashevskiy static void kvm_spapr_tce_release_vfio_group(struct kvm *kvm,
1012f99073aSYi Liu struct kvm_vfio_file *kvf)
102121f80baSAlexey Kardashevskiy {
1032f99073aSYi Liu if (WARN_ON_ONCE(!kvf->iommu_group))
104121f80baSAlexey Kardashevskiy return;
105121f80baSAlexey Kardashevskiy
1062f99073aSYi Liu kvm_spapr_tce_release_iommu_group(kvm, kvf->iommu_group);
1072f99073aSYi Liu iommu_group_put(kvf->iommu_group);
1082f99073aSYi Liu kvf->iommu_group = NULL;
109121f80baSAlexey Kardashevskiy }
110121f80baSAlexey Kardashevskiy #endif
111121f80baSAlexey Kardashevskiy
112e0f0bbc5SAlex Williamson /*
1132f99073aSYi Liu * Groups/devices can use the same or different IOMMU domains. If the same
1142f99073aSYi Liu * then adding a new group/device may change the coherency of groups/devices
1152f99073aSYi Liu * we've previously been told about. We don't want to care about any of
1162f99073aSYi Liu * that so we retest each group/device and bail as soon as we find one that's
1172f99073aSYi Liu * noncoherent. This means we only ever [un]register_noncoherent_dma once
1182f99073aSYi Liu * for the whole device.
119e0f0bbc5SAlex Williamson */
kvm_vfio_update_coherency(struct kvm_device * dev)120e0f0bbc5SAlex Williamson static void kvm_vfio_update_coherency(struct kvm_device *dev)
121e0f0bbc5SAlex Williamson {
122e0f0bbc5SAlex Williamson struct kvm_vfio *kv = dev->private;
123e0f0bbc5SAlex Williamson bool noncoherent = false;
1242f99073aSYi Liu struct kvm_vfio_file *kvf;
125e0f0bbc5SAlex Williamson
1262f99073aSYi Liu list_for_each_entry(kvf, &kv->file_list, node) {
1272f99073aSYi Liu if (!kvm_vfio_file_enforced_coherent(kvf->file)) {
128e0f0bbc5SAlex Williamson noncoherent = true;
129e0f0bbc5SAlex Williamson break;
130e0f0bbc5SAlex Williamson }
1319d830d47SAlex Williamson }
132e0f0bbc5SAlex Williamson
133e0f0bbc5SAlex Williamson if (noncoherent != kv->noncoherent) {
134e0f0bbc5SAlex Williamson kv->noncoherent = noncoherent;
135e0f0bbc5SAlex Williamson
136e0f0bbc5SAlex Williamson if (kv->noncoherent)
137e0f0bbc5SAlex Williamson kvm_arch_register_noncoherent_dma(dev->kvm);
138e0f0bbc5SAlex Williamson else
139e0f0bbc5SAlex Williamson kvm_arch_unregister_noncoherent_dma(dev->kvm);
140e0f0bbc5SAlex Williamson }
141e0f0bbc5SAlex Williamson }
142e0f0bbc5SAlex Williamson
kvm_vfio_file_add(struct kvm_device * dev,unsigned int fd)1432f99073aSYi Liu static int kvm_vfio_file_add(struct kvm_device *dev, unsigned int fd)
144ec53500fSAlex Williamson {
145ec53500fSAlex Williamson struct kvm_vfio *kv = dev->private;
1462f99073aSYi Liu struct kvm_vfio_file *kvf;
147d55d9e7aSJason Gunthorpe struct file *filp;
148*73e2f19dSDmitry Torokhov int ret = 0;
149ec53500fSAlex Williamson
150d55d9e7aSJason Gunthorpe filp = fget(fd);
151d55d9e7aSJason Gunthorpe if (!filp)
152ec53500fSAlex Williamson return -EBADF;
153ec53500fSAlex Williamson
154b1a59be8SYi Liu /* Ensure the FD is a vfio FD. */
155b1a59be8SYi Liu if (!kvm_vfio_file_is_valid(filp)) {
1563e5449d5SJason Gunthorpe ret = -EINVAL;
157*73e2f19dSDmitry Torokhov goto out_fput;
1583e5449d5SJason Gunthorpe }
1593e5449d5SJason Gunthorpe
160ec53500fSAlex Williamson mutex_lock(&kv->lock);
161ec53500fSAlex Williamson
1622f99073aSYi Liu list_for_each_entry(kvf, &kv->file_list, node) {
1632f99073aSYi Liu if (kvf->file == filp) {
16473b0565fSJason Gunthorpe ret = -EEXIST;
165*73e2f19dSDmitry Torokhov goto out_unlock;
166ec53500fSAlex Williamson }
167ec53500fSAlex Williamson }
168ec53500fSAlex Williamson
1692f99073aSYi Liu kvf = kzalloc(sizeof(*kvf), GFP_KERNEL_ACCOUNT);
1702f99073aSYi Liu if (!kvf) {
17173b0565fSJason Gunthorpe ret = -ENOMEM;
172*73e2f19dSDmitry Torokhov goto out_unlock;
173ec53500fSAlex Williamson }
174ec53500fSAlex Williamson
175*73e2f19dSDmitry Torokhov kvf->file = get_file(filp);
1762f99073aSYi Liu list_add_tail(&kvf->node, &kv->file_list);
177ec53500fSAlex Williamson
1785544eb9bSPaolo Bonzini kvm_arch_start_assignment(dev->kvm);
1799e0f4f29SDmitry Torokhov kvm_vfio_file_set_kvm(kvf->file, dev->kvm);
180e0f0bbc5SAlex Williamson kvm_vfio_update_coherency(dev);
181e0f0bbc5SAlex Williamson
182*73e2f19dSDmitry Torokhov out_unlock:
18373b0565fSJason Gunthorpe mutex_unlock(&kv->lock);
184*73e2f19dSDmitry Torokhov out_fput:
185d55d9e7aSJason Gunthorpe fput(filp);
18673b0565fSJason Gunthorpe return ret;
18773b0565fSJason Gunthorpe }
188ec53500fSAlex Williamson
kvm_vfio_file_del(struct kvm_device * dev,unsigned int fd)1892f99073aSYi Liu static int kvm_vfio_file_del(struct kvm_device *dev, unsigned int fd)
19073b0565fSJason Gunthorpe {
19173b0565fSJason Gunthorpe struct kvm_vfio *kv = dev->private;
1922f99073aSYi Liu struct kvm_vfio_file *kvf;
19373b0565fSJason Gunthorpe struct fd f;
19473b0565fSJason Gunthorpe int ret;
195ec53500fSAlex Williamson
196ec53500fSAlex Williamson f = fdget(fd);
197ec53500fSAlex Williamson if (!f.file)
198ec53500fSAlex Williamson return -EBADF;
199ec53500fSAlex Williamson
200ec53500fSAlex Williamson ret = -ENOENT;
201ec53500fSAlex Williamson
202ec53500fSAlex Williamson mutex_lock(&kv->lock);
203ec53500fSAlex Williamson
2042f99073aSYi Liu list_for_each_entry(kvf, &kv->file_list, node) {
2052f99073aSYi Liu if (kvf->file != f.file)
206ec53500fSAlex Williamson continue;
207ec53500fSAlex Williamson
2082f99073aSYi Liu list_del(&kvf->node);
209e323369bSAlex Williamson kvm_arch_end_assignment(dev->kvm);
210e323369bSAlex Williamson #ifdef CONFIG_SPAPR_TCE_IOMMU
2112f99073aSYi Liu kvm_spapr_tce_release_vfio_group(dev->kvm, kvf);
212e323369bSAlex Williamson #endif
2132f99073aSYi Liu kvm_vfio_file_set_kvm(kvf->file, NULL);
2142f99073aSYi Liu fput(kvf->file);
2152f99073aSYi Liu kfree(kvf);
216ec53500fSAlex Williamson ret = 0;
217ec53500fSAlex Williamson break;
218ec53500fSAlex Williamson }
219ec53500fSAlex Williamson
220*73e2f19dSDmitry Torokhov kvm_vfio_update_coherency(dev);
221*73e2f19dSDmitry Torokhov
222ec53500fSAlex Williamson mutex_unlock(&kv->lock);
223ec53500fSAlex Williamson
2245d6dee80SAlex Williamson fdput(f);
225ec53500fSAlex Williamson
226ec53500fSAlex Williamson return ret;
22773b0565fSJason Gunthorpe }
228121f80baSAlexey Kardashevskiy
229121f80baSAlexey Kardashevskiy #ifdef CONFIG_SPAPR_TCE_IOMMU
kvm_vfio_file_set_spapr_tce(struct kvm_device * dev,void __user * arg)2302f99073aSYi Liu static int kvm_vfio_file_set_spapr_tce(struct kvm_device *dev,
23173b0565fSJason Gunthorpe void __user *arg)
23273b0565fSJason Gunthorpe {
233121f80baSAlexey Kardashevskiy struct kvm_vfio_spapr_tce param;
234121f80baSAlexey Kardashevskiy struct kvm_vfio *kv = dev->private;
2352f99073aSYi Liu struct kvm_vfio_file *kvf;
236121f80baSAlexey Kardashevskiy struct fd f;
23773b0565fSJason Gunthorpe int ret;
238121f80baSAlexey Kardashevskiy
23973b0565fSJason Gunthorpe if (copy_from_user(¶m, arg, sizeof(struct kvm_vfio_spapr_tce)))
240121f80baSAlexey Kardashevskiy return -EFAULT;
241121f80baSAlexey Kardashevskiy
242121f80baSAlexey Kardashevskiy f = fdget(param.groupfd);
243121f80baSAlexey Kardashevskiy if (!f.file)
244121f80baSAlexey Kardashevskiy return -EBADF;
245121f80baSAlexey Kardashevskiy
246121f80baSAlexey Kardashevskiy ret = -ENOENT;
247121f80baSAlexey Kardashevskiy
248121f80baSAlexey Kardashevskiy mutex_lock(&kv->lock);
249121f80baSAlexey Kardashevskiy
2502f99073aSYi Liu list_for_each_entry(kvf, &kv->file_list, node) {
2512f99073aSYi Liu if (kvf->file != f.file)
252121f80baSAlexey Kardashevskiy continue;
253121f80baSAlexey Kardashevskiy
2542f99073aSYi Liu if (!kvf->iommu_group) {
2552f99073aSYi Liu kvf->iommu_group = kvm_vfio_file_iommu_group(kvf->file);
2562f99073aSYi Liu if (WARN_ON_ONCE(!kvf->iommu_group)) {
257d55d9e7aSJason Gunthorpe ret = -EIO;
258d55d9e7aSJason Gunthorpe goto err_fdput;
259d55d9e7aSJason Gunthorpe }
260819da99aSJason Gunthorpe }
261d55d9e7aSJason Gunthorpe
26273b0565fSJason Gunthorpe ret = kvm_spapr_tce_attach_iommu_group(dev->kvm, param.tablefd,
2632f99073aSYi Liu kvf->iommu_group);
264121f80baSAlexey Kardashevskiy break;
265121f80baSAlexey Kardashevskiy }
266121f80baSAlexey Kardashevskiy
267d55d9e7aSJason Gunthorpe err_fdput:
2686b17ca8eSWan Jiabing mutex_unlock(&kv->lock);
269d55d9e7aSJason Gunthorpe fdput(f);
270121f80baSAlexey Kardashevskiy return ret;
271121f80baSAlexey Kardashevskiy }
27273b0565fSJason Gunthorpe #endif
27373b0565fSJason Gunthorpe
kvm_vfio_set_file(struct kvm_device * dev,long attr,void __user * arg)2742f99073aSYi Liu static int kvm_vfio_set_file(struct kvm_device *dev, long attr,
27573b0565fSJason Gunthorpe void __user *arg)
27673b0565fSJason Gunthorpe {
27773b0565fSJason Gunthorpe int32_t __user *argp = arg;
27873b0565fSJason Gunthorpe int32_t fd;
27973b0565fSJason Gunthorpe
28073b0565fSJason Gunthorpe switch (attr) {
281dcc31ea6SYi Liu case KVM_DEV_VFIO_FILE_ADD:
28273b0565fSJason Gunthorpe if (get_user(fd, argp))
28373b0565fSJason Gunthorpe return -EFAULT;
2842f99073aSYi Liu return kvm_vfio_file_add(dev, fd);
28573b0565fSJason Gunthorpe
286dcc31ea6SYi Liu case KVM_DEV_VFIO_FILE_DEL:
28773b0565fSJason Gunthorpe if (get_user(fd, argp))
28873b0565fSJason Gunthorpe return -EFAULT;
2892f99073aSYi Liu return kvm_vfio_file_del(dev, fd);
29073b0565fSJason Gunthorpe
29173b0565fSJason Gunthorpe #ifdef CONFIG_SPAPR_TCE_IOMMU
29273b0565fSJason Gunthorpe case KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE:
2932f99073aSYi Liu return kvm_vfio_file_set_spapr_tce(dev, arg);
29473b0565fSJason Gunthorpe #endif
295ec53500fSAlex Williamson }
296ec53500fSAlex Williamson
297ec53500fSAlex Williamson return -ENXIO;
298ec53500fSAlex Williamson }
299ec53500fSAlex Williamson
kvm_vfio_set_attr(struct kvm_device * dev,struct kvm_device_attr * attr)300ec53500fSAlex Williamson static int kvm_vfio_set_attr(struct kvm_device *dev,
301ec53500fSAlex Williamson struct kvm_device_attr *attr)
302ec53500fSAlex Williamson {
303ec53500fSAlex Williamson switch (attr->group) {
304dcc31ea6SYi Liu case KVM_DEV_VFIO_FILE:
3052f99073aSYi Liu return kvm_vfio_set_file(dev, attr->attr,
30673b0565fSJason Gunthorpe u64_to_user_ptr(attr->addr));
307ec53500fSAlex Williamson }
308ec53500fSAlex Williamson
309ec53500fSAlex Williamson return -ENXIO;
310ec53500fSAlex Williamson }
311ec53500fSAlex Williamson
kvm_vfio_has_attr(struct kvm_device * dev,struct kvm_device_attr * attr)312ec53500fSAlex Williamson static int kvm_vfio_has_attr(struct kvm_device *dev,
313ec53500fSAlex Williamson struct kvm_device_attr *attr)
314ec53500fSAlex Williamson {
315ec53500fSAlex Williamson switch (attr->group) {
316dcc31ea6SYi Liu case KVM_DEV_VFIO_FILE:
317ec53500fSAlex Williamson switch (attr->attr) {
318dcc31ea6SYi Liu case KVM_DEV_VFIO_FILE_ADD:
319dcc31ea6SYi Liu case KVM_DEV_VFIO_FILE_DEL:
320121f80baSAlexey Kardashevskiy #ifdef CONFIG_SPAPR_TCE_IOMMU
321121f80baSAlexey Kardashevskiy case KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE:
322121f80baSAlexey Kardashevskiy #endif
323ec53500fSAlex Williamson return 0;
324ec53500fSAlex Williamson }
325ec53500fSAlex Williamson
326ec53500fSAlex Williamson break;
327ec53500fSAlex Williamson }
328ec53500fSAlex Williamson
329ec53500fSAlex Williamson return -ENXIO;
330ec53500fSAlex Williamson }
331ec53500fSAlex Williamson
kvm_vfio_release(struct kvm_device * dev)33251cdc8bcSYi Liu static void kvm_vfio_release(struct kvm_device *dev)
333ec53500fSAlex Williamson {
334ec53500fSAlex Williamson struct kvm_vfio *kv = dev->private;
3352f99073aSYi Liu struct kvm_vfio_file *kvf, *tmp;
336ec53500fSAlex Williamson
3372f99073aSYi Liu list_for_each_entry_safe(kvf, tmp, &kv->file_list, node) {
338121f80baSAlexey Kardashevskiy #ifdef CONFIG_SPAPR_TCE_IOMMU
3392f99073aSYi Liu kvm_spapr_tce_release_vfio_group(dev->kvm, kvf);
340121f80baSAlexey Kardashevskiy #endif
3412f99073aSYi Liu kvm_vfio_file_set_kvm(kvf->file, NULL);
3422f99073aSYi Liu fput(kvf->file);
3432f99073aSYi Liu list_del(&kvf->node);
3442f99073aSYi Liu kfree(kvf);
3455544eb9bSPaolo Bonzini kvm_arch_end_assignment(dev->kvm);
346ec53500fSAlex Williamson }
347ec53500fSAlex Williamson
348e0f0bbc5SAlex Williamson kvm_vfio_update_coherency(dev);
349e0f0bbc5SAlex Williamson
350ec53500fSAlex Williamson kfree(kv);
35151cdc8bcSYi Liu kfree(dev); /* alloc by kvm_ioctl_create_device, free by .release */
352ec53500fSAlex Williamson }
353ec53500fSAlex Williamson
35480ce1639SWill Deacon static int kvm_vfio_create(struct kvm_device *dev, u32 type);
35580ce1639SWill Deacon
35680ce1639SWill Deacon static struct kvm_device_ops kvm_vfio_ops = {
35780ce1639SWill Deacon .name = "kvm-vfio",
35880ce1639SWill Deacon .create = kvm_vfio_create,
35951cdc8bcSYi Liu .release = kvm_vfio_release,
36080ce1639SWill Deacon .set_attr = kvm_vfio_set_attr,
36180ce1639SWill Deacon .has_attr = kvm_vfio_has_attr,
36280ce1639SWill Deacon };
36380ce1639SWill Deacon
kvm_vfio_create(struct kvm_device * dev,u32 type)364ec53500fSAlex Williamson static int kvm_vfio_create(struct kvm_device *dev, u32 type)
365ec53500fSAlex Williamson {
366ec53500fSAlex Williamson struct kvm_device *tmp;
367ec53500fSAlex Williamson struct kvm_vfio *kv;
368ec53500fSAlex Williamson
369ec53500fSAlex Williamson /* Only one VFIO "device" per VM */
370ec53500fSAlex Williamson list_for_each_entry(tmp, &dev->kvm->devices, vm_node)
371ec53500fSAlex Williamson if (tmp->ops == &kvm_vfio_ops)
372ec53500fSAlex Williamson return -EBUSY;
373ec53500fSAlex Williamson
374b12ce36aSBen Gardon kv = kzalloc(sizeof(*kv), GFP_KERNEL_ACCOUNT);
375ec53500fSAlex Williamson if (!kv)
376ec53500fSAlex Williamson return -ENOMEM;
377ec53500fSAlex Williamson
3782f99073aSYi Liu INIT_LIST_HEAD(&kv->file_list);
379ec53500fSAlex Williamson mutex_init(&kv->lock);
380ec53500fSAlex Williamson
381ec53500fSAlex Williamson dev->private = kv;
382ec53500fSAlex Williamson
383ec53500fSAlex Williamson return 0;
384ec53500fSAlex Williamson }
385ec53500fSAlex Williamson
kvm_vfio_ops_init(void)3863c3c29fdSPaolo Bonzini int kvm_vfio_ops_init(void)
38780ce1639SWill Deacon {
38880ce1639SWill Deacon return kvm_register_device_ops(&kvm_vfio_ops, KVM_DEV_TYPE_VFIO);
38980ce1639SWill Deacon }
390571ee1b6SWanpeng Li
kvm_vfio_ops_exit(void)391571ee1b6SWanpeng Li void kvm_vfio_ops_exit(void)
392571ee1b6SWanpeng Li {
393571ee1b6SWanpeng Li kvm_unregister_device_ops(KVM_DEV_TYPE_VFIO);
394571ee1b6SWanpeng Li }
395