]> Git Repo - linux.git/commitdiff
Merge branches 'dma-debug/next', 'amd-iommu/command-cleanups', 'amd-iommu/ats' and...
authorJoerg Roedel <[email protected]>
Tue, 10 May 2011 08:25:23 +0000 (10:25 +0200)
committerJoerg Roedel <[email protected]>
Tue, 10 May 2011 08:25:23 +0000 (10:25 +0200)
Conflicts:
arch/x86/include/asm/amd_iommu_types.h
arch/x86/kernel/amd_iommu.c
arch/x86/kernel/amd_iommu_init.c

1  2  3  4 
arch/x86/include/asm/amd_iommu_types.h
arch/x86/kernel/amd_iommu.c
arch/x86/kernel/amd_iommu_init.c
drivers/pci/intel-iommu.c

index e3509fc303bf5a54069e5b9b6b6edbc9ec390a49,e3509fc303bf5a54069e5b9b6b6edbc9ec390a49,7434377b2ab969fc78dab5dbcb81a90c67934082,df62d26ed2ab4acf5bae5226dd5e9f9599286007..4c9982995414a3f84a06f7483733ddb7d9d160a7
    #define MMIO_CONTROL_OFFSET     0x0018
    #define MMIO_EXCL_BASE_OFFSET   0x0020
    #define MMIO_EXCL_LIMIT_OFFSET  0x0028
+++ #define MMIO_EXT_FEATURES   0x0030
    #define MMIO_CMD_HEAD_OFFSET        0x2000
    #define MMIO_CMD_TAIL_OFFSET        0x2008
    #define MMIO_EVT_HEAD_OFFSET        0x2010
    #define MMIO_EVT_TAIL_OFFSET        0x2018
    #define MMIO_STATUS_OFFSET  0x2020
    
+++ 
+++ /* Extended Feature Bits */
+++ #define FEATURE_PREFETCH    (1ULL<<0)
+++ #define FEATURE_PPR         (1ULL<<1)
+++ #define FEATURE_X2APIC              (1ULL<<2)
+++ #define FEATURE_NX          (1ULL<<3)
+++ #define FEATURE_GT          (1ULL<<4)
+++ #define FEATURE_IA          (1ULL<<6)
+++ #define FEATURE_GA          (1ULL<<7)
+++ #define FEATURE_HE          (1ULL<<8)
+++ #define FEATURE_PC          (1ULL<<9)
+++ 
    /* MMIO status bits */
    #define MMIO_STATUS_COM_WAIT_INT_MASK       0x04
    
    /* command specific defines */
    #define CMD_COMPL_WAIT          0x01
    #define CMD_INV_DEV_ENTRY       0x02
-- -#define CMD_INV_IOMMU_PAGES     0x03
++ +#define CMD_INV_IOMMU_PAGES 0x03
++ +#define CMD_INV_IOTLB_PAGES 0x04
+++ #define CMD_INV_ALL         0x08
    
    #define CMD_COMPL_WAIT_STORE_MASK   0x01
    #define CMD_COMPL_WAIT_INT_MASK             0x02
    #define IOMMU_PTE_IR (1ULL << 61)
    #define IOMMU_PTE_IW (1ULL << 62)
    
++ +#define DTE_FLAG_IOTLB      0x01
++ +
    #define IOMMU_PAGE_MASK (((1ULL << 52) - 1) & ~0xfffULL)
    #define IOMMU_PTE_PRESENT(pte) ((pte) & IOMMU_PTE_P)
    #define IOMMU_PTE_PAGE(pte) (phys_to_virt((pte) & IOMMU_PAGE_MASK))
    /* IOMMU capabilities */
    #define IOMMU_CAP_IOTLB   24
    #define IOMMU_CAP_NPCACHE 26
+++ #define IOMMU_CAP_EFR     27
    
    #define MAX_DOMAIN_ID 65536
    
@@@@@ -249,6 -249,6 -252,8 -264,6 +267,8 @@@@@ extern bool amd_iommu_dump
    
    /* global flag if IOMMUs cache non-present entries */
    extern bool amd_iommu_np_cache;
++ +/* Only true if all IOMMUs support device IOTLBs */
++ +extern bool amd_iommu_iotlb_sup;
    
    /*
     * Make iterating over all IOMMUs easier
@@@@@ -371,6 -371,6 -376,6 -386,9 +391,9 @@@@@ struct amd_iommu 
        /* flags read from acpi table */
        u8 acpi_flags;
    
+++     /* Extended features */
+++     u64 features;
+++ 
        /*
         * Capability pointer. There could be more than one IOMMU per PCI
         * device function if there are more than one AMD IOMMU capability
        /* if one, we need to send a completion wait command */
        bool need_sync;
    
--      /* becomes true if a command buffer reset is running */
--      bool reset_in_progress;
--  
        /* default dma_ops domain for that IOMMU */
        struct dma_ops_domain *default_dom;
    
index 57ca777872206a7ab9df16158f769ee174ed5721,57ca777872206a7ab9df16158f769ee174ed5721,e4791f66aa3831bba6d7dceb0fc685e9d832866d,d6192bcf9f094ae7516f0000b0ad11f05c04b913..dc5dddafe5c24a148d28736b9cfe2f9f2ef8c97d
     */
    
    #include <linux/pci.h>
++ +#include <linux/pci-ats.h>
    #include <linux/bitmap.h>
    #include <linux/slab.h>
    #include <linux/debugfs.h>
    #include <linux/dma-mapping.h>
    #include <linux/iommu-helper.h>
    #include <linux/iommu.h>
++  #include <linux/delay.h>
    #include <asm/proto.h>
    #include <asm/iommu.h>
    #include <asm/gart.h>
    
    #define CMD_SET_TYPE(cmd, t) ((cmd)->data[1] |= ((t) << 28))
    
--  #define EXIT_LOOP_COUNT 10000000
++  #define LOOP_TIMEOUT        100000
    
    static DEFINE_RWLOCK(amd_iommu_devtable_lock);
    
