All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alex Williamson <alex.williamson-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
To: Joerg Roedel <joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
Cc: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org,
	jroedel-l3A5Bk7waGM@public.gmane.org,
	David Woodhouse <dwmw2-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org>,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: Re: [PATCH 03/26] iommu/vt-d: Split up iommu->domains array
Date: Thu, 06 Aug 2015 13:20:09 -0600	[thread overview]
Message-ID: <1438888809.4023.121.camel@redhat.com> (raw)
In-Reply-To: <1438787937-7340-4-git-send-email-joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>

On Wed, 2015-08-05 at 17:18 +0200, Joerg Roedel wrote:
> From: Joerg Roedel <jroedel-l3A5Bk7waGM@public.gmane.org>
> 
> This array is indexed by the domain-id and contains the
> pointers to the domains attached to this iommu. Modern
> systems support 65536 domain ids, so that this array has a
> size of 512kb, per iommu.
> 
> This is a huge waste of space, as the array is usually
> sparsely populated. This patch makes the array
> two-dimensional and allocates the memory for the domain
> pointers on-demand.
> 
> Signed-off-by: Joerg Roedel <jroedel-l3A5Bk7waGM@public.gmane.org>
> ---
>  drivers/iommu/intel-iommu.c | 54 ++++++++++++++++++++++++++++++++++++---------
>  include/linux/intel-iommu.h |  2 +-
>  2 files changed, 44 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
> index e6a5966..7f2e6c8 100644
> --- a/drivers/iommu/intel-iommu.c
> +++ b/drivers/iommu/intel-iommu.c
> @@ -569,13 +569,32 @@ static struct kmem_cache *iommu_devinfo_cache;
>  
>  static struct dmar_domain* get_iommu_domain(struct intel_iommu *iommu, u16 did)
>  {
> -	return iommu->domains[did];
> +	struct dmar_domain **domains;
> +	int idx = did >> 8;
> +
> +	domains = iommu->domains[idx];
> +	if (!domains)
> +		return NULL;
> +
> +	return domains[did & 0xff];
>  }
>  
>  static void set_iommu_domain(struct intel_iommu *iommu, u16 did,
>  			     struct dmar_domain *domain)
>  {
> -	iommu->domains[did] = domain;
> +	struct dmar_domain **domains;
> +	int idx = did >> 8;
> +
> +	if (!iommu->domains[idx]) {
> +		size_t size = 256 * sizeof(struct dmar_domain *);
> +		iommu->domains[idx] = kzalloc(size, GFP_ATOMIC);
> +	}
> +
> +	domains = iommu->domains[idx];
> +	if (WARN_ON(!domains))
> +		return;
> +	else
> +		domains[did & 0xff] = domain;
>  }

I'm tempted to suggest using pages here since we're dealing with 2k
second level arrays, but maybe caring about pointers per page just makes
that ugly.

