]> Git Repo - linux.git/commitdiff
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu
authorLinus Torvalds <[email protected]>
Tue, 10 Jan 2012 19:08:21 +0000 (11:08 -0800)
committerLinus Torvalds <[email protected]>
Tue, 10 Jan 2012 19:08:21 +0000 (11:08 -0800)
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: (53 commits)
  iommu/amd: Set IOTLB invalidation timeout
  iommu/amd: Init stats for iommu=pt
  iommu/amd: Remove unnecessary cache flushes in amd_iommu_resume
  iommu/amd: Add invalidate-context call-back
  iommu/amd: Add amd_iommu_device_info() function
  iommu/amd: Adapt IOMMU driver to PCI register name changes
  iommu/amd: Add invalid_ppr callback
  iommu/amd: Implement notifiers for IOMMUv2
  iommu/amd: Implement IO page-fault handler
  iommu/amd: Add routines to bind/unbind a pasid
  iommu/amd: Implement device aquisition code for IOMMUv2
  iommu/amd: Add driver stub for AMD IOMMUv2 support
  iommu/amd: Add stat counter for IOMMUv2 events
  iommu/amd: Add device errata handling
  iommu/amd: Add function to get IOMMUv2 domain for pdev
  iommu/amd: Implement function to send PPR completions
  iommu/amd: Implement functions to manage GCR3 table
  iommu/amd: Implement IOMMUv2 TLB flushing routines
  iommu/amd: Add support for IOMMUv2 domain mode
  iommu/amd: Add amd_iommu_domain_direct_map function
  ...

1  2 
Documentation/kernel-parameters.txt
arch/arm/mach-omap2/devices.c
drivers/iommu/intel-iommu.c
virt/kvm/iommu.c

index e69a461a06c233573431f19ec9fdf95ee8cdcb8a,8f540d8abec589ff17b844f1373fb6704f2907c8..9373d95319c15754069f2af1600a7ef61aa31e17
@@@ -329,6 -329,11 +329,11 @@@ bytes respectively. Such letter suffixe
                                    is a lot of faster
                        off       - do not initialize any AMD IOMMU found in
                                    the system
+                       force_isolation - Force device isolation for all
+                                         devices. The IOMMU driver is not
+                                         allowed anymore to lift isolation
+                                         requirements as needed. This option
+                                         does not override iommu=pt
  
        amijoy.map=     [HW,JOY] Amiga joystick support
                        Map of devices attached to JOY0DAT and JOY1DAT
                nomerge
                forcesac
                soft
-               pt      [x86, IA-64]
+               pt              [x86, IA-64]
+               group_mf        [x86, IA-64]
  
        io7=            [HW] IO7 for Marvel based alpha systems
                        See comment before marvel_specify_io7 in
        kvm.ignore_msrs=[KVM] Ignore guest accesses to unhandled MSRs.
                        Default is 0 (don't ignore, but inject #GP)
  
 -      kvm.oos_shadow= [KVM] Disable out-of-sync shadow paging.
 -                      Default is 1 (enabled)
 -
        kvm.mmu_audit=  [KVM] This is a R/W parameter which allows audit
                        KVM MMU at runtime.
                        Default is 0 (off)
                        arch_perfmon: [X86] Force use of architectural
                                perfmon on Intel CPUs instead of the
                                CPU specific event set.
 +                      timer: [X86] Force use of architectural NMI
 +                              timer mode (see also oprofile.timer
 +                              for generic hr timer mode)
 +                              [s390] Force legacy basic mode sampling
 +                                (report cpu_type "timer")
  
        oops=panic      Always panic on oopses. Default is to just kill the
                        process, but there is a small probability of
                        [USB] Start with the old device initialization
                        scheme (default 0 = off).
  
 +      usbcore.usbfs_memory_mb=
 +                      [USB] Memory limit (in MB) for buffers allocated by
 +                      usbfs (default = 16, 0 = max = 2047).
 +
        usbcore.use_both_schemes=
                        [USB] Try the other device initialization scheme
                        if the first one fails (default 1 = enabled).
                        functions are at fixed addresses, they make nice
                        targets for exploits that can control RIP.
  
 -                      emulate     Vsyscalls turn into traps and are emulated
 -                                  reasonably safely.
 +                      emulate     [default] Vsyscalls turn into traps and are
 +                                  emulated reasonably safely.
  
 -                      native      [default] Vsyscalls are native syscall
 -                                  instructions.
 +                      native      Vsyscalls are native syscall instructions.
                                    This is a little bit faster than trapping
                                    and makes a few dynamic recompilers work
                                    better than they would in emulation mode.
index 35d5dffab7e11c4fa3f4efefe2397d3cf429dc5d,9ceabf02eeb796a9d8c1ca3c4b48e68f78f68879..46dfd1ae8f71a6001f90ecdcea237103f906dcc4
@@@ -28,6 -28,7 +28,7 @@@
  #include <plat/board.h>
  #include <plat/mcbsp.h>
  #include <plat/mmc.h>
+ #include <plat/iommu.h>
  #include <plat/dma.h>
  #include <plat/omap_hwmod.h>
  #include <plat/omap_device.h>
@@@ -211,9 -212,15 +212,15 @@@ static struct platform_device omap3isp_
        .resource       = omap3isp_resources,
  };
  