@@@@@ -57,7 -57,7 -59,6 -58,6 +59,6 @@@@@ struct iommu_cmd 
        u32 data[4];
    };
    
--  static void reset_iommu_command_buffer(struct amd_iommu *iommu);
    static void update_domain(struct protection_domain *domain);
    
    /****************************************************************************
@@@@@ -322,8 -322,8 -323,6 -322,6 +323,6 @@@@@ static void iommu_print_event(struct am
                break;
        case EVENT_TYPE_ILL_CMD:
                printk("ILLEGAL_COMMAND_ERROR address=0x%016llx]\n", address);
--              iommu->reset_in_progress = true;
--              reset_iommu_command_buffer(iommu);
                dump_command(address);
                break;
        case EVENT_TYPE_CMD_HARD_ERR:
@@@@@ -383,188 -383,188 -382,271 -381,230 +382,291 @@@@@ irqreturn_t amd_iommu_int_handler(int i
     *
     ****************************************************************************/
    
--  /*
--   * Writes the command to the IOMMUs command buffer and informs the
--   * hardware about the new command. Must be called with iommu->lock held.
--   */
--  static int __iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
++  static int wait_on_sem(volatile u64 *sem)
++  {
++      int i = 0;
++  
++      while (*sem == 0 && i < LOOP_TIMEOUT) {
++              udelay(1);
++              i += 1;
++      }
++  
++      if (i == LOOP_TIMEOUT) {
++              pr_alert("AMD-Vi: Completion-Wait loop timed out\n");
++              return -EIO;
++      }
++  
++      return 0;
++  }
++  
++  static void copy_cmd_to_buffer(struct amd_iommu *iommu,
++                             struct iommu_cmd *cmd,
++                             u32 tail)
    {
--      u32 tail, head;
        u8 *target;
    
--      WARN_ON(iommu->cmd_buf_size & CMD_BUFFER_UNINITIALIZED);
--      tail = readl(iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
        target = iommu->cmd_buf + tail;
--      memcpy_toio(target, cmd, sizeof(*cmd));
--      tail = (tail + sizeof(*cmd)) % iommu->cmd_buf_size;
--      head = readl(iommu->mmio_base + MMIO_CMD_HEAD_OFFSET);
--      if (tail == head)
--              return -ENOMEM;
++      tail   = (tail + sizeof(*cmd)) % iommu->cmd_buf_size;
++  
++      /* Copy command to buffer */
++      memcpy(target, cmd, sizeof(*cmd));
++  
++      /* Tell the IOMMU about it */
        writel(tail, iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
++  }
    
--      return 0;
++  static void build_completion_wait(struct iommu_cmd *cmd, u64 address)
++  {
++      WARN_ON(address & 0x7ULL);
++  
++      memset(cmd, 0, sizeof(*cmd));
++      cmd->data[0] = lower_32_bits(__pa(address)) | CMD_COMPL_WAIT_STORE_MASK;
++      cmd->data[1] = upper_32_bits(__pa(address));
++      cmd->data[2] = 1;
++      CMD_SET_TYPE(cmd, CMD_COMPL_WAIT);
++  }
++  
++  static void build_inv_dte(struct iommu_cmd *cmd, u16 devid)
++  {
++      memset(cmd, 0, sizeof(*cmd));
++      cmd->data[0] = devid;
++      CMD_SET_TYPE(cmd, CMD_INV_DEV_ENTRY);
++  }
++  
++  static void build_inv_iommu_pages(struct iommu_cmd *cmd, u64 address,
++                                size_t size, u16 domid, int pde)
++  {
++      u64 pages;
++      int s;
++  
++      pages = iommu_num_pages(address, size, PAGE_SIZE);
++      s     = 0;
++  
++      if (pages > 1) {
++              /*
++               * If we have to flush more than one page, flush all
++               * TLB entries for this domain
++               */
++              address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS;
++              s = 1;
++      }
++  
++      address &= PAGE_MASK;
++  
++      memset(cmd, 0, sizeof(*cmd));
++      cmd->data[1] |= domid;
++      cmd->data[2]  = lower_32_bits(address);
++      cmd->data[3]  = upper_32_bits(address);
++      CMD_SET_TYPE(cmd, CMD_INV_IOMMU_PAGES);
++      if (s) /* size bit - we flush more than one 4kb page */
++              cmd->data[2] |= CMD_INV_IOMMU_PAGES_SIZE_MASK;
++      if (pde) /* PDE bit - we wan't flush everything not only the PTEs */
++              cmd->data[2] |= CMD_INV_IOMMU_PAGES_PDE_MASK;
++  }
++  
++ +static void build_inv_iotlb_pages(struct iommu_cmd *cmd, u16 devid, int qdep,
++ +                              u64 address, size_t size)
++ +{
++ +    u64 pages;
++ +    int s;
++ +
++ +    pages = iommu_num_pages(address, size, PAGE_SIZE);
++ +    s     = 0;
++ +
++ +    if (pages > 1) {
++ +            /*
++ +             * If we have to flush more than one page, flush all
++ +             * TLB entries for this domain
++ +             */
++ +            address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS;
++ +            s = 1;
++ +    }
++ +
++ +    address &= PAGE_MASK;
++ +
++ +    memset(cmd, 0, sizeof(*cmd));
++ +    cmd->data[0]  = devid;
++ +    cmd->data[0] |= (qdep & 0xff) << 24;
++ +    cmd->data[1]  = devid;
++ +    cmd->data[2]  = lower_32_bits(address);
++ +    cmd->data[3]  = upper_32_bits(address);
++ +    CMD_SET_TYPE(cmd, CMD_INV_IOTLB_PAGES);
++ +    if (s)
++ +            cmd->data[2] |= CMD_INV_IOMMU_PAGES_SIZE_MASK;
++ +}
++ +
+++ static void build_inv_all(struct iommu_cmd *cmd)
+++ {
+++     memset(cmd, 0, sizeof(*cmd));
+++     CMD_SET_TYPE(cmd, CMD_INV_ALL);
  + }
  + 
    /*
--   * General queuing function for commands. Takes iommu->lock and calls
--   * __iommu_queue_command().
++   * Writes the command to the IOMMUs command buffer and informs the
++   * hardware about the new command.
     */
    static int iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
    {
++      u32 left, tail, head, next_tail;
        unsigned long flags;
--      int ret;
    
++      WARN_ON(iommu->cmd_buf_size & CMD_BUFFER_UNINITIALIZED);
++  
++  again:
        spin_lock_irqsave(&iommu->lock, flags);
--      ret = __iommu_queue_command(iommu, cmd);
--      if (!ret)
--              iommu->need_sync = true;
--      spin_unlock_irqrestore(&iommu->lock, flags);
    
--      return ret;
--  }
++      head      = readl(iommu->mmio_base + MMIO_CMD_HEAD_OFFSET);
++      tail      = readl(iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
++      next_tail = (tail + sizeof(*cmd)) % iommu->cmd_buf_size;
++      left      = (head - next_tail) % iommu->cmd_buf_size;
    
--  /*
--   * This function waits until an IOMMU has completed a completion
--   * wait command
--   */
--  static void __iommu_wait_for_completion(struct amd_iommu *iommu)
--  {
--      int ready = 0;
--      unsigned status = 0;
--      unsigned long i = 0;
++      if (left <= 2) {
++              struct iommu_cmd sync_cmd;
++              volatile u64 sem = 0;
++              int ret;
    
--      INC_STATS_COUNTER(compl_wait);
++              build_completion_wait(&sync_cmd, (u64)&sem);
++              copy_cmd_to_buffer(iommu, &sync_cmd, tail);
    
--      while (!ready && (i < EXIT_LOOP_COUNT)) {
--              ++i;
--              /* wait for the bit to become one */
--              status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET);
--              ready = status & MMIO_STATUS_COM_WAIT_INT_MASK;
++              spin_unlock_irqrestore(&iommu->lock, flags);
++  
++              if ((ret = wait_on_sem(&sem)) != 0)
++                      return ret;
++  
++              goto again;
        }
    
--      /* set bit back to zero */
--      status &= ~MMIO_STATUS_COM_WAIT_INT_MASK;
--      writel(status, iommu->mmio_base + MMIO_STATUS_OFFSET);
++      copy_cmd_to_buffer(iommu, cmd, tail);
++  
++      /* We need to sync now to make sure all commands are processed */
++      iommu->need_sync = true;
++  
++      spin_unlock_irqrestore(&iommu->lock, flags);
    
--      if (unlikely(i == EXIT_LOOP_COUNT))
--              iommu->reset_in_progress = true;
++      return 0;
    }
    
    /*
     * This function queues a completion wait command into the command
     * buffer of an IOMMU
     */
--  static int __iommu_completion_wait(struct amd_iommu *iommu)
++  static int iommu_completion_wait(struct amd_iommu *iommu)
    {
        struct iommu_cmd cmd;
++      volatile u64 sem = 0;
++      int ret;
    
--       memset(&cmd, 0, sizeof(cmd));
--       cmd.data[0] = CMD_COMPL_WAIT_INT_MASK;
--       CMD_SET_TYPE(&cmd, CMD_COMPL_WAIT);
++      if (!iommu->need_sync)
++              return 0;
++  
++      build_completion_wait(&cmd, (u64)&sem);
++  
++      ret = iommu_queue_command(iommu, &cmd);
++      if (ret)
++              return ret;
    
--       return __iommu_queue_command(iommu, &cmd);
++      return wait_on_sem(&sem);
    }
    
--  /*
--   * This function is called whenever we need to ensure that the IOMMU has
--   * completed execution of all commands we sent. It sends a
--   * COMPLETION_WAIT command and waits for it to finish. The IOMMU informs
--   * us about that by writing a value to a physical address we pass with
--   * the command.
--   */
--  static int iommu_completion_wait(struct amd_iommu *iommu)
++  static int iommu_flush_dte(struct amd_iommu *iommu, u16 devid)
    {
--      int ret = 0;
--      unsigned long flags;
++      struct iommu_cmd cmd;
    
--      spin_lock_irqsave(&iommu->lock, flags);
++      build_inv_dte(&cmd, devid);
    
--      if (!iommu->need_sync)
--              goto out;
++      return iommu_queue_command(iommu, &cmd);
++  }
    
--      ret = __iommu_completion_wait(iommu);
++  static void iommu_flush_dte_all(struct amd_iommu *iommu)
++  {
++      u32 devid;
    
--      iommu->need_sync = false;
++      for (devid = 0; devid <= 0xffff; ++devid)
++              iommu_flush_dte(iommu, devid);
    
--      if (ret)
--              goto out;
--  
--      __iommu_wait_for_completion(iommu);
++      iommu_completion_wait(iommu);
++  }
    
--  out:
--      spin_unlock_irqrestore(&iommu->lock, flags);
++  /*
++   * This function uses heavy locking and may disable irqs for some time. But
++   * this is no issue because it is only called during resume.
++   */
++  static void iommu_flush_tlb_all(struct amd_iommu *iommu)
++  {
++      u32 dom_id;
    
--      if (iommu->reset_in_progress)
--              reset_iommu_command_buffer(iommu);
++      for (dom_id = 0; dom_id <= 0xffff; ++dom_id) {
++              struct iommu_cmd cmd;
++              build_inv_iommu_pages(&cmd, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS,
++                                    dom_id, 1);
++              iommu_queue_command(iommu, &cmd);
++      }
    
--      return 0;
++      iommu_completion_wait(iommu);
    }
    
--  static void iommu_flush_complete(struct protection_domain *domain)
+++ static void iommu_flush_all(struct amd_iommu *iommu)
  + {
--      int i;
+++     struct iommu_cmd cmd;
  + 
--      for (i = 0; i < amd_iommus_present; ++i) {
--              if (!domain->dev_iommu[i])
--                      continue;
+++     build_inv_all(&cmd);
  + 
--              /*
--               * Devices of this domain are behind this IOMMU
--               * We need to wait for completion of all commands.
--               */
--              iommu_completion_wait(amd_iommus[i]);
+++     iommu_queue_command(iommu, &cmd);
+++     iommu_completion_wait(iommu);
+++ }
+++ 
++  void iommu_flush_all_caches(struct amd_iommu *iommu)
++  {
  -     iommu_flush_dte_all(iommu);
  -     iommu_flush_tlb_all(iommu);
+++     if (iommu_feature(iommu, FEATURE_IA)) {
+++             iommu_flush_all(iommu);
+++     } else {
+++             iommu_flush_dte_all(iommu);
+++             iommu_flush_tlb_all(iommu);
  +     }
    }
    
--   * Command send function for invalidating a device table entry
   +/*
--  static int iommu_flush_device(struct device *dev)
++ + * Command send function for flushing on-device TLB
   + */
--      /* Build command */
--      memset(&cmd, 0, sizeof(cmd));
--      CMD_SET_TYPE(&cmd, CMD_INV_DEV_ENTRY);
--      cmd.data[0] = devid;
++ +static int device_flush_iotlb(struct device *dev, u64 address, size_t size)
   +{
++ +    struct pci_dev *pdev = to_pci_dev(dev);
   +    struct amd_iommu *iommu;
   +    struct iommu_cmd cmd;
   +    u16 devid;
++ +    int qdep;
   +
++ +    qdep  = pci_ats_queue_depth(pdev);
   +    devid = get_device_id(dev);
   +    iommu = amd_iommu_rlookup_table[devid];
   +
--  static void __iommu_build_inv_iommu_pages(struct iommu_cmd *cmd, u64 address,
--                                        u16 domid, int pde, int s)
--  {
--      memset(cmd, 0, sizeof(*cmd));
--      address &= PAGE_MASK;
--      CMD_SET_TYPE(cmd, CMD_INV_IOMMU_PAGES);
--      cmd->data[1] |= domid;
--      cmd->data[2] = lower_32_bits(address);
--      cmd->data[3] = upper_32_bits(address);
--      if (s) /* size bit - we flush more than one 4kb page */
--              cmd->data[2] |= CMD_INV_IOMMU_PAGES_SIZE_MASK;
--      if (pde) /* PDE bit - we wan't flush everything not only the PTEs */
--              cmd->data[2] |= CMD_INV_IOMMU_PAGES_PDE_MASK;
--  }
--  
++ +    build_inv_iotlb_pages(&cmd, devid, qdep, address, size);
   +
   +    return iommu_queue_command(iommu, &cmd);
   +}
   +
    /*
--   * Generic command send function for invalidaing TLB entries
++   * Command send function for invalidating a device table entry
     */
--  static int iommu_queue_inv_iommu_pages(struct amd_iommu *iommu,
--              u64 address, u16 domid, int pde, int s)
++  static int device_flush_dte(struct device *dev)
    {
--      struct iommu_cmd cmd;
++      struct amd_iommu *iommu;
++ +    struct pci_dev *pdev;
++      u16 devid;
   +    int ret;
    
--      __iommu_build_inv_iommu_pages(&cmd, address, domid, pde, s);
++ +    pdev  = to_pci_dev(dev);
++      devid = get_device_id(dev);
++      iommu = amd_iommu_rlookup_table[devid];
    
--      ret = iommu_queue_command(iommu, &cmd);
   -    return iommu_flush_dte(iommu, devid);
++ +    ret = iommu_flush_dte(iommu, devid);
++ +    if (ret)
++ +            return ret;
++ +
++ +    if (pci_ats_enabled(pdev))
++ +            ret = device_flush_iotlb(dev, 0, ~0UL);
   +
   +    return ret;
    }
    
    /*
     * It invalidates a single PTE if the range to flush is within a single
     * page. Otherwise it flushes the whole TLB of the IOMMU.
     */
--  static void __iommu_flush_pages(struct protection_domain *domain,
--                              u64 address, size_t size, int pde)
++  static void __domain_flush_pages(struct protection_domain *domain,
++                               u64 address, size_t size, int pde)
    {
--      int s = 0, i;
--      unsigned long pages = iommu_num_pages(address, size, PAGE_SIZE);
--  
--      address &= PAGE_MASK;
--  
--      if (pages > 1) {
--              /*
--               * If we have to flush more than one page, flush all
--               * TLB entries for this domain
--               */
--              address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS;
--              s = 1;
--      }
++ +    struct iommu_dev_data *dev_data;
++      struct iommu_cmd cmd;
++      int ret = 0, i;
    
++      build_inv_iommu_pages(&cmd, address, size, domain->id, pde);
    
        for (i = 0; i < amd_iommus_present; ++i) {
                if (!domain->dev_iommu[i])
                 * Devices of this domain are behind this IOMMU
                 * We need a TLB flush
                 */
--              iommu_queue_inv_iommu_pages(amd_iommus[i], address,
--                                          domain->id, pde, s);
++              ret |= iommu_queue_command(amd_iommus[i], &cmd);
        }
    
--      return;
++ +    list_for_each_entry(dev_data, &domain->dev_list, list) {
++ +            struct pci_dev *pdev = to_pci_dev(dev_data->dev);
++ +
++ +            if (!pci_ats_enabled(pdev))
++ +                    continue;
++ +
++ +            ret |= device_flush_iotlb(dev_data->dev, address, size);
++ +    }
++ +
++      WARN_ON(ret);
    }
    
--  static void iommu_flush_pages(struct protection_domain *domain,
--                           u64 address, size_t size)
++  static void domain_flush_pages(struct protection_domain *domain,
++                             u64 address, size_t size)
    {
--      __iommu_flush_pages(domain, address, size, 0);
++      __domain_flush_pages(domain, address, size, 0);
    }
    
    /* Flush the whole IO/TLB for a given protection domain */
--  static void iommu_flush_tlb(struct protection_domain *domain)
++  static void domain_flush_tlb(struct protection_domain *domain)
    {
--      __iommu_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 0);
++      __domain_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 0);
    }
    
    /* Flush the whole IO/TLB for a given protection domain - including PDE */
--  static void iommu_flush_tlb_pde(struct protection_domain *domain)
++  static void domain_flush_tlb_pde(struct protection_domain *domain)
    {
--      __iommu_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 1);
++      __domain_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 1);
    }
    
