Skip to content

Commit

Permalink
intel-iommu: Snooping control support
Browse files Browse the repository at this point in the history
Snooping control enabled IOMMU to guarantee DMA cache coherency and thus reduce
software effort (VMM) in maintaining effective memory type.

Signed-off-by: Sheng Yang <sheng@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
  • Loading branch information
Sheng Yang authored and David Woodhouse committed Mar 24, 2009
1 parent a1e4ee2 commit 58c610b
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 6 deletions.
38 changes: 33 additions & 5 deletions drivers/pci/intel-iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ struct dmar_domain {
int flags; /* flags to find out type of domain */

int iommu_coherency;/* indicate coherency of iommu access */
int iommu_snooping; /* indicate snooping control feature*/
int iommu_count; /* reference count of iommu */
spinlock_t iommu_lock; /* protect iommu set in domain */
u64 max_addr; /* maximum mapped address */
Expand Down Expand Up @@ -421,7 +422,6 @@ static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
return g_iommus[iommu_id];
}

/* "Coherency" capability may be different across iommus */
static void domain_update_iommu_coherency(struct dmar_domain *domain)
{
int i;
Expand All @@ -438,6 +438,29 @@ static void domain_update_iommu_coherency(struct dmar_domain *domain)
}
}

static void domain_update_iommu_snooping(struct dmar_domain *domain)
{
int i;

domain->iommu_snooping = 1;

i = find_first_bit(&domain->iommu_bmp, g_num_of_iommus);
for (; i < g_num_of_iommus; ) {
if (!ecap_sc_support(g_iommus[i]->ecap)) {
domain->iommu_snooping = 0;
break;
}
i = find_next_bit(&domain->iommu_bmp, g_num_of_iommus, i+1);
}
}

/* Some capabilities may be different across iommus */
static void domain_update_iommu_cap(struct dmar_domain *domain)
{
domain_update_iommu_coherency(domain);
domain_update_iommu_snooping(domain);
}

static struct intel_iommu *device_to_iommu(u8 bus, u8 devfn)
{
struct dmar_drhd_unit *drhd = NULL;
Expand Down Expand Up @@ -1429,6 +1452,11 @@ static int domain_init(struct dmar_domain *domain, int guest_width)
else
domain->iommu_coherency = 0;

if (ecap_sc_support(iommu->ecap))
domain->iommu_snooping = 1;
else
domain->iommu_snooping = 0;

domain->iommu_count = 1;

/* always allocate the top pgd */
Expand Down Expand Up @@ -1557,7 +1585,7 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
spin_lock_irqsave(&domain->iommu_lock, flags);
if (!test_and_set_bit(iommu->seq_id, &domain->iommu_bmp)) {
domain->iommu_count++;
domain_update_iommu_coherency(domain);
domain_update_iommu_cap(domain);
}
spin_unlock_irqrestore(&domain->iommu_lock, flags);
return 0;
Expand Down Expand Up @@ -2820,7 +2848,7 @@ static void vm_domain_remove_one_dev_info(struct dmar_domain *domain,
spin_lock_irqsave(&domain->iommu_lock, tmp_flags);
clear_bit(iommu->seq_id, &domain->iommu_bmp);
domain->iommu_count--;
domain_update_iommu_coherency(domain);
domain_update_iommu_cap(domain);
spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags);
}

Expand Down Expand Up @@ -2848,13 +2876,13 @@ static void vm_domain_remove_all_dev_info(struct dmar_domain *domain)
iommu_detach_dev(iommu, info->bus, info->devfn);

/* clear this iommu in iommu_bmp, update iommu count
* and coherency
* and capabilities
*/
spin_lock_irqsave(&domain->iommu_lock, flags2);
if (test_and_clear_bit(iommu->seq_id,
&domain->iommu_bmp)) {
domain->iommu_count--;
domain_update_iommu_coherency(domain);
domain_update_iommu_cap(domain);
}
spin_unlock_irqrestore(&domain->iommu_lock, flags2);

Expand Down
2 changes: 1 addition & 1 deletion include/linux/intel-iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ static inline void dmar_writeq(void __iomem *addr, u64 val)
#define ecap_eim_support(e) ((e >> 4) & 0x1)
#define ecap_ir_support(e) ((e >> 3) & 0x1)
#define ecap_max_handle_mask(e) ((e >> 20) & 0xf)

#define ecap_sc_support(e) ((e >> 7) & 0x1) /* Snooping Control */

/* IOTLB_REG */
#define DMA_TLB_FLUSH_GRANU_OFFSET 60
Expand Down

0 comments on commit 58c610b

Please sign in to comment.