All of lore.kernel.org
 help / color / mirror / Atom feed
From: Imre Deak <imre.deak@intel.com>
To: Ben Widawsky <benjamin.widawsky@intel.com>
Cc: Intel GFX <intel-gfx@lists.freedesktop.org>,
	Ben Widawsky <ben@bwidawsk.net>
Subject: Re: [PATCH 2/9] drm/i915/bdw: Reorganize PPGTT init
Date: Wed, 19 Feb 2014 16:59:49 +0200	[thread overview]
Message-ID: <1392821989.19792.13.camel@intelbox> (raw)
In-Reply-To: <1392244132-6806-3-git-send-email-benjamin.widawsky@intel.com>


[-- Attachment #1.1: Type: text/plain, Size: 9829 bytes --]

On Wed, 2014-02-12 at 14:28 -0800, Ben Widawsky wrote:
> Create 3 clear stages in PPGTT init. This will help with upcoming
> changes be more readable. The 3 stages are, allocation, dma mapping, and
> writing the P[DT]Es
> 
> One nice benefit to the patches is that it makes 2 very clear error
> points, allocation, and mapping, and avoids having to do any handling
> after writing PTEs (something which was likely buggy before). This
> simplified error handling I suspect will be helpful when we move to
> deferred/dynamic page table allocation and mapping.
> 
> The patches also attempts to break up some of the steps into more
> logical reviewable chunks, particularly when we free.
> 
> v2: Don't call cleanup on the error path since that takes down the
> drm_mm and list entry, which aren't setup at this point.
> 
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
> ---
>  drivers/gpu/drm/i915/i915_drv.h     |   2 +-
>  drivers/gpu/drm/i915/i915_gem_gtt.c | 124 +++++++++++++++++++++---------------
>  2 files changed, 73 insertions(+), 53 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 2572a95..cecbb9a 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -709,7 +709,7 @@ struct i915_hw_ppgtt {
>  	};
>  	union {
>  		dma_addr_t *pt_dma_addr;
> -		dma_addr_t *gen8_pt_dma_addr[4];
> +		dma_addr_t **gen8_pt_dma_addr;

If there isn't any reason to allocate this dynamically I'd just leave
the static array. This would make the error path a bit simpler and be
more symmetric wrt. pd_dma_addr which is also a static array.

>  	};
>  
>  	int (*enable)(struct i915_hw_ppgtt *ppgtt);
> diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
> index ee38faf..c6c221c 100644
> --- a/drivers/gpu/drm/i915/i915_gem_gtt.c
> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
> @@ -326,12 +326,14 @@ static void gen8_ppgtt_free(struct i915_hw_ppgtt *ppgtt)
>  	for (i = 0; i < ppgtt->num_pd_pages ; i++)
>  		kfree(ppgtt->gen8_pt_dma_addr[i]);
>  
> +	kfree(ppgtt->gen8_pt_dma_addr);
>  	__free_pages(ppgtt->gen8_pt_pages, get_order(ppgtt->num_pt_pages << PAGE_SHIFT));
>  	__free_pages(ppgtt->pd_pages, get_order(ppgtt->num_pd_pages << PAGE_SHIFT));
>  }
>  
>  static void gen8_ppgtt_unmap_pages(struct i915_hw_ppgtt *ppgtt)
>  {
> +	struct pci_dev *hwdev = ppgtt->base.dev->pdev;
>  	int i, j;
>  
>  	for (i = 0; i < ppgtt->num_pd_pages; i++) {
> @@ -340,18 +342,14 @@ static void gen8_ppgtt_unmap_pages(struct i915_hw_ppgtt *ppgtt)
>  		if (!ppgtt->pd_dma_addr[i])
>  			continue;
>  
> -		pci_unmap_page(ppgtt->base.dev->pdev,
> -			       ppgtt->pd_dma_addr[i],
> -			       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
> +		pci_unmap_page(hwdev, ppgtt->pd_dma_addr[i], PAGE_SIZE,
> +			       PCI_DMA_BIDIRECTIONAL);
>  
>  		for (j = 0; j < GEN8_PDES_PER_PAGE; j++) {
>  			dma_addr_t addr = ppgtt->gen8_pt_dma_addr[i][j];
>  			if (addr)
> -				pci_unmap_page(ppgtt->base.dev->pdev,
> -				       addr,
> -				       PAGE_SIZE,
> -				       PCI_DMA_BIDIRECTIONAL);
> -
> +				pci_unmap_page(hwdev, addr, PAGE_SIZE,
> +					       PCI_DMA_BIDIRECTIONAL);
>  		}
>  	}
>  }
> @@ -369,27 +367,26 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
>  }
>  
>  /**
> - * GEN8 legacy ppgtt programming is accomplished through 4 PDP registers with a
> - * net effect resembling a 2-level page table in normal x86 terms. Each PDP
> - * represents 1GB of memory
> - * 4 * 512 * 512 * 4096 = 4GB legacy 32b address space.
> + * GEN8 legacy ppgtt programming is accomplished through a max 4 PDP registers
> + * with a net effect resembling a 2-level page table in normal x86 terms. Each
> + * PDP represents 1GB of memory 4 * 512 * 512 * 4096 = 4GB legacy 32b address
> + * space.
>   *
> + * FIXME: split allocation into smaller pieces. For now we only ever do this
> + * once, but with full PPGTT, the multiple contiguous allocations will be bad.
>   * TODO: Do something with the size parameter
> - **/
> + */
>  static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size)
>  {
>  	struct page *pt_pages;
> -	int i, j, ret = -ENOMEM;
>  	const int max_pdp = DIV_ROUND_UP(size, 1 << 30);
>  	const int num_pt_pages = GEN8_PDES_PER_PAGE * max_pdp;
> +	int i, j, ret;
>  
>  	if (size % (1<<30))
>  		DRM_INFO("Pages will be wasted unless GTT size (%llu) is divisible by 1GB\n", size);
>  
> -	/* FIXME: split allocation into smaller pieces. For now we only ever do
> -	 * this once, but with full PPGTT, the multiple contiguous allocations
> -	 * will be bad.
> -	 */
> +	/* 1. Do all our allocations for page directories and page tables */
>  	ppgtt->pd_pages = alloc_pages(GFP_KERNEL, get_order(max_pdp << PAGE_SHIFT));
>  	if (!ppgtt->pd_pages)
>  		return -ENOMEM;
> @@ -404,52 +401,66 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size)
>  	ppgtt->num_pd_pages = 1 << get_order(max_pdp << PAGE_SHIFT);
>  	ppgtt->num_pt_pages = 1 << get_order(num_pt_pages << PAGE_SHIFT);
>  	ppgtt->num_pd_entries = max_pdp * GEN8_PDES_PER_PAGE;
> -	ppgtt->enable = gen8_ppgtt_enable;
> -	ppgtt->switch_mm = gen8_mm_switch;
> -	ppgtt->base.clear_range = gen8_ppgtt_clear_range;
> -	ppgtt->base.insert_entries = gen8_ppgtt_insert_entries;
> -	ppgtt->base.cleanup = gen8_ppgtt_cleanup;
> -	ppgtt->base.start = 0;
> -	ppgtt->base.total = ppgtt->num_pt_pages * GEN8_PTES_PER_PAGE * PAGE_SIZE;
> -
>  	BUG_ON(ppgtt->num_pd_pages > GEN8_LEGACY_PDPS);
>  
> +	ppgtt->gen8_pt_dma_addr = kcalloc(max_pdp,
> +					  sizeof(*ppgtt->gen8_pt_dma_addr),
> +					  GFP_KERNEL);
> +	if (!ppgtt->gen8_pt_dma_addr) {
> +		ret = -ENOMEM;
> +		goto bail;

On the error path, in gen8_ppgtt_free() we'd dereference the above NULL
ptr.

> +	}
> +
> +	for (i = 0; i < max_pdp; i++) {
> +		ppgtt->gen8_pt_dma_addr[i] = kcalloc(GEN8_PDES_PER_PAGE,
> +						     sizeof(dma_addr_t),
> +						     GFP_KERNEL);
> +		if (!ppgtt->gen8_pt_dma_addr[i]) {
> +			ret = -ENOMEM;
> +			goto bail;
> +		}
> +	}
> +
>  	/*
> -	 * - Create a mapping for the page directories.
> -	 * - For each page directory:
> -	 *      allocate space for page table mappings.
> -	 *      map each page table
> +	 * 2. Create all the DMA mappings for the page directories and page
> +	 * tables
>  	 */
>  	for (i = 0; i < max_pdp; i++) {
> -		dma_addr_t temp;
> -		temp = pci_map_page(ppgtt->base.dev->pdev,
> -				    &ppgtt->pd_pages[i], 0,
> -				    PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
> -		if (pci_dma_mapping_error(ppgtt->base.dev->pdev, temp))
> -			goto err_out;
> -
> -		ppgtt->pd_dma_addr[i] = temp;
> -
> -		ppgtt->gen8_pt_dma_addr[i] = kmalloc(sizeof(dma_addr_t) * GEN8_PDES_PER_PAGE, GFP_KERNEL);
> -		if (!ppgtt->gen8_pt_dma_addr[i])
> -			goto err_out;
> +		dma_addr_t pd_addr, pt_addr;
>  
> +		/* Get the page table mappings per page directory */
>  		for (j = 0; j < GEN8_PDES_PER_PAGE; j++) {
>  			struct page *p = &pt_pages[i * GEN8_PDES_PER_PAGE + j];
> -			temp = pci_map_page(ppgtt->base.dev->pdev,
> -					    p, 0, PAGE_SIZE,
> -					    PCI_DMA_BIDIRECTIONAL);
>  
> -			if (pci_dma_mapping_error(ppgtt->base.dev->pdev, temp))
> -				goto err_out;
> +			pt_addr = pci_map_page(ppgtt->base.dev->pdev,
> +					       p, 0, PAGE_SIZE,
> +					       PCI_DMA_BIDIRECTIONAL);
> +			ret = pci_dma_mapping_error(ppgtt->base.dev->pdev, pt_addr);
> +			if (ret)
> +				goto bail;
>  
> -			ppgtt->gen8_pt_dma_addr[i][j] = temp;
> +			ppgtt->gen8_pt_dma_addr[i][j] = pt_addr;
>  		}
> +
> +		/* And the page directory mappings */
> +		pd_addr = pci_map_page(ppgtt->base.dev->pdev,
> +				       &ppgtt->pd_pages[i], 0,
> +				       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
> +		ret = pci_dma_mapping_error(ppgtt->base.dev->pdev, pd_addr);
> +		if (ret)
> +			goto bail;

The error path here would leak the above page table mappings, since
ppgtt->pd_dma_addr[i] is still zero, but in gen8_ppgtt_unmap_pages() we
do a if (!ppgtt->pd_dma_addr[i]) continue; skipping the page table unmap
part. This is reworked in your later patches, but the issue is still
there in the final version. 

> +
> +		ppgtt->pd_dma_addr[i] = pd_addr;
>  	}
>  
> -	/* For now, the PPGTT helper functions all require that the PDEs are
> +	/*
> +	 * 3. Map all the page directory entires to point to the page tables
> +	 * we've allocated.
> +	 *
> +	 * For now, the PPGTT helper functions all require that the PDEs are
>  	 * plugged in correctly. So we do that now/here. For aliasing PPGTT, we
> -	 * will never need to touch the PDEs again */
> +	 * will never need to touch the PDEs again.
> +	 */
>  	for (i = 0; i < max_pdp; i++) {
>  		gen8_ppgtt_pde_t *pd_vaddr;
>  		pd_vaddr = kmap_atomic(&ppgtt->pd_pages[i]);
> @@ -461,6 +472,14 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size)
>  		kunmap_atomic(pd_vaddr);
>  	}
>  
> +	ppgtt->enable = gen8_ppgtt_enable;
> +	ppgtt->switch_mm = gen8_mm_switch;
> +	ppgtt->base.clear_range = gen8_ppgtt_clear_range;
> +	ppgtt->base.insert_entries = gen8_ppgtt_insert_entries;
> +	ppgtt->base.cleanup = gen8_ppgtt_cleanup;
> +	ppgtt->base.start = 0;
> +	ppgtt->base.total = ppgtt->num_pt_pages * GEN8_PTES_PER_PAGE * PAGE_SIZE;
> +
>  	ppgtt->base.clear_range(&ppgtt->base, 0,
>  				ppgtt->num_pd_entries * GEN8_PTES_PER_PAGE,
>  				true);
> @@ -473,8 +492,9 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size)
>  			 size % (1<<30));
>  	return 0;
>  
> -err_out:
> -	ppgtt->base.cleanup(&ppgtt->base);
> +bail:
> +	gen8_ppgtt_unmap_pages(ppgtt);
> +	gen8_ppgtt_free(ppgtt);
>  	return ret;
>  }
>  


