From fb77347f7115a5f88d755ecd89eebc8053ae00f2 Mon Sep 17 00:00:00 2001 From: Patrick Daly Date: Mon, 16 May 2016 19:41:57 -0700 Subject: [PATCH] ion: system_secure_heap: Support ION_IOC_DRAIN Memory in the secure page pool cannot be used for other tasks. If the ion client is aware that the memory will not be used for the foreseeable future then there is no point in caching it. Implement a method for the client to communicate this usecase to the kernel. Change-Id: Ib7e58e5ee739c65612602c5f9783600c8b2d6827 Signed-off-by: Patrick Daly --- .../android/ion/ion_system_secure_heap.c | 49 +++++++++++++++++-- drivers/staging/android/ion/msm/msm_ion.c | 8 +++ drivers/staging/android/ion/msm_ion_priv.h | 1 + 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/drivers/staging/android/ion/ion_system_secure_heap.c b/drivers/staging/android/ion/ion_system_secure_heap.c index 489c84a39dde..fecb7889f4a6 100644 --- a/drivers/staging/android/ion/ion_system_secure_heap.c +++ b/drivers/staging/android/ion/ion_system_secure_heap.c @@ -36,6 +36,7 @@ struct prefetch_info { struct list_head list; int vmid; size_t size; + bool shrink; }; static bool is_cp_flag_present(unsigned long flags) @@ -161,6 +162,31 @@ out: sys_heap->ops->free(&buffer); } +static void process_one_shrink(struct ion_heap *sys_heap, + struct prefetch_info *info) +{ + struct ion_buffer buffer; + size_t pool_size, size; + int ret; + + buffer.heap = sys_heap; + buffer.flags = info->vmid; + + pool_size = ion_system_heap_secure_page_pool_total(sys_heap, + info->vmid); + size = min(pool_size, info->size); + ret = sys_heap->ops->allocate(sys_heap, &buffer, size, PAGE_SIZE, + buffer.flags); + if (ret) { + pr_debug("%s: Failed to shrink 0x%zx, ret = %d\n", + __func__, info->size, ret); + return; + } + + buffer.private_flags = ION_PRIV_FLAG_SHRINKER_FREE; + sys_heap->ops->free(&buffer); +} + static void ion_system_secure_heap_prefetch_work(struct work_struct *work) { struct ion_system_secure_heap *secure_heap = container_of(work, @@ -176,7 +202,10 @@ static void ion_system_secure_heap_prefetch_work(struct work_struct *work) list_del(&info->list); spin_unlock_irqrestore(&secure_heap->work_lock, flags); - process_one_prefetch(sys_heap, info); + if (info->shrink) + process_one_shrink(sys_heap, info); + else + process_one_prefetch(sys_heap, info); kfree(info); spin_lock_irqsave(&secure_heap->work_lock, flags); @@ -186,7 +215,7 @@ static void ion_system_secure_heap_prefetch_work(struct work_struct *work) static int alloc_prefetch_info( struct ion_prefetch_regions __user *user_regions, - struct list_head *items) + bool shrink, struct list_head *items) { struct prefetch_info *info; size_t __user *user_sizes; @@ -215,6 +244,7 @@ static int alloc_prefetch_info( goto out_free; info->vmid = vmid; + info->shrink = shrink; INIT_LIST_HEAD(&info->list); list_add_tail(&info->list, items); } @@ -224,7 +254,8 @@ out_free: return err; } -int ion_system_secure_heap_prefetch(struct ion_heap *heap, void *ptr) +static int __ion_system_secure_heap_resize(struct ion_heap *heap, void *ptr, + bool shrink) { struct ion_system_secure_heap *secure_heap = container_of(heap, struct ion_system_secure_heap, @@ -242,7 +273,7 @@ int ion_system_secure_heap_prefetch(struct ion_heap *heap, void *ptr) return -EINVAL; for (i = 0; i < data->nr_regions; i++) { - ret = alloc_prefetch_info(&data->regions[i], &items); + ret = alloc_prefetch_info(&data->regions[i], shrink, &items); if (ret) goto out_free; } @@ -266,6 +297,16 @@ out_free: return ret; } +int ion_system_secure_heap_prefetch(struct ion_heap *heap, void *ptr) +{ + return __ion_system_secure_heap_resize(heap, ptr, false); +} + +int ion_system_secure_heap_drain(struct ion_heap *heap, void *ptr) +{ + return __ion_system_secure_heap_resize(heap, ptr, true); +} + static struct sg_table *ion_system_secure_heap_map_dma(struct ion_heap *heap, struct ion_buffer *buffer) { diff --git a/drivers/staging/android/ion/msm/msm_ion.c b/drivers/staging/android/ion/msm/msm_ion.c index 46d7aae9b1c4..cd420c429031 100644 --- a/drivers/staging/android/ion/msm/msm_ion.c +++ b/drivers/staging/android/ion/msm/msm_ion.c @@ -766,6 +766,14 @@ long msm_ion_custom_ioctl(struct ion_client *client, (void *)data.prefetch_data.len, ion_secure_cma_drain_pool); + if (ret) + return ret; + + ret = ion_walk_heaps(client, data.prefetch_data.heap_id, + ION_HEAP_TYPE_SYSTEM_SECURE, + (void *)&data.prefetch_data, + ion_system_secure_heap_drain); + if (ret) return ret; break; diff --git a/drivers/staging/android/ion/msm_ion_priv.h b/drivers/staging/android/ion/msm_ion_priv.h index 7ffab548313d..d6b58ad53c01 100644 --- a/drivers/staging/android/ion/msm_ion_priv.h +++ b/drivers/staging/android/ion/msm_ion_priv.h @@ -52,6 +52,7 @@ void ion_cp_heap_destroy(struct ion_heap *); struct ion_heap *ion_system_secure_heap_create(struct ion_platform_heap *); void ion_system_secure_heap_destroy(struct ion_heap *); int ion_system_secure_heap_prefetch(struct ion_heap *heap, void *data); +int ion_system_secure_heap_drain(struct ion_heap *heap, void *data); struct ion_heap *ion_cma_secure_heap_create(struct ion_platform_heap *); void ion_cma_secure_heap_destroy(struct ion_heap *);