aboutsummaryrefslogtreecommitdiffstats
path: root/virt/kvm/vfio.c
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2013-10-30 13:02:30 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2013-10-30 14:02:23 -0400
commite0f0bbc527f6e9c0261f1d16b2a0b47612b7f235 (patch)
tree623b954e7571767c4d5f0581ad8ba6eacd48785d /virt/kvm/vfio.c
parentd96eb2c6f480769bff32054e78b964860dae4d56 (diff)
kvm: Create non-coherent DMA registeration
We currently use some ad-hoc arch variables tied to legacy KVM device assignment to manage emulation of instructions that depend on whether non-coherent DMA is present. Create an interface for this, adapting legacy KVM device assignment and adding VFIO via the KVM-VFIO device. For now we assume that non-coherent DMA is possible any time we have a VFIO group. Eventually an interface can be developed as part of the VFIO external user interface to query the coherency of a group. Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'virt/kvm/vfio.c')
-rw-r--r--virt/kvm/vfio.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/virt/kvm/vfio.c b/virt/kvm/vfio.c
index 597c258245ea..ca4260e35037 100644
--- a/virt/kvm/vfio.c
+++ b/virt/kvm/vfio.c
@@ -27,6 +27,7 @@ struct kvm_vfio_group {
27struct kvm_vfio { 27struct kvm_vfio {
28 struct list_head group_list; 28 struct list_head group_list;
29 struct mutex lock; 29 struct mutex lock;
30 bool noncoherent;
30}; 31};
31 32
32static struct vfio_group *kvm_vfio_group_get_external_user(struct file *filep) 33static struct vfio_group *kvm_vfio_group_get_external_user(struct file *filep)
@@ -58,6 +59,43 @@ static void kvm_vfio_group_put_external_user(struct vfio_group *vfio_group)
58 symbol_put(vfio_group_put_external_user); 59 symbol_put(vfio_group_put_external_user);
59} 60}
60 61
62/*
63 * Groups can use the same or different IOMMU domains. If the same then
64 * adding a new group may change the coherency of groups we've previously
65 * been told about. We don't want to care about any of that so we retest
66 * each group and bail as soon as we find one that's noncoherent. This
67 * means we only ever [un]register_noncoherent_dma once for the whole device.
68 */
69static void kvm_vfio_update_coherency(struct kvm_device *dev)
70{
71 struct kvm_vfio *kv = dev->private;
72 bool noncoherent = false;
73 struct kvm_vfio_group *kvg;
74
75 mutex_lock(&kv->lock);
76
77 list_for_each_entry(kvg, &kv->group_list, node) {
78 /*
79 * TODO: We need an interface to check the coherency of
80 * the IOMMU domain this group is using. For now, assume
81 * it's always noncoherent.
82 */
83 noncoherent = true;
84 break;
85 }
86
87 if (noncoherent != kv->noncoherent) {
88 kv->noncoherent = noncoherent;
89
90 if (kv->noncoherent)
91 kvm_arch_register_noncoherent_dma(dev->kvm);
92 else
93 kvm_arch_unregister_noncoherent_dma(dev->kvm);
94 }
95
96 mutex_unlock(&kv->lock);
97}
98
61static int kvm_vfio_set_group(struct kvm_device *dev, long attr, u64 arg) 99static int kvm_vfio_set_group(struct kvm_device *dev, long attr, u64 arg)
62{ 100{
63 struct kvm_vfio *kv = dev->private; 101 struct kvm_vfio *kv = dev->private;
@@ -105,6 +143,8 @@ static int kvm_vfio_set_group(struct kvm_device *dev, long attr, u64 arg)
105 143
106 mutex_unlock(&kv->lock); 144 mutex_unlock(&kv->lock);
107 145
146 kvm_vfio_update_coherency(dev);
147
108 return 0; 148 return 0;
109 149
110 case KVM_DEV_VFIO_GROUP_DEL: 150 case KVM_DEV_VFIO_GROUP_DEL:
@@ -140,6 +180,8 @@ static int kvm_vfio_set_group(struct kvm_device *dev, long attr, u64 arg)
140 180
141 kvm_vfio_group_put_external_user(vfio_group); 181 kvm_vfio_group_put_external_user(vfio_group);
142 182
183 kvm_vfio_update_coherency(dev);
184
143 return ret; 185 return ret;
144 } 186 }
145 187
@@ -185,6 +227,8 @@ static void kvm_vfio_destroy(struct kvm_device *dev)
185 kfree(kvg); 227 kfree(kvg);
186 } 228 }
187 229
230 kvm_vfio_update_coherency(dev);
231
188 kfree(kv); 232 kfree(kv);
189 kfree(dev); /* alloc by kvm_ioctl_create_device, free by .destroy */ 233 kfree(dev); /* alloc by kvm_ioctl_create_device, free by .destroy */
190} 234}