[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

  reply	other threads:[~2014-02-19 15:00 UTC|newest]

Thread overview: 63+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <to=1387921357-22942-1-git-send-email-benjamin.widawsky@intel.com>
2014-02-12 22:28 ` [PATCH 0/9] [REPOST] BDW 4G GGTT + PPGTT cleanups Ben Widawsky
2014-02-12 22:28   ` [PATCH 1/9] drm/i915/bdw: Split up PPGTT cleanup Ben Widawsky
2014-02-13 10:40     ` Chris Wilson
2014-02-12 22:28   ` [PATCH 2/9] drm/i915/bdw: Reorganize PPGTT init Ben Widawsky
2014-02-19 14:59     ` Imre Deak [this message]
2014-02-19 20:06       ` [PATCH] [v3] " Ben Widawsky
2014-02-19 21:00         ` Imre Deak
2014-02-19 21:18           ` Ben Widawsky
2014-02-12 22:28   ` [PATCH 3/9] drm/i915/bdw: Split ppgtt initialization up Ben Widawsky
2014-02-19 17:03     ` Imre Deak
2014-02-12 22:28   ` [PATCH 4/9] drm/i915: Make clear/insert vfuncs args absolute Ben Widawsky
2014-02-13  0:14     ` Chris Wilson
2014-02-13  0:34       ` Ben Widawsky
2014-02-19 17:26     ` Imre Deak
2014-02-12 22:28   ` [PATCH 5/9] drm/i915/bdw: Reorganize PT allocations Ben Widawsky
2014-02-12 23:45     ` Chris Wilson
2014-02-12 23:52       ` Ben Widawsky
2014-02-19 19:11     ` Imre Deak
2014-02-19 19:25       ` Imre Deak
2014-02-19 21:06       ` Ben Widawsky
2014-02-19 21:20         ` Imre Deak
2014-02-19 21:31           ` Ben Widawsky
2014-02-12 22:28   ` [PATCH 6/9] Revert "drm/i915/bdw: Limit GTT to 2GB" Ben Widawsky
2014-02-19 19:14     ` Imre Deak
2014-02-12 22:28   ` [PATCH 7/9] drm/i915: Update i915_gem_gtt.c copyright Ben Widawsky
2014-02-12 23:19     ` Damien Lespiau
2014-02-12 23:22       ` Ben Widawsky
2014-02-19 19:20     ` Imre Deak
2014-02-12 22:28   ` [PATCH 8/9] drm/i915: Split GEN6 PPGTT cleanup Ben Widawsky
2014-02-13 10:29     ` Chris Wilson
2014-02-12 22:28   ` [PATCH 9/9] drm/i915: Split GEN6 PPGTT initialization up Ben Widawsky
2014-02-13 10:33     ` Chris Wilson
2014-02-13 11:47   ` [PATCH 0/9] [REPOST] BDW 4G GGTT + PPGTT cleanups Ville Syrjälä
2014-02-19 17:17     ` Ben Widawsky
2014-02-20  6:05   ` [PATCH 0/9] [v2] " Ben Widawsky
2014-02-21 21:06     ` [PATCH 10/9] drm/i915/bdw: Kill ppgtt->num_pt_pages Ben Widawsky
2014-02-24 17:17       ` Imre Deak
2014-03-04 15:42         ` Daniel Vetter
2014-03-04 14:50     ` [PATCH 0/9] [v2] BDW 4G GGTT + PPGTT cleanups Daniel Vetter
2014-02-20  6:05   ` [PATCH 1/9] drm/i915/bdw: Free PPGTT struct Ben Widawsky
2014-02-20  9:31     ` Imre Deak
2014-02-20 19:47     ` [PATCH .5/9] drm/i915: Move ppgtt_release out of the header Ben Widawsky
2014-02-20 19:47       ` [PATCH 1/9] [v2] drm/i915/bdw: Free PPGTT struct Ben Widawsky
2014-02-24 16:43         ` Imre Deak
2014-02-24 16:18       ` [PATCH .5/9] drm/i915: Move ppgtt_release out of the header Imre Deak
2014-03-04 14:53       ` Daniel Vetter
2014-02-20  6:05   ` [PATCH 2/9] drm/i915/bdw: Reorganize PPGTT init Ben Widawsky
2014-02-20  6:05   ` [PATCH 3/9] drm/i915/bdw: Split ppgtt initialization up Ben Widawsky
2014-02-20 13:10     ` Imre Deak
2014-02-20  6:05   ` [PATCH 4/9] drm/i915: Make clear/insert vfuncs args absolute Ben Widawsky
2014-02-20 10:37     ` Imre Deak
2014-02-20 19:35       ` Ben Widawsky
2014-02-20 19:50     ` [PATCH 4/9] [v3] " Ben Widawsky
2014-02-24 16:52       ` Imre Deak
2014-02-20  6:05   ` [PATCH 5/9] drm/i915/bdw: Reorganize PT allocations Ben Widawsky
2014-02-20 11:28     ` Imre Deak
2014-02-20 19:51     ` [PATCH 5/9] [v5] " Ben Widawsky
2014-02-24 17:03       ` Imre Deak
2014-02-24 23:38         ` Ben Widawsky
2014-02-20  6:05   ` [PATCH 6/9] Revert "drm/i915/bdw: Limit GTT to 2GB" Ben Widawsky
2014-02-20  6:05   ` [PATCH 7/9] drm/i915: Update i915_gem_gtt.c copyright Ben Widawsky
2014-02-20  6:05   ` [PATCH 8/9] drm/i915: Split GEN6 PPGTT cleanup Ben Widawsky
2014-02-20  6:05   ` [PATCH 9/9] drm/i915: Split GEN6 PPGTT initialization up Ben Widawsky

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=1392821989.19792.13.camel@intelbox \
    --to=imre.deak@intel.com \
    --cc=ben@bwidawsk.net \
    --cc=benjamin.widawsky@intel.com \
    --cc=intel-gfx@lists.freedesktop.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.