aboutsummaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-01-04 04:59:36 -0500
committerIngo Molnar <mingo@elte.hu>2009-01-04 04:59:36 -0500
commit4010b0192ddf6ec7ec1b9feb9b0953692aeb7329 (patch)
tree188a36186f6ce580b479a9f90404fa7bfd8b22d7 /virt
parent79ff56ebd3edfb16f8badc558cb439b203a3298f (diff)
parent7d3b56ba37a95f1f370f50258ed3954c304c524b (diff)
Merge branch 'linus' into core/urgent
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/iommu.c (renamed from virt/kvm/vtd.c)135
-rw-r--r--virt/kvm/kvm_main.c50
2 files changed, 128 insertions, 57 deletions
diff --git a/virt/kvm/vtd.c b/virt/kvm/iommu.c
index a770874f3a3a..e9693a29d00e 100644
--- a/virt/kvm/vtd.c
+++ b/virt/kvm/iommu.c
@@ -25,6 +25,7 @@
25#include <linux/kvm_host.h> 25#include <linux/kvm_host.h>
26#include <linux/pci.h> 26#include <linux/pci.h>
27#include <linux/dmar.h> 27#include <linux/dmar.h>
28#include <linux/iommu.h>
28#include <linux/intel-iommu.h> 29#include <linux/intel-iommu.h>
29 30
30static int kvm_iommu_unmap_memslots(struct kvm *kvm); 31static int kvm_iommu_unmap_memslots(struct kvm *kvm);
@@ -37,7 +38,7 @@ int kvm_iommu_map_pages(struct kvm *kvm,
37 gfn_t gfn = base_gfn; 38 gfn_t gfn = base_gfn;
38 pfn_t pfn; 39 pfn_t pfn;
39 int i, r = 0; 40 int i, r = 0;
40 struct dmar_domain *domain = kvm->arch.intel_iommu_domain; 41 struct iommu_domain *domain = kvm->arch.iommu_domain;
41 42
42 /* check if iommu exists and in use */ 43 /* check if iommu exists and in use */
43 if (!domain) 44 if (!domain)
@@ -45,20 +46,17 @@ int kvm_iommu_map_pages(struct kvm *kvm,
45 46
46 for (i = 0; i < npages; i++) { 47 for (i = 0; i < npages; i++) {
47 /* check if already mapped */ 48 /* check if already mapped */
48 pfn = (pfn_t)intel_iommu_iova_to_pfn(domain, 49 if (iommu_iova_to_phys(domain, gfn_to_gpa(gfn)))
49 gfn_to_gpa(gfn));
50 if (pfn)
51 continue; 50 continue;
52 51
53 pfn = gfn_to_pfn(kvm, gfn); 52 pfn = gfn_to_pfn(kvm, gfn);
54 r = intel_iommu_page_mapping(domain, 53 r = iommu_map_range(domain,
55 gfn_to_gpa(gfn), 54 gfn_to_gpa(gfn),
56 pfn_to_hpa(pfn), 55 pfn_to_hpa(pfn),
57 PAGE_SIZE, 56 PAGE_SIZE,
58 DMA_PTE_READ | 57 IOMMU_READ | IOMMU_WRITE);
59 DMA_PTE_WRITE);
60 if (r) { 58 if (r) {
61 printk(KERN_ERR "kvm_iommu_map_pages:" 59 printk(KERN_ERR "kvm_iommu_map_address:"
62 "iommu failed to map pfn=%lx\n", pfn); 60 "iommu failed to map pfn=%lx\n", pfn);
63 goto unmap_pages; 61 goto unmap_pages;
64 } 62 }
@@ -73,7 +71,7 @@ unmap_pages:
73 71
74static int kvm_iommu_map_memslots(struct kvm *kvm) 72static int kvm_iommu_map_memslots(struct kvm *kvm)
75{ 73{
76 int i, r; 74 int i, r = 0;
77 75
78 down_read(&kvm->slots_lock); 76 down_read(&kvm->slots_lock);
79 for (i = 0; i < kvm->nmemslots; i++) { 77 for (i = 0; i < kvm->nmemslots; i++) {
@@ -86,50 +84,79 @@ static int kvm_iommu_map_memslots(struct kvm *kvm)
86 return r; 84 return r;
87} 85}
88 86
89int kvm_iommu_map_guest(struct kvm *kvm, 87int kvm_assign_device(struct kvm *kvm,
90 struct kvm_assigned_dev_kernel *assigned_dev) 88 struct kvm_assigned_dev_kernel *assigned_dev)
91{ 89{
92 struct pci_dev *pdev = NULL; 90 struct pci_dev *pdev = NULL;
91 struct iommu_domain *domain = kvm->arch.iommu_domain;
93 int r; 92 int r;
94 93
95 if (!intel_iommu_found()) { 94 /* check if iommu exists and in use */
96 printk(KERN_ERR "%s: intel iommu not found\n", __func__); 95 if (!domain)
96 return 0;
97
98 pdev = assigned_dev->dev;
99 if (pdev == NULL)
97 return -ENODEV; 100 return -ENODEV;
101
102 r = iommu_attach_device(domain, &pdev->dev);
103 if (r) {
104 printk(KERN_ERR "assign device %x:%x.%x failed",
105 pdev->bus->number,
106 PCI_SLOT(pdev->devfn),
107 PCI_FUNC(pdev->devfn));
108 return r;
98 } 109 }
99 110
100 printk(KERN_DEBUG "VT-d direct map: host bdf = %x:%x:%x\n", 111 printk(KERN_DEBUG "assign device: host bdf = %x:%x:%x\n",
101 assigned_dev->host_busnr, 112 assigned_dev->host_busnr,
102 PCI_SLOT(assigned_dev->host_devfn), 113 PCI_SLOT(assigned_dev->host_devfn),
103 PCI_FUNC(assigned_dev->host_devfn)); 114 PCI_FUNC(assigned_dev->host_devfn));
115
116 return 0;
117}
118
119int kvm_deassign_device(struct kvm *kvm,
120 struct kvm_assigned_dev_kernel *assigned_dev)
121{
122 struct iommu_domain *domain = kvm->arch.iommu_domain;
123 struct pci_dev *pdev = NULL;
124
125 /* check if iommu exists and in use */
126 if (!domain)
127 return 0;
104 128
105 pdev = assigned_dev->dev; 129 pdev = assigned_dev->dev;
130 if (pdev == NULL)
131 return -ENODEV;
106 132
107 if (pdev == NULL) { 133 iommu_detach_device(domain, &pdev->dev);
108 if (kvm->arch.intel_iommu_domain) { 134
109 intel_iommu_domain_exit(kvm->arch.intel_iommu_domain); 135 printk(KERN_DEBUG "deassign device: host bdf = %x:%x:%x\n",
110 kvm->arch.intel_iommu_domain = NULL; 136 assigned_dev->host_busnr,
111 } 137 PCI_SLOT(assigned_dev->host_devfn),
138 PCI_FUNC(assigned_dev->host_devfn));
139
140 return 0;
141}
142
143int kvm_iommu_map_guest(struct kvm *kvm)
144{
145 int r;
146
147 if (!iommu_found()) {
148 printk(KERN_ERR "%s: iommu not found\n", __func__);
112 return -ENODEV; 149 return -ENODEV;
113 } 150 }
114 151
115 kvm->arch.intel_iommu_domain = intel_iommu_domain_alloc(pdev); 152 kvm->arch.iommu_domain = iommu_domain_alloc();
116 if (!kvm->arch.intel_iommu_domain) 153 if (!kvm->arch.iommu_domain)
117 return -ENODEV; 154 return -ENOMEM;
118 155
119 r = kvm_iommu_map_memslots(kvm); 156 r = kvm_iommu_map_memslots(kvm);
120 if (r) 157 if (r)
121 goto out_unmap; 158 goto out_unmap;
122 159
123 intel_iommu_detach_dev(kvm->arch.intel_iommu_domain,
124 pdev->bus->number, pdev->devfn);
125
126 r = intel_iommu_context_mapping(kvm->arch.intel_iommu_domain,
127 pdev);
128 if (r) {
129 printk(KERN_ERR "Domain context map for %s failed",
130 pci_name(pdev));
131 goto out_unmap;
132 }
133 return 0; 160 return 0;
134 161
135out_unmap: 162out_unmap:
@@ -138,19 +165,26 @@ out_unmap:
138} 165}
139 166
140static void kvm_iommu_put_pages(struct kvm *kvm, 167static void kvm_iommu_put_pages(struct kvm *kvm,
141 gfn_t base_gfn, unsigned long npages) 168 gfn_t base_gfn, unsigned long npages)
142{ 169{
143 gfn_t gfn = base_gfn; 170 gfn_t gfn = base_gfn;
144 pfn_t pfn; 171 pfn_t pfn;
145 struct dmar_domain *domain = kvm->arch.intel_iommu_domain; 172 struct iommu_domain *domain = kvm->arch.iommu_domain;
146 int i; 173 unsigned long i;
174 u64 phys;
175
176 /* check if iommu exists and in use */
177 if (!domain)
178 return;
147 179
148 for (i = 0; i < npages; i++) { 180 for (i = 0; i < npages; i++) {
149 pfn = (pfn_t)intel_iommu_iova_to_pfn(domain, 181 phys = iommu_iova_to_phys(domain, gfn_to_gpa(gfn));
150 gfn_to_gpa(gfn)); 182 pfn = phys >> PAGE_SHIFT;
151 kvm_release_pfn_clean(pfn); 183 kvm_release_pfn_clean(pfn);
152 gfn++; 184 gfn++;
153 } 185 }
186
187 iommu_unmap_range(domain, gfn_to_gpa(base_gfn), PAGE_SIZE * npages);
154} 188}
155 189
156static int kvm_iommu_unmap_memslots(struct kvm *kvm) 190static int kvm_iommu_unmap_memslots(struct kvm *kvm)
@@ -168,24 +202,13 @@ static int kvm_iommu_unmap_memslots(struct kvm *kvm)
168 202
169int kvm_iommu_unmap_guest(struct kvm *kvm) 203int kvm_iommu_unmap_guest(struct kvm *kvm)
170{ 204{
171 struct kvm_assigned_dev_kernel *entry; 205 struct iommu_domain *domain = kvm->arch.iommu_domain;
172 struct dmar_domain *domain = kvm->arch.intel_iommu_domain;
173 206
174 /* check if iommu exists and in use */ 207 /* check if iommu exists and in use */
175 if (!domain) 208 if (!domain)
176 return 0; 209 return 0;
177 210
178 list_for_each_entry(entry, &kvm->arch.assigned_dev_head, list) {
179 printk(KERN_DEBUG "VT-d unmap: host bdf = %x:%x:%x\n",
180 entry->host_busnr,
181 PCI_SLOT(entry->host_devfn),
182 PCI_FUNC(entry->host_devfn));
183
184 /* detach kvm dmar domain */
185 intel_iommu_detach_dev(domain, entry->host_busnr,
186 entry->host_devfn);
187 }
188 kvm_iommu_unmap_memslots(kvm); 211 kvm_iommu_unmap_memslots(kvm);
189 intel_iommu_domain_exit(domain); 212 iommu_domain_free(domain);
190 return 0; 213 return 0;
191} 214}
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
535static 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
557out:
558 mutex_unlock(&kvm->lock);
559 return r;
560}
561#endif
562
528static inline int valid_vcpu(int n) 563static 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 }