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.34-rc2 241 lines 5.6 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 35int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot) 36{ 37 gfn_t gfn = slot->base_gfn; 38 unsigned long npages = slot->npages; 39 pfn_t pfn; 40 int i, r = 0; 41 struct iommu_domain *domain = kvm->arch.iommu_domain; 42 int flags; 43 44 /* check if iommu exists and in use */ 45 if (!domain) 46 return 0; 47 48 flags = IOMMU_READ | IOMMU_WRITE; 49 if (kvm->arch.iommu_flags & KVM_IOMMU_CACHE_COHERENCY) 50 flags |= IOMMU_CACHE; 51 52 for (i = 0; i < npages; i++) { 53 /* check if already mapped */ 54 if (iommu_iova_to_phys(domain, gfn_to_gpa(gfn))) 55 continue; 56 57 pfn = gfn_to_pfn_memslot(kvm, slot, gfn); 58 r = iommu_map_range(domain, 59 gfn_to_gpa(gfn), 60 pfn_to_hpa(pfn), 61 PAGE_SIZE, flags); 62 if (r) { 63 printk(KERN_ERR "kvm_iommu_map_address:" 64 "iommu failed to map pfn=%lx\n", pfn); 65 goto unmap_pages; 66 } 67 gfn++; 68 } 69 return 0; 70 71unmap_pages: 72 kvm_iommu_put_pages(kvm, slot->base_gfn, i); 73 return r; 74} 75 76static int kvm_iommu_map_memslots(struct kvm *kvm) 77{ 78 int i, r = 0; 79 struct kvm_memslots *slots; 80 81 slots = rcu_dereference(kvm->memslots); 82 83 for (i = 0; i < slots->nmemslots; i++) { 84 r = kvm_iommu_map_pages(kvm, &slots->memslots[i]); 85 if (r) 86 break; 87 } 88 89 return r; 90} 91 92int kvm_assign_device(struct kvm *kvm, 93 struct kvm_assigned_dev_kernel *assigned_dev) 94{ 95 struct pci_dev *pdev = NULL; 96 struct iommu_domain *domain = kvm->arch.iommu_domain; 97 int r, last_flags; 98 99 /* check if iommu exists and in use */ 100 if (!domain) 101 return 0; 102 103 pdev = assigned_dev->dev; 104 if (pdev == NULL) 105 return -ENODEV; 106 107 r = iommu_attach_device(domain, &pdev->dev); 108 if (r) { 109 printk(KERN_ERR "assign device %x:%x:%x.%x failed", 110 pci_domain_nr(pdev->bus), 111 pdev->bus->number, 112 PCI_SLOT(pdev->devfn), 113 PCI_FUNC(pdev->devfn)); 114 return r; 115 } 116 117 last_flags = kvm->arch.iommu_flags; 118 if (iommu_domain_has_cap(kvm->arch.iommu_domain, 119 IOMMU_CAP_CACHE_COHERENCY)) 120 kvm->arch.iommu_flags |= KVM_IOMMU_CACHE_COHERENCY; 121 122 /* Check if need to update IOMMU page table for guest memory */ 123 if ((last_flags ^ kvm->arch.iommu_flags) == 124 KVM_IOMMU_CACHE_COHERENCY) { 125 kvm_iommu_unmap_memslots(kvm); 126 r = kvm_iommu_map_memslots(kvm); 127 if (r) 128 goto out_unmap; 129 } 130 131 printk(KERN_DEBUG "assign device %x:%x:%x.%x\n", 132 assigned_dev->host_segnr, 133 assigned_dev->host_busnr, 134 PCI_SLOT(assigned_dev->host_devfn), 135 PCI_FUNC(assigned_dev->host_devfn)); 136 137 return 0; 138out_unmap: 139 kvm_iommu_unmap_memslots(kvm); 140 return r; 141} 142 143int kvm_deassign_device(struct kvm *kvm, 144 struct kvm_assigned_dev_kernel *assigned_dev) 145{ 146 struct iommu_domain *domain = kvm->arch.iommu_domain; 147 struct pci_dev *pdev = NULL; 148 149 /* check if iommu exists and in use */ 150 if (!domain) 151 return 0; 152 153 pdev = assigned_dev->dev; 154 if (pdev == NULL) 155 return -ENODEV; 156 157 iommu_detach_device(domain, &pdev->dev); 158 159 printk(KERN_DEBUG "deassign device %x:%x:%x.%x\n", 160 assigned_dev->host_segnr, 161 assigned_dev->host_busnr, 162 PCI_SLOT(assigned_dev->host_devfn), 163 PCI_FUNC(assigned_dev->host_devfn)); 164 165 return 0; 166} 167 168int kvm_iommu_map_guest(struct kvm *kvm) 169{ 170 int r; 171 172 if (!iommu_found()) { 173 printk(KERN_ERR "%s: iommu not found\n", __func__); 174 return -ENODEV; 175 } 176 177 kvm->arch.iommu_domain = iommu_domain_alloc(); 178 if (!kvm->arch.iommu_domain) 179 return -ENOMEM; 180 181 r = kvm_iommu_map_memslots(kvm); 182 if (r) 183 goto out_unmap; 184 185 return 0; 186 187out_unmap: 188 kvm_iommu_unmap_memslots(kvm); 189 return r; 190} 191 192static void kvm_iommu_put_pages(struct kvm *kvm, 193 gfn_t base_gfn, unsigned long npages) 194{ 195 gfn_t gfn = base_gfn; 196 pfn_t pfn; 197 struct iommu_domain *domain = kvm->arch.iommu_domain; 198 unsigned long i; 199 u64 phys; 200 201 /* check if iommu exists and in use */ 202 if (!domain) 203 return; 204 205 for (i = 0; i < npages; i++) { 206 phys = iommu_iova_to_phys(domain, gfn_to_gpa(gfn)); 207 pfn = phys >> PAGE_SHIFT; 208 kvm_release_pfn_clean(pfn); 209 gfn++; 210 } 211 212 iommu_unmap_range(domain, gfn_to_gpa(base_gfn), PAGE_SIZE * npages); 213} 214 215static int kvm_iommu_unmap_memslots(struct kvm *kvm) 216{ 217 int i; 218 struct kvm_memslots *slots; 219 220 slots = rcu_dereference(kvm->memslots); 221 222 for (i = 0; i < slots->nmemslots; i++) { 223 kvm_iommu_put_pages(kvm, slots->memslots[i].base_gfn, 224 slots->memslots[i].npages); 225 } 226 227 return 0; 228} 229 230int kvm_iommu_unmap_guest(struct kvm *kvm) 231{ 232 struct iommu_domain *domain = kvm->arch.iommu_domain; 233 234 /* check if iommu exists and in use */ 235 if (!domain) 236 return 0; 237 238 kvm_iommu_unmap_memslots(kvm); 239 iommu_domain_free(domain); 240 return 0; 241}