--  
--  /*
--   * This function flushes the DTEs for all devices in domain
--   */
--  static void iommu_flush_domain_devices(struct protection_domain *domain)
++  static void domain_flush_complete(struct protection_domain *domain)
    {
--      struct iommu_dev_data *dev_data;
--      unsigned long flags;
--  
--      spin_lock_irqsave(&domain->lock, flags);
--  
--      list_for_each_entry(dev_data, &domain->dev_list, list)
--              iommu_flush_device(dev_data->dev);
--  
--      spin_unlock_irqrestore(&domain->lock, flags);
--  }
--  
--  static void iommu_flush_all_domain_devices(void)
--  {
--      struct protection_domain *domain;
--      unsigned long flags;
++      int i;
    
--      spin_lock_irqsave(&amd_iommu_pd_lock, flags);
++      for (i = 0; i < amd_iommus_present; ++i) {
++              if (!domain->dev_iommu[i])
++                      continue;
    
--      list_for_each_entry(domain, &amd_iommu_pd_list, list) {
--              iommu_flush_domain_devices(domain);
--              iommu_flush_complete(domain);
++              /*
++               * Devices of this domain are behind this IOMMU
++               * We need to wait for completion of all commands.
++               */
++              iommu_completion_wait(amd_iommus[i]);
        }
--  
--      spin_unlock_irqrestore(&amd_iommu_pd_lock, flags);
    }
    
--  void amd_iommu_flush_all_devices(void)
--  {
--      iommu_flush_all_domain_devices();
--  }
    
    /*
--   * This function uses heavy locking and may disable irqs for some time. But
--   * this is no issue because it is only called during resume.
++   * This function flushes the DTEs for all devices in domain
     */
--  void amd_iommu_flush_all_domains(void)
++  static void domain_flush_devices(struct protection_domain *domain)
    {
--      struct protection_domain *domain;
++      struct iommu_dev_data *dev_data;
        unsigned long flags;
    
--      spin_lock_irqsave(&amd_iommu_pd_lock, flags);
--  
--      list_for_each_entry(domain, &amd_iommu_pd_list, list) {
--              spin_lock(&domain->lock);
--              iommu_flush_tlb_pde(domain);
--              iommu_flush_complete(domain);
--              spin_unlock(&domain->lock);
--      }
--  
--      spin_unlock_irqrestore(&amd_iommu_pd_lock, flags);
--  }
--  
--  static void reset_iommu_command_buffer(struct amd_iommu *iommu)
--  {
--      pr_err("AMD-Vi: Resetting IOMMU command buffer\n");
--  
--      if (iommu->reset_in_progress)
--              panic("AMD-Vi: ILLEGAL_COMMAND_ERROR while resetting command buffer\n");
++      spin_lock_irqsave(&domain->lock, flags);
    
--      amd_iommu_reset_cmd_buffer(iommu);
--      amd_iommu_flush_all_devices();
--      amd_iommu_flush_all_domains();
++      list_for_each_entry(dev_data, &domain->dev_list, list)
++              device_flush_dte(dev_data->dev);
    
--      iommu->reset_in_progress = false;
++      spin_unlock_irqrestore(&domain->lock, flags);
    }
    
    /****************************************************************************
@@@@@ -1410,17 -1410,17 -1452,22 -1400,17 +1472,22 @@@@@ static bool dma_ops_domain(struct prote
        return domain->flags & PD_DMA_OPS_MASK;
    }
    
-- -static void set_dte_entry(u16 devid, struct protection_domain *domain)
++ +static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats)
    {
        u64 pte_root = virt_to_phys(domain->pt_root);
++ +    u32 flags = 0;
    
        pte_root |= (domain->mode & DEV_ENTRY_MODE_MASK)
                    << DEV_ENTRY_MODE_SHIFT;
        pte_root |= IOMMU_PTE_IR | IOMMU_PTE_IW | IOMMU_PTE_P | IOMMU_PTE_TV;
    
-- -    amd_iommu_dev_table[devid].data[2] = domain->id;
-- -    amd_iommu_dev_table[devid].data[1] = upper_32_bits(pte_root);
-- -    amd_iommu_dev_table[devid].data[0] = lower_32_bits(pte_root);
++ +    if (ats)
++ +            flags |= DTE_FLAG_IOTLB;
++ +
++ +    amd_iommu_dev_table[devid].data[3] |= flags;
++ +    amd_iommu_dev_table[devid].data[2]  = domain->id;
++ +    amd_iommu_dev_table[devid].data[1]  = upper_32_bits(pte_root);
++ +    amd_iommu_dev_table[devid].data[0]  = lower_32_bits(pte_root);
    }
    
    static void clear_dte_entry(u16 devid)
@@@@@ -1437,34 -1437,34 -1484,42 -1427,34 +1504,42 @@@@@ static void do_attach(struct device *de
    {
        struct iommu_dev_data *dev_data;
        struct amd_iommu *iommu;
++ +    struct pci_dev *pdev;
++ +    bool ats = false;
        u16 devid;
    
        devid    = get_device_id(dev);
        iommu    = amd_iommu_rlookup_table[devid];
        dev_data = get_dev_data(dev);
++ +    pdev     = to_pci_dev(dev);
++ +
++ +    if (amd_iommu_iotlb_sup)
++ +            ats = pci_ats_enabled(pdev);
    
        /* Update data structures */
        dev_data->domain = domain;
        list_add(&dev_data->list, &domain->dev_list);
-- -    set_dte_entry(devid, domain);
++ +    set_dte_entry(devid, domain, ats);
    
        /* Do reference counting */
        domain->dev_iommu[iommu->index] += 1;
        domain->dev_cnt                 += 1;
    
        /* Flush the DTE entry */
--      iommu_flush_device(dev);
++      device_flush_dte(dev);
    }
    
    static void do_detach(struct device *dev)
    {
        struct iommu_dev_data *dev_data;
        struct amd_iommu *iommu;
++ +    struct pci_dev *pdev;
        u16 devid;
    
        devid    = get_device_id(dev);
        iommu    = amd_iommu_rlookup_table[devid];
        dev_data = get_dev_data(dev);
++ +    pdev     = to_pci_dev(dev);
    
        /* decrease reference counters */
        dev_data->domain->dev_iommu[iommu->index] -= 1;
        clear_dte_entry(devid);
    
        /* Flush the DTE entry */
--      iommu_flush_device(dev);
++      device_flush_dte(dev);
    }
    
    /*
@@@@@ -1539,9 -1539,9 -1594,13 -1529,9 +1614,13 @@@@@ out_unlock
    static int attach_device(struct device *dev,
                         struct protection_domain *domain)
    {
++ +    struct pci_dev *pdev = to_pci_dev(dev);
        unsigned long flags;
        int ret;
    
++ +    if (amd_iommu_iotlb_sup)
++ +            pci_enable_ats(pdev, PAGE_SHIFT);
++ +
        write_lock_irqsave(&amd_iommu_devtable_lock, flags);
        ret = __attach_device(dev, domain);
        write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
         * left the caches in the IOMMU dirty. So we have to flush
         * here to evict all dirty stuff.
         */
