dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] drm/ttm: add swap_glob_mem in ttm_mem_global
@ 2018-01-29  8:31 Roger He
  2018-01-29  8:31 ` [PATCH 2/2] drm/ttm: add ttm page_flags TTM_PAGE_FLAG_PAGEFAULT Roger He
  2018-01-31  7:43 ` [PATCH 1/2] drm/ttm: add swap_glob_mem in ttm_mem_global Chunming Zhou
  0 siblings, 2 replies; 5+ messages in thread
From: Roger He @ 2018-01-29  8:31 UTC (permalink / raw)
  To: dri-devel; +Cc: Roger He, Christian.Koenig

separate swapped memory account from zone->used_mem because swapped
ttm pages can be flushed into SWAP disk/file under high memory pressure.

add check conditon in ttm_mem_global_reserve to prevent triggering OOM.
because if SWAP disk/file is full, all swapped ttm page would stay in
system memory which can't be flushed into disk/file. At this time, any
memory request will trigger OOM killer.

v2: always get total system swap size rather than getting it once
at module init time

Signed-off-by: Roger He <Hongbo.He@amd.com>
---
 drivers/gpu/drm/ttm/ttm_memory.c | 24 ++++++++++++++++--------
 drivers/gpu/drm/ttm/ttm_tt.c     | 13 +++++++++++--
 include/drm/ttm/ttm_memory.h     |  2 ++
 3 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c
index aa0c381..06024ba 100644
--- a/drivers/gpu/drm/ttm/ttm_memory.c
+++ b/drivers/gpu/drm/ttm/ttm_memory.c
@@ -36,6 +36,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/swap.h>
 
 #define TTM_MEMORY_ALLOC_RETRIES 4
 
@@ -183,20 +184,20 @@ static bool ttm_zones_above_swap_target(struct ttm_mem_global *glob,
 {
 	unsigned int i;
 	struct ttm_mem_zone *zone;
-	uint64_t target;
+	uint64_t target, limit;
 
 	for (i = 0; i < glob->num_zones; ++i) {
 		zone = glob->zones[i];
 
+		limit = (capable(CAP_SYS_ADMIN)) ?
+				zone->emer_mem : zone->max_mem;
+
 		if (from_wq)
 			target = zone->swap_limit;
-		else if (capable(CAP_SYS_ADMIN))
-			target = zone->emer_mem;
 		else
-			target = zone->max_mem;
+			target = limit;
 
 		target = (extra > target) ? 0ULL : target;
-
 		if (zone->used_mem > target)
 			return true;
 	}
@@ -373,6 +374,7 @@ int ttm_mem_global_init(struct ttm_mem_global *glob)
 		return ret;
 	}
 
+	atomic64_set(&glob->swap_glob_mem, 0);
 	si_meminfo(&si);
 
 	ret = ttm_mem_init_kernel_zone(glob, &si);
@@ -473,10 +475,14 @@ static int ttm_mem_global_reserve(struct ttm_mem_global *glob,
 				  struct ttm_mem_zone *single_zone,
 				  uint64_t amount, bool reserve)
 {
-	uint64_t limit;
+	uint64_t swap_glob_mem, max_swap_cache;
+	uint64_t limit, total_used_mem;
+	struct ttm_mem_zone *zone;
 	int ret = -ENOMEM;
 	unsigned int i;
-	struct ttm_mem_zone *zone;
+
+	swap_glob_mem = atomic64_read(&glob->swap_glob_mem);
+	max_swap_cache = (get_total_swap_pages() >> 1) << PAGE_SHIFT;
 
 	spin_lock(&glob->lock);
 	for (i = 0; i < glob->num_zones; ++i) {
@@ -487,7 +493,9 @@ static int ttm_mem_global_reserve(struct ttm_mem_global *glob,
 		limit = (capable(CAP_SYS_ADMIN)) ?
 			zone->emer_mem : zone->max_mem;
 
-		if (zone->used_mem > limit)
+		total_used_mem = zone->used_mem + swap_glob_mem;
+		limit += max_swap_cache;
+		if (total_used_mem > limit)
 			goto out_unlock;
 	}
 
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
index 9e4d43d..395cac0 100644
--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -177,8 +177,11 @@ void ttm_tt_destroy(struct ttm_tt *ttm)
 		ttm_tt_unpopulate(ttm);
 
 	if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTENT_SWAP) &&
-	    ttm->swap_storage)
+	    ttm->swap_storage) {
 		fput(ttm->swap_storage);
+		atomic64_sub_return(ttm->num_pages << PAGE_SHIFT,
+				    &ttm->glob->mem_glob->swap_glob_mem);
+	}
 
 	ttm->swap_storage = NULL;
 	ttm->func->destroy(ttm);
@@ -318,8 +321,11 @@ int ttm_tt_swapin(struct ttm_tt *ttm)
 		put_page(from_page);
 	}
 
