mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-12-30 01:46:30 -05:00
209 lines
6.6 KiB
Diff
209 lines
6.6 KiB
Diff
From 15701ca335357e98a0eb98ef079fe45e3b830591 Mon Sep 17 00:00:00 2001
|
|
From: Sunil Khatri <sunilkh@codeaurora.org>
|
|
Date: Mon, 13 Jun 2016 15:45:19 -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
|
|
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 | 103 +++++++++++++++++++++++++++++++------------------
|
|
1 file changed, 65 insertions(+), 38 deletions(-)
|
|
|
|
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
|
|
index a4986a75b6260..31a403a939242 100644
|
|
--- a/drivers/gpu/msm/kgsl.c
|
|
+++ b/drivers/gpu/msm/kgsl.c
|
|
@@ -1,4 +1,4 @@
|
|
-/* Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
|
|
+/* Copyright (c) 2008-2013,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
|
|
@@ -246,18 +246,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
|
|
@@ -265,8 +260,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;
|
|
|
|
assert_spin_locked(&process->mem_lock);
|
|
/*
|
|
@@ -274,36 +267,17 @@ kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process,
|
|
* gpu address
|
|
*/
|
|
if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
|
|
- if (!entry->memdesc.gpuaddr)
|
|
- goto done;
|
|
- } else if (entry->memdesc.gpuaddr) {
|
|
- WARN_ONCE(1, "gpuaddr assigned w/o holding memory lock\n");
|
|
- ret = -EINVAL;
|
|
- goto done;
|
|
- }
|
|
- if (!kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
|
|
- ret = kgsl_mmu_get_gpuaddr(process->pagetable, &entry->memdesc);
|
|
- if (ret)
|
|
+ /* cpu map flag is enabled. do nothing */
|
|
+ } else {
|
|
+ if (entry->memdesc.gpuaddr) {
|
|
+ WARN_ONCE(1, "gpuaddr assigned w/o holding memory lock\n");
|
|
+ ret = -EINVAL;
|
|
goto done;
|
|
- }
|
|
-
|
|
- node = &process->mem_rb.rb_node;
|
|
-
|
|
- while (*node) {
|
|
- struct kgsl_mem_entry *cur;
|
|
-
|
|
- parent = *node;
|
|
- cur = rb_entry(parent, struct kgsl_mem_entry, node);
|
|
+ }
|
|
|
|
- if (entry->memdesc.gpuaddr < cur->memdesc.gpuaddr)
|
|
- node = &parent->rb_left;
|
|
- else
|
|
- node = &parent->rb_right;
|
|
+ ret = kgsl_mmu_get_gpuaddr(process->pagetable, &entry->memdesc);
|
|
}
|
|
|
|
- rb_link_node(&entry->node, parent, node);
|
|
- rb_insert_color(&entry->node, &process->mem_rb);
|
|
-
|
|
done:
|
|
return ret;
|
|
}
|
|
@@ -327,6 +301,47 @@ kgsl_mem_entry_untrack_gpuaddr(struct kgsl_process_private *process,
|
|
}
|
|
}
|
|
|
|
+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;
|
|
+
|
|
+ parent = *node;
|
|
+ cur = rb_entry(parent, struct kgsl_mem_entry, node);
|
|
+
|
|
+ if (entry->memdesc.gpuaddr < cur->memdesc.gpuaddr)
|
|
+ node = &parent->rb_left;
|
|
+ else
|
|
+ node = &parent->rb_right;
|
|
+ }
|
|
+
|
|
+ rb_link_node(&entry->node, parent, node);
|
|
+ rb_insert_color(&entry->node, &process->mem_rb);
|
|
+}
|
|
+
|
|
+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);
|
|
+}
|
|
+
|
|
/**
|
|
* kgsl_mem_entry_attach_process - Attach a mem_entry to its owner process
|
|
* @entry: the memory entry
|
|
@@ -357,9 +372,11 @@ kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry,
|
|
}
|
|
|
|
spin_lock(&process->mem_lock);
|
|
- ret = idr_get_new_above(&process->mem_idr, entry, 1,
|
|
+ /* Allocate the ID but don't attach the pointer just yet */
|
|
+ ret = idr_get_new_above(&process->mem_idr, NULL, 1,
|
|
&entry->id);
|
|
spin_unlock(&process->mem_lock);
|
|
+
|
|
if (ret == 0)
|
|
break;
|
|
else if (ret != -EAGAIN)
|
|
@@ -2894,6 +2911,7 @@ static 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:
|
|
@@ -3181,6 +3199,8 @@ 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);
|
|
@@ -3217,6 +3237,8 @@ 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)
|
|
@@ -3804,6 +3826,11 @@ kgsl_get_unmapped_area(struct file *file, unsigned long addr,
|
|
kgsl_mem_entry_untrack_gpuaddr(private, entry);
|
|
spin_unlock(&private->mem_lock);
|
|
ret = ret_val;
|
|
+ } 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);
|
|
}
|
|
break;
|
|
}
|