--      iommu_flush_tlb_pde(domain);
++      domain_flush_tlb_pde(domain);
    
        return ret;
    }
@@@@@ -1598,12 -1598,12 -1657,16 -1588,12 +1677,16 @@@@@ static void __detach_device(struct devi
     */
    static void detach_device(struct device *dev)
    {
++ +    struct pci_dev *pdev = to_pci_dev(dev);
        unsigned long flags;
    
        /* lock device table */
        write_lock_irqsave(&amd_iommu_devtable_lock, flags);
        __detach_device(dev);
        write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
++ +
++ +    if (amd_iommu_iotlb_sup && pci_ats_enabled(pdev))
++ +            pci_disable_ats(pdev);
    }
    
    /*
@@@@@ -1692,7 -1692,7 -1755,7 -1682,7 +1775,7 @@@@@ static int device_change_notifier(struc
                goto out;
        }
    
--      iommu_flush_device(dev);
++      device_flush_dte(dev);
        iommu_completion_wait(iommu);
    
    out:
@@@@@ -1753,8 -1753,8 -1816,9 -1743,8 +1836,9 @@@@@ static void update_device_table(struct 
        struct iommu_dev_data *dev_data;
    
        list_for_each_entry(dev_data, &domain->dev_list, list) {
++ +            struct pci_dev *pdev = to_pci_dev(dev_data->dev);
                u16 devid = get_device_id(dev_data->dev);
-- -            set_dte_entry(devid, domain);
++ +            set_dte_entry(devid, domain, pci_ats_enabled(pdev));
        }
    }
    
@@@@@ -1764,8 -1764,8 -1828,9 -1754,9 +1848,9 @@@@@ static void update_domain(struct protec
                return;
    
        update_device_table(domain);
--      iommu_flush_domain_devices(domain);
--      iommu_flush_tlb_pde(domain);
++  
++      domain_flush_devices(domain);
++      domain_flush_tlb_pde(domain);
    
        domain->updated = false;
    }
        ADD_STATS_COUNTER(alloced_io_mem, size);
    
        if (unlikely(dma_dom->need_flush && !amd_iommu_unmap_flush)) {
--              iommu_flush_tlb(&dma_dom->domain);
++              domain_flush_tlb(&dma_dom->domain);
                dma_dom->need_flush = false;
        } else if (unlikely(amd_iommu_np_cache))
--              iommu_flush_pages(&dma_dom->domain, address, size);
++              domain_flush_pages(&dma_dom->domain, address, size);
    
    out:
        return address;
@@@@@ -1976,7 -1976,7 -2041,7 -1967,7 +2061,7 @@@@@ static void __unmap_single(struct dma_o
        dma_ops_free_addresses(dma_dom, dma_addr, pages);
    
        if (amd_iommu_unmap_flush || dma_dom->need_flush) {
--              iommu_flush_pages(&dma_dom->domain, flush_addr, size);
++              domain_flush_pages(&dma_dom->domain, flush_addr, size);
                dma_dom->need_flush = false;
        }
    }
@@@@@ -2012,7 -2012,7 -2077,7 -2003,7 +2097,7 @@@@@ static dma_addr_t map_page(struct devic
        if (addr == DMA_ERROR_CODE)
                goto out;
    
--      iommu_flush_complete(domain);
++      domain_flush_complete(domain);
    
    out:
        spin_unlock_irqrestore(&domain->lock, flags);
@@@@@ -2039,7 -2039,7 -2104,7 -2030,7 +2124,7 @@@@@ static void unmap_page(struct device *d
    
        __unmap_single(domain->priv, dma_addr, size, dir);
    
--      iommu_flush_complete(domain);
++      domain_flush_complete(domain);
    
        spin_unlock_irqrestore(&domain->lock, flags);
    }
@@@@@ -2104,7 -2104,7 -2169,7 -2095,7 +2189,7 @@@@@ static int map_sg(struct device *dev, s
                        goto unmap;
        }
    
--      iommu_flush_complete(domain);
++      domain_flush_complete(domain);
    
    out:
        spin_unlock_irqrestore(&domain->lock, flags);
@@@@@ -2150,7 -2150,7 -2215,7 -2141,7 +2235,7 @@@@@ static void unmap_sg(struct device *dev
                s->dma_address = s->dma_length = 0;
        }
    
--      iommu_flush_complete(domain);
++      domain_flush_complete(domain);
    
        spin_unlock_irqrestore(&domain->lock, flags);
    }
@@@@@ -2200,7 -2200,7 -2265,7 -2191,7 +2285,7 @@@@@ static void *alloc_coherent(struct devi
                goto out_free;
        }
    
--      iommu_flush_complete(domain);
++      domain_flush_complete(domain);
    
        spin_unlock_irqrestore(&domain->lock, flags);
    
@@@@@ -2232,7 -2232,7 -2297,7 -2223,7 +2317,7 @@@@@ static void free_coherent(struct devic
    
        __unmap_single(domain->priv, dma_addr, size, DMA_BIDIRECTIONAL);
    
--      iommu_flush_complete(domain);
++      domain_flush_complete(domain);
    
        spin_unlock_irqrestore(&domain->lock, flags);
    
@@@@@ -2476,7 -2476,7 -2541,7 -2467,7 +2561,7 @@@@@ static void amd_iommu_detach_device(str
        if (!iommu)
                return;
    
--      iommu_flush_device(dev);
++      device_flush_dte(dev);
        iommu_completion_wait(iommu);
    }
    
@@@@@ -2542,7 -2542,7 -2607,7 -2533,7 +2627,7 @@@@@ static int amd_iommu_unmap(struct iommu
        unmap_size = iommu_unmap_page(domain, iova, page_size);
        mutex_unlock(&domain->api_lock);
    
--      iommu_flush_tlb_pde(domain);
++      domain_flush_tlb_pde(domain);
    
        return get_order(unmap_size);
    }
index 246d727b65b7987babfaf64dc71dd5f78271a64b,246d727b65b7987babfaf64dc71dd5f78271a64b,b6c634f3dc07e917de7d2670b9b953c8ac600899,047905dc3e14e2f995a96e9035aac70a638d4a3d..28b07813368870f238384ee472fbc0133e971b14
@@@@@ -137,6 -137,6 -137,7 -137,6 +137,7 @@@@@ int amd_iommus_present
    
    /* IOMMUs have a non-present cache? */
    bool amd_iommu_np_cache __read_mostly;
++ +bool amd_iommu_iotlb_sup __read_mostly = true;
    
    /*
     * The ACPI table parsing functions set this variable on an error
@@@@@ -180,6 -180,6 -181,12 -180,12 +181,12 @@@@@ static u32 dev_table_size;    /* size of t
    static u32 alias_table_size;        /* size of the alias table */
    static u32 rlookup_table_size;      /* size if the rlookup table */
    
++  /*
++   * This function flushes all internal caches of
++   * the IOMMU used by this driver.
++   */
++  extern void iommu_flush_all_caches(struct amd_iommu *iommu);
++  
    static inline void update_last_devid(u16 devid)
    {
        if (devid > amd_iommu_last_bdf)
@@@@@ -293,9 -293,9 -300,9 -299,23 +300,23 @@@@@ static void iommu_feature_disable(struc
    /* Function to enable the hardware */
    static void iommu_enable(struct amd_iommu *iommu)
    {
---     printk(KERN_INFO "AMD-Vi: Enabling IOMMU at %s cap 0x%hx\n",
+++     static const char * const feat_str[] = {
+++             "PreF", "PPR", "X2APIC", "NX", "GT", "[5]",
+++             "IA", "GA", "HE", "PC", NULL
+++     };
+++     int i;
+++ 
+++     printk(KERN_INFO "AMD-Vi: Enabling IOMMU at %s cap 0x%hx",
               dev_name(&iommu->dev->dev), iommu->cap_ptr);
    
+++     if (iommu->cap & (1 << IOMMU_CAP_EFR)) {
+++             printk(KERN_CONT " extended features: ");
+++             for (i = 0; feat_str[i]; ++i)
+++                     if (iommu_feature(iommu, (1ULL << i)))
+++                             printk(KERN_CONT " %s", feat_str[i]);
+++     }
+++     printk(KERN_CONT "\n");
+++ 
        iommu_feature_enable(iommu, CONTROL_IOMMU_EN);
    }
    
@@@@@ -651,7 -651,7 -658,7 -671,7 +672,7 @@@@@ static void __init set_device_exclusion
    static void __init init_iommu_from_pci(struct amd_iommu *iommu)
    {
        int cap_ptr = iommu->cap_ptr;
---     u32 range, misc;
+++     u32 range, misc, low, high;
        int i, j;
    
        pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET,
                                        MMIO_GET_LD(range));
        iommu->evt_msi_num = MMIO_MSI_NUM(misc);
    
++ +    if (!(iommu->cap & (1 << IOMMU_CAP_IOTLB)))
++ +            amd_iommu_iotlb_sup = false;
++ +
+++     /* read extended feature bits */
+++     low  = readl(iommu->mmio_base + MMIO_EXT_FEATURES);
+++     high = readl(iommu->mmio_base + MMIO_EXT_FEATURES + 4);
+++ 
+++     iommu->features = ((u64)high << 32) | low;
+++ 
        if (!is_rd890_iommu(iommu->dev))
                return;
    
@@@@@ -1244,6 -1244,6 -1254,7 -1270,7 +1274,7 @@@@@ static void enable_iommus(void
                iommu_set_exclusion_range(iommu);
                iommu_init_msi(iommu);
                iommu_enable(iommu);
++              iommu_flush_all_caches(iommu);
        }
    }
    
@@@@@ -1274,8 -1274,8 -1285,8 -1301,8 +1305,8 @@@@@ static void amd_iommu_resume(void
         * we have to flush after the IOMMUs are enabled because a
         * disabled IOMMU will never execute the commands we send
         */
--      amd_iommu_flush_all_devices();
--      amd_iommu_flush_all_domains();
++      for_each_iommu(iommu)
++              iommu_flush_all_caches(iommu);
    }
    
    static int amd_iommu_suspend(void)
index d552d2c77844327010074ee71550e58ccb0a3280,7da3bef60d8708c12f2cc421de27ef968b00eb1e,fdb2cef2b908c0eb49af219538bc470d306810ed,7da3bef60d8708c12f2cc421de27ef968b00eb1e..6af6b628175b459f03c2f0969f9b2be6d65dba48
    #include <linux/syscore_ops.h>
    #include <linux/tboot.h>
    #include <linux/dmi.h>
++ +#include <linux/pci-ats.h>
    #include <asm/cacheflush.h>
    #include <asm/iommu.h>
    #include "pci.h"
@@@@@ -1299,7 -1299,7 -1300,7 -1299,7 +1300,7 @@@@@ static void iommu_detach_domain(struct 
    static struct iova_domain reserved_iova_list;
    static struct lock_class_key reserved_rbtree_key;
    
 ---static void dmar_init_reserved_ranges(void)
 +++static int dmar_init_reserved_ranges(void)
    {
        struct pci_dev *pdev = NULL;
        struct iova *iova;
        /* IOAPIC ranges shouldn't be accessed by DMA */
        iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START),
                IOVA_PFN(IOAPIC_RANGE_END));
 ---    if (!iova)
 +++    if (!iova) {
                printk(KERN_ERR "Reserve IOAPIC range failed\n");
 +++            return -ENODEV;
 +++    }
    
        /* Reserve all PCI MMIO to avoid peer-to-peer access */
        for_each_pci_dev(pdev) {
                        iova = reserve_iova(&reserved_iova_list,
                                            IOVA_PFN(r->start),
                                            IOVA_PFN(r->end));
 ---                    if (!iova)
 +++                    if (!iova) {
                                printk(KERN_ERR "Reserve iova failed\n");
 +++                            return -ENODEV;
 +++                    }
                }
        }
 ---
 +++    return 0;
    }
    
    static void domain_reserve_special_ranges(struct dmar_domain *domain)
@@@@@ -1839,7 -1835,7 -1836,7 -1835,7 +1840,7 @@@@@ static struct dmar_domain *get_domain_f
    
        ret = iommu_attach_domain(domain, iommu);
        if (ret) {
 ---            domain_exit(domain);
 +++            free_domain_mem(domain);
                goto error;
        }
    
@@@@@ -2217,7 -2213,7 -2214,7 -2213,7 +2218,7 @@@@@ static int __init iommu_prepare_static_
        return 0;
    }
    
 ---int __init init_dmars(void)
 +++static int __init init_dmars(int force_on)
    {
        struct dmar_drhd_unit *drhd;
        struct dmar_rmrr_unit *rmrr;
                /*
                 * TBD:
                 * we could share the same root & context tables
 ---             * amoung all IOMMU's. Need to Split it later.
 +++             * among all IOMMU's. Need to Split it later.
                 */
                ret = iommu_alloc_root_entry(iommu);
                if (ret) {
         *   enable translation
         */
        for_each_drhd_unit(drhd) {
 ---            if (drhd->ignored)
 +++            if (drhd->ignored) {
 +++                    /*
 +++                     * we always have to disable PMRs or DMA may fail on
 +++                     * this device
 +++                     */
 +++                    if (force_on)
 +++                            iommu_disable_protect_mem_regions(drhd->iommu);
                        continue;
 +++            }
                iommu = drhd->iommu;
    
                iommu_flush_write_buffer(iommu);
@@@@@ -3251,15 -3240,9 -3241,9 -3240,9 +3252,15 @@@@@ static int device_notifier(struct notif
        if (!domain)
                return 0;
    
 ---    if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through)
 +++    if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through) {
                domain_remove_one_dev_info(domain, pdev);
    
 +++            if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) &&
 +++                !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) &&
 +++                list_empty(&domain->devices))
 +++                    domain_exit(domain);
 +++    }
 +++
        return 0;
    }
    
