aboutsummaryrefslogtreecommitdiffstats
path: root/virt/kvm/kvm_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'virt/kvm/kvm_main.c')
-rw-r--r--virt/kvm/kvm_main.c68
1 files changed, 38 insertions, 30 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 8966fd13e848..ef2f03cf42c0 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -176,6 +176,41 @@ void kvm_free_all_assigned_devices(struct kvm *kvm)
176 } 176 }
177} 177}
178 178
179static int assigned_device_update_intx(struct kvm *kvm,
180 struct kvm_assigned_dev_kernel *adev,
181 struct kvm_assigned_irq *airq)
182{
183 if (adev->irq_requested) {
184 adev->guest_irq = airq->guest_irq;
185 adev->ack_notifier.gsi = airq->guest_irq;
186 return 0;
187 }
188
189 if (irqchip_in_kernel(kvm)) {
190 if (!capable(CAP_SYS_RAWIO))
191 return -EPERM;
192
193 if (airq->host_irq)
194 adev->host_irq = airq->host_irq;
195 else
196 adev->host_irq = adev->dev->irq;
197 adev->guest_irq = airq->guest_irq;
198 adev->ack_notifier.gsi = airq->guest_irq;
199
200 /* Even though this is PCI, we don't want to use shared
201 * interrupts. Sharing host devices with guest-assigned devices
202 * on the same interrupt line is not a happy situation: there
203 * are going to be long delays in accepting, acking, etc.
204 */
205 if (request_irq(adev->host_irq, kvm_assigned_dev_intr,
206 0, "kvm_assigned_intx_device", (void *)adev))
207 return -EIO;
208 }
209
210 adev->irq_requested = true;
211 return 0;
212}
213
179static int kvm_vm_ioctl_assign_irq(struct kvm *kvm, 214static int kvm_vm_ioctl_assign_irq(struct kvm *kvm,
180 struct kvm_assigned_irq 215 struct kvm_assigned_irq
181 *assigned_irq) 216 *assigned_irq)
@@ -210,39 +245,12 @@ static int kvm_vm_ioctl_assign_irq(struct kvm *kvm,
210 else 245 else
211 match->irq_source_id = r; 246 match->irq_source_id = r;
212 } 247 }
213 } else {
214 match->guest_irq = assigned_irq->guest_irq;
215 match->ack_notifier.gsi = assigned_irq->guest_irq;
216 mutex_unlock(&kvm->lock);
217 return 0;
218 } 248 }
219 249
220 if (irqchip_in_kernel(kvm)) { 250 r = assigned_device_update_intx(kvm, match, assigned_irq);
221 if (!capable(CAP_SYS_RAWIO)) { 251 if (r)
222 r = -EPERM; 252 goto out_release;
223 goto out_release;
224 }
225
226 if (assigned_irq->host_irq)
227 match->host_irq = assigned_irq->host_irq;
228 else
229 match->host_irq = match->dev->irq;
230 match->guest_irq = assigned_irq->guest_irq;
231 match->ack_notifier.gsi = assigned_irq->guest_irq;
232
233 /* Even though this is PCI, we don't want to use shared
234 * interrupts. Sharing host devices with guest-assigned devices
235 * on the same interrupt line is not a happy situation: there
236 * are going to be long delays in accepting, acking, etc.
237 */
238 if (request_irq(match->host_irq, kvm_assigned_dev_intr, 0,
239 "kvm_assigned_device", (void *)match)) {
240 r = -EIO;
241 goto out_release;
242 }
243 }
244 253
245 match->irq_requested = true;
246 mutex_unlock(&kvm->lock); 254 mutex_unlock(&kvm->lock);
247 return r; 255 return r;
248out_release: 256out_release: