mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-10-01 01:35:54 -04:00
164 lines
5.6 KiB
Diff
164 lines
5.6 KiB
Diff
From f5f0a2fe84b589793baa5713ea2aa16779e00d5e Mon Sep 17 00:00:00 2001
|
|
From: Sunil Khatri <sunilkh@codeaurora.org>
|
|
Date: Mon, 13 Jun 2016 15:42:24 -0700
|
|
Subject: [PATCH] msm: kgsl: Defer adding the mem entry to a process
|
|
|
|
If we add the mem entry pointer in the process idr and rb tree
|
|
too early, other threads can do operations on the entry by
|
|
guessing the ID or GPU address before the object gets returned
|
|
by the creating operation.
|
|
|
|
Allocate an ID for the object but don't assign the pointer until
|
|
right before the creating function returns ensuring that another
|
|
operation can't access it until it is ready.
|
|
|
|
Bug: 28026365
|
|
Bug: 28377352
|
|
CRs-Fixed: 1002974
|
|
Change-Id: Ic0dedbadc0dd2125bd2a7bcc152972c0555e07f8
|
|
Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
|
|
Signed-off-by: Sunil Khatri <sunilkh@codeaurora.org>
|
|
Signed-off-by: Santhosh Punugu <spunug@codeaurora.org>
|
|
---
|
|
drivers/gpu/msm/kgsl.c | 60 ++++++++++++++++++++++++++++++++++++--------------
|
|
1 file changed, 43 insertions(+), 17 deletions(-)
|
|
|
|
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
|
|
index a1394b6d3d824..f62fe8ad0b857 100644
|
|
--- a/drivers/gpu/msm/kgsl.c
|
|
+++ b/drivers/gpu/msm/kgsl.c
|
|
@@ -1,4 +1,4 @@
|
|
-/* Copyright (c) 2008-2015, The Linux Foundation. All rights reserved.
|
|
+/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 and
|
|
@@ -296,18 +296,13 @@ kgsl_mem_entry_destroy(struct kref *kref)
|
|
EXPORT_SYMBOL(kgsl_mem_entry_destroy);
|
|
|
|
/**
|
|
- * kgsl_mem_entry_track_gpuaddr - Insert a mem_entry in the address tree and
|
|
- * assign it with a gpu address space before insertion
|
|
+ * kgsl_mem_entry_track_gpuaddr - Get the entry gpu address space before
|
|
+ * insertion to the process
|
|
* @process: the process that owns the memory
|
|
* @entry: the memory entry
|
|
*
|
|
- * @returns - 0 on succcess else error code
|
|
+ * @returns - 0 on success else error code
|
|
*
|
|
- * Insert the kgsl_mem_entry in to the rb_tree for searching by GPU address.
|
|
- * The assignment of gpu address and insertion into list needs to
|
|
- * happen with the memory lock held to avoid race conditions between
|
|
- * gpu address being selected and some other thread looking through the
|
|
- * rb list in search of memory based on gpuaddr
|
|
* This function should be called with processes memory spinlock held
|
|
*/
|
|
static int
|
|
@@ -315,8 +310,6 @@ kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process,
|
|
struct kgsl_mem_entry *entry)
|
|
{
|
|
int ret = 0;
|
|
- struct rb_node **node;
|
|
- struct rb_node *parent = NULL;
|
|
struct kgsl_pagetable *pagetable = process->pagetable;
|
|
|
|
assert_spin_locked(&process->mem_lock);
|
|
@@ -337,11 +330,22 @@ kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process,
|
|
pagetable = pagetable->mmu->securepagetable;
|
|
|
|
ret = kgsl_mmu_get_gpuaddr(pagetable, &entry->memdesc);
|
|
- if (ret)
|
|
- goto done;
|
|
|
|
- node = &process->mem_rb.rb_node;
|
|
+done:
|
|
+ return ret;
|
|
+}
|
|
|
|
+static void kgsl_mem_entry_commit_mem_list(struct kgsl_process_private *process,
|
|
+ struct kgsl_mem_entry *entry)
|
|
+{
|
|
+ struct rb_node **node;
|
|
+ struct rb_node *parent = NULL;
|
|
+
|
|
+ if (!entry->memdesc.gpuaddr)
|
|
+ return;
|
|
+
|
|
+ /* Insert mem entry in mem_rb tree */
|
|
+ node = &process->mem_rb.rb_node;
|
|
while (*node) {
|
|
struct kgsl_mem_entry *cur;
|
|
|
|
@@ -356,9 +360,20 @@ kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process,
|
|
|
|
rb_link_node(&entry->node, parent, node);
|
|
rb_insert_color(&entry->node, &process->mem_rb);
|
|
+}
|
|
|
|
-done:
|
|
- return ret;
|
|
+static void kgsl_mem_entry_commit_process(struct kgsl_process_private *process,
|
|
+ struct kgsl_mem_entry *entry)
|
|
+{
|
|
+ if (!entry)
|
|
+ return;
|
|
+
|
|
+ spin_lock(&entry->priv->mem_lock);
|
|
+ /* Insert mem entry in mem_rb tree */
|
|
+ kgsl_mem_entry_commit_mem_list(process, entry);
|
|
+ /* Replace mem entry in mem_idr using id */
|
|
+ idr_replace(&entry->priv->mem_idr, entry, entry->id);
|
|
+ spin_unlock(&entry->priv->mem_lock);
|
|
}
|
|
|
|
/**
|
|
@@ -407,7 +422,8 @@ kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry,
|
|
return -EBADF;
|
|
idr_preload(GFP_KERNEL);
|
|
spin_lock(&process->mem_lock);
|
|
- id = idr_alloc(&process->mem_idr, entry, 1, 0, GFP_NOWAIT);
|
|
+ /* Allocate the ID but don't attach the pointer just yet */
|
|
+ id = idr_alloc(&process->mem_idr, NULL, 1, 0, GFP_NOWAIT);
|
|
spin_unlock(&process->mem_lock);
|
|
idr_preload_end();
|
|
|
|
@@ -3247,6 +3263,7 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv,
|
|
|
|
trace_kgsl_mem_map(entry, param->fd);
|
|
|
|
+ kgsl_mem_entry_commit_process(private, entry);
|
|
return result;
|
|
|
|
error_attach:
|
|
@@ -3601,6 +3618,8 @@ long kgsl_ioctl_gpumem_alloc(struct kgsl_device_private *dev_priv,
|
|
param->gpuaddr = entry->memdesc.gpuaddr;
|
|
param->size = entry->memdesc.size;
|
|
param->flags = entry->memdesc.flags;
|
|
+
|
|
+ kgsl_mem_entry_commit_process(private, entry);
|
|
return result;
|
|
err:
|
|
kgsl_sharedmem_free(&entry->memdesc);
|
|
@@ -3646,6 +3665,8 @@ long kgsl_ioctl_gpumem_alloc_id(struct kgsl_device_private *dev_priv,
|
|
param->size = entry->memdesc.size;
|
|
param->mmapsize = kgsl_memdesc_mmapsize(&entry->memdesc);
|
|
param->gpuaddr = entry->memdesc.gpuaddr;
|
|
+
|
|
+ kgsl_mem_entry_commit_process(private, entry);
|
|
return result;
|
|
err:
|
|
if (entry)
|
|
@@ -4169,6 +4190,11 @@ static int kgsl_check_gpu_addr_collision(
|
|
spin_lock(&private->mem_lock);
|
|
kgsl_mem_entry_untrack_gpuaddr(private, entry);
|
|
spin_unlock(&private->mem_lock);
|
|
+ } else {
|
|
+ /* Insert mem entry in mem_rb tree */
|
|
+ spin_lock(&private->mem_lock);
|
|
+ kgsl_mem_entry_commit_mem_list(private, entry);
|
|
+ spin_unlock(&private->mem_lock);
|
|
}
|
|
} else {
|
|
trace_kgsl_mem_unmapped_area_collision(entry, addr, len,
|