diff options
author | Alex Williamson <alex.williamson@redhat.com> | 2013-10-30 13:02:30 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2013-10-30 14:02:23 -0400 |
commit | e0f0bbc527f6e9c0261f1d16b2a0b47612b7f235 (patch) | |
tree | 623b954e7571767c4d5f0581ad8ba6eacd48785d /virt/kvm/vfio.c | |
parent | d96eb2c6f480769bff32054e78b964860dae4d56 (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.c | 44 |
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 { | |||
27 | struct kvm_vfio { | 27 | struct 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 | ||
32 | static struct vfio_group *kvm_vfio_group_get_external_user(struct file *filep) | 33 | static 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 | */ | ||
69 | static 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 | |||
61 | static int kvm_vfio_set_group(struct kvm_device *dev, long attr, u64 arg) | 99 | static 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 | } |