-	if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTENT_SWAP))
+	if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTENT_SWAP)) {
 		fput(swap_storage);
+		atomic64_sub_return(ttm->num_pages << PAGE_SHIFT,
+				    &ttm->glob->mem_glob->swap_glob_mem);
+	}
 	ttm->swap_storage = NULL;
 	ttm->page_flags &= ~TTM_PAGE_FLAG_SWAPPED;
 
@@ -378,6 +384,9 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
 	ttm->page_flags |= TTM_PAGE_FLAG_SWAPPED;
 	if (persistent_swap_storage)
 		ttm->page_flags |= TTM_PAGE_FLAG_PERSISTENT_SWAP;
+	else
+		atomic64_add_return(ttm->num_pages << PAGE_SHIFT,
+			    &ttm->glob->mem_glob->swap_glob_mem);
 
 	return 0;
 out_err:
diff --git a/include/drm/ttm/ttm_memory.h b/include/drm/ttm/ttm_memory.h
index 8936285..a273581 100644
--- a/include/drm/ttm/ttm_memory.h
+++ b/include/drm/ttm/ttm_memory.h
@@ -49,6 +49,7 @@
  * @work: The workqueue callback for the shrink queue.
  * @lock: Lock to protect the @shrink - and the memory accounting members,
  * that is, essentially the whole structure with some exceptions.
+ * @swap_glob_mem: total size of ttm page which has been swapped out
  * @zones: Array of pointers to accounting zones.
  * @num_zones: Number of populated entries in the @zones array.
  * @zone_kernel: Pointer to the kernel zone.
@@ -67,6 +68,7 @@ struct ttm_mem_global {
 	struct workqueue_struct *swap_queue;
 	struct work_struct work;
 	spinlock_t lock;
+	atomic64_t swap_glob_mem;
 	struct ttm_mem_zone *zones[TTM_MEM_MAX_ZONES];
 	unsigned int num_zones;
 	struct ttm_mem_zone *zone_kernel;
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/2] drm/ttm: add ttm page_flags TTM_PAGE_FLAG_PAGEFAULT
  2018-01-29  8:31 [PATCH 1/2] drm/ttm: add swap_glob_mem in ttm_mem_global Roger He
@ 2018-01-29  8:31 ` Roger He
  2018-01-29 13:47   ` Christian König
  2018-01-31  7:53   ` Chunming Zhou
  2018-01-31  7:43 ` [PATCH 1/2] drm/ttm: add swap_glob_mem in ttm_mem_global Chunming Zhou
  1 sibling, 2 replies; 5+ messages in thread
From: Roger He @ 2018-01-29  8:31 UTC (permalink / raw)
  To: dri-devel; +Cc: Roger He, Christian.Koenig

to indicate whether we are serving for page fault routine when in
ttm_mem_global_reserve.

for ttm_mem_global_reserve if in page fault routine, allow success
always. because page fault routing already grabbed system memory
successfully and allow this exception is harmless.
Otherwise, it will trigger OOM killer.

v2: add new page flag TTM_PAGE_FLAG_PAGEFAULT rather than using
struct ttm_operation_ctx

Signed-off-by: Roger He <Hongbo.He@amd.com>
---
 drivers/gpu/drm/ttm/ttm_bo_vm.c          |  6 ++++--
 drivers/gpu/drm/ttm/ttm_memory.c         | 27 +++++++++++++++++++--------
 drivers/gpu/drm/ttm/ttm_page_alloc.c     |  5 ++++-
 drivers/gpu/drm/ttm/ttm_page_alloc_dma.c |  9 ++++++---
 drivers/gpu/drm/ttm/ttm_tt.c             |  2 +-
 include/drm/ttm/ttm_bo_driver.h          |  1 +
 include/drm/ttm/ttm_memory.h             |  3 ++-
 7 files changed, 37 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c
index 08a3c32..1aee124 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_vm.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c
@@ -235,9 +235,11 @@ static int ttm_bo_vm_fault(struct vm_fault *vmf)
 		ttm = bo->ttm;
 		cvma.vm_page_prot = ttm_io_prot(bo->mem.placement,
 						cvma.vm_page_prot);
-
+		ttm->page_flags |= TTM_PAGE_FLAG_PAGEFAULT;
 		/* Allocate all page at once, most common usage */
