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

Commit 1fa4f71d authored by Jordan Crouse's avatar Jordan Crouse
Browse files

msm: kgsl: Track the pagetable ID for the free mem list



When running with global pagetables the PID that freed the memory
and the pagetable ID (0) are different so don't use the PID of
the freeing process as the index to the entry. But it is still
interesting to store the pid of the process that freed the memory
(in fact even more interesting with global pagetables) so record
that still and print it on failure.

Change-Id: Ic0dedbad09f78998f7758777c60075780d1d7694
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
parent 71a815d0
Loading
Loading
Loading
Loading
+13 −5
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@ static const struct file_operations kgsl_fops;
static DEFINE_SPINLOCK(memfree_lock);

struct memfree_entry {
	pid_t ptname;
	uint64_t gpuaddr;
	uint64_t size;
	pid_t pid;
@@ -114,8 +115,8 @@ static void kgsl_memfree_exit(void)
	memset(&memfree, 0, sizeof(memfree));
}

int kgsl_memfree_find_entry(pid_t pid, uint64_t *gpuaddr,
	uint64_t *size, uint64_t *flags)
int kgsl_memfree_find_entry(pid_t ptname, uint64_t *gpuaddr,
	uint64_t *size, uint64_t *flags, pid_t *pid)
{
	int ptr;

@@ -132,12 +133,13 @@ int kgsl_memfree_find_entry(pid_t pid, uint64_t *gpuaddr,
	while (ptr != memfree.tail) {
		struct memfree_entry *entry = &memfree.list[ptr];

		if ((entry->pid == pid) &&
		if ((entry->ptname == ptname) &&
			(*gpuaddr >= entry->gpuaddr &&
			 *gpuaddr < (entry->gpuaddr + entry->size))) {
			*gpuaddr = entry->gpuaddr;
			*flags = entry->flags;
			*size = entry->size;
			*pid = entry->pid;

			spin_unlock(&memfree_lock);
			return 1;
@@ -153,7 +155,7 @@ int kgsl_memfree_find_entry(pid_t pid, uint64_t *gpuaddr,
	return 0;
}

static void kgsl_memfree_add(pid_t pid, uint64_t gpuaddr,
static void kgsl_memfree_add(pid_t pid, pid_t ptname, uint64_t gpuaddr,
		uint64_t size, uint64_t flags)

{
@@ -167,6 +169,7 @@ static void kgsl_memfree_add(pid_t pid, uint64_t gpuaddr,
	entry = &memfree.list[memfree.head];

	entry->pid = pid;
	entry->ptname = ptname;
	entry->gpuaddr = gpuaddr;
	entry->size = size;
	entry->flags = flags;
@@ -1657,12 +1660,17 @@ long kgsl_ioctl_drawctxt_destroy(struct kgsl_device_private *dev_priv,

static long gpumem_free_entry(struct kgsl_mem_entry *entry)
{
	pid_t ptname = 0;

	if (!kgsl_mem_entry_set_pend(entry))
		return -EBUSY;

	trace_kgsl_mem_free(entry);

	kgsl_memfree_add(entry->priv->pid, entry->memdesc.gpuaddr,
	if (entry->memdesc.pagetable != NULL)
		ptname = entry->memdesc.pagetable->name;

	kgsl_memfree_add(entry->priv->pid, ptname, entry->memdesc.gpuaddr,
		entry->memdesc.size, entry->memdesc.flags);

	kgsl_mem_entry_put(entry);
+2 −2
Original line number Diff line number Diff line
@@ -622,8 +622,8 @@ int kgsl_context_init(struct kgsl_device_private *, struct kgsl_context

void kgsl_context_dump(struct kgsl_context *context);

int kgsl_memfree_find_entry(pid_t pid, uint64_t *gpuaddr,
	uint64_t *size, uint64_t *flags);
int kgsl_memfree_find_entry(pid_t ptname, uint64_t *gpuaddr,
	uint64_t *size, uint64_t *flags, pid_t *pid);

long kgsl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);

+7 −6
Original line number Diff line number Diff line
@@ -239,16 +239,17 @@ static void _print_entry(struct kgsl_device *device, struct _mem_entry *entry)
}

static void _check_if_freed(struct kgsl_iommu_context *ctx,
	uint64_t addr, pid_t pid)
	uint64_t addr, pid_t ptname)
{
	uint64_t gpuaddr = addr;
	uint64_t size = 0;
	uint64_t flags = 0;
	pid_t pid;

	char name[32];
	memset(name, 0, sizeof(name));

	if (kgsl_memfree_find_entry(pid, &gpuaddr, &size, &flags)) {
	if (kgsl_memfree_find_entry(ptname, &gpuaddr, &size, &flags, &pid)) {
		kgsl_get_memory_usage(name, sizeof(name) - 1, flags);
		KGSL_LOG_DUMP(ctx->kgsldev, "---- premature free ----\n");
		KGSL_LOG_DUMP(ctx->kgsldev,
@@ -266,7 +267,7 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain,
	struct kgsl_iommu *iommu;
	struct kgsl_iommu_context *ctx;
	phys_addr_t ptbase;
	pid_t pid;
	pid_t ptname;
	struct _mem_entry prev, next;
	int write;
	struct kgsl_device *device;
@@ -327,7 +328,7 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain,
	ptbase = KGSL_IOMMU_GET_CTX_REG_Q(iommu, ctx->ctx_id, TTBR0)
			& KGSL_IOMMU_CTX_TTBR0_ADDR_MASK;

	pid = kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase);
	ptname = kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase);

	if (test_bit(KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE,
		&adreno_dev->ft_pf_policy))
@@ -335,13 +336,13 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain,

	if (!no_page_fault_log) {
		KGSL_MEM_CRIT(ctx->kgsldev,
			"GPU PAGE FAULT: addr = %lX pid = %d\n", addr, pid);
			"GPU PAGE FAULT: addr = %lX pid = %d\n", addr, ptname);
		KGSL_MEM_CRIT(ctx->kgsldev,
			"context = %d TTBR0 = %pa (%s %s fault)\n",
			ctx->ctx_id, &ptbase,
			write ? "write" : "read", fault_type);

		_check_if_freed(ctx, addr, pid);
		_check_if_freed(ctx, addr, ptname);

		KGSL_LOG_DUMP(ctx->kgsldev, "---- nearby memory ----\n");