>  
>  static inline void *alloc_pgtable_page(int node)
> @@ -1528,35 +1547,43 @@ static void iommu_disable_translation(struct intel_iommu *iommu)
>  
>  static int iommu_init_domains(struct intel_iommu *iommu)
>  {
> -	unsigned long ndomains;
> -	unsigned long nlongs;
> +	u32 ndomains, nlongs;
> +	size_t size;
>  
>  	ndomains = cap_ndoms(iommu->cap);
> -	pr_debug("%s: Number of Domains supported <%ld>\n",
> +	pr_debug("%s: Number of Domains supported <%d>\n",
>  		 iommu->name, ndomains);
>  	nlongs = BITS_TO_LONGS(ndomains);
>  
>  	spin_lock_init(&iommu->lock);
>  
> -	/* TBD: there might be 64K domains,
> -	 * consider other allocation for future chip
> -	 */
>  	iommu->domain_ids = kcalloc(nlongs, sizeof(unsigned long), GFP_KERNEL);
>  	if (!iommu->domain_ids) {
>  		pr_err("%s: Allocating domain id array failed\n",
>  		       iommu->name);
>  		return -ENOMEM;
>  	}
> -	iommu->domains = kcalloc(ndomains, sizeof(struct dmar_domain *),
> -			GFP_KERNEL);
> -	if (!iommu->domains) {
> +
> +	size = ((ndomains >> 8) + 1) * sizeof(struct dmar_domain **);
> +	iommu->domains = kzalloc(size, GFP_KERNEL);
> +
> +	if (iommu->domains) {
> +		size = 256 * sizeof(struct dmar_domain *);
> +		iommu->domains[0] = kzalloc(size, GFP_KERNEL);
> +	}
> +
> +	if (!iommu->domains || !iommu->domains[0]) {
>  		pr_err("%s: Allocating domain array failed\n",
>  		       iommu->name);
>  		kfree(iommu->domain_ids);
> +		kfree(iommu->domains);
>  		iommu->domain_ids = NULL;
> +		iommu->domains    = NULL;
>  		return -ENOMEM;
>  	}
>  
> +
> +
>  	/*
>  	 * If Caching mode is set, then invalid translations are tagged
>  	 * with domain-id 0, hence we need to pre-allocate it. We also
> @@ -1598,6 +1625,11 @@ static void disable_dmar_iommu(struct intel_iommu *iommu)
>  static void free_dmar_iommu(struct intel_iommu *iommu)
>  {
>  	if ((iommu->domains) && (iommu->domain_ids)) {
> +		int elems = (cap_ndoms(iommu->cap) >> 8) + 1;
> +		int i;
> +
> +		for (i = 0; i < elems; i++)
> +			kfree(iommu->domains[i]);
>  		kfree(iommu->domains);
>  		kfree(iommu->domain_ids);
>  		iommu->domains = NULL;
> diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
> index d9a366d..6240063 100644
> --- a/include/linux/intel-iommu.h
> +++ b/include/linux/intel-iommu.h
> @@ -344,7 +344,7 @@ struct intel_iommu {
>  
>  #ifdef CONFIG_INTEL_IOMMU
>  	unsigned long 	*domain_ids; /* bitmap of domains */
> -	struct dmar_domain **domains; /* ptr to domains */
> +	struct dmar_domain ***domains; /* ptr to domains */
>  	spinlock_t	lock; /* protect context, domain ids */
>  	struct root_entry *root_entry; /* virtual address */
>  

WARNING: multiple messages have this Message-ID (diff)
From: Alex Williamson <alex.williamson@redhat.com>
To: Joerg Roedel <joro@8bytes.org>
Cc: iommu@lists.linux-foundation.org,
	David Woodhouse <dwmw2@infradead.org>,
	linux-kernel@vger.kernel.org, jroedel@suse.de
Subject: Re: [PATCH 03/26] iommu/vt-d: Split up iommu->domains array
Date: Thu, 06 Aug 2015 13:20:09 -0600	[thread overview]
Message-ID: <1438888809.4023.121.camel@redhat.com> (raw)
In-Reply-To: <1438787937-7340-4-git-send-email-joro@8bytes.org>

On Wed, 2015-08-05 at 17:18 +0200, Joerg Roedel wrote:
> From: Joerg Roedel <jroedel@suse.de>
> 
> This array is indexed by the domain-id and contains the
> pointers to the domains attached to this iommu. Modern
> systems support 65536 domain ids, so that this array has a
> size of 512kb, per iommu.
> 
> This is a huge waste of space, as the array is usually
> sparsely populated. This patch makes the array
> two-dimensional and allocates the memory for the domain
> pointers on-demand.
> 
> Signed-off-by: Joerg Roedel <jroedel@suse.de>
> ---
>  drivers/iommu/intel-iommu.c | 54 ++++++++++++++++++++++++++++++++++++---------
>  include/linux/intel-iommu.h |  2 +-
>  2 files changed, 44 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
> index e6a5966..7f2e6c8 100644
> --- a/drivers/iommu/intel-iommu.c
> +++ b/drivers/iommu/intel-iommu.c
> @@ -569,13 +569,32 @@ static struct kmem_cache *iommu_devinfo_cache;
>  
>  static struct dmar_domain* get_iommu_domain(struct intel_iommu *iommu, u16 did)
>  {
> -	return iommu->domains[did];
> +	struct dmar_domain **domains;
> +	int idx = did >> 8;
> +
> +	domains = iommu->domains[idx];
> +	if (!domains)
> +		return NULL;
> +
> +	return domains[did & 0xff];
>  }
>  
>  static void set_iommu_domain(struct intel_iommu *iommu, u16 did,
>  			     struct dmar_domain *domain)
>  {
> -	iommu->domains[did] = domain;
> +	struct dmar_domain **domains;
> +	int idx = did >> 8;
> +
> +	if (!iommu->domains[idx]) {
> +		size_t size = 256 * sizeof(struct dmar_domain *);
> +		iommu->domains[idx] = kzalloc(size, GFP_ATOMIC);
> +	}
> +
> +	domains = iommu->domains[idx];
> +	if (WARN_ON(!domains))
> +		return;
> +	else
> +		domains[did & 0xff] = domain;
>  }

I'm tempted to suggest using pages here since we're dealing with 2k
second level arrays, but maybe caring about pointers per page just makes
that ugly.

>  
>  static inline void *alloc_pgtable_page(int node)
> @@ -1528,35 +1547,43 @@ static void iommu_disable_translation(struct intel_iommu *iommu)
>  
>  static int iommu_init_domains(struct intel_iommu *iommu)
>  {
> -	unsigned long ndomains;
> -	unsigned long nlongs;
> +	u32 ndomains, nlongs;
> +	size_t size;
>  
>  	ndomains = cap_ndoms(iommu->cap);
> -	pr_debug("%s: Number of Domains supported <%ld>\n",
> +	pr_debug("%s: Number of Domains supported <%d>\n",
>  		 iommu->name, ndomains);
>  	nlongs = BITS_TO_LONGS(ndomains);
>  
>  	spin_lock_init(&iommu->lock);
>  
> -	/* TBD: there might be 64K domains,
> -	 * consider other allocation for future chip
> -	 */
>  	iommu->domain_ids = kcalloc(nlongs, sizeof(unsigned long), GFP_KERNEL);
>  	if (!iommu->domain_ids) {
>  		pr_err("%s: Allocating domain id array failed\n",
>  		       iommu->name);
>  		return -ENOMEM;
>  	}
> -	iommu->domains = kcalloc(ndomains, sizeof(struct dmar_domain *),
> -			GFP_KERNEL);
> -	if (!iommu->domains) {
> +
> +	size = ((ndomains >> 8) + 1) * sizeof(struct dmar_domain **);
> +	iommu->domains = kzalloc(size, GFP_KERNEL);
> +
> +	if (iommu->domains) {
> +		size = 256 * sizeof(struct dmar_domain *);
> +		iommu->domains[0] = kzalloc(size, GFP_KERNEL);
> +	}
> +
> +	if (!iommu->domains || !iommu->domains[0]) {
>  		pr_err("%s: Allocating domain array failed\n",
>  		       iommu->name);
>  		kfree(iommu->domain_ids);
> +		kfree(iommu->domains);
>  		iommu->domain_ids = NULL;
> +		iommu->domains    = NULL;
>  		return -ENOMEM;
>  	}
>  
> +
> +
>  	/*
>  	 * If Caching mode is set, then invalid translations are tagged
>  	 * with domain-id 0, hence we need to pre-allocate it. We also
> @@ -1598,6 +1625,11 @@ static void disable_dmar_iommu(struct intel_iommu *iommu)
>  static void free_dmar_iommu(struct intel_iommu *iommu)
>  {
>  	if ((iommu->domains) && (iommu->domain_ids)) {
> +		int elems = (cap_ndoms(iommu->cap) >> 8) + 1;
> +		int i;
> +
> +		for (i = 0; i < elems; i++)
> +			kfree(iommu->domains[i]);
>  		kfree(iommu->domains);
>  		kfree(iommu->domain_ids);
>  		iommu->domains = NULL;
> diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
> index d9a366d..6240063 100644
> --- a/include/linux/intel-iommu.h
> +++ b/include/linux/intel-iommu.h
> @@ -344,7 +344,7 @@ struct intel_iommu {
>  
>  #ifdef CONFIG_INTEL_IOMMU
>  	unsigned long 	*domain_ids; /* bitmap of domains */
> -	struct dmar_domain **domains; /* ptr to domains */
> +	struct dmar_domain ***domains; /* ptr to domains */
>  	spinlock_t	lock; /* protect context, domain ids */
>  	struct root_entry *root_entry; /* virtual address */
>  




  parent reply	other threads:[~2015-08-06 19:20 UTC|newest]

Thread overview: 68+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-08-05 15:18 [PATCH 00/26] iommu/vt-d: Clean up device<->domain attachment Joerg Roedel
2015-08-05 15:18 ` Joerg Roedel
     [not found] ` <1438787937-7340-1-git-send-email-joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2015-08-05 15:18   ` [PATCH 01/26] iommu/vt-d: Keep track of per-iommu domain ids Joerg Roedel
2015-08-05 15:18     ` Joerg Roedel
     [not found]     ` <1438787937-7340-2-git-send-email-joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2015-08-06 19:19       ` Alex Williamson
2015-08-06 19:19         ` Alex Williamson
     [not found]         ` <1438888792.4023.118.camel-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2015-08-07 11:07           ` Joerg Roedel
2015-08-07 11:07             ` Joerg Roedel
2015-08-05 15:18   ` [PATCH 02/26] iommu/vt-d: Add access functions for iommu->domains Joerg Roedel
2015-08-05 15:18     ` Joerg Roedel
2015-08-05 15:18   ` [PATCH 03/26] iommu/vt-d: Split up iommu->domains array Joerg Roedel
2015-08-05 15:18     ` Joerg Roedel
     [not found]     ` <1438787937-7340-4-git-send-email-joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2015-08-06 19:20       ` Alex Williamson [this message]
2015-08-06 19:20         ` Alex Williamson
     [not found]         ` <1438888809.4023.121.camel-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2015-08-07 11:11           ` Joerg Roedel
2015-08-07 11:11             ` Joerg Roedel
2015-08-05 15:18   ` [PATCH 04/26] iommu/vt-d: Get rid of iommu_attach_vm_domain() Joerg Roedel
2015-08-05 15:18     ` Joerg Roedel
2015-08-05 15:18   ` [PATCH 05/26] iommu/vt-d: Calculate translation in domain_context_mapping_one Joerg Roedel
2015-08-05 15:18     ` Joerg Roedel
     [not found]     ` <1438787937-7340-6-git-send-email-joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2015-08-06 19:20       ` Alex Williamson
2015-08-06 19:20         ` Alex Williamson
     [not found]         ` <1438888801.4023.120.camel-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2015-08-07 11:13           ` Joerg Roedel
2015-08-07 11:13             ` Joerg Roedel
2015-08-05 15:18   ` [PATCH 06/26] iommu/vt-d: Simplify domain_context_mapping_one Joerg Roedel
2015-08-05 15:18     ` Joerg Roedel
2015-08-05 15:18   ` [PATCH 08/26] iommu/vt-d: Don't pre-allocate domain ids for si_domain Joerg Roedel
2015-08-05 15:18     ` Joerg Roedel
2015-08-05 15:18   ` [PATCH 10/26] iommu/vt-d: Replace iommu_bmp with a refcount Joerg Roedel
2015-08-05 15:18     ` Joerg Roedel
     [not found]     ` <1438787937-7340-11-git-send-email-joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2015-08-06 19:19       ` Alex Williamson
2015-08-06 19:19         ` Alex Williamson
     [not found]         ` <1438888797.4023.119.camel-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2015-08-07 11:17           ` Joerg Roedel
2015-08-07 11:17             ` Joerg Roedel
2015-08-05 15:18   ` [PATCH 11/26] iommu/vt-d: Simplify io/tlb flushing in intel_iommu_unmap Joerg Roedel
2015-08-05 15:18     ` Joerg Roedel
2015-08-05 15:18   ` [PATCH 12/26] iommu/vt-d: Simplify domain_remove_one_dev_info() Joerg Roedel
2015-08-05 15:18     ` Joerg Roedel
2015-08-05 15:18   ` [PATCH 13/26] iommu/vt-d: Simplify domain_remove_dev_info() Joerg Roedel
2015-08-05 15:18     ` Joerg Roedel
2015-08-05 15:18   ` [PATCH 14/26] iommu/vt-d: Move context-mapping into dmar_insert_dev_info Joerg Roedel
2015-08-05 15:18     ` Joerg Roedel
2015-08-05 15:18   ` [PATCH 15/26] iommu/vt-d: Rename dmar_insert_dev_info() Joerg Roedel
2015-08-05 15:18     ` Joerg Roedel
2015-08-05 15:18   ` [PATCH 16/26] iommu/vt-d: Rename domain_remove_one_dev_info() Joerg Roedel
2015-08-05 15:18     ` Joerg Roedel
2015-08-05 15:18   ` [PATCH 17/26] iommu/vt-d: Rename iommu_detach_dependent_devices() Joerg Roedel
2015-08-05 15:18     ` Joerg Roedel
2015-08-05 15:18   ` [PATCH 18/26] iommu/vt-d: Pass an iommu pointer to domain_init() Joerg Roedel
2015-08-05 15:18     ` Joerg Roedel
2015-08-05 15:18   ` [PATCH 20/26] iommu/vt-d: Unify domain->iommu attach/detachment Joerg Roedel
2015-08-05 15:18     ` Joerg Roedel
2015-08-05 15:18   ` [PATCH 21/26] iommu/vt-d: Only call domain_remove_one_dev_info to detach old domain Joerg Roedel
2015-08-05 15:18     ` Joerg Roedel
2015-08-05 15:18   ` [PATCH 22/26] iommu/vt-d: Get rid of domain->iommu_lock Joerg Roedel
2015-08-05 15:18     ` Joerg Roedel
2015-08-05 15:18   ` [PATCH 23/26] iommu/vt-d: Remove dmar_global_lock from device_notifier Joerg Roedel
2015-08-05 15:18     ` Joerg Roedel
2015-08-06 19:19   ` [PATCH 00/26] iommu/vt-d: Clean up device<->domain attachment Alex Williamson
2015-08-06 19:19     ` Alex Williamson
     [not found]     ` <1438888787.4023.116.camel-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2015-08-07 11:22       ` Joerg Roedel
2015-08-07 11:22         ` Joerg Roedel
2015-08-05 15:18 ` [PATCH 07/26] iommu/vt-d: Pass dmar_domain directly into iommu_flush_iotlb_psi Joerg Roedel
2015-08-05 15:18 ` [PATCH 09/26] iommu/vt-d: Kill dmar_domain->id Joerg Roedel
2015-08-05 15:18 ` [PATCH 19/26] iommu/vt-d: Establish domain<->iommu link in dmar_insert_one_dev_info Joerg Roedel
2015-08-05 15:18 ` [PATCH 24/26] iommu/vt-d: Pass device_domain_info to __dmar_remove_one_dev_info Joerg Roedel
2015-08-05 15:18 ` [PATCH 25/26] iommu/vt-d: Only insert alias dev_info if there is an alias Joerg Roedel
2015-08-05 15:18 ` [PATCH 26/26] iommu/vt-d: Avoid duplicate device_domain_info structures Joerg Roedel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1438888809.4023.121.camel@redhat.com \
    --to=alex.williamson-h+wxahxf7alqt0dzr+alfa@public.gmane.org \
    --cc=dwmw2-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org \
    --cc=iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org \
    --cc=joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org \
    --cc=jroedel-l3A5Bk7waGM@public.gmane.org \
    --cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.