Loading drivers/staging/android/ion/ion_cma_heap.c +51 −19 Original line number Original line Diff line number Diff line Loading @@ -4,7 +4,7 @@ * Copyright (C) Linaro 2012 * Copyright (C) Linaro 2012 * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson. * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson. * * * Copyright (c) 2016, The Linux Foundation. All rights reserved. * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * * This software is licensed under the terms of the GNU General Public * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * License version 2, as published by the Free Software Foundation, and Loading Loading @@ -242,28 +242,37 @@ void ion_cma_heap_destroy(struct ion_heap *heap) static void ion_secure_cma_free(struct ion_buffer *buffer) static void ion_secure_cma_free(struct ion_buffer *buffer) { { int ret = 0; int ret = 0; u32 source_vm; int *source_vm_list; int source_nelems; int dest_vmid; int dest_vmid; int dest_perms; int dest_perms; struct ion_cma_buffer_info *info = buffer->priv_virt; struct ion_cma_buffer_info *info = buffer->priv_virt; source_vm = get_secure_vmid(buffer->flags); source_nelems = count_set_bits(buffer->flags & ION_FLAGS_CP_MASK); if (source_vm < 0) { source_vm_list = kcalloc(source_nelems, sizeof(*source_vm_list), pr_err("%s: Failed to get secure vmid\n", __func__); GFP_KERNEL); if (!source_vm_list) return; return; ret = populate_vm_list(buffer->flags, source_vm_list, source_nelems); if (ret) { pr_err("%s: Failed to get secure vmids\n", __func__); goto out_free_source; } } dest_vmid = VMID_HLOS; dest_vmid = VMID_HLOS; dest_perms = PERM_READ | PERM_WRITE | PERM_EXEC; dest_perms = PERM_READ | PERM_WRITE | PERM_EXEC; ret = hyp_assign_table(info->table, &source_vm, 1, ret = hyp_assign_table(info->table, source_vm_list, source_nelems, &dest_vmid, &dest_perms, 1); &dest_vmid, &dest_perms, 1); if (ret) { if (ret) { pr_err("%s: Not freeing memory since assign failed\n", pr_err("%s: Not freeing memory since assign failed\n", __func__); __func__); return; goto out_free_source; } } ion_cma_free(buffer); ion_cma_free(buffer); out_free_source: kfree(source_vm_list); } } static int ion_secure_cma_allocate( static int ion_secure_cma_allocate( Loading @@ -272,41 +281,64 @@ static int ion_secure_cma_allocate( unsigned long align, unsigned long flags) unsigned long align, unsigned long flags) { { int ret = 0; int ret = 0; int count; int source_vm; int source_vm; int dest_vm; int *dest_vm_list = NULL; int dest_perms; int *dest_perms = NULL; int dest_nelems; struct ion_cma_buffer_info *info; struct ion_cma_buffer_info *info; source_vm = VMID_HLOS; source_vm = VMID_HLOS; dest_vm = get_secure_vmid(flags); if (dest_vm < 0) { dest_nelems = count_set_bits(flags & ION_FLAGS_CP_MASK); pr_err("%s: Failed to get secure vmid\n", __func__); dest_vm_list = kcalloc(dest_nelems, sizeof(*dest_vm_list), GFP_KERNEL); return -EINVAL; if (!dest_vm_list) { ret = -ENOMEM; goto out; } dest_perms = kcalloc(dest_nelems, sizeof(*dest_perms), GFP_KERNEL); if (!dest_perms) { ret = -ENOMEM; goto out_free_dest_vm; } ret = populate_vm_list(flags, dest_vm_list, dest_nelems); if (ret) { pr_err("%s: Failed to get secure vmid(s)\n", __func__); goto out_free_dest; } } if (dest_vm == VMID_CP_SEC_DISPLAY) for (count = 0; count < dest_nelems; count++) { dest_perms = PERM_READ; if (dest_vm_list[count] == VMID_CP_SEC_DISPLAY) dest_perms[count] = PERM_READ; else else dest_perms = PERM_READ | PERM_WRITE; dest_perms[count] = PERM_READ | PERM_WRITE; } ret = ion_cma_allocate(heap, buffer, len, align, flags); ret = ion_cma_allocate(heap, buffer, len, align, flags); if (ret) { if (ret) { dev_err(heap->priv, "Unable to allocate cma buffer"); dev_err(heap->priv, "Unable to allocate cma buffer"); return ret; goto out_free_dest; } } info = buffer->priv_virt; info = buffer->priv_virt; ret = hyp_assign_table(info->table, &source_vm, 1, ret = hyp_assign_table(info->table, &source_vm, 1, &dest_vm, &dest_perms, 1); dest_vm_list, dest_perms, dest_nelems); if (ret) { if (ret) { pr_err("%s: Assign call failed\n", __func__); pr_err("%s: Assign call failed\n", __func__); goto err; goto err; } } kfree(dest_vm_list); kfree(dest_perms); return ret; return ret; err: err: ion_secure_cma_free(buffer); ion_secure_cma_free(buffer); out_free_dest: kfree(dest_perms); out_free_dest_vm: kfree(dest_vm_list); out: return ret; return ret; } } Loading drivers/staging/android/ion/ion_priv.h +3 −1 Original line number Original line Diff line number Diff line Loading @@ -2,7 +2,7 @@ * drivers/staging/android/ion/ion_priv.h * drivers/staging/android/ion/ion_priv.h * * * Copyright (C) 2011 Google, Inc. * Copyright (C) 2011 Google, Inc. * Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. * * * This software is licensed under the terms of the GNU General Public * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * License version 2, as published by the Free Software Foundation, and Loading Loading @@ -294,6 +294,8 @@ long msm_ion_custom_ioctl(struct ion_client *client, int ion_heap_is_system_secure_heap_type(enum ion_heap_type type); int ion_heap_is_system_secure_heap_type(enum ion_heap_type type); int get_secure_vmid(unsigned long flags); int get_secure_vmid(unsigned long flags); bool is_secure_vmid_valid(int vmid); bool is_secure_vmid_valid(int vmid); unsigned int count_set_bits(unsigned long val); int populate_vm_list(unsigned long flags, unsigned int *vm_list, int nelems); /** /** * Functions to help assign/unassign sg_table for System Secure Heap * Functions to help assign/unassign sg_table for System Secure Heap Loading drivers/staging/android/ion/msm/msm_ion.c +24 −0 Original line number Original line Diff line number Diff line Loading @@ -31,6 +31,7 @@ #include <linux/highmem.h> #include <linux/highmem.h> #include <linux/cma.h> #include <linux/cma.h> #include <linux/module.h> #include <linux/module.h> #include <linux/bitops.h> #include <linux/show_mem_notifier.h> #include <linux/show_mem_notifier.h> #include <asm/cacheflush.h> #include <asm/cacheflush.h> #include "../ion_priv.h" #include "../ion_priv.h" Loading Loading @@ -622,6 +623,29 @@ bool is_secure_vmid_valid(int vmid) vmid == VMID_CP_SPSS_SP); vmid == VMID_CP_SPSS_SP); } } unsigned int count_set_bits(unsigned long val) { return ((unsigned int)bitmap_weight(&val, BITS_PER_LONG)); } int populate_vm_list(unsigned long flags, unsigned int *vm_list, int nelems) { unsigned int itr = 0; int vmid; flags = flags & ION_FLAGS_CP_MASK; for_each_set_bit(itr, &flags, BITS_PER_LONG) { vmid = get_secure_vmid(0x1UL << itr); if (vmid < 0 || !nelems) return -EINVAL; vm_list[nelems - 1] = vmid; nelems--; } return 0; } int get_secure_vmid(unsigned long flags) int get_secure_vmid(unsigned long flags) { { if (flags & ION_FLAG_CP_TOUCH) if (flags & ION_FLAG_CP_TOUCH) Loading drivers/staging/android/ion/msm/msm_ion.h +3 −1 Original line number Original line Diff line number Diff line /* Copyright (c) 2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and Loading @@ -22,6 +22,8 @@ enum ion_permission_type { IPT_TYPE_MDP_WRITEBACK = 2, IPT_TYPE_MDP_WRITEBACK = 2, }; }; #define ION_FLAGS_CP_MASK 0x7FFF0000 /* /* * This flag allows clients when mapping into the IOMMU to specify to * This flag allows clients when mapping into the IOMMU to specify to * defer un-mapping from the IOMMU until the buffer memory is freed. * defer un-mapping from the IOMMU until the buffer memory is freed. Loading Loading
drivers/staging/android/ion/ion_cma_heap.c +51 −19 Original line number Original line Diff line number Diff line Loading @@ -4,7 +4,7 @@ * Copyright (C) Linaro 2012 * Copyright (C) Linaro 2012 * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson. * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson. * * * Copyright (c) 2016, The Linux Foundation. All rights reserved. * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * * This software is licensed under the terms of the GNU General Public * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * License version 2, as published by the Free Software Foundation, and Loading Loading @@ -242,28 +242,37 @@ void ion_cma_heap_destroy(struct ion_heap *heap) static void ion_secure_cma_free(struct ion_buffer *buffer) static void ion_secure_cma_free(struct ion_buffer *buffer) { { int ret = 0; int ret = 0; u32 source_vm; int *source_vm_list; int source_nelems; int dest_vmid; int dest_vmid; int dest_perms; int dest_perms; struct ion_cma_buffer_info *info = buffer->priv_virt; struct ion_cma_buffer_info *info = buffer->priv_virt; source_vm = get_secure_vmid(buffer->flags); source_nelems = count_set_bits(buffer->flags & ION_FLAGS_CP_MASK); if (source_vm < 0) { source_vm_list = kcalloc(source_nelems, sizeof(*source_vm_list), pr_err("%s: Failed to get secure vmid\n", __func__); GFP_KERNEL); if (!source_vm_list) return; return; ret = populate_vm_list(buffer->flags, source_vm_list, source_nelems); if (ret) { pr_err("%s: Failed to get secure vmids\n", __func__); goto out_free_source; } } dest_vmid = VMID_HLOS; dest_vmid = VMID_HLOS; dest_perms = PERM_READ | PERM_WRITE | PERM_EXEC; dest_perms = PERM_READ | PERM_WRITE | PERM_EXEC; ret = hyp_assign_table(info->table, &source_vm, 1, ret = hyp_assign_table(info->table, source_vm_list, source_nelems, &dest_vmid, &dest_perms, 1); &dest_vmid, &dest_perms, 1); if (ret) { if (ret) { pr_err("%s: Not freeing memory since assign failed\n", pr_err("%s: Not freeing memory since assign failed\n", __func__); __func__); return; goto out_free_source; } } ion_cma_free(buffer); ion_cma_free(buffer); out_free_source: kfree(source_vm_list); } } static int ion_secure_cma_allocate( static int ion_secure_cma_allocate( Loading @@ -272,41 +281,64 @@ static int ion_secure_cma_allocate( unsigned long align, unsigned long flags) unsigned long align, unsigned long flags) { { int ret = 0; int ret = 0; int count; int source_vm; int source_vm; int dest_vm; int *dest_vm_list = NULL; int dest_perms; int *dest_perms = NULL; int dest_nelems; struct ion_cma_buffer_info *info; struct ion_cma_buffer_info *info; source_vm = VMID_HLOS; source_vm = VMID_HLOS; dest_vm = get_secure_vmid(flags); if (dest_vm < 0) { dest_nelems = count_set_bits(flags & ION_FLAGS_CP_MASK); pr_err("%s: Failed to get secure vmid\n", __func__); dest_vm_list = kcalloc(dest_nelems, sizeof(*dest_vm_list), GFP_KERNEL); return -EINVAL; if (!dest_vm_list) { ret = -ENOMEM; goto out; } dest_perms = kcalloc(dest_nelems, sizeof(*dest_perms), GFP_KERNEL); if (!dest_perms) { ret = -ENOMEM; goto out_free_dest_vm; } ret = populate_vm_list(flags, dest_vm_list, dest_nelems); if (ret) { pr_err("%s: Failed to get secure vmid(s)\n", __func__); goto out_free_dest; } } if (dest_vm == VMID_CP_SEC_DISPLAY) for (count = 0; count < dest_nelems; count++) { dest_perms = PERM_READ; if (dest_vm_list[count] == VMID_CP_SEC_DISPLAY) dest_perms[count] = PERM_READ; else else dest_perms = PERM_READ | PERM_WRITE; dest_perms[count] = PERM_READ | PERM_WRITE; } ret = ion_cma_allocate(heap, buffer, len, align, flags); ret = ion_cma_allocate(heap, buffer, len, align, flags); if (ret) { if (ret) { dev_err(heap->priv, "Unable to allocate cma buffer"); dev_err(heap->priv, "Unable to allocate cma buffer"); return ret; goto out_free_dest; } } info = buffer->priv_virt; info = buffer->priv_virt; ret = hyp_assign_table(info->table, &source_vm, 1, ret = hyp_assign_table(info->table, &source_vm, 1, &dest_vm, &dest_perms, 1); dest_vm_list, dest_perms, dest_nelems); if (ret) { if (ret) { pr_err("%s: Assign call failed\n", __func__); pr_err("%s: Assign call failed\n", __func__); goto err; goto err; } } kfree(dest_vm_list); kfree(dest_perms); return ret; return ret; err: err: ion_secure_cma_free(buffer); ion_secure_cma_free(buffer); out_free_dest: kfree(dest_perms); out_free_dest_vm: kfree(dest_vm_list); out: return ret; return ret; } } Loading
drivers/staging/android/ion/ion_priv.h +3 −1 Original line number Original line Diff line number Diff line Loading @@ -2,7 +2,7 @@ * drivers/staging/android/ion/ion_priv.h * drivers/staging/android/ion/ion_priv.h * * * Copyright (C) 2011 Google, Inc. * Copyright (C) 2011 Google, Inc. * Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. * * * This software is licensed under the terms of the GNU General Public * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * License version 2, as published by the Free Software Foundation, and Loading Loading @@ -294,6 +294,8 @@ long msm_ion_custom_ioctl(struct ion_client *client, int ion_heap_is_system_secure_heap_type(enum ion_heap_type type); int ion_heap_is_system_secure_heap_type(enum ion_heap_type type); int get_secure_vmid(unsigned long flags); int get_secure_vmid(unsigned long flags); bool is_secure_vmid_valid(int vmid); bool is_secure_vmid_valid(int vmid); unsigned int count_set_bits(unsigned long val); int populate_vm_list(unsigned long flags, unsigned int *vm_list, int nelems); /** /** * Functions to help assign/unassign sg_table for System Secure Heap * Functions to help assign/unassign sg_table for System Secure Heap Loading
drivers/staging/android/ion/msm/msm_ion.c +24 −0 Original line number Original line Diff line number Diff line Loading @@ -31,6 +31,7 @@ #include <linux/highmem.h> #include <linux/highmem.h> #include <linux/cma.h> #include <linux/cma.h> #include <linux/module.h> #include <linux/module.h> #include <linux/bitops.h> #include <linux/show_mem_notifier.h> #include <linux/show_mem_notifier.h> #include <asm/cacheflush.h> #include <asm/cacheflush.h> #include "../ion_priv.h" #include "../ion_priv.h" Loading Loading @@ -622,6 +623,29 @@ bool is_secure_vmid_valid(int vmid) vmid == VMID_CP_SPSS_SP); vmid == VMID_CP_SPSS_SP); } } unsigned int count_set_bits(unsigned long val) { return ((unsigned int)bitmap_weight(&val, BITS_PER_LONG)); } int populate_vm_list(unsigned long flags, unsigned int *vm_list, int nelems) { unsigned int itr = 0; int vmid; flags = flags & ION_FLAGS_CP_MASK; for_each_set_bit(itr, &flags, BITS_PER_LONG) { vmid = get_secure_vmid(0x1UL << itr); if (vmid < 0 || !nelems) return -EINVAL; vm_list[nelems - 1] = vmid; nelems--; } return 0; } int get_secure_vmid(unsigned long flags) int get_secure_vmid(unsigned long flags) { { if (flags & ION_FLAG_CP_TOUCH) if (flags & ION_FLAG_CP_TOUCH) Loading
drivers/staging/android/ion/msm/msm_ion.h +3 −1 Original line number Original line Diff line number Diff line /* Copyright (c) 2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 and Loading @@ -22,6 +22,8 @@ enum ion_permission_type { IPT_TYPE_MDP_WRITEBACK = 2, IPT_TYPE_MDP_WRITEBACK = 2, }; }; #define ION_FLAGS_CP_MASK 0x7FFF0000 /* /* * This flag allows clients when mapping into the IOMMU to specify to * This flag allows clients when mapping into the IOMMU to specify to * defer un-mapping from the IOMMU until the buffer memory is freed. * defer un-mapping from the IOMMU until the buffer memory is freed. Loading