diff options
Diffstat (limited to 'virt/kvm/kvm_main.c')
-rw-r--r-- | virt/kvm/kvm_main.c | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index fc6127cbea1f..3a5a08298aab 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -496,6 +496,7 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm, | |||
496 | match->assigned_dev_id = assigned_dev->assigned_dev_id; | 496 | match->assigned_dev_id = assigned_dev->assigned_dev_id; |
497 | match->host_busnr = assigned_dev->busnr; | 497 | match->host_busnr = assigned_dev->busnr; |
498 | match->host_devfn = assigned_dev->devfn; | 498 | match->host_devfn = assigned_dev->devfn; |
499 | match->flags = assigned_dev->flags; | ||
499 | match->dev = dev; | 500 | match->dev = dev; |
500 | match->irq_source_id = -1; | 501 | match->irq_source_id = -1; |
501 | match->kvm = kvm; | 502 | match->kvm = kvm; |
@@ -503,7 +504,12 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm, | |||
503 | list_add(&match->list, &kvm->arch.assigned_dev_head); | 504 | list_add(&match->list, &kvm->arch.assigned_dev_head); |
504 | 505 | ||
505 | if (assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU) { | 506 | if (assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU) { |
506 | r = kvm_iommu_map_guest(kvm, match); | 507 | if (!kvm->arch.iommu_domain) { |
508 | r = kvm_iommu_map_guest(kvm); | ||
509 | if (r) | ||
510 | goto out_list_del; | ||
511 | } | ||
512 | r = kvm_assign_device(kvm, match); | ||
507 | if (r) | 513 | if (r) |
508 | goto out_list_del; | 514 | goto out_list_del; |
509 | } | 515 | } |
@@ -525,6 +531,35 @@ out_free: | |||
525 | } | 531 | } |
526 | #endif | 532 | #endif |
527 | 533 | ||
534 | #ifdef KVM_CAP_DEVICE_DEASSIGNMENT | ||
535 | static int kvm_vm_ioctl_deassign_device(struct kvm *kvm, | ||
536 | struct kvm_assigned_pci_dev *assigned_dev) | ||
537 | { | ||
538 | int r = 0; | ||
539 | struct kvm_assigned_dev_kernel *match; | ||
540 | |||
541 | mutex_lock(&kvm->lock); | ||
542 | |||
543 | match = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head, | ||
544 | assigned_dev->assigned_dev_id); | ||
545 | if (!match) { | ||
546 | printk(KERN_INFO "%s: device hasn't been assigned before, " | ||
547 | "so cannot be deassigned\n", __func__); | ||
548 | r = -EINVAL; | ||
549 | goto out; | ||
550 | } | ||
551 | |||
552 | if (assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU) | ||
553 | kvm_deassign_device(kvm, match); | ||
554 | |||
555 | kvm_free_assigned_device(kvm, match); | ||
556 | |||
557 | out: | ||
558 | mutex_unlock(&kvm->lock); | ||
559 | return r; | ||
560 | } | ||
561 | #endif | ||
562 | |||
528 | static inline int valid_vcpu(int n) | 563 | static inline int valid_vcpu(int n) |
529 | { | 564 | { |
530 | return likely(n >= 0 && n < KVM_MAX_VCPUS); | 565 | return likely(n >= 0 && n < KVM_MAX_VCPUS); |
@@ -1858,6 +1893,19 @@ static long kvm_vm_ioctl(struct file *filp, | |||
1858 | break; | 1893 | break; |
1859 | } | 1894 | } |
1860 | #endif | 1895 | #endif |
1896 | #ifdef KVM_CAP_DEVICE_DEASSIGNMENT | ||
1897 | case KVM_DEASSIGN_PCI_DEVICE: { | ||
1898 | struct kvm_assigned_pci_dev assigned_dev; | ||
1899 | |||
1900 | r = -EFAULT; | ||
1901 | if (copy_from_user(&assigned_dev, argp, sizeof assigned_dev)) | ||
1902 | goto out; | ||
1903 | r = kvm_vm_ioctl_deassign_device(kvm, &assigned_dev); | ||
1904 | if (r) | ||
1905 | goto out; | ||
1906 | break; | ||
1907 | } | ||
1908 | #endif | ||
1861 | default: | 1909 | default: |
1862 | r = kvm_arch_vm_ioctl(filp, ioctl, arg); | 1910 | r = kvm_arch_vm_ioctl(filp, ioctl, arg); |
1863 | } | 1911 | } |