aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/kvm_host.h8
-rw-r--r--virt/kvm/kvm_main.c42
-rw-r--r--virt/kvm/vtd.c24
3 files changed, 74 insertions, 0 deletions
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index c96739b4b7a3..ce5d1c17ce26 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -334,6 +334,8 @@ int kvm_iommu_map_guest(struct kvm *kvm);
334int kvm_iommu_unmap_guest(struct kvm *kvm); 334int kvm_iommu_unmap_guest(struct kvm *kvm);
335int kvm_assign_device(struct kvm *kvm, 335int kvm_assign_device(struct kvm *kvm,
336 struct kvm_assigned_dev_kernel *assigned_dev); 336 struct kvm_assigned_dev_kernel *assigned_dev);
337int kvm_deassign_device(struct kvm *kvm,
338 struct kvm_assigned_dev_kernel *assigned_dev);
337#else /* CONFIG_DMAR */ 339#else /* CONFIG_DMAR */
338static inline int kvm_iommu_map_pages(struct kvm *kvm, 340static inline int kvm_iommu_map_pages(struct kvm *kvm,
339 gfn_t base_gfn, 341 gfn_t base_gfn,
@@ -357,6 +359,12 @@ static inline int kvm_assign_device(struct kvm *kvm,
357{ 359{
358 return 0; 360 return 0;
359} 361}
362
363static inline int kvm_deassign_device(struct kvm *kvm,
364 struct kvm_assigned_dev_kernel *assigned_dev)
365{
366 return 0;
367}
360#endif /* CONFIG_DMAR */ 368#endif /* CONFIG_DMAR */
361 369
362static inline void kvm_guest_enter(void) 370static inline void kvm_guest_enter(void)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index c92b63462b79..3238e08e4651 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -530,6 +530,35 @@ out_free:
530} 530}
531#endif 531#endif
532 532
533#ifdef KVM_CAP_DEVICE_DEASSIGNMENT
534static int kvm_vm_ioctl_deassign_device(struct kvm *kvm,
535 struct kvm_assigned_pci_dev *assigned_dev)
536{
537 int r = 0;
538 struct kvm_assigned_dev_kernel *match;
539
540 mutex_lock(&kvm->lock);
541
542 match = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head,
543 assigned_dev->assigned_dev_id);
544 if (!match) {
545 printk(KERN_INFO "%s: device hasn't been assigned before, "
546 "so cannot be deassigned\n", __func__);
547 r = -EINVAL;
548 goto out;
549 }
550
551 if (assigned_dev->flags & KVM_DEV_ASSIGN_ENABLE_IOMMU)
552 kvm_deassign_device(kvm, match);
553
554 kvm_free_assigned_device(kvm, match);
555
556out:
557 mutex_unlock(&kvm->lock);
558 return r;
559}
560#endif
561
533static inline int valid_vcpu(int n) 562static inline int valid_vcpu(int n)
534{ 563{
535 return likely(n >= 0 && n < KVM_MAX_VCPUS); 564 return likely(n >= 0 && n < KVM_MAX_VCPUS);
@@ -1863,6 +1892,19 @@ static long kvm_vm_ioctl(struct file *filp,
1863 break; 1892 break;
1864 } 1893 }
1865#endif 1894#endif
1895#ifdef KVM_CAP_DEVICE_DEASSIGNMENT
1896 case KVM_DEASSIGN_PCI_DEVICE: {
1897 struct kvm_assigned_pci_dev assigned_dev;
1898
1899 r = -EFAULT;
1900 if (copy_from_user(&assigned_dev, argp, sizeof assigned_dev))
1901 goto out;
1902 r = kvm_vm_ioctl_deassign_device(kvm, &assigned_dev);
1903 if (r)
1904 goto out;
1905 break;
1906 }
1907#endif
1866 default: 1908 default:
1867 r = kvm_arch_vm_ioctl(filp, ioctl, arg); 1909 r = kvm_arch_vm_ioctl(filp, ioctl, arg);
1868 } 1910 }
diff --git a/virt/kvm/vtd.c b/virt/kvm/vtd.c
index 44bb58a395a5..174ea1f8cee5 100644
--- a/virt/kvm/vtd.c
+++ b/virt/kvm/vtd.c
@@ -116,6 +116,30 @@ int kvm_assign_device(struct kvm *kvm,
116 return 0; 116 return 0;
117} 117}
118 118
119int kvm_deassign_device(struct kvm *kvm,
120 struct kvm_assigned_dev_kernel *assigned_dev)
121{
122 struct dmar_domain *domain = kvm->arch.intel_iommu_domain;
123 struct pci_dev *pdev = NULL;
124
125 /* check if iommu exists and in use */
126 if (!domain)
127 return 0;
128
129 pdev = assigned_dev->dev;
130 if (pdev == NULL)
131 return -ENODEV;
132
133 intel_iommu_detach_device(domain, pdev);
134
135 printk(KERN_DEBUG "deassign device: host bdf = %x:%x:%x\n",
136 assigned_dev->host_busnr,
137 PCI_SLOT(assigned_dev->host_devfn),
138 PCI_FUNC(assigned_dev->host_devfn));
139
140 return 0;
141}
142
119int kvm_iommu_map_guest(struct kvm *kvm) 143int kvm_iommu_map_guest(struct kvm *kvm)
120{ 144{
121 int r; 145 int r;