-		if (ttm->bdev->driver->ttm_tt_populate(ttm, &ctx)) {
+		ret = ttm->bdev->driver->ttm_tt_populate(ttm, &ctx);
+		ttm->page_flags &= ~TTM_PAGE_FLAG_PAGEFAULT;
+		if (ret) {
 			retval = VM_FAULT_OOM;
 			goto out_io_unlock;
 		}
diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c
index 06024ba..d0312a7 100644
--- a/drivers/gpu/drm/ttm/ttm_memory.c
+++ b/drivers/gpu/drm/ttm/ttm_memory.c
@@ -473,7 +473,8 @@ EXPORT_SYMBOL(ttm_mem_global_free);
 
 static int ttm_mem_global_reserve(struct ttm_mem_global *glob,
 				  struct ttm_mem_zone *single_zone,
-				  uint64_t amount, bool reserve)
+				  uint64_t amount, bool reserve,
+				  bool in_pagefault)
 {
 	uint64_t swap_glob_mem, max_swap_cache;
 	uint64_t limit, total_used_mem;
@@ -485,6 +486,13 @@ static int ttm_mem_global_reserve(struct ttm_mem_global *glob,
 	max_swap_cache = (get_total_swap_pages() >> 1) << PAGE_SHIFT;
 
 	spin_lock(&glob->lock);
+	/*
+	 * if in page_fault allow reserve successfully anyway since it
+	 * already allocated system pages. Otherwise it will trigger OOM
+	 */
+	if (in_pagefault)
+		goto reserve_direct;
+
 	for (i = 0; i < glob->num_zones; ++i) {
 		zone = glob->zones[i];
 		if (single_zone && zone != single_zone)
@@ -499,6 +507,7 @@ static int ttm_mem_global_reserve(struct ttm_mem_global *glob,
 			goto out_unlock;
 	}
 
+reserve_direct:
 	if (reserve) {
 		for (i = 0; i < glob->num_zones; ++i) {
 			zone = glob->zones[i];
@@ -520,13 +529,13 @@ static int ttm_mem_global_reserve(struct ttm_mem_global *glob,
 static int ttm_mem_global_alloc_zone(struct ttm_mem_global *glob,
 				     struct ttm_mem_zone *single_zone,
 				     uint64_t memory,
-				     struct ttm_operation_ctx *ctx)
+				     struct ttm_operation_ctx *ctx,
+				     bool in_pagefault)
 {
 	int count = TTM_MEMORY_ALLOC_RETRIES;
 
-	while (unlikely(ttm_mem_global_reserve(glob,
-					       single_zone,
-					       memory, true)
+	while (unlikely(ttm_mem_global_reserve(glob, single_zone, memory,
+					       true, in_pagefault)
 			!= 0)) {
 		if (ctx->no_wait_gpu)
 			return -ENOMEM;
@@ -546,13 +555,14 @@ int ttm_mem_global_alloc(struct ttm_mem_global *glob, uint64_t memory,
 	 * all zones.
 	 */
 
-	return ttm_mem_global_alloc_zone(glob, NULL, memory, ctx);
+	return ttm_mem_global_alloc_zone(glob, NULL, memory, ctx, false);
 }
 EXPORT_SYMBOL(ttm_mem_global_alloc);
 
 int ttm_mem_global_alloc_page(struct ttm_mem_global *glob,
 			      struct page *page, uint64_t size,
-			      struct ttm_operation_ctx *ctx)
+			      struct ttm_operation_ctx *ctx,
+			      bool in_pagefault)
 {
 	struct ttm_mem_zone *zone = NULL;
 
@@ -568,7 +578,8 @@ int ttm_mem_global_alloc_page(struct ttm_mem_global *glob,
 	if (glob->zone_dma32 && page_to_pfn(page) > 0x00100000UL)
 		zone = glob->zone_kernel;
 #endif
-	return ttm_mem_global_alloc_zone(glob, zone, size, ctx);
+	return ttm_mem_global_alloc_zone(glob, zone, size,
+					 ctx, in_pagefault);
 }
 
 void ttm_mem_global_free_page(struct ttm_mem_global *glob, struct page *page,
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c
index 5edcd89..39b184f 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
@@ -1094,6 +1094,7 @@ ttm_pool_unpopulate_helper(struct ttm_tt *ttm, unsigned mem_count_update)
 int ttm_pool_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx)
 {
 	struct ttm_mem_global *mem_glob = ttm->glob->mem_glob;
+	bool in_pagefault;
 	unsigned i;
 	int ret;
 
@@ -1107,9 +1108,11 @@ int ttm_pool_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx)
 		return ret;
 	}
 
+	in_pagefault = ttm->page_flags | TTM_PAGE_FLAG_PAGEFAULT;
 	for (i = 0; i < ttm->num_pages; ++i) {
 		ret = ttm_mem_global_alloc_page(mem_glob, ttm->pages[i],
-						PAGE_SIZE, ctx);
+						PAGE_SIZE, ctx,
+						in_pagefault);
 		if (unlikely(ret != 0)) {
 			ttm_pool_unpopulate_helper(ttm, i);
 			return -ENOMEM;
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
index 9e90d0e..77dd167 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
@@ -939,6 +939,7 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev,
 	struct dma_pool *pool;
 	struct dma_page *d_page;
 	enum pool_type type;
+	bool in_pagefault;
 	unsigned i;
 	int ret;
 
@@ -948,8 +949,8 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev,
 	INIT_LIST_HEAD(&ttm_dma->pages_list);
 	i = 0;
 
+	in_pagefault = ttm_dma->ttm.page_flags | TTM_PAGE_FLAG_PAGEFAULT;
 	type = ttm_to_type(ttm->page_flags, ttm->caching_state);
-
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 	if (ttm->page_flags & TTM_PAGE_FLAG_DMA32)
 		goto skip_huge;
@@ -971,7 +972,8 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev,
 			break;
 
 		ret = ttm_mem_global_alloc_page(mem_glob, ttm->pages[i],
-						pool->size, ctx);
+						pool->size, ctx,
+						in_pagefault);
 		if (unlikely(ret != 0)) {
 			ttm_dma_unpopulate(ttm_dma, dev);
 			return -ENOMEM;
@@ -1008,7 +1010,8 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev,
 		}
 
 		ret = ttm_mem_global_alloc_page(mem_glob, ttm->pages[i],
-						pool->size, ctx);
+						pool->size, ctx,
+						in_pagefault);
 		if (unlikely(ret != 0)) {
 			ttm_dma_unpopulate(ttm_dma, dev);
 			return -ENOMEM;
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
index 395cac0..c36db66 100644
--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -386,7 +386,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
 		ttm->page_flags |= TTM_PAGE_FLAG_PERSISTENT_SWAP;
 	else
 		atomic64_add_return(ttm->num_pages << PAGE_SHIFT,
-			    &ttm->glob->mem_glob->swap_glob_mem);
+				    &ttm->glob->mem_glob->swap_glob_mem);
 
 	return 0;
 out_err:
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
index 9b417eb..8f68781 100644
--- a/include/drm/ttm/ttm_bo_driver.h
+++ b/include/drm/ttm/ttm_bo_driver.h
@@ -87,6 +87,7 @@ struct ttm_backend_func {
 #define TTM_PAGE_FLAG_DMA32           (1 << 7)
 #define TTM_PAGE_FLAG_SG              (1 << 8)
 #define TTM_PAGE_FLAG_NO_RETRY	      (1 << 9)
+#define TTM_PAGE_FLAG_PAGEFAULT       (1 << 10)
 
 enum ttm_caching_state {
 	tt_uncached,
diff --git a/include/drm/ttm/ttm_memory.h b/include/drm/ttm/ttm_memory.h
index a273581..b801010 100644
--- a/include/drm/ttm/ttm_memory.h
+++ b/include/drm/ttm/ttm_memory.h
@@ -87,7 +87,8 @@ extern void ttm_mem_global_free(struct ttm_mem_global *glob,
 				uint64_t amount);
 extern int ttm_mem_global_alloc_page(struct ttm_mem_global *glob,
 				     struct page *page, uint64_t size,
-				     struct ttm_operation_ctx *ctx);
+				     struct ttm_operation_ctx *ctx,
+				     bool in_pagefault);
 extern void ttm_mem_global_free_page(struct ttm_mem_global *glob,
 				     struct page *page, uint64_t size);
 extern size_t ttm_round_pot(size_t size);
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 2/2] drm/ttm: add ttm page_flags TTM_PAGE_FLAG_PAGEFAULT
  2018-01-29  8:31 ` [PATCH 2/2] drm/ttm: add ttm page_flags TTM_PAGE_FLAG_PAGEFAULT Roger He
@ 2018-01-29 13:47   ` Christian König
  2018-01-31  7:53   ` Chunming Zhou
  1 sibling, 0 replies; 5+ messages in thread
From: Christian König @ 2018-01-29 13:47 UTC (permalink / raw)
  To: Roger He, dri-devel; +Cc: Christian.Koenig


> @@ -1107,9 +1108,11 @@ int ttm_pool_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx)
>   		return ret;
>   	}
>   
> +	in_pagefault = ttm->page_flags | TTM_PAGE_FLAG_PAGEFAULT;

That should probably be "ttm->page_flags & TTM_PAGE_FLAG_PAGEFAULT;".

>   	for (i = 0; i < ttm->num_pages; ++i) {
>   		ret = ttm_mem_global_alloc_page(mem_glob, ttm->pages[i],
> -						PAGE_SIZE, ctx);
> +						PAGE_SIZE, ctx,
> +						in_pagefault);
>   		if (unlikely(ret != 0)) {
>   			ttm_pool_unpopulate_helper(ttm, i);
>   			return -ENOMEM;
> diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
> index 9e90d0e..77dd167 100644
> --- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
> +++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
> @@ -939,6 +939,7 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev,
>   	struct dma_pool *pool;
>   	struct dma_page *d_page;
>   	enum pool_type type;
> +	bool in_pagefault;
>   	unsigned i;
>   	int ret;
>   
> @@ -948,8 +949,8 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev,
>   	INIT_LIST_HEAD(&ttm_dma->pages_list);
>   	i = 0;
>   
> +	in_pagefault = ttm_dma->ttm.page_flags | TTM_PAGE_FLAG_PAGEFAULT;

Dito.

Christian.

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/2] drm/ttm: add swap_glob_mem in ttm_mem_global
  2018-01-29  8:31 [PATCH 1/2] drm/ttm: add swap_glob_mem in ttm_mem_global Roger He
  2018-01-29  8:31 ` [PATCH 2/2] drm/ttm: add ttm page_flags TTM_PAGE_FLAG_PAGEFAULT Roger He
@ 2018-01-31  7:43 ` Chunming Zhou
  1 sibling, 0 replies; 5+ messages in thread
From: Chunming Zhou @ 2018-01-31  7:43 UTC (permalink / raw)
  To: Roger He, dri-devel; +Cc: Christian.Koenig



On 2018年01月29日 16:31, Roger He wrote:
> separate swapped memory account from zone->used_mem because swapped
> ttm pages can be flushed into SWAP disk/file under high memory pressure.
>
> add check conditon in ttm_mem_global_reserve to prevent triggering OOM.
> because if SWAP disk/file is full, all swapped ttm page would stay in
> system memory which can't be flushed into disk/file. At this time, any
> memory request will trigger OOM killer.
>
> v2: always get total system swap size rather than getting it once
> at module init time
>
> Signed-off-by: Roger He <Hongbo.He@amd.com>
> ---
>   drivers/gpu/drm/ttm/ttm_memory.c | 24 ++++++++++++++++--------
>   drivers/gpu/drm/ttm/ttm_tt.c     | 13 +++++++++++--
>   include/drm/ttm/ttm_memory.h     |  2 ++
>   3 files changed, 29 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c
> index aa0c381..06024ba 100644
> --- a/drivers/gpu/drm/ttm/ttm_memory.c
> +++ b/drivers/gpu/drm/ttm/ttm_memory.c
> @@ -36,6 +36,7 @@
>   #include <linux/mm.h>
>   #include <linux/module.h>
>   #include <linux/slab.h>
> +#include <linux/swap.h>
>   
>   #define TTM_MEMORY_ALLOC_RETRIES 4
>   
> @@ -183,20 +184,20 @@ static bool ttm_zones_above_swap_target(struct ttm_mem_global *glob,
>   {
>   	unsigned int i;
>   	struct ttm_mem_zone *zone;
> -	uint64_t target;
> +	uint64_t target, limit;
Don't need limit variable.

>   
>   	for (i = 0; i < glob->num_zones; ++i) {
>   		zone = glob->zones[i];
>   
> +		limit = (capable(CAP_SYS_ADMIN)) ?
> +				zone->emer_mem : zone->max_mem;
directly target = ...
> +
>   		if (from_wq)
>   			target = zone->swap_limit;
> -		else if (capable(CAP_SYS_ADMIN))
> -			target = zone->emer_mem;
>   		else
> -			target = zone->max_mem;
> +			target = limit;
Don't need `else` case.

>   
>   		target = (extra > target) ? 0ULL : target;
> -
>   		if (zone->used_mem > target)
>   			return true;
>   	}
> @@ -373,6 +374,7 @@ int ttm_mem_global_init(struct ttm_mem_global *glob)
>   		return ret;
>   	}
>   
> +	atomic64_set(&glob->swap_glob_mem, 0);
>   	si_meminfo(&si);
>   
>   	ret = ttm_mem_init_kernel_zone(glob, &si);
> @@ -473,10 +475,14 @@ static int ttm_mem_global_reserve(struct ttm_mem_global *glob,
>   				  struct ttm_mem_zone *single_zone,
>   				  uint64_t amount, bool reserve)
>   {
> -	uint64_t limit;
> +	uint64_t swap_glob_mem, max_swap_cache;
> +	uint64_t limit, total_used_mem;
> +	struct ttm_mem_zone *zone;
>   	int ret = -ENOMEM;
>   	unsigned int i;
> -	struct ttm_mem_zone *zone;
> +
> +	swap_glob_mem = atomic64_read(&glob->swap_glob_mem);
> +	max_swap_cache = (get_total_swap_pages() >> 1) << PAGE_SHIFT;
>   
>   	spin_lock(&glob->lock);
>   	for (i = 0; i < glob->num_zones; ++i) {
> @@ -487,7 +493,9 @@ static int ttm_mem_global_reserve(struct ttm_mem_global *glob,
>   		limit = (capable(CAP_SYS_ADMIN)) ?
>   			zone->emer_mem : zone->max_mem;
>   
> -		if (zone->used_mem > limit)
> +		total_used_mem = zone->used_mem + swap_glob_mem;
Good catch for total used mem.

Regards,
David Zhou
> +		limit += max_swap_cache;
> +		if (total_used_mem > limit)
>   			goto out_unlock;
>   	}
>   
> diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
> index 9e4d43d..395cac0 100644
> --- a/drivers/gpu/drm/ttm/ttm_tt.c
> +++ b/drivers/gpu/drm/ttm/ttm_tt.c
> @@ -177,8 +177,11 @@ void ttm_tt_destroy(struct ttm_tt *ttm)
>   		ttm_tt_unpopulate(ttm);
>   
>   	if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTENT_SWAP) &&
> -	    ttm->swap_storage)
> +	    ttm->swap_storage) {
>   		fput(ttm->swap_storage);
> +		atomic64_sub_return(ttm->num_pages << PAGE_SHIFT,
> +				    &ttm->glob->mem_glob->swap_glob_mem);
> +	}
>   
>   	ttm->swap_storage = NULL;
>   	ttm->func->destroy(ttm);
> @@ -318,8 +321,11 @@ int ttm_tt_swapin(struct ttm_tt *ttm)
>   		put_page(from_page);
>   	}
>   
> -	if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTENT_SWAP))
> +	if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTENT_SWAP)) {
>   		fput(swap_storage);
> +		atomic64_sub_return(ttm->num_pages << PAGE_SHIFT,
> +				    &ttm->glob->mem_glob->swap_glob_mem);
> +	}
>   	ttm->swap_storage = NULL;
>   	ttm->page_flags &= ~TTM_PAGE_FLAG_SWAPPED;
>   
> @@ -378,6 +384,9 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
>   	ttm->page_flags |= TTM_PAGE_FLAG_SWAPPED;
>   	if (persistent_swap_storage)
>   		ttm->page_flags |= TTM_PAGE_FLAG_PERSISTENT_SWAP;
> +	else
> +		atomic64_add_return(ttm->num_pages << PAGE_SHIFT,
> +			    &ttm->glob->mem_glob->swap_glob_mem);
>   
>   	return 0;
>   out_err:
> diff --git a/include/drm/ttm/ttm_memory.h b/include/drm/ttm/ttm_memory.h
> index 8936285..a273581 100644
> --- a/include/drm/ttm/ttm_memory.h
> +++ b/include/drm/ttm/ttm_memory.h
> @@ -49,6 +49,7 @@
>    * @work: The workqueue callback for the shrink queue.
>    * @lock: Lock to protect the @shrink - and the memory accounting members,
>    * that is, essentially the whole structure with some exceptions.
> + * @swap_glob_mem: total size of ttm page which has been swapped out
>    * @zones: Array of pointers to accounting zones.
>    * @num_zones: Number of populated entries in the @zones array.
>    * @zone_kernel: Pointer to the kernel zone.
> @@ -67,6 +68,7 @@ struct ttm_mem_global {
>   	struct workqueue_struct *swap_queue;
>   	struct work_struct work;
>   	spinlock_t lock;
> +	atomic64_t swap_glob_mem;
>   	struct ttm_mem_zone *zones[TTM_MEM_MAX_ZONES];
>   	unsigned int num_zones;
>   	struct ttm_mem_zone *zone_kernel;

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 2/2] drm/ttm: add ttm page_flags TTM_PAGE_FLAG_PAGEFAULT
  2018-01-29  8:31 ` [PATCH 2/2] drm/ttm: add ttm page_flags TTM_PAGE_FLAG_PAGEFAULT Roger He
  2018-01-29 13:47   ` Christian König
@ 2018-01-31  7:53   ` Chunming Zhou
  1 sibling, 0 replies; 5+ messages in thread
From: Chunming Zhou @ 2018-01-31  7:53 UTC (permalink / raw)
  To: Roger He, dri-devel; +Cc: Christian.Koenig



On 2018年01月29日 16:31, Roger He wrote:
> to indicate whether we are serving for page fault routine when in
> ttm_mem_global_reserve.
>
> for ttm_mem_global_reserve if in page fault routine, allow success
> always. because page fault routing already grabbed system memory
> successfully and allow this exception is harmless.
> Otherwise, it will trigger OOM killer.
>
> v2: add new page flag TTM_PAGE_FLAG_PAGEFAULT rather than using
> struct ttm_operation_ctx
>
> Signed-off-by: Roger He <Hongbo.He@amd.com>
> ---
>   drivers/gpu/drm/ttm/ttm_bo_vm.c          |  6 ++++--
>   drivers/gpu/drm/ttm/ttm_memory.c         | 27 +++++++++++++++++++--------
>   drivers/gpu/drm/ttm/ttm_page_alloc.c     |  5 ++++-
>   drivers/gpu/drm/ttm/ttm_page_alloc_dma.c |  9 ++++++---
>   drivers/gpu/drm/ttm/ttm_tt.c             |  2 +-
>   include/drm/ttm/ttm_bo_driver.h          |  1 +
>   include/drm/ttm/ttm_memory.h             |  3 ++-
>   7 files changed, 37 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c
> index 08a3c32..1aee124 100644
> --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c
> +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c
> @@ -235,9 +235,11 @@ static int ttm_bo_vm_fault(struct vm_fault *vmf)
>   		ttm = bo->ttm;
>   		cvma.vm_page_prot = ttm_io_prot(bo->mem.placement,
>   						cvma.vm_page_prot);
> -
> +		ttm->page_flags |= TTM_PAGE_FLAG_PAGEFAULT;
>   		/* Allocate all page at once, most common usage */
> -		if (ttm->bdev->driver->ttm_tt_populate(ttm, &ctx)) {
> +		ret = ttm->bdev->driver->ttm_tt_populate(ttm, &ctx);
> +		ttm->page_flags &= ~TTM_PAGE_FLAG_PAGEFAULT;
> +		if (ret) {
>   			retval = VM_FAULT_OOM;
>   			goto out_io_unlock;
>   		}
> diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c
> index 06024ba..d0312a7 100644
> --- a/drivers/gpu/drm/ttm/ttm_memory.c
> +++ b/drivers/gpu/drm/ttm/ttm_memory.c
> @@ -473,7 +473,8 @@ EXPORT_SYMBOL(ttm_mem_global_free);
>   
>   static int ttm_mem_global_reserve(struct ttm_mem_global *glob,
>   				  struct ttm_mem_zone *single_zone,
> -				  uint64_t amount, bool reserve)
> +				  uint64_t amount, bool reserve,
> +				  bool in_pagefault)
>   {
>   	uint64_t swap_glob_mem, max_swap_cache;
>   	uint64_t limit, total_used_mem;
> @@ -485,6 +486,13 @@ static int ttm_mem_global_reserve(struct ttm_mem_global *glob,
>   	max_swap_cache = (get_total_swap_pages() >> 1) << PAGE_SHIFT;
>   
>   	spin_lock(&glob->lock);
> +	/*
> +	 * if in page_fault allow reserve successfully anyway since it
> +	 * already allocated system pages. Otherwise it will trigger OOM
> +	 */
> +	if (in_pagefault)
> +		goto reserve_direct;
> +
>   	for (i = 0; i < glob->num_zones; ++i) {
>   		zone = glob->zones[i];
>   		if (single_zone && zone != single_zone)
> @@ -499,6 +507,7 @@ static int ttm_mem_global_reserve(struct ttm_mem_global *glob,
>   			goto out_unlock;
>   	}
>   
> +reserve_direct:
>   	if (reserve) {
>   		for (i = 0; i < glob->num_zones; ++i) {
>   			zone = glob->zones[i];
> @@ -520,13 +529,13 @@ static int ttm_mem_global_reserve(struct ttm_mem_global *glob,
>   static int ttm_mem_global_alloc_zone(struct ttm_mem_global *glob,
>   				     struct ttm_mem_zone *single_zone,
>   				     uint64_t memory,
> -				     struct ttm_operation_ctx *ctx)
> +				     struct ttm_operation_ctx *ctx,
> +				     bool in_pagefault)
>   {
>   	int count = TTM_MEMORY_ALLOC_RETRIES;
>   
> -	while (unlikely(ttm_mem_global_reserve(glob,
> -					       single_zone,
> -					       memory, true)
> +	while (unlikely(ttm_mem_global_reserve(glob, single_zone, memory,
> +					       true, in_pagefault)
>   			!= 0)) {
>   		if (ctx->no_wait_gpu)
>   			return -ENOMEM;
> @@ -546,13 +555,14 @@ int ttm_mem_global_alloc(struct ttm_mem_global *glob, uint64_t memory,
>   	 * all zones.
>   	 */
>   
> -	return ttm_mem_global_alloc_zone(glob, NULL, memory, ctx);
> +	return ttm_mem_global_alloc_zone(glob, NULL, memory, ctx, false);
>   }
>   EXPORT_SYMBOL(ttm_mem_global_alloc);
>   
>   int ttm_mem_global_alloc_page(struct ttm_mem_global *glob,
>   			      struct page *page, uint64_t size,
> -			      struct ttm_operation_ctx *ctx)
> +			      struct ttm_operation_ctx *ctx,
> +			      bool in_pagefault)
>   {
>   	struct ttm_mem_zone *zone = NULL;
>   
> @@ -568,7 +578,8 @@ int ttm_mem_global_alloc_page(struct ttm_mem_global *glob,
>   	if (glob->zone_dma32 && page_to_pfn(page) > 0x00100000UL)
>   		zone = glob->zone_kernel;
>   #endif
> -	return ttm_mem_global_alloc_zone(glob, zone, size, ctx);
> +	return ttm_mem_global_alloc_zone(glob, zone, size,
> +					 ctx, in_pagefault);
>   }
>   
>   void ttm_mem_global_free_page(struct ttm_mem_global *glob, struct page *page,
> diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c
> index 5edcd89..39b184f 100644
> --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
> +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
> @@ -1094,6 +1094,7 @@ ttm_pool_unpopulate_helper(struct ttm_tt *ttm, unsigned mem_count_update)
>   int ttm_pool_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx)
>   {
>   	struct ttm_mem_global *mem_glob = ttm->glob->mem_glob;
> +	bool in_pagefault;
>   	unsigned i;
>   	int ret;
>   
> @@ -1107,9 +1108,11 @@ int ttm_pool_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx)
>   		return ret;
>   	}
>   
> +	in_pagefault = ttm->page_flags | TTM_PAGE_FLAG_PAGEFAULT;
I guess you want to write as "in_pagefault = ttm->page_flags & 
TTM_PAGE_FLAG_PAGEFAULT; ".

>   	for (i = 0; i < ttm->num_pages; ++i) {
>   		ret = ttm_mem_global_alloc_page(mem_glob, ttm->pages[i],
> -						PAGE_SIZE, ctx);
> +						PAGE_SIZE, ctx,
> +						in_pagefault);
>   		if (unlikely(ret != 0)) {
>   			ttm_pool_unpopulate_helper(ttm, i);
>   			return -ENOMEM;
> diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
> index 9e90d0e..77dd167 100644
> --- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
> +++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
> @@ -939,6 +939,7 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev,
>   	struct dma_pool *pool;
>   	struct dma_page *d_page;
>   	enum pool_type type;
> +	bool in_pagefault;
>   	unsigned i;
>   	int ret;
>   
> @@ -948,8 +949,8 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev,
>   	INIT_LIST_HEAD(&ttm_dma->pages_list);
>   	i = 0;
>   
> +	in_pagefault = ttm_dma->ttm.page_flags | TTM_PAGE_FLAG_PAGEFAULT;
same above, should be "in_pagefault = ttm->page_flags & 
TTM_PAGE_FLAG_PAGEFAULT; ".

Regards,
David Zhou
>   	type = ttm_to_type(ttm->page_flags, ttm->caching_state);
> -
>   #ifdef CONFIG_TRANSPARENT_HUGEPAGE
>   	if (ttm->page_flags & TTM_PAGE_FLAG_DMA32)
>   		goto skip_huge;
> @@ -971,7 +972,8 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev,
>   			break;
>   
>   		ret = ttm_mem_global_alloc_page(mem_glob, ttm->pages[i],
> -						pool->size, ctx);
> +						pool->size, ctx,
> +						in_pagefault);
>   		if (unlikely(ret != 0)) {
>   			ttm_dma_unpopulate(ttm_dma, dev);
>   			return -ENOMEM;
> @@ -1008,7 +1010,8 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev,
>   		}
>   
>   		ret = ttm_mem_global_alloc_page(mem_glob, ttm->pages[i],
> -						pool->size, ctx);
> +						pool->size, ctx,
> +						in_pagefault);
>   		if (unlikely(ret != 0)) {
>   			ttm_dma_unpopulate(ttm_dma, dev);
>   			return -ENOMEM;
> diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
> index 395cac0..c36db66 100644
> --- a/drivers/gpu/drm/ttm/ttm_tt.c
> +++ b/drivers/gpu/drm/ttm/ttm_tt.c
> @@ -386,7 +386,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
>   		ttm->page_flags |= TTM_PAGE_FLAG_PERSISTENT_SWAP;
>   	else
>   		atomic64_add_return(ttm->num_pages << PAGE_SHIFT,
> -			    &ttm->glob->mem_glob->swap_glob_mem);
> +				    &ttm->glob->mem_glob->swap_glob_mem);
>   
>   	return 0;
>   out_err:
> diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
> index 9b417eb..8f68781 100644
> --- a/include/drm/ttm/ttm_bo_driver.h
> +++ b/include/drm/ttm/ttm_bo_driver.h
> @@ -87,6 +87,7 @@ struct ttm_backend_func {
>   #define TTM_PAGE_FLAG_DMA32           (1 << 7)
>   #define TTM_PAGE_FLAG_SG              (1 << 8)
>   #define TTM_PAGE_FLAG_NO_RETRY	      (1 << 9)
> +#define TTM_PAGE_FLAG_PAGEFAULT       (1 << 10)
>   
>   enum ttm_caching_state {
>   	tt_uncached,
> diff --git a/include/drm/ttm/ttm_memory.h b/include/drm/ttm/ttm_memory.h
> index a273581..b801010 100644
> --- a/include/drm/ttm/ttm_memory.h
> +++ b/include/drm/ttm/ttm_memory.h
> @@ -87,7 +87,8 @@ extern void ttm_mem_global_free(struct ttm_mem_global *glob,
>   				uint64_t amount);
>   extern int ttm_mem_global_alloc_page(struct ttm_mem_global *glob,
>   				     struct page *page, uint64_t size,
> -				     struct ttm_operation_ctx *ctx);
> +				     struct ttm_operation_ctx *ctx,
> +				     bool in_pagefault);
>   extern void ttm_mem_global_free_page(struct ttm_mem_global *glob,
>   				     struct page *page, uint64_t size);
>   extern size_t ttm_round_pot(size_t size);

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2018-01-31  7:53 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-29  8:31 [PATCH 1/2] drm/ttm: add swap_glob_mem in ttm_mem_global Roger He
2018-01-29  8:31 ` [PATCH 2/2] drm/ttm: add ttm page_flags TTM_PAGE_FLAG_PAGEFAULT Roger He
2018-01-29 13:47   ` Christian König
2018-01-31  7:53   ` Chunming Zhou
2018-01-31  7:43 ` [PATCH 1/2] drm/ttm: add swap_glob_mem in ttm_mem_global Chunming Zhou

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).