diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-16 18:36:00 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-16 18:36:00 -0400 |
| commit | 08d19f51f05a68ce89a289320ce4ed96e757df72 (patch) | |
| tree | 31c5d718d0aeaff5083fe533cd6e1f9fbbe846bb /drivers/pci/intel-iommu.c | |
| parent | 1c95e1b69073cff5ff179e592fa1a1e182c78a17 (diff) | |
| parent | 2381ad241d0bea1253a37f314b270848067640bb (diff) | |
Merge branch 'kvm-updates/2.6.28' of git://git.kernel.org/pub/scm/linux/kernel/git/avi/kvm
* 'kvm-updates/2.6.28' of git://git.kernel.org/pub/scm/linux/kernel/git/avi/kvm: (134 commits)
KVM: ia64: Add intel iommu support for guests.
KVM: ia64: add directed mmio range support for kvm guests
KVM: ia64: Make pmt table be able to hold physical mmio entries.
KVM: Move irqchip_in_kernel() from ioapic.h to irq.h
KVM: Separate irq ack notification out of arch/x86/kvm/irq.c
KVM: Change is_mmio_pfn to kvm_is_mmio_pfn, and make it common for all archs
KVM: Move device assignment logic to common code
KVM: Device Assignment: Move vtd.c from arch/x86/kvm/ to virt/kvm/
KVM: VMX: enable invlpg exiting if EPT is disabled
KVM: x86: Silence various LAPIC-related host kernel messages
KVM: Device Assignment: Map mmio pages into VT-d page table
KVM: PIC: enhance IPI avoidance
KVM: MMU: add "oos_shadow" parameter to disable oos
KVM: MMU: speed up mmu_unsync_walk
KVM: MMU: out of sync shadow core
KVM: MMU: mmu_convert_notrap helper
KVM: MMU: awareness of new kvm_mmu_zap_page behaviour
KVM: MMU: mmu_parent_walk
KVM: x86: trap invlpg
KVM: MMU: sync roots on mmu reload
...
Diffstat (limited to 'drivers/pci/intel-iommu.c')
| -rw-r--r-- | drivers/pci/intel-iommu.c | 116 |
1 files changed, 112 insertions, 4 deletions
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 389fdd6f4a9f..fc5f2dbf5323 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
| @@ -33,8 +33,8 @@ | |||
| 33 | #include <linux/dma-mapping.h> | 33 | #include <linux/dma-mapping.h> |
| 34 | #include <linux/mempool.h> | 34 | #include <linux/mempool.h> |
| 35 | #include <linux/timer.h> | 35 | #include <linux/timer.h> |
| 36 | #include "iova.h" | 36 | #include <linux/iova.h> |
| 37 | #include "intel-iommu.h" | 37 | #include <linux/intel-iommu.h> |
| 38 | #include <asm/proto.h> /* force_iommu in this header in x86-64*/ | 38 | #include <asm/proto.h> /* force_iommu in this header in x86-64*/ |
| 39 | #include <asm/cacheflush.h> | 39 | #include <asm/cacheflush.h> |
| 40 | #include <asm/iommu.h> | 40 | #include <asm/iommu.h> |
| @@ -156,7 +156,7 @@ static inline void *alloc_domain_mem(void) | |||
| 156 | return iommu_kmem_cache_alloc(iommu_domain_cache); | 156 | return iommu_kmem_cache_alloc(iommu_domain_cache); |
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | static inline void free_domain_mem(void *vaddr) | 159 | static void free_domain_mem(void *vaddr) |
| 160 | { | 160 | { |
| 161 | kmem_cache_free(iommu_domain_cache, vaddr); | 161 | kmem_cache_free(iommu_domain_cache, vaddr); |
| 162 | } | 162 | } |
| @@ -1341,7 +1341,7 @@ static void domain_remove_dev_info(struct dmar_domain *domain) | |||
| 1341 | * find_domain | 1341 | * find_domain |
| 1342 | * Note: we use struct pci_dev->dev.archdata.iommu stores the info | 1342 | * Note: we use struct pci_dev->dev.archdata.iommu stores the info |
| 1343 | */ | 1343 | */ |
| 1344 | struct dmar_domain * | 1344 | static struct dmar_domain * |
| 1345 | find_domain(struct pci_dev *pdev) | 1345 | find_domain(struct pci_dev *pdev) |
| 1346 | { | 1346 | { |
| 1347 | struct device_domain_info *info; | 1347 | struct device_domain_info *info; |
| @@ -2318,3 +2318,111 @@ int __init intel_iommu_init(void) | |||
| 2318 | return 0; | 2318 | return 0; |
| 2319 | } | 2319 | } |
| 2320 | 2320 | ||
| 2321 | void intel_iommu_domain_exit(struct dmar_domain *domain) | ||
| 2322 | { | ||
| 2323 | u64 end; | ||
| 2324 | |||
| 2325 | /* Domain 0 is reserved, so dont process it */ | ||
| 2326 | if (!domain) | ||
| 2327 | return; | ||
| 2328 | |||
| 2329 | end = DOMAIN_MAX_ADDR(domain->gaw); | ||
| 2330 | end = end & (~PAGE_MASK_4K); | ||
| 2331 | |||
| 2332 | /* clear ptes */ | ||
| 2333 | dma_pte_clear_range(domain, 0, end); | ||
| 2334 | |||
| 2335 | /* free page tables */ | ||
| 2336 | dma_pte_free_pagetable(domain, 0, end); | ||
| 2337 | |||
| 2338 | iommu_free_domain(domain); | ||
| 2339 | free_domain_mem(domain); | ||
| 2340 | } | ||
| 2341 | EXPORT_SYMBOL_GPL(intel_iommu_domain_exit); | ||
| 2342 | |||
| 2343 | struct dmar_domain *intel_iommu_domain_alloc(struct pci_dev *pdev) | ||
| 2344 | { | ||
| 2345 | struct dmar_drhd_unit *drhd; | ||
| 2346 | struct dmar_domain *domain; | ||
| 2347 | struct intel_iommu *iommu; | ||
| 2348 | |||
| 2349 | drhd = dmar_find_matched_drhd_unit(pdev); | ||
| 2350 | if (!drhd) { | ||
| 2351 | printk(KERN_ERR "intel_iommu_domain_alloc: drhd == NULL\n"); | ||
| 2352 | return NULL; | ||
| 2353 | } | ||
| 2354 | |||
| 2355 | iommu = drhd->iommu; | ||
| 2356 | if (!iommu) { | ||
| 2357 | printk(KERN_ERR | ||
| 2358 | "intel_iommu_domain_alloc: iommu == NULL\n"); | ||
| 2359 | return NULL; | ||
| 2360 | } | ||
| 2361 | domain = iommu_alloc_domain(iommu); | ||
| 2362 | if (!domain) { | ||
| 2363 | printk(KERN_ERR | ||
| 2364 | "intel_iommu_domain_alloc: domain == NULL\n"); | ||
| 2365 | return NULL; | ||
| 2366 | } | ||
| 2367 | if (domain_init(domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) { | ||
| 2368 | printk(KERN_ERR | ||
| 2369 | "intel_iommu_domain_alloc: domain_init() failed\n"); | ||
| 2370 | intel_iommu_domain_exit(domain); | ||
| 2371 | return NULL; | ||
| 2372 | } | ||
| 2373 | return domain; | ||
| 2374 | } | ||
| 2375 | EXPORT_SYMBOL_GPL(intel_iommu_domain_alloc); | ||
| 2376 | |||
| 2377 | int intel_iommu_context_mapping( | ||
| 2378 | struct dmar_domain *domain, struct pci_dev *pdev) | ||
| 2379 | { | ||
| 2380 | int rc; | ||
| 2381 | rc = domain_context_mapping(domain, pdev); | ||
| 2382 | return rc; | ||
| 2383 | } | ||
| 2384 | EXPORT_SYMBOL_GPL(intel_iommu_context_mapping); | ||
| 2385 | |||
| 2386 | int intel_iommu_page_mapping( | ||
| 2387 | struct dmar_domain *domain, dma_addr_t iova, | ||
| 2388 | u64 hpa, size_t size, int prot) | ||
| 2389 | { | ||
| 2390 | int rc; | ||
| 2391 | rc = domain_page_mapping(domain, iova, hpa, size, prot); | ||
| 2392 | return rc; | ||
| 2393 | } | ||
| 2394 | EXPORT_SYMBOL_GPL(intel_iommu_page_mapping); | ||
| 2395 | |||
| 2396 | void intel_iommu_detach_dev(struct dmar_domain *domain, u8 bus, u8 devfn) | ||
| 2397 | { | ||
| 2398 | detach_domain_for_dev(domain, bus, devfn); | ||
| 2399 | } | ||
| 2400 | EXPORT_SYMBOL_GPL(intel_iommu_detach_dev); | ||
| 2401 | |||
| 2402 | struct dmar_domain * | ||
| 2403 | intel_iommu_find_domain(struct pci_dev *pdev) | ||
| 2404 | { | ||
| 2405 | return find_domain(pdev); | ||
| 2406 | } | ||
| 2407 | EXPORT_SYMBOL_GPL(intel_iommu_find_domain); | ||
| 2408 | |||
| 2409 | int intel_iommu_found(void) | ||
| 2410 | { | ||
| 2411 | return g_num_of_iommus; | ||
| 2412 | } | ||
| 2413 | EXPORT_SYMBOL_GPL(intel_iommu_found); | ||
| 2414 | |||
| 2415 | u64 intel_iommu_iova_to_pfn(struct dmar_domain *domain, u64 iova) | ||
| 2416 | { | ||
| 2417 | struct dma_pte *pte; | ||
| 2418 | u64 pfn; | ||
| 2419 | |||
| 2420 | pfn = 0; | ||
| 2421 | pte = addr_to_dma_pte(domain, iova); | ||
| 2422 | |||
| 2423 | if (pte) | ||
| 2424 | pfn = dma_pte_addr(*pte); | ||
| 2425 | |||
| 2426 | return pfn >> PAGE_SHIFT_4K; | ||
| 2427 | } | ||
| 2428 | EXPORT_SYMBOL_GPL(intel_iommu_iova_to_pfn); | ||
