From 41513329a1f1e396a383d61f808b578a87561cc9 Mon Sep 17 00:00:00 2001 From: securecrt Date: Wed, 25 Jul 2012 19:47:35 +0800 Subject: [PATCH] msm: kgsl: Detach memory objects from a process ahead of destroy time Previously, memory objects assumed that they remained attached to a process until they are destroyed. In the past this was mostly true, but worked by luck because a process could technically map the memory and then close the file descriptor which would eventually explode. Now we do the process related cleanup (MMU unmap, fixup statistics) when the object is released from the process so the process can go away without affecting the other holders of the mem object refcount. --- drivers/gpu/msm/kgsl.c | 21 ++++++++++++++++++--- drivers/gpu/msm/kgsl_mmu.c | 4 ++-- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 50fb5515..a954df73 100755 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -199,6 +199,21 @@ void kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry, entry->priv = process; } +/* Detach a memory entry from a process and unmap it from the MMU */ + +static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry) +{ + if (entry == NULL) + return; + + entry->priv->stats[entry->memtype].cur -= entry->memdesc.size; + entry->priv = NULL; + + kgsl_mmu_unmap(entry->memdesc.pagetable, &entry->memdesc); + + kgsl_mem_entry_put(entry); +} + /* Allocate a new context id */ static struct kgsl_context * @@ -597,7 +612,7 @@ kgsl_put_process_private(struct kgsl_device *device, list_for_each_entry_safe(entry, entry_tmp, &private->mem_list, list) { list_del(&entry->list); - kgsl_mem_entry_put(entry); + kgsl_mem_entry_detach_process(entry); } kgsl_mmu_putpagetable(private->pagetable); @@ -1022,7 +1037,7 @@ static void kgsl_freemem_event_cb(struct kgsl_device *device, spin_lock(&entry->priv->mem_lock); list_del(&entry->list); spin_unlock(&entry->priv->mem_lock); - kgsl_mem_entry_put(entry); + kgsl_mem_entry_detach_process(entry); } static long kgsl_ioctl_cmdstream_freememontimestamp(struct kgsl_device_private @@ -1116,7 +1131,7 @@ static long kgsl_ioctl_sharedmem_free(struct kgsl_device_private *dev_priv, spin_unlock(&private->mem_lock); if (entry) { - kgsl_mem_entry_put(entry); + kgsl_mem_entry_detach_process(entry); } else { KGSL_CORE_ERR("invalid gpuaddr %08x\n", param->gpuaddr); result = -EINVAL; diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c index 82f33c06..f03f4195 100755 --- a/drivers/gpu/msm/kgsl_mmu.c +++ b/drivers/gpu/msm/kgsl_mmu.c @@ -1,5 +1,4 @@ -/* Copyright (c) 2002,2007-2011, Code Aurora Forum. All rights reserved. - * Copyright (C) 2011 Sony Ericsson Mobile Communications AB. +/* Copyright (c) 2002,2007-2012, Code Aurora Forum. 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 @@ -593,6 +592,7 @@ kgsl_mmu_unmap(struct kgsl_pagetable *pagetable, memdesc->gpuaddr & KGSL_MMU_ALIGN_MASK, memdesc->size); + memdesc->gpuaddr = 0; return 0; } EXPORT_SYMBOL(kgsl_mmu_unmap);