+ static struct omap_iommu_arch_data omap3_isp_iommu = {
+       .name = "isp",
+ };
  int omap3_init_camera(struct isp_platform_data *pdata)
  {
        omap3isp_device.dev.platform_data = pdata;
+       omap3isp_device.dev.archdata.iommu = &omap3_isp_iommu;
        return platform_device_register(&omap3isp_device);
  }
  
@@@ -336,27 -343,6 +343,27 @@@ static void omap_init_mcpdm(void
  static inline void omap_init_mcpdm(void) {}
  #endif
  
 +#if defined(CONFIG_SND_OMAP_SOC_DMIC) || \
 +              defined(CONFIG_SND_OMAP_SOC_DMIC_MODULE)
 +
 +static void omap_init_dmic(void)
 +{
 +      struct omap_hwmod *oh;
 +      struct platform_device *pdev;
 +
 +      oh = omap_hwmod_lookup("dmic");
 +      if (!oh) {
 +              printk(KERN_ERR "Could not look up mcpdm hw_mod\n");
 +              return;
 +      }
 +
 +      pdev = omap_device_build("omap-dmic", -1, oh, NULL, 0, NULL, 0, 0);
 +      WARN(IS_ERR(pdev), "Can't build omap_device for omap-dmic.\n");
 +}
 +#else
 +static inline void omap_init_dmic(void) {}
 +#endif
 +
  #if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE)
  
  #include <plat/mcspi.h>
@@@ -702,7 -688,6 +709,7 @@@ static int __init omap2_init_devices(vo
         */
        omap_init_audio();
        omap_init_mcpdm();
 +      omap_init_dmic();
        omap_init_camera();
        omap_init_mbox();
        omap_init_mcspi();
index 31053a951c3452640d7dd4e2a6f4c9c2460dee63,77e3b917c8da8a6767e47fae9bf9532394c1190d..c9c6053198d403626d08e2d0826fde7b633baef9
@@@ -41,7 -41,6 +41,7 @@@
  #include <linux/tboot.h>
  #include <linux/dmi.h>
  #include <linux/pci-ats.h>
 +#include <linux/memblock.h>
  #include <asm/cacheflush.h>
  #include <asm/iommu.h>
  
  #define LEVEL_STRIDE          (9)
  #define LEVEL_MASK            (((u64)1 << LEVEL_STRIDE) - 1)
  
+ /*
+  * This bitmap is used to advertise the page sizes our hardware support
+  * to the IOMMU core, which will then use this information to split
+  * physically contiguous memory regions it is mapping into page sizes
+  * that we support.
+  *
+  * Traditionally the IOMMU core just handed us the mappings directly,
+  * after making sure the size is an order of a 4KiB page and that the
+  * mapping has natural alignment.
+  *
+  * To retain this behavior, we currently advertise that we support
+  * all page sizes that are an order of 4KiB.
+  *
+  * If at some point we'd like to utilize the IOMMU core's new behavior,
+  * we could change this to advertise the real page sizes we support.
+  */
+ #define INTEL_IOMMU_PGSIZES   (~0xFFFUL)
  static inline int agaw_to_level(int agaw)
  {
        return agaw + 2;
@@@ -2189,6 -2206,18 +2207,6 @@@ static inline void iommu_prepare_isa(vo
  
  static int md_domain_init(struct dmar_domain *domain, int guest_width);
  
 -static int __init si_domain_work_fn(unsigned long start_pfn,
 -                                  unsigned long end_pfn, void *datax)
 -{
 -      int *ret = datax;
 -
 -      *ret = iommu_domain_identity_map(si_domain,
 -                                       (uint64_t)start_pfn << PAGE_SHIFT,
 -                                       (uint64_t)end_pfn << PAGE_SHIFT);
 -      return *ret;
 -
 -}
 -
  static int __init si_domain_init(int hw)
  {
        struct dmar_drhd_unit *drhd;
                return 0;
  
        for_each_online_node(nid) {
 -              work_with_active_regions(nid, si_domain_work_fn, &ret);
 -              if (ret)
 -                      return ret;
 +              unsigned long start_pfn, end_pfn;
 +              int i;
 +
 +              for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, NULL) {
 +                      ret = iommu_domain_identity_map(si_domain,
 +                                      PFN_PHYS(start_pfn), PFN_PHYS(end_pfn));
 +                      if (ret)
 +                              return ret;
 +              }
        }
  
        return 0;
@@@ -3979,12 -4002,11 +3997,11 @@@ static void intel_iommu_detach_device(s
  
  static int intel_iommu_map(struct iommu_domain *domain,
                           unsigned long iova, phys_addr_t hpa,
-                          int gfp_order, int iommu_prot)
+                          size_t size, int iommu_prot)
  {
        struct dmar_domain *dmar_domain = domain->priv;
        u64 max_addr;
        int prot = 0;
-       size_t size;
        int ret;
  
        if (iommu_prot & IOMMU_READ)
        if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping)
                prot |= DMA_PTE_SNP;
  
-       size     = PAGE_SIZE << gfp_order;
        max_addr = iova + size;
        if (dmar_domain->max_addr < max_addr) {
                u64 end;
        return ret;
  }
  
- static int intel_iommu_unmap(struct iommu_domain *domain,
-                            unsigned long iova, int gfp_order)
+ static size_t intel_iommu_unmap(struct iommu_domain *domain,
+                            unsigned long iova, size_t size)
  {
        struct dmar_domain *dmar_domain = domain->priv;
-       size_t size = PAGE_SIZE << gfp_order;
        int order;
  
        order = dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT,
        if (dmar_domain->max_addr == iova + size)
                dmar_domain->max_addr = iova;
  
-       return order;
+       return PAGE_SIZE << order;
  }
  
  static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
@@@ -4060,6 -4080,54 +4075,54 @@@ static int intel_iommu_domain_has_cap(s
        return 0;
  }
  
+ /*
+  * Group numbers are arbitrary.  Device with the same group number
+  * indicate the iommu cannot differentiate between them.  To avoid
+  * tracking used groups we just use the seg|bus|devfn of the lowest
+  * level we're able to differentiate devices
+  */
+ static int intel_iommu_device_group(struct device *dev, unsigned int *groupid)
+ {
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct pci_dev *bridge;
+       union {
+               struct {
+                       u8 devfn;
+                       u8 bus;
+                       u16 segment;
+               } pci;
+               u32 group;
+       } id;
+       if (iommu_no_mapping(dev))
+               return -ENODEV;
+       id.pci.segment = pci_domain_nr(pdev->bus);
+       id.pci.bus = pdev->bus->number;
+       id.pci.devfn = pdev->devfn;
+       if (!device_to_iommu(id.pci.segment, id.pci.bus, id.pci.devfn))
+               return -ENODEV;
+       bridge = pci_find_upstream_pcie_bridge(pdev);
+       if (bridge) {
+               if (pci_is_pcie(bridge)) {
+                       id.pci.bus = bridge->subordinate->number;
+                       id.pci.devfn = 0;
+               } else {
+                       id.pci.bus = bridge->bus->number;
+                       id.pci.devfn = bridge->devfn;
+               }
+       }
+       if (!pdev->is_virtfn && iommu_group_mf)
+               id.pci.devfn = PCI_DEVFN(PCI_SLOT(id.pci.devfn), 0);
+       *groupid = id.group;
+       return 0;
+ }
  static struct iommu_ops intel_iommu_ops = {
        .domain_init    = intel_iommu_domain_init,
        .domain_destroy = intel_iommu_domain_destroy,
        .unmap          = intel_iommu_unmap,
        .iova_to_phys   = intel_iommu_iova_to_phys,
        .domain_has_cap = intel_iommu_domain_has_cap,
+       .device_group   = intel_iommu_device_group,
+       .pgsize_bitmap  = INTEL_IOMMU_PGSIZES,
  };
  
  static void __devinit quirk_iommu_rwbf(struct pci_dev *dev)
diff --combined virt/kvm/iommu.c
index 4e5f7b7f1d2be1828005e5081ab3af86d7f447f2,304d7e5717e93fbee1684e72feae56872cc332bb..0fb448e6a1a33288694e78ae764540df7e7a80bb
@@@ -113,7 -113,7 +113,7 @@@ int kvm_iommu_map_pages(struct kvm *kvm
  
                /* Map into IO address space */
                r = iommu_map(domain, gfn_to_gpa(gfn), pfn_to_hpa(pfn),
-                             get_order(page_size), flags);
+                             page_size, flags);
                if (r) {
                        printk(KERN_ERR "kvm_iommu_map_address:"
                               "iommu failed to map pfn=%llx\n", pfn);
@@@ -134,15 -134,14 +134,15 @@@ unmap_pages
  
  static int kvm_iommu_map_memslots(struct kvm *kvm)
  {
 -      int i, idx, r = 0;
 +      int idx, r = 0;
        struct kvm_memslots *slots;
 +      struct kvm_memory_slot *memslot;
  
        idx = srcu_read_lock(&kvm->srcu);
        slots = kvm_memslots(kvm);
  
 -      for (i = 0; i < slots->nmemslots; i++) {
 -              r = kvm_iommu_map_pages(kvm, &slots->memslots[i]);
 +      kvm_for_each_memslot(memslot, slots) {
 +              r = kvm_iommu_map_pages(kvm, memslot);
                if (r)
                        break;
        }
@@@ -293,15 -292,15 +293,15 @@@ static void kvm_iommu_put_pages(struct 
  
        while (gfn < end_gfn) {
                unsigned long unmap_pages;
-               int order;
+               size_t size;
  
                /* Get physical address */
                phys = iommu_iova_to_phys(domain, gfn_to_gpa(gfn));
                pfn  = phys >> PAGE_SHIFT;
  
                /* Unmap address from IO address space */
-               order       = iommu_unmap(domain, gfn_to_gpa(gfn), 0);
-               unmap_pages = 1ULL << order;
+               size       = iommu_unmap(domain, gfn_to_gpa(gfn), PAGE_SIZE);
+               unmap_pages = 1ULL << get_order(size);
  
                /* Unpin all pages we just unmapped to not leak any memory */
                kvm_unpin_pages(kvm, pfn, unmap_pages);
  
  static int kvm_iommu_unmap_memslots(struct kvm *kvm)
  {
 -      int i, idx;
 +      int idx;
        struct kvm_memslots *slots;
 +      struct kvm_memory_slot *memslot;
  
        idx = srcu_read_lock(&kvm->srcu);
        slots = kvm_memslots(kvm);
  
 -      for (i = 0; i < slots->nmemslots; i++) {
 -              kvm_iommu_put_pages(kvm, slots->memslots[i].base_gfn,
 -                                  slots->memslots[i].npages);
 -      }
 +      kvm_for_each_memslot(memslot, slots)
 +              kvm_iommu_put_pages(kvm, memslot->base_gfn, memslot->npages);
 +
        srcu_read_unlock(&kvm->srcu, idx);
  
        return 0;
This page took 0.080369 seconds and 4 git commands to generate.