Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/virt/kvm/vfio.c
26278 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* VFIO-KVM bridge pseudo device
4
*
5
* Copyright (C) 2013 Red Hat, Inc. All rights reserved.
6
* Author: Alex Williamson <[email protected]>
7
*/
8
9
#include <linux/errno.h>
10
#include <linux/file.h>
11
#include <linux/kvm_host.h>
12
#include <linux/list.h>
13
#include <linux/module.h>
14
#include <linux/mutex.h>
15
#include <linux/slab.h>
16
#include <linux/uaccess.h>
17
#include <linux/vfio.h>
18
#include "vfio.h"
19
20
#ifdef CONFIG_SPAPR_TCE_IOMMU
21
#include <asm/kvm_ppc.h>
22
#endif
23
24
struct kvm_vfio_file {
25
struct list_head node;
26
struct file *file;
27
#ifdef CONFIG_SPAPR_TCE_IOMMU
28
struct iommu_group *iommu_group;
29
#endif
30
};
31
32
struct kvm_vfio {
33
struct list_head file_list;
34
struct mutex lock;
35
bool noncoherent;
36
};
37
38
static void kvm_vfio_file_set_kvm(struct file *file, struct kvm *kvm)
39
{
40
void (*fn)(struct file *file, struct kvm *kvm);
41
42
fn = symbol_get(vfio_file_set_kvm);
43
if (!fn)
44
return;
45
46
fn(file, kvm);
47
48
symbol_put(vfio_file_set_kvm);
49
}
50
51
static bool kvm_vfio_file_enforced_coherent(struct file *file)
52
{
53
bool (*fn)(struct file *file);
54
bool ret;
55
56
fn = symbol_get(vfio_file_enforced_coherent);
57
if (!fn)
58
return false;
59
60
ret = fn(file);
61
62
symbol_put(vfio_file_enforced_coherent);
63
64
return ret;
65
}
66
67
static bool kvm_vfio_file_is_valid(struct file *file)
68
{
69
bool (*fn)(struct file *file);
70
bool ret;
71
72
fn = symbol_get(vfio_file_is_valid);
73
if (!fn)
74
return false;
75
76
ret = fn(file);
77
78
symbol_put(vfio_file_is_valid);
79
80
return ret;
81
}
82
83
#ifdef CONFIG_SPAPR_TCE_IOMMU
84
static struct iommu_group *kvm_vfio_file_iommu_group(struct file *file)
85
{
86
struct iommu_group *(*fn)(struct file *file);
87
struct iommu_group *ret;
88
89
fn = symbol_get(vfio_file_iommu_group);
90
if (!fn)
91
return NULL;
92
93
ret = fn(file);
94
95
symbol_put(vfio_file_iommu_group);
96
97
return ret;
98
}
99
100
static void kvm_spapr_tce_release_vfio_group(struct kvm *kvm,
101
struct kvm_vfio_file *kvf)
102
{
103
if (WARN_ON_ONCE(!kvf->iommu_group))
104
return;
105
106
kvm_spapr_tce_release_iommu_group(kvm, kvf->iommu_group);
107
iommu_group_put(kvf->iommu_group);
108
kvf->iommu_group = NULL;
109
}
110
#endif
111
112
/*
113
* Groups/devices can use the same or different IOMMU domains. If the same
114
* then adding a new group/device may change the coherency of groups/devices
115
* we've previously been told about. We don't want to care about any of
116
* that so we retest each group/device and bail as soon as we find one that's
117
* noncoherent. This means we only ever [un]register_noncoherent_dma once
118
* for the whole device.
119
*/
120
static void kvm_vfio_update_coherency(struct kvm_device *dev)
121
{
122
struct kvm_vfio *kv = dev->private;
123
bool noncoherent = false;
124
struct kvm_vfio_file *kvf;
125
126
list_for_each_entry(kvf, &kv->file_list, node) {
127
if (!kvm_vfio_file_enforced_coherent(kvf->file)) {
128
noncoherent = true;
129
break;
130
}
131
}
132
133
if (noncoherent != kv->noncoherent) {
134
kv->noncoherent = noncoherent;
135
136
if (kv->noncoherent)
137
kvm_arch_register_noncoherent_dma(dev->kvm);
138
else
139
kvm_arch_unregister_noncoherent_dma(dev->kvm);
140
}
141
}
142
143
static int kvm_vfio_file_add(struct kvm_device *dev, unsigned int fd)
144
{
145
struct kvm_vfio *kv = dev->private;
146
struct kvm_vfio_file *kvf;
147
struct file *filp;
148
int ret = 0;
149
150
filp = fget(fd);
151
if (!filp)
152
return -EBADF;
153
154
/* Ensure the FD is a vfio FD. */
155
if (!kvm_vfio_file_is_valid(filp)) {
156
ret = -EINVAL;
157
goto out_fput;
158
}
159
160
mutex_lock(&kv->lock);
161
162
list_for_each_entry(kvf, &kv->file_list, node) {
163
if (kvf->file == filp) {
164
ret = -EEXIST;
165
goto out_unlock;
166
}
167
}
168
169
kvf = kzalloc(sizeof(*kvf), GFP_KERNEL_ACCOUNT);
170
if (!kvf) {
171
ret = -ENOMEM;
172
goto out_unlock;
173
}
174
175
kvf->file = get_file(filp);
176
list_add_tail(&kvf->node, &kv->file_list);
177
178
kvm_vfio_file_set_kvm(kvf->file, dev->kvm);
179
kvm_vfio_update_coherency(dev);
180
181
out_unlock:
182
mutex_unlock(&kv->lock);
183
out_fput:
184
fput(filp);
185
return ret;
186
}
187
188
static int kvm_vfio_file_del(struct kvm_device *dev, unsigned int fd)
189
{
190
struct kvm_vfio *kv = dev->private;
191
struct kvm_vfio_file *kvf;
192
CLASS(fd, f)(fd);
193
int ret;
194
195
if (fd_empty(f))
196
return -EBADF;
197
198
ret = -ENOENT;
199
200
mutex_lock(&kv->lock);
201
202
list_for_each_entry(kvf, &kv->file_list, node) {
203
if (kvf->file != fd_file(f))
204
continue;
205
206
list_del(&kvf->node);
207
#ifdef CONFIG_SPAPR_TCE_IOMMU
208
kvm_spapr_tce_release_vfio_group(dev->kvm, kvf);
209
#endif
210
kvm_vfio_file_set_kvm(kvf->file, NULL);
211
fput(kvf->file);
212
kfree(kvf);
213
ret = 0;
214
break;
215
}
216
217
kvm_vfio_update_coherency(dev);
218
219
mutex_unlock(&kv->lock);
220
return ret;
221
}
222
223
#ifdef CONFIG_SPAPR_TCE_IOMMU
224
static int kvm_vfio_file_set_spapr_tce(struct kvm_device *dev,
225
void __user *arg)
226
{
227
struct kvm_vfio_spapr_tce param;
228
struct kvm_vfio *kv = dev->private;
229
struct kvm_vfio_file *kvf;
230
int ret;
231
232
if (copy_from_user(&param, arg, sizeof(struct kvm_vfio_spapr_tce)))
233
return -EFAULT;
234
235
CLASS(fd, f)(param.groupfd);
236
if (fd_empty(f))
237
return -EBADF;
238
239
ret = -ENOENT;
240
241
mutex_lock(&kv->lock);
242
243
list_for_each_entry(kvf, &kv->file_list, node) {
244
if (kvf->file != fd_file(f))
245
continue;
246
247
if (!kvf->iommu_group) {
248
kvf->iommu_group = kvm_vfio_file_iommu_group(kvf->file);
249
if (WARN_ON_ONCE(!kvf->iommu_group)) {
250
ret = -EIO;
251
goto err_fdput;
252
}
253
}
254
255
ret = kvm_spapr_tce_attach_iommu_group(dev->kvm, param.tablefd,
256
kvf->iommu_group);
257
break;
258
}
259
260
err_fdput:
261
mutex_unlock(&kv->lock);
262
return ret;
263
}
264
#endif
265
266
static int kvm_vfio_set_file(struct kvm_device *dev, long attr,
267
void __user *arg)
268
{
269
int32_t __user *argp = arg;
270
int32_t fd;
271
272
switch (attr) {
273
case KVM_DEV_VFIO_FILE_ADD:
274
if (get_user(fd, argp))
275
return -EFAULT;
276
return kvm_vfio_file_add(dev, fd);
277
278
case KVM_DEV_VFIO_FILE_DEL:
279
if (get_user(fd, argp))
280
return -EFAULT;
281
return kvm_vfio_file_del(dev, fd);
282
283
#ifdef CONFIG_SPAPR_TCE_IOMMU
284
case KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE:
285
return kvm_vfio_file_set_spapr_tce(dev, arg);
286
#endif
287
}
288
289
return -ENXIO;
290
}
291
292
static int kvm_vfio_set_attr(struct kvm_device *dev,
293
struct kvm_device_attr *attr)
294
{
295
switch (attr->group) {
296
case KVM_DEV_VFIO_FILE:
297
return kvm_vfio_set_file(dev, attr->attr,
298
u64_to_user_ptr(attr->addr));
299
}
300
301
return -ENXIO;
302
}
303
304
static int kvm_vfio_has_attr(struct kvm_device *dev,
305
struct kvm_device_attr *attr)
306
{
307
switch (attr->group) {
308
case KVM_DEV_VFIO_FILE:
309
switch (attr->attr) {
310
case KVM_DEV_VFIO_FILE_ADD:
311
case KVM_DEV_VFIO_FILE_DEL:
312
#ifdef CONFIG_SPAPR_TCE_IOMMU
313
case KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE:
314
#endif
315
return 0;
316
}
317
318
break;
319
}
320
321
return -ENXIO;
322
}
323
324
static void kvm_vfio_release(struct kvm_device *dev)
325
{
326
struct kvm_vfio *kv = dev->private;
327
struct kvm_vfio_file *kvf, *tmp;
328
329
list_for_each_entry_safe(kvf, tmp, &kv->file_list, node) {
330
#ifdef CONFIG_SPAPR_TCE_IOMMU
331
kvm_spapr_tce_release_vfio_group(dev->kvm, kvf);
332
#endif
333
kvm_vfio_file_set_kvm(kvf->file, NULL);
334
fput(kvf->file);
335
list_del(&kvf->node);
336
kfree(kvf);
337
}
338
339
kvm_vfio_update_coherency(dev);
340
341
kfree(kv);
342
kfree(dev); /* alloc by kvm_ioctl_create_device, free by .release */
343
}
344
345
static int kvm_vfio_create(struct kvm_device *dev, u32 type);
346
347
static const struct kvm_device_ops kvm_vfio_ops = {
348
.name = "kvm-vfio",
349
.create = kvm_vfio_create,
350
.release = kvm_vfio_release,
351
.set_attr = kvm_vfio_set_attr,
352
.has_attr = kvm_vfio_has_attr,
353
};
354
355
static int kvm_vfio_create(struct kvm_device *dev, u32 type)
356
{
357
struct kvm_device *tmp;
358
struct kvm_vfio *kv;
359
360
lockdep_assert_held(&dev->kvm->lock);
361
362
/* Only one VFIO "device" per VM */
363
list_for_each_entry(tmp, &dev->kvm->devices, vm_node)
364
if (tmp->ops == &kvm_vfio_ops)
365
return -EBUSY;
366
367
kv = kzalloc(sizeof(*kv), GFP_KERNEL_ACCOUNT);
368
if (!kv)
369
return -ENOMEM;
370
371
INIT_LIST_HEAD(&kv->file_list);
372
mutex_init(&kv->lock);
373
374
dev->private = kv;
375
376
return 0;
377
}
378
379
int kvm_vfio_ops_init(void)
380
{
381
return kvm_register_device_ops(&kvm_vfio_ops, KVM_DEV_TYPE_VFIO);
382
}
383
384
void kvm_vfio_ops_exit(void)
385
{
386
kvm_unregister_device_ops(KVM_DEV_TYPE_VFIO);
387
}
388
389