@@@@@ -3294,21 -3277,12 -3278,12 -3277,12 +3295,21 @@@@@ int __init intel_iommu_init(void
        if (no_iommu || dmar_disabled)
                return -ENODEV;
    
 ---    iommu_init_mempool();
 ---    dmar_init_reserved_ranges();
 +++    if (iommu_init_mempool()) {
 +++            if (force_on)
 +++                    panic("tboot: Failed to initialize iommu memory\n");
 +++            return  -ENODEV;
 +++    }
 +++
 +++    if (dmar_init_reserved_ranges()) {
 +++            if (force_on)
 +++                    panic("tboot: Failed to reserve iommu ranges\n");
 +++            return  -ENODEV;
 +++    }
    
        init_no_remapping_devices();
    
 ---    ret = init_dmars();
 +++    ret = init_dmars(force_on);
        if (ret) {
                if (force_on)
                        panic("tboot: Failed to initialize DMARs\n");
@@@@@ -3417,11 -3391,6 -3392,6 -3391,6 +3418,11 @@@@@ static void domain_remove_one_dev_info(
                domain->iommu_count--;
                domain_update_iommu_cap(domain);
                spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags);
 +++
 +++            spin_lock_irqsave(&iommu->lock, tmp_flags);
 +++            clear_bit(domain->id, iommu->domain_ids);
 +++            iommu->domains[domain->id] = NULL;
 +++            spin_unlock_irqrestore(&iommu->lock, tmp_flags);
        }
    
        spin_unlock_irqrestore(&device_domain_lock, flags);
@@@@@ -3638,9 -3607,9 -3608,9 -3607,9 +3639,9 @@@@@ static int intel_iommu_attach_device(st
    
                pte = dmar_domain->pgd;
                if (dma_pte_present(pte)) {
 ---                    free_pgtable_page(dmar_domain->pgd);
                        dmar_domain->pgd = (struct dma_pte *)
                                phys_to_virt(dma_pte_addr(pte));
 +++                    free_pgtable_page(pte);
                }
                dmar_domain->agaw--;
        }
This page took 0.125857 seconds and 4 git commands to generate.