Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.35-rc2 310 lines 7.1 kB view raw
1/* 2 * Copyright (c) 2006, Intel Corporation. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms and conditions of the GNU General Public License, 6 * version 2, as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 * more details. 12 * 13 * You should have received a copy of the GNU General Public License along with 14 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 15 * Place - Suite 330, Boston, MA 02111-1307 USA. 16 * 17 * Copyright (C) 2006-2008 Intel Corporation 18 * Copyright IBM Corporation, 2008 19 * Author: Allen M. Kay <allen.m.kay@intel.com> 20 * Author: Weidong Han <weidong.han@intel.com> 21 * Author: Ben-Ami Yassour <benami@il.ibm.com> 22 */ 23 24#include <linux/list.h> 25#include <linux/kvm_host.h> 26#include <linux/pci.h> 27#include <linux/dmar.h> 28#include <linux/iommu.h> 29#include <linux/intel-iommu.h> 30 31static int kvm_iommu_unmap_memslots(struct kvm *kvm); 32static void kvm_iommu_put_pages(struct kvm *kvm, 33 gfn_t base_gfn, unsigned long npages); 34 35static pfn_t kvm_pin_pages(struct kvm *kvm, struct kvm_memory_slot *slot, 36 gfn_t gfn, unsigned long size) 37{ 38 gfn_t end_gfn; 39 pfn_t pfn; 40 41 pfn = gfn_to_pfn_memslot(kvm, slot, gfn); 42 end_gfn = gfn + (size >> PAGE_SHIFT); 43 gfn += 1; 44 45 if (is_error_pfn(pfn)) 46 return pfn; 47 48 while (gfn < end_gfn) 49 gfn_to_pfn_memslot(kvm, slot, gfn++); 50 51 return pfn; 52} 53 54int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot) 55{ 56 gfn_t gfn, end_gfn; 57 pfn_t pfn; 58 int r = 0; 59 struct iommu_domain *domain = kvm->arch.iommu_domain; 60 int flags; 61 62 /* check if iommu exists and in use */ 63 if (!domain) 64 return 0; 65 66 gfn = slot->base_gfn; 67 end_gfn = gfn + slot->npages; 68 69 flags = IOMMU_READ | IOMMU_WRITE; 70 if (kvm->arch.iommu_flags & KVM_IOMMU_CACHE_COHERENCY) 71 flags |= IOMMU_CACHE; 72 73 74 while (gfn < end_gfn) { 75 unsigned long page_size; 76 77 /* Check if already mapped */ 78 if (iommu_iova_to_phys(domain, gfn_to_gpa(gfn))) { 79 gfn += 1; 80 continue; 81 } 82 83 /* Get the page size we could use to map */ 84 page_size = kvm_host_page_size(kvm, gfn); 85 86 /* Make sure the page_size does not exceed the memslot */ 87 while ((gfn + (page_size >> PAGE_SHIFT)) > end_gfn) 88 page_size >>= 1; 89 90 /* Make sure gfn is aligned to the page size we want to map */ 91 while ((gfn << PAGE_SHIFT) & (page_size - 1)) 92 page_size >>= 1; 93 94 /* 95 * Pin all pages we are about to map in memory. This is 96 * important because we unmap and unpin in 4kb steps later. 97 */ 98 pfn = kvm_pin_pages(kvm, slot, gfn, page_size); 99 if (is_error_pfn(pfn)) { 100 gfn += 1; 101 continue; 102 } 103 104 /* Map into IO address space */ 105 r = iommu_map(domain, gfn_to_gpa(gfn), pfn_to_hpa(pfn), 106 get_order(page_size), flags); 107 if (r) { 108 printk(KERN_ERR "kvm_iommu_map_address:" 109 "iommu failed to map pfn=%lx\n", pfn); 110 goto unmap_pages; 111 } 112 113 gfn += page_size >> PAGE_SHIFT; 114 115 116 } 117 118 return 0; 119 120unmap_pages: 121 kvm_iommu_put_pages(kvm, slot->base_gfn, gfn); 122 return r; 123} 124 125static int kvm_iommu_map_memslots(struct kvm *kvm) 126{ 127 int i, r = 0; 128 struct kvm_memslots *slots; 129 130 slots = kvm_memslots(kvm); 131 132 for (i = 0; i < slots->nmemslots; i++) { 133 r = kvm_iommu_map_pages(kvm, &slots->memslots[i]); 134 if (r) 135 break; 136 } 137 138 return r; 139} 140 141int kvm_assign_device(struct kvm *kvm, 142 struct kvm_assigned_dev_kernel *assigned_dev) 143{ 144 struct pci_dev *pdev = NULL; 145 struct iommu_domain *domain = kvm->arch.iommu_domain; 146 int r, last_flags; 147 148 /* check if iommu exists and in use */ 149 if (!domain) 150 return 0; 151 152 pdev = assigned_dev->dev; 153 if (pdev == NULL) 154 return -ENODEV; 155 156 r = iommu_attach_device(domain, &pdev->dev); 157 if (r) { 158 printk(KERN_ERR "assign device %x:%x:%x.%x failed", 159 pci_domain_nr(pdev->bus), 160 pdev->bus->number, 161 PCI_SLOT(pdev->devfn), 162 PCI_FUNC(pdev->devfn)); 163 return r; 164 } 165 166 last_flags = kvm->arch.iommu_flags; 167 if (iommu_domain_has_cap(kvm->arch.iommu_domain, 168 IOMMU_CAP_CACHE_COHERENCY)) 169 kvm->arch.iommu_flags |= KVM_IOMMU_CACHE_COHERENCY; 170 171 /* Check if need to update IOMMU page table for guest memory */ 172 if ((last_flags ^ kvm->arch.iommu_flags) == 173 KVM_IOMMU_CACHE_COHERENCY) { 174 kvm_iommu_unmap_memslots(kvm); 175 r = kvm_iommu_map_memslots(kvm); 176 if (r) 177 goto out_unmap; 178 } 179 180 printk(KERN_DEBUG "assign device %x:%x:%x.%x\n", 181 assigned_dev->host_segnr, 182 assigned_dev->host_busnr, 183 PCI_SLOT(assigned_dev->host_devfn), 184 PCI_FUNC(assigned_dev->host_devfn)); 185 186 return 0; 187out_unmap: 188 kvm_iommu_unmap_memslots(kvm); 189 return r; 190} 191 192int kvm_deassign_device(struct kvm *kvm, 193 struct kvm_assigned_dev_kernel *assigned_dev) 194{ 195 struct iommu_domain *domain = kvm->arch.iommu_domain; 196 struct pci_dev *pdev = NULL; 197 198 /* check if iommu exists and in use */ 199 if (!domain) 200 return 0; 201 202 pdev = assigned_dev->dev; 203 if (pdev == NULL) 204 return -ENODEV; 205 206 iommu_detach_device(domain, &pdev->dev); 207 208 printk(KERN_DEBUG "deassign device %x:%x:%x.%x\n", 209 assigned_dev->host_segnr, 210 assigned_dev->host_busnr, 211 PCI_SLOT(assigned_dev->host_devfn), 212 PCI_FUNC(assigned_dev->host_devfn)); 213 214 return 0; 215} 216 217int kvm_iommu_map_guest(struct kvm *kvm) 218{ 219 int r; 220 221 if (!iommu_found()) { 222 printk(KERN_ERR "%s: iommu not found\n", __func__); 223 return -ENODEV; 224 } 225 226 kvm->arch.iommu_domain = iommu_domain_alloc(); 227 if (!kvm->arch.iommu_domain) 228 return -ENOMEM; 229 230 r = kvm_iommu_map_memslots(kvm); 231 if (r) 232 goto out_unmap; 233 234 return 0; 235 236out_unmap: 237 kvm_iommu_unmap_memslots(kvm); 238 return r; 239} 240 241static void kvm_unpin_pages(struct kvm *kvm, pfn_t pfn, unsigned long npages) 242{ 243 unsigned long i; 244 245 for (i = 0; i < npages; ++i) 246 kvm_release_pfn_clean(pfn + i); 247} 248 249static void kvm_iommu_put_pages(struct kvm *kvm, 250 gfn_t base_gfn, unsigned long npages) 251{ 252 struct iommu_domain *domain; 253 gfn_t end_gfn, gfn; 254 pfn_t pfn; 255 u64 phys; 256 257 domain = kvm->arch.iommu_domain; 258 end_gfn = base_gfn + npages; 259 gfn = base_gfn; 260 261 /* check if iommu exists and in use */ 262 if (!domain) 263 return; 264 265 while (gfn < end_gfn) { 266 unsigned long unmap_pages; 267 int order; 268 269 /* Get physical address */ 270 phys = iommu_iova_to_phys(domain, gfn_to_gpa(gfn)); 271 pfn = phys >> PAGE_SHIFT; 272 273 /* Unmap address from IO address space */ 274 order = iommu_unmap(domain, gfn_to_gpa(gfn), PAGE_SIZE); 275 unmap_pages = 1ULL << order; 276 277 /* Unpin all pages we just unmapped to not leak any memory */ 278 kvm_unpin_pages(kvm, pfn, unmap_pages); 279 280 gfn += unmap_pages; 281 } 282} 283 284static int kvm_iommu_unmap_memslots(struct kvm *kvm) 285{ 286 int i; 287 struct kvm_memslots *slots; 288 289 slots = kvm_memslots(kvm); 290 291 for (i = 0; i < slots->nmemslots; i++) { 292 kvm_iommu_put_pages(kvm, slots->memslots[i].base_gfn, 293 slots->memslots[i].npages); 294 } 295 296 return 0; 297} 298 299int kvm_iommu_unmap_guest(struct kvm *kvm) 300{ 301 struct iommu_domain *domain = kvm->arch.iommu_domain; 302 303 /* check if iommu exists and in use */ 304 if (!domain) 305 return 0; 306 307 kvm_iommu_unmap_memslots(kvm); 308 iommu_domain_free(domain); 309 return 0; 310}