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

Commit ea5788e6 authored by Sushmita Susheelendra's avatar Sushmita Susheelendra
Browse files

msm: kgsl: Use fault context to retrieve process information



Instead of looking up the process by pagetable base and
name, use the fault context to extract the pid and other
process specific information. This works for both the
per-process and global pagetable configurations and also
reduces some locking. This also reports the correct
pid and task name in the global pagetable configuration.

CRs-Fixed: 971753
Change-Id: I9c869527c3d1b2606f3d12234163935d6f5e43a9
Signed-off-by: default avatarSushmita Susheelendra <ssusheel@codeaurora.org>
parent 2d22d761
Loading
Loading
Loading
Loading
+12 −26
Original line number Diff line number Diff line
@@ -390,11 +390,10 @@ static void _get_entries(struct kgsl_process_private *private,
}

static void _find_mem_entries(struct kgsl_mmu *mmu, uint64_t faultaddr,
	phys_addr_t ptbase, struct _mem_entry *preventry,
	struct _mem_entry *nextentry)
		struct _mem_entry *preventry, struct _mem_entry *nextentry,
		struct kgsl_context *context)
{
	struct kgsl_process_private *private = NULL, *p;
	int id = kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase);
	struct kgsl_process_private *private;

	memset(preventry, 0, sizeof(*preventry));
	memset(nextentry, 0, sizeof(*nextentry));
@@ -402,22 +401,11 @@ static void _find_mem_entries(struct kgsl_mmu *mmu, uint64_t faultaddr,
	/* Set the maximum possible size as an initial value */
	nextentry->gpuaddr = (uint64_t) -1;

	mutex_lock(&kgsl_driver.process_mutex);
	list_for_each_entry(p, &kgsl_driver.process_list, list) {
		if (p->pagetable && (p->pagetable->name == id)) {
			if (kgsl_process_private_get(p))
				private = p;
			break;
		}
	}
	mutex_unlock(&kgsl_driver.process_mutex);

	if (private != NULL) {
	if (context) {
		private = context->proc_priv;
		spin_lock(&private->mem_lock);
		_get_entries(private, faultaddr, preventry, nextentry);
		spin_unlock(&private->mem_lock);

		kgsl_process_private_put(private);
	}
}

@@ -467,6 +455,7 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain,
	struct kgsl_iommu_context *ctx;
	u64 ptbase;
	u32 contextidr;
	pid_t tid = 0;
	pid_t ptname;
	struct _mem_entry prev, next;
	int write;
@@ -507,9 +496,7 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain,
	if (context != NULL) {
		/* save pagefault timestamp for GFT */
		set_bit(KGSL_CONTEXT_PRIV_PAGEFAULT, &context->priv);

		kgsl_context_put(context);
		context = NULL;
		tid = context->tid;
	}

	ctx->fault = 1;
@@ -535,7 +522,8 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain,
	ptbase = KGSL_IOMMU_GET_CTX_REG_Q(ctx, TTBR0);
	contextidr = KGSL_IOMMU_GET_CTX_REG(ctx, CONTEXTIDR);

	ptname = kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase);
	ptname = MMU_FEATURE(mmu, KGSL_MMU_GLOBAL_PAGETABLE) ?
		KGSL_MMU_GLOBAL_PT : tid;

	if (test_bit(KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE,
		&adreno_dev->ft_pf_policy))
@@ -556,8 +544,7 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain,
			KGSL_LOG_DUMP(ctx->kgsldev,
				"---- nearby memory ----\n");

			_find_mem_entries(mmu, addr, ptbase, &prev, &next);

			_find_mem_entries(mmu, addr, &prev, &next, context);
			if (prev.gpuaddr)
				_print_entry(ctx->kgsldev, &prev);
			else
@@ -570,13 +557,11 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain,
				_print_entry(ctx->kgsldev, &next);
			else
				KGSL_LOG_DUMP(ctx->kgsldev, "*EMPTY*\n");

		}
	}

	trace_kgsl_mmu_pagefault(ctx->kgsldev, addr,
			kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase),
			write ? "write" : "read");
			ptname, write ? "write" : "read");

	/*
	 * We do not want the h/w to resume fetching data from an iommu
@@ -602,6 +587,7 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain,
		adreno_dispatcher_schedule(device);
	}

	kgsl_context_put(context);
	return ret;
}

+0 −22
Original line number Diff line number Diff line
@@ -217,28 +217,6 @@ kgsl_mmu_detach_pagetable(struct kgsl_pagetable *pagetable)
	pagetable_remove_sysfs_objects(pagetable);
}

int
kgsl_mmu_get_ptname_from_ptbase(struct kgsl_mmu *mmu, u64 pt_base)
{
	struct kgsl_pagetable *pt;
	int ptid = -1;

	if (!MMU_OP_VALID(mmu, mmu_pt_equal))
		return KGSL_MMU_GLOBAL_PT;

	spin_lock(&kgsl_driver.ptlock);
	list_for_each_entry(pt, &kgsl_driver.pagetable_list, list) {
		if (mmu->mmu_ops->mmu_pt_equal(mmu, pt, pt_base)) {
			ptid = (int) pt->name;
			break;
		}
	}
	spin_unlock(&kgsl_driver.ptlock);

	return ptid;
}
EXPORT_SYMBOL(kgsl_mmu_get_ptname_from_ptbase);

struct kgsl_pagetable *kgsl_mmu_get_pt_from_ptname(struct kgsl_mmu *mmu,
						int ptname)
{
+0 −1
Original line number Diff line number Diff line
@@ -166,7 +166,6 @@ int kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
void kgsl_mmu_put_gpuaddr(struct kgsl_pagetable *pagetable,
		 struct kgsl_memdesc *memdesc);
unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr);
int kgsl_mmu_get_ptname_from_ptbase(struct kgsl_mmu *mmu, u64 pt_base);
unsigned int kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu,
		u64 ttbr0, uint64_t addr);
enum kgsl_mmutype kgsl_mmu_get_mmutype(struct kgsl_device *device);
+9 −9
Original line number Diff line number Diff line
@@ -129,11 +129,10 @@ static size_t snapshot_os(struct kgsl_device *device,
{
	struct kgsl_snapshot_linux *header = (struct kgsl_snapshot_linux *)buf;
	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
	struct task_struct *task;
	pid_t pid;
	int ctxtcount = 0;
	size_t size = sizeof(*header);
	u64 temp_ptbase;
	struct kgsl_context *context;

	/* Figure out how many active contexts there are - these will
	 * be appended on the end of the structure */
@@ -176,19 +175,20 @@ static size_t snapshot_os(struct kgsl_device *device,
	kgsl_sharedmem_readl(&device->memstore, &header->current_context,
		KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context));

	context = kgsl_context_get(device, header->current_context);

	/* Get the current PT base */
	temp_ptbase = kgsl_mmu_get_current_ttbr0(&device->mmu);
	/* Truncate to 32 bits in case LPAE is used */
	header->ptbase = (__u32)temp_ptbase;
	/* And the PID for the task leader */
	pid = header->pid = kgsl_mmu_get_ptname_from_ptbase(&device->mmu,
								temp_ptbase);

	task = find_task_by_vpid(pid);

	if (task)
		get_task_comm(header->comm, task);
	if (context) {
		header->pid = context->tid;
		strlcpy(header->comm, context->proc_priv->comm,
				sizeof(header->comm));
		kgsl_context_put(context);
		context = NULL;
	}

	header->ctxtcount = ctxtcount;