lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Thu, 06 Aug 2015 13:19:57 -0600
From:	Alex Williamson <alex.williamson@...hat.com>
To:	Joerg Roedel <joro@...tes.org>
Cc:	iommu@...ts.linux-foundation.org,
	David Woodhouse <dwmw2@...radead.org>,
	linux-kernel@...r.kernel.org, jroedel@...e.de
Subject: Re: [PATCH 10/26] iommu/vt-d: Replace iommu_bmp with a refcount

On Wed, 2015-08-05 at 17:18 +0200, Joerg Roedel wrote:
> From: Joerg Roedel <jroedel@...e.de>
> 
> This replaces the dmar_domain->iommu_bmp with a similar
> reference count array. This allows us to keep track of how
> many devices behind each iommu are attached to the domain.
> 
> This is necessary for further simplifications and
> optimizations to the iommu<->domain attachment code.
> 
> Signed-off-by: Joerg Roedel <jroedel@...e.de>
> ---
>  drivers/iommu/intel-iommu.c | 82 +++++++++++++++++++++++++--------------------
>  1 file changed, 45 insertions(+), 37 deletions(-)
> 
> diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
> index 25b2ba7..c46afb6 100644
> --- a/drivers/iommu/intel-iommu.c
> +++ b/drivers/iommu/intel-iommu.c
> @@ -373,10 +373,16 @@ static int hw_pass_through = 1;
>  /* si_domain contains mulitple devices */
>  #define DOMAIN_FLAG_STATIC_IDENTITY	(1 << 1)
>  
> +#define for_each_domain_iommu(idx, domain)			\
> +	for (idx = 0; idx < g_num_of_iommus; idx++)		\
> +		if (domain->iommu_refcnt[idx])
> +
>  struct dmar_domain {
>  	int	nid;			/* node id */
> -	DECLARE_BITMAP(iommu_bmp, DMAR_UNITS_SUPPORTED);
> -					/* bitmap of iommus this domain uses*/
> +
> +	int		iommu_refcnt[DMAR_UNITS_SUPPORTED];
> +					/* Refcount of devices per iommu */

unsigned?

> +
>  
>  	u16	iommu_did[DMAR_UNITS_SUPPORTED];
>  					/* Domain ids per IOMMU */
> @@ -697,7 +703,9 @@ static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
>  
>  	/* si_domain and vm domain should not get here. */
>  	BUG_ON(domain_type_is_vm_or_si(domain));
> -	iommu_id = find_first_bit(domain->iommu_bmp, g_num_of_iommus);
> +	for_each_domain_iommu(iommu_id, domain)
> +		break;
> +
>  	if (iommu_id < 0 || iommu_id >= g_num_of_iommus)
>  		return NULL;
>  
> @@ -713,7 +721,7 @@ static void domain_update_iommu_coherency(struct dmar_domain *domain)
>  
>  	domain->iommu_coherency = 1;
>  
> -	for_each_set_bit(i, domain->iommu_bmp, g_num_of_iommus) {
> +	for_each_domain_iommu(i, domain) {
>  		found = true;
>  		if (!ecap_coherent(g_iommus[i]->ecap)) {
>  			domain->iommu_coherency = 0;
> @@ -1605,25 +1613,26 @@ static int iommu_init_domains(struct intel_iommu *iommu)
>  
>  static void disable_dmar_iommu(struct intel_iommu *iommu)
>  {
> -	struct dmar_domain *domain;
> -	int i;
> +	struct device_domain_info *info, *tmp;
>  
> -	if ((iommu->domains) && (iommu->domain_ids)) {
> -		for_each_set_bit(i, iommu->domain_ids, cap_ndoms(iommu->cap)) {
> -			/*
> -			 * Domain id 0 is reserved for invalid translation
> -			 * if hardware supports caching mode and used as
> -			 * a non-allocated marker.
> -			 */
> -			if (i == 0)
> -				continue;
> +	if (!iommu->domains || !iommu->domain_ids)
> +		return;
>  
> -			domain = get_iommu_domain(iommu, i);
> -			clear_bit(i, iommu->domain_ids);
> -			if (domain_detach_iommu(domain, iommu) == 0 &&
> -			    !domain_type_is_vm(domain))
> -				domain_exit(domain);
> -		}
> +	list_for_each_entry_safe(info, tmp, &device_domain_list, global) {
> +		struct dmar_domain *domain;
> +
> +		if (info->iommu != iommu)
> +			continue;
> +
> +		if (!info->dev || !info->domain)
> +			continue;
> +
> +		domain = info->domain;
> +
> +		domain_remove_one_dev_info(domain, info->dev);
> +
> +		if (!domain_type_is_vm_or_si(domain))
> +			domain_exit(domain);
>  	}
>  
>  	if (iommu->gcmd & DMA_GCMD_TE)
> @@ -1731,10 +1740,10 @@ static void domain_attach_iommu(struct dmar_domain *domain,
>  	unsigned long flags;
>  
>  	spin_lock_irqsave(&domain->iommu_lock, flags);
> -	if (!test_and_set_bit(iommu->seq_id, domain->iommu_bmp)) {
> -		domain->iommu_count++;
> -		if (domain->iommu_count == 1)
> -			domain->nid = iommu->node;
> +	domain->iommu_refcnt[iommu->seq_id] += 1;
> +	domain->iommu_count += 1;
> +	if (domain->iommu_refcnt[iommu->seq_id] == 1) {
> +		domain->nid = iommu->node;
>  		domain_update_iommu_cap(domain);
>  	}
>  	spin_unlock_irqrestore(&domain->iommu_lock, flags);
> @@ -1747,8 +1756,9 @@ static int domain_detach_iommu(struct dmar_domain *domain,
>  	int count = INT_MAX;
>  
>  	spin_lock_irqsave(&domain->iommu_lock, flags);
> -	if (test_and_clear_bit(iommu->seq_id, domain->iommu_bmp)) {
> -		count = --domain->iommu_count;
> +	domain->iommu_refcnt[iommu->seq_id] -= 1;
> +	count = --domain->iommu_count;
> +	if (domain->iommu_refcnt[iommu->seq_id] == 0) {
>  		domain_update_iommu_cap(domain);
>  		domain->iommu_did[iommu->seq_id] = 0;
>  	}
> @@ -1873,9 +1883,8 @@ static int domain_init(struct dmar_domain *domain, int guest_width)
>  
>  static void domain_exit(struct dmar_domain *domain)
>  {
> -	struct dmar_drhd_unit *drhd;
> -	struct intel_iommu *iommu;
>  	struct page *freelist = NULL;
> +	int i;
>  
>  	/* Domain 0 is reserved, so dont process it */
>  	if (!domain)
> @@ -1895,10 +1904,8 @@ static void domain_exit(struct dmar_domain *domain)
>  
>  	/* clear attached or cached domains */
>  	rcu_read_lock();
> -	for_each_active_iommu(iommu, drhd)
> -		if (domain_type_is_vm(domain) ||
> -		    test_bit(iommu->seq_id, domain->iommu_bmp))
> -			iommu_detach_domain(domain, iommu);
> +	for_each_domain_iommu(i, domain)
> +		iommu_detach_domain(domain, g_iommus[i]);

Yay!

>  	rcu_read_unlock();
>  
>  	dma_free_pagelist(freelist);
> @@ -4610,9 +4617,10 @@ static void domain_remove_one_dev_info(struct dmar_domain *domain,
>  				continue;
>  		}
>  
> -		/* if there is no other devices under the same iommu
> -		 * owned by this domain, clear this iommu in iommu_bmp
> -		 * update iommu count and coherency
> +		/*
> +		 * If there is no other devices under the same iommu owned by
> +		 * this domain, clear this iommu in iommu_refcnt update iommu
> +		 * count and coherency.
>  		 */
>  		if (info->iommu == iommu)
>  			found = true;
> @@ -4820,7 +4828,7 @@ static size_t intel_iommu_unmap(struct iommu_domain *domain,
>  
>  	npages = last_pfn - start_pfn + 1;
>  
> -	for_each_set_bit(iommu_id, dmar_domain->iommu_bmp, g_num_of_iommus) {
> +	for_each_domain_iommu(iommu_id, dmar_domain) {
>  		iommu = g_iommus[iommu_id];
>  
>  		/*



--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