Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e45d69b8 authored by Puranam V G Tejaswi's avatar Puranam V G Tejaswi
Browse files

msm: kgsl: add support to reclaim pages of a process



To make kgsl pages reclaimable and to swap the pages, the already present
infrastructure of shmem is used. shmem provides the option of keeping
track of the swapped pages and getting the pages back when required.

At a given time, kgsl can make only those pages available for reclaim that
are not being used by GPU or by the user. The pages allowed to be reclaimed
should be chosen wisely, so that GPU or user do not use them immediately
after reclaim. Also, it is desirable that the swap out and swap in of pages
do not cause any performance impact on the active GPU use cases. Keeping
these in mind, making reclaimable all the pages of the processes that are
in background seems to be the best option. Here the pages are less likely
to be used any time soon and all the work is done while the process is
moving to foreground and no impact is seen when the process actually comes
to foreground and does something with the GPU. A sysfs node is exposed for
each process in /sys/class/kgsl/kgsl/proc/<pid>. The perf daemon that has
the knowledge about the process foreground and background communicates the
same to kgsl.

To make the pages reclaimable as part of PPR (Per Process Reclaim), kgsl
has to register to a notifier that would be called based on the system
wide memory pressure. The callback is necessary, as PPR works on the
process address space and all the pages that are not mapped to user space
will be left out, as PPR will never have the knowledge of the unmapped
kgsl pages. In the callback, kgsl decides if it can allow reclaim.

Allowing reclaim of too many pages will impact the next launch latency
of the application. So expose a node in /sys/class/kgsl/kgsl/ to set the
maximum limit that can be reclaimed per process. This is again set by
the perf daemon.

Expose a node /sys/class/kgsl/kgsl/proc/<pid>/gpumem_reclaimed to know
how much memory of the process has been reclaimed.

Change-Id: I94e8b6df0ace2ddc848c9d683c6b0d5314c7d309
Signed-off-by: default avatarPuranam V G Tejaswi <pvgtejas@codeaurora.org>
parent d8d879b5
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -35,3 +35,14 @@ config QCOM_KGSL_USE_SHMEM
	  there will be no support for the memory pools and higher order pages.
	  But using shmem will help in making kgsl pages available for
	  reclaiming.

config QCOM_KGSL_PROCESS_RECLAIM
	bool "Make driver pages available for reclaim"
	depends on QCOM_KGSL && PROCESS_RECLAIM
	select QCOM_KGSL_USE_SHMEM
	help
	  Say 'Y' to make driver pages available for reclaiming. If enabled,
	  shmem will be used for allocation. kgsl would know the process
	  foreground/background activity through the sysfs entry exposed per
	  process. Based on this kgsl can unpin the pages of the process and
	  make those pages available to the Per Process Reclaim (PPR).
+1 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ msm_kgsl_core-$(CONFIG_QCOM_KGSL_IOMMU) += kgsl_iommu.o
msm_kgsl_core-$(CONFIG_DEBUG_FS) += kgsl_debugfs.o
msm_kgsl_core-$(CONFIG_SYNC_FILE) += kgsl_sync.o
msm_kgsl_core-$(CONFIG_COMPAT) += kgsl_compat.o
msm_kgsl_core-$(CONFIG_QCOM_KGSL_PROCESS_RECLAIM) += kgsl_reclaim.o

ifndef CONFIG_QCOM_KGSL_USE_SHMEM
	msm_kgsl_core-y += kgsl_pool.o
+3 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
 */

#include <linux/slab.h>
@@ -152,6 +152,8 @@ static int adreno_ib_add(struct kgsl_process_private *process,
		adreno_ib_init_ib_obj(gpuaddr, size, type, entry,
			&(ib_obj_list->obj_list[ib_obj_list->num_objs]));
		ib_obj_list->num_objs++;
		/* Skip reclaim for the memdesc until it is dumped */
		entry->memdesc.priv |= KGSL_MEMDESC_SKIP_RECLAIM;
	}
	return 0;
}
+2 −0
Original line number Diff line number Diff line
@@ -155,6 +155,8 @@ static int snapshot_freeze_obj_list(struct kgsl_snapshot *snapshot,
				(ib_objs->gpuaddr + ib_objs->size)) &&
				(objbuf[index].entry->priv == process)) {
				freeze = 0;
				objbuf[index].entry->memdesc.priv &=
					~KGSL_MEMDESC_SKIP_RECLAIM;
				break;
			}
		}
+43 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include "kgsl_debugfs.h"
#include "kgsl_device.h"
#include "kgsl_mmu.h"
#include "kgsl_reclaim.h"
#include "kgsl_sync.h"
#include "kgsl_trace.h"

@@ -508,6 +509,10 @@ static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry)

	kgsl_mmu_put_gpuaddr(&entry->memdesc);

	atomic_sub(entry->memdesc.reclaimed_page_count,
			&entry->priv->reclaimed_page_count);


	kgsl_process_private_put(entry->priv);

	entry->priv = NULL;
@@ -980,6 +985,8 @@ static struct kgsl_process_private *kgsl_process_private_new(
	idr_init(&private->mem_idr);
	idr_init(&private->syncsource_idr);

	kgsl_reclaim_proc_private_init(private);

	/* Allocate a pagetable for the new process object */
	private->pagetable = kgsl_mmu_getpagetable(&device->mmu, tgid);
	if (IS_ERR(private->pagetable)) {
@@ -1856,6 +1863,9 @@ long kgsl_ioctl_rb_issueibcmds(struct kgsl_device_private *dev_priv,
		result = kgsl_drawobj_cmd_add_ibdesc(device, cmdobj, &ibdesc);
	}

	if (result == 0)
		result = kgsl_reclaim_to_pinned_state(dev_priv->process_priv);

	if (result == 0)
		result = dev_priv->device->ftbl->queue_cmds(dev_priv, context,
				&drawobj, 1, &param->timestamp);
@@ -1968,6 +1978,13 @@ long kgsl_ioctl_submit_commands(struct kgsl_device_private *dev_priv,
		if (cmdobj->profiling_buf_entry == NULL)
			DRAWOBJ(cmdobj)->flags &=
				~(unsigned long)KGSL_DRAWOBJ_PROFILING;

		if (type & CMDOBJ_TYPE) {
			result = kgsl_reclaim_to_pinned_state(
					dev_priv->process_priv);
			if (result)
				goto done;
		}
	}

	result = device->ftbl->queue_cmds(dev_priv, context, drawobj,
@@ -2058,6 +2075,13 @@ long kgsl_ioctl_gpu_command(struct kgsl_device_private *dev_priv,
		if (cmdobj->profiling_buf_entry == NULL)
			DRAWOBJ(cmdobj)->flags &=
				~(unsigned long)KGSL_DRAWOBJ_PROFILING;

		if (type & CMDOBJ_TYPE) {
			result = kgsl_reclaim_to_pinned_state(
					dev_priv->process_priv);
			if (result)
				goto done;
		}
	}

	result = device->ftbl->queue_cmds(dev_priv, context, drawobj,
@@ -3418,6 +3442,7 @@ struct kgsl_mem_entry *gpumem_alloc_entry(
	struct kgsl_mem_entry *entry;
	struct kgsl_mmu *mmu = &dev_priv->device->mmu;
	unsigned int align;
	u32 cachemode;

	flags &= KGSL_MEMFLAGS_GPUREADONLY
		| KGSL_CACHEMODE_MASK
@@ -3470,6 +3495,17 @@ struct kgsl_mem_entry *gpumem_alloc_entry(
		goto err;
	}

	cachemode = kgsl_memdesc_get_cachemode(&entry->memdesc);
	/*
	 * Secure buffers cannot be reclaimed. Avoid reclaim of cached buffers
	 * as we could get request for cache operations on these buffers when
	 * they are reclaimed.
	 */
	if (!(flags & KGSL_MEMFLAGS_SECURE) &&
			!(cachemode == KGSL_CACHEMODE_WRITEBACK) &&
			!(cachemode == KGSL_CACHEMODE_WRITETHROUGH))
		entry->memdesc.priv |= KGSL_MEMDESC_CAN_RECLAIM;

	kgsl_process_add_stats(private,
			kgsl_memdesc_usermem_type(&entry->memdesc),
			entry->memdesc.size);
@@ -4877,6 +4913,7 @@ static int kgsl_mmap(struct file *file, struct vm_area_struct *vma)

	vma->vm_file = file;

	entry->memdesc.vma = vma;
	entry->memdesc.useraddr = vma->vm_start;

	/*
@@ -5108,6 +5145,10 @@ int kgsl_device_platform_probe(struct kgsl_device *device)
	/* Initialize the memory pools */
	kgsl_init_page_pools(device->pdev);

	status = kgsl_reclaim_init();
	if (status)
		goto error_close_mmu;

	/*
	 * The default request type PM_QOS_REQ_ALL_CORES is
	 * applicable to all CPU cores that are online and
@@ -5200,6 +5241,8 @@ static void kgsl_core_exit(void)
	kgsl_events_exit();
	kgsl_core_debugfs_close();

	kgsl_reclaim_close();

	/*
	 * We call kgsl_sharedmem_uninit_sysfs() and device_unregister()
	 * only if kgsl_driver.virtdev has been populated.
Loading