Loading Documentation/devicetree/bindings/arm/msm/msm_ion.txt +31 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ Required properties for Ion heaps - "SYSTEM" - "SYSTEM_CONTIG" - "CARVEOUT" - "SECURE_CARVEOUT" - "CHUNK" - "CP" - "DMA" Loading @@ -41,6 +42,7 @@ Optional properties for Ion heaps Will set to a reasonable default value (e.g. the maximum heap size) if this option is not set. Example: qcom,ion { compatible = "qcom,msm-ion"; Loading Loading @@ -70,3 +72,32 @@ Example: qcom,ion-heap-type = "CARVEOUT"; }; }; "SECURE_CARVEOUT" This heap type is expected to contain multiple child nodes. Each child node shall contain the following required properties: - memory-regions: Refer to Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt - token: A u32 containing the set of secure domains which will be able to access the memory-region. Example: qcom,ion { compatible = "qcom,msm-ion"; #address-cells = <1>; #size-cells = <0>; qcom,ion-heap@14 { reg = <14>; qcom,ion-heap-type = "SECURE_CARVEOUT"; node1 { memory-regions = <&cp_region>; token = <ION_FLAG_CP_TOUCH>; }; }; }; drivers/staging/android/ion/ion_carveout_heap.c +221 −0 Original line number Diff line number Diff line Loading @@ -206,3 +206,224 @@ void ion_carveout_heap_destroy(struct ion_heap *heap) kfree(carveout_heap); carveout_heap = NULL; } #include "msm/msm_ion.h" #include <soc/qcom/secure_buffer.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/msm_ion.h> struct ion_sc_entry { struct list_head list; struct ion_heap *heap; u32 token; }; struct ion_sc_heap { struct ion_heap heap; struct device *dev; struct list_head children; }; static struct ion_heap *ion_sc_find_child(struct ion_heap *heap, u32 flags) { struct ion_sc_heap *manager; struct ion_sc_entry *entry; manager = container_of(heap, struct ion_sc_heap, heap); flags = flags & ION_FLAGS_CP_MASK; list_for_each_entry(entry, &manager->children, list) { if (entry->token == flags) return entry->heap; } return NULL; } static int ion_sc_heap_allocate(struct ion_heap *heap, struct ion_buffer *buffer, unsigned long len, unsigned long align, unsigned long flags) { struct ion_heap *child; /* cache maintenance is not possible on secure memory */ flags &= ~((unsigned long)ION_FLAG_CACHED); buffer->flags = flags; child = ion_sc_find_child(heap, flags); if (!child) return -EINVAL; return ion_carveout_heap_allocate(child, buffer, len, align, flags); } static void ion_sc_heap_free(struct ion_buffer *buffer) { struct ion_heap *child; struct sg_table *table = buffer->priv_virt; struct page *page = sg_page(table->sgl); ion_phys_addr_t paddr = PFN_PHYS(page_to_pfn(page)); child = ion_sc_find_child(buffer->heap, buffer->flags); if (!child) { WARN(1, "ion_secure_carvout: invalid buffer flags on free. Memory will be leaked\n."); return; } ion_carveout_free(child, paddr, buffer->size); sg_free_table(table); kfree(table); } static struct ion_heap_ops ion_sc_heap_ops = { .allocate = ion_sc_heap_allocate, .free = ion_sc_heap_free, .phys = ion_carveout_heap_phys, .map_dma = ion_carveout_heap_map_dma, .unmap_dma = ion_carveout_heap_unmap_dma, }; static int ion_sc_get_dt_token(struct ion_sc_entry *entry, struct device_node *np, u64 base, u64 size) { u32 token; u32 *vmids, *modes; u32 nr, i; int ret = -EINVAL; u32 src_vm = VMID_HLOS; if (of_property_read_u32(np, "token", &token)) return -EINVAL; nr = count_set_bits(token); vmids = kcalloc(nr, sizeof(*vmids), GFP_KERNEL); if (!vmids) return -ENOMEM; modes = kcalloc(nr, sizeof(*modes), GFP_KERNEL); if (!modes) { kfree(vmids); return -ENOMEM; } if ((token & ~ION_FLAGS_CP_MASK) || populate_vm_list(token, vmids, nr)) { pr_err("secure_carveout_heap: Bad token %x\n", token); goto out; } for (i = 0; i < nr; i++) if (vmids[i] == VMID_CP_SEC_DISPLAY) modes[i] = PERM_READ; else modes[i] = PERM_READ | PERM_WRITE; ret = hyp_assign_phys(base, size, &src_vm, 1, vmids, modes, nr); if (ret) pr_err("secure_carveout_heap: Assign token 0x%x failed\n", token); else entry->token = token; out: kfree(modes); kfree(vmids); return ret; } static int ion_sc_add_child(struct ion_sc_heap *manager, struct device_node *np) { struct device *dev = manager->dev; struct ion_platform_heap heap_data = {0}; struct ion_sc_entry *entry; struct device_node *phandle; const __be32 *basep; u64 base, size; int ret; entry = kzalloc(sizeof(*entry), GFP_KERNEL); if (!entry) return -ENOMEM; INIT_LIST_HEAD(&entry->list); phandle = of_parse_phandle(np, "memory-region", 0); if (!phandle) goto out_free; basep = of_get_address(phandle, 0, &size, NULL); if (!basep) goto out_free; base = of_translate_address(phandle, basep); if (base == OF_BAD_ADDR) goto out_free; heap_data.priv = dev; heap_data.base = base; heap_data.size = size; /* This will zero memory initially */ entry->heap = ion_carveout_heap_create(&heap_data); if (IS_ERR(entry->heap)) goto out_free; ret = ion_sc_get_dt_token(entry, np, base, size); if (ret) goto out_free_carveout; list_add(&entry->list, &manager->children); dev_info(dev, "ion_secure_carveout: creating heap@0x%llx, size 0x%llx\n", base, size); return 0; out_free_carveout: ion_carveout_heap_destroy(entry->heap); out_free: kfree(entry); return -EINVAL; } void ion_secure_carveout_heap_destroy(struct ion_heap *heap) { struct ion_sc_heap *manager = container_of(heap, struct ion_sc_heap, heap); struct ion_sc_entry *entry, *tmp; list_for_each_entry_safe(entry, tmp, &manager->children, list) { ion_carveout_heap_destroy(entry->heap); kfree(entry); } kfree(manager); } struct ion_heap *ion_secure_carveout_heap_create( struct ion_platform_heap *heap_data) { struct device *dev = heap_data->priv; int ret; struct ion_sc_heap *manager; struct device_node *np; manager = kzalloc(sizeof(*manager), GFP_KERNEL); if (!manager) return ERR_PTR(-ENOMEM); INIT_LIST_HEAD(&manager->children); manager->dev = dev; for_each_child_of_node(dev->of_node, np) { ret = ion_sc_add_child(manager, np); if (ret) { dev_err(dev, "Creating child pool %s failed\n", np->name); goto err; } } manager->heap.ops = &ion_sc_heap_ops; manager->heap.type = ION_HEAP_TYPE_SECURE_CARVEOUT; return &manager->heap; err: ion_secure_carveout_heap_destroy(&manager->heap); return ERR_PTR(-EINVAL); } drivers/staging/android/ion/msm/msm_ion.c +11 −0 Original line number Diff line number Diff line Loading @@ -122,6 +122,10 @@ static struct ion_heap_desc ion_heap_meta[] = { { .id = ION_SECURE_DISPLAY_HEAP_ID, .name = ION_SECURE_DISPLAY_HEAP_NAME, }, { .id = ION_SECURE_CARVEOUT_HEAP_ID, .name = ION_SECURE_CARVEOUT_HEAP_NAME, } }; #endif Loading Loading @@ -443,6 +447,7 @@ static struct heap_types_info { MAKE_HEAP_TYPE_MAPPING(SYSTEM), MAKE_HEAP_TYPE_MAPPING(SYSTEM_CONTIG), MAKE_HEAP_TYPE_MAPPING(CARVEOUT), MAKE_HEAP_TYPE_MAPPING(SECURE_CARVEOUT), MAKE_HEAP_TYPE_MAPPING(CHUNK), MAKE_HEAP_TYPE_MAPPING(DMA), MAKE_HEAP_TYPE_MAPPING(SECURE_DMA), Loading Loading @@ -1021,6 +1026,9 @@ static struct ion_heap *msm_ion_heap_create(struct ion_platform_heap *heap_data) case ION_HEAP_TYPE_HYP_CMA: heap = ion_cma_secure_heap_create(heap_data); break; case ION_HEAP_TYPE_SECURE_CARVEOUT: heap = ion_secure_carveout_heap_create(heap_data); break; default: heap = ion_heap_create(heap_data); } Loading Loading @@ -1056,6 +1064,9 @@ static void msm_ion_heap_destroy(struct ion_heap *heap) case ION_HEAP_TYPE_HYP_CMA: ion_cma_secure_heap_destroy(heap); break; case ION_HEAP_TYPE_SECURE_CARVEOUT: ion_secure_carveout_heap_destroy(heap); break; default: ion_heap_destroy(heap); } Loading drivers/staging/android/ion/msm_ion_priv.h +5 −1 Original line number Diff line number Diff line Loading @@ -2,7 +2,7 @@ * drivers/staging/android/ion/msm_ion_priv.h * * Copyright (C) 2011 Google, Inc. * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and Loading Loading @@ -40,6 +40,10 @@ int ion_system_secure_heap_drain(struct ion_heap *heap, void *data); struct ion_heap *ion_cma_secure_heap_create(struct ion_platform_heap *heap); void ion_cma_secure_heap_destroy(struct ion_heap *heap); struct ion_heap *ion_secure_carveout_heap_create( struct ion_platform_heap *heap); void ion_secure_carveout_heap_destroy(struct ion_heap *heap); long msm_ion_custom_ioctl(struct ion_client *client, unsigned int cmd, unsigned long arg); Loading drivers/staging/android/uapi/msm_ion.h +3 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ enum msm_ion_heap_types { ION_HEAP_TYPE_SECURE_DMA = ION_HEAP_TYPE_MSM_START, ION_HEAP_TYPE_SYSTEM_SECURE, ION_HEAP_TYPE_HYP_CMA, ION_HEAP_TYPE_SECURE_CARVEOUT, /* * if you add a heap type here you should also add it to * heap_types_info[] in msm_ion.c Loading @@ -32,6 +33,7 @@ enum ion_heap_ids { ION_SECURE_DISPLAY_HEAP_ID = 10, ION_CP_MFC_HEAP_ID = 12, ION_SPSS_HEAP_ID = 13, /* Secure Processor ION heap */ ION_SECURE_CARVEOUT_HEAP_ID = 14, ION_CP_WB_HEAP_ID = 16, /* 8660 only */ ION_QSECOM_TA_HEAP_ID = 19, ION_CAMERA_HEAP_ID = 20, /* 8660 only */ Loading Loading @@ -133,6 +135,7 @@ enum cp_mem_usage { #define ION_IOMMU_HEAP_NAME "iommu" #define ION_MFC_HEAP_NAME "mfc" #define ION_SPSS_HEAP_NAME "spss" #define ION_SECURE_CARVEOUT_HEAP_NAME "secure_carveout" #define ION_WB_HEAP_NAME "wb" #define ION_MM_FIRMWARE_HEAP_NAME "mm_fw" #define ION_PIL1_HEAP_NAME "pil_1" Loading Loading
Documentation/devicetree/bindings/arm/msm/msm_ion.txt +31 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ Required properties for Ion heaps - "SYSTEM" - "SYSTEM_CONTIG" - "CARVEOUT" - "SECURE_CARVEOUT" - "CHUNK" - "CP" - "DMA" Loading @@ -41,6 +42,7 @@ Optional properties for Ion heaps Will set to a reasonable default value (e.g. the maximum heap size) if this option is not set. Example: qcom,ion { compatible = "qcom,msm-ion"; Loading Loading @@ -70,3 +72,32 @@ Example: qcom,ion-heap-type = "CARVEOUT"; }; }; "SECURE_CARVEOUT" This heap type is expected to contain multiple child nodes. Each child node shall contain the following required properties: - memory-regions: Refer to Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt - token: A u32 containing the set of secure domains which will be able to access the memory-region. Example: qcom,ion { compatible = "qcom,msm-ion"; #address-cells = <1>; #size-cells = <0>; qcom,ion-heap@14 { reg = <14>; qcom,ion-heap-type = "SECURE_CARVEOUT"; node1 { memory-regions = <&cp_region>; token = <ION_FLAG_CP_TOUCH>; }; }; };
drivers/staging/android/ion/ion_carveout_heap.c +221 −0 Original line number Diff line number Diff line Loading @@ -206,3 +206,224 @@ void ion_carveout_heap_destroy(struct ion_heap *heap) kfree(carveout_heap); carveout_heap = NULL; } #include "msm/msm_ion.h" #include <soc/qcom/secure_buffer.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/msm_ion.h> struct ion_sc_entry { struct list_head list; struct ion_heap *heap; u32 token; }; struct ion_sc_heap { struct ion_heap heap; struct device *dev; struct list_head children; }; static struct ion_heap *ion_sc_find_child(struct ion_heap *heap, u32 flags) { struct ion_sc_heap *manager; struct ion_sc_entry *entry; manager = container_of(heap, struct ion_sc_heap, heap); flags = flags & ION_FLAGS_CP_MASK; list_for_each_entry(entry, &manager->children, list) { if (entry->token == flags) return entry->heap; } return NULL; } static int ion_sc_heap_allocate(struct ion_heap *heap, struct ion_buffer *buffer, unsigned long len, unsigned long align, unsigned long flags) { struct ion_heap *child; /* cache maintenance is not possible on secure memory */ flags &= ~((unsigned long)ION_FLAG_CACHED); buffer->flags = flags; child = ion_sc_find_child(heap, flags); if (!child) return -EINVAL; return ion_carveout_heap_allocate(child, buffer, len, align, flags); } static void ion_sc_heap_free(struct ion_buffer *buffer) { struct ion_heap *child; struct sg_table *table = buffer->priv_virt; struct page *page = sg_page(table->sgl); ion_phys_addr_t paddr = PFN_PHYS(page_to_pfn(page)); child = ion_sc_find_child(buffer->heap, buffer->flags); if (!child) { WARN(1, "ion_secure_carvout: invalid buffer flags on free. Memory will be leaked\n."); return; } ion_carveout_free(child, paddr, buffer->size); sg_free_table(table); kfree(table); } static struct ion_heap_ops ion_sc_heap_ops = { .allocate = ion_sc_heap_allocate, .free = ion_sc_heap_free, .phys = ion_carveout_heap_phys, .map_dma = ion_carveout_heap_map_dma, .unmap_dma = ion_carveout_heap_unmap_dma, }; static int ion_sc_get_dt_token(struct ion_sc_entry *entry, struct device_node *np, u64 base, u64 size) { u32 token; u32 *vmids, *modes; u32 nr, i; int ret = -EINVAL; u32 src_vm = VMID_HLOS; if (of_property_read_u32(np, "token", &token)) return -EINVAL; nr = count_set_bits(token); vmids = kcalloc(nr, sizeof(*vmids), GFP_KERNEL); if (!vmids) return -ENOMEM; modes = kcalloc(nr, sizeof(*modes), GFP_KERNEL); if (!modes) { kfree(vmids); return -ENOMEM; } if ((token & ~ION_FLAGS_CP_MASK) || populate_vm_list(token, vmids, nr)) { pr_err("secure_carveout_heap: Bad token %x\n", token); goto out; } for (i = 0; i < nr; i++) if (vmids[i] == VMID_CP_SEC_DISPLAY) modes[i] = PERM_READ; else modes[i] = PERM_READ | PERM_WRITE; ret = hyp_assign_phys(base, size, &src_vm, 1, vmids, modes, nr); if (ret) pr_err("secure_carveout_heap: Assign token 0x%x failed\n", token); else entry->token = token; out: kfree(modes); kfree(vmids); return ret; } static int ion_sc_add_child(struct ion_sc_heap *manager, struct device_node *np) { struct device *dev = manager->dev; struct ion_platform_heap heap_data = {0}; struct ion_sc_entry *entry; struct device_node *phandle; const __be32 *basep; u64 base, size; int ret; entry = kzalloc(sizeof(*entry), GFP_KERNEL); if (!entry) return -ENOMEM; INIT_LIST_HEAD(&entry->list); phandle = of_parse_phandle(np, "memory-region", 0); if (!phandle) goto out_free; basep = of_get_address(phandle, 0, &size, NULL); if (!basep) goto out_free; base = of_translate_address(phandle, basep); if (base == OF_BAD_ADDR) goto out_free; heap_data.priv = dev; heap_data.base = base; heap_data.size = size; /* This will zero memory initially */ entry->heap = ion_carveout_heap_create(&heap_data); if (IS_ERR(entry->heap)) goto out_free; ret = ion_sc_get_dt_token(entry, np, base, size); if (ret) goto out_free_carveout; list_add(&entry->list, &manager->children); dev_info(dev, "ion_secure_carveout: creating heap@0x%llx, size 0x%llx\n", base, size); return 0; out_free_carveout: ion_carveout_heap_destroy(entry->heap); out_free: kfree(entry); return -EINVAL; } void ion_secure_carveout_heap_destroy(struct ion_heap *heap) { struct ion_sc_heap *manager = container_of(heap, struct ion_sc_heap, heap); struct ion_sc_entry *entry, *tmp; list_for_each_entry_safe(entry, tmp, &manager->children, list) { ion_carveout_heap_destroy(entry->heap); kfree(entry); } kfree(manager); } struct ion_heap *ion_secure_carveout_heap_create( struct ion_platform_heap *heap_data) { struct device *dev = heap_data->priv; int ret; struct ion_sc_heap *manager; struct device_node *np; manager = kzalloc(sizeof(*manager), GFP_KERNEL); if (!manager) return ERR_PTR(-ENOMEM); INIT_LIST_HEAD(&manager->children); manager->dev = dev; for_each_child_of_node(dev->of_node, np) { ret = ion_sc_add_child(manager, np); if (ret) { dev_err(dev, "Creating child pool %s failed\n", np->name); goto err; } } manager->heap.ops = &ion_sc_heap_ops; manager->heap.type = ION_HEAP_TYPE_SECURE_CARVEOUT; return &manager->heap; err: ion_secure_carveout_heap_destroy(&manager->heap); return ERR_PTR(-EINVAL); }
drivers/staging/android/ion/msm/msm_ion.c +11 −0 Original line number Diff line number Diff line Loading @@ -122,6 +122,10 @@ static struct ion_heap_desc ion_heap_meta[] = { { .id = ION_SECURE_DISPLAY_HEAP_ID, .name = ION_SECURE_DISPLAY_HEAP_NAME, }, { .id = ION_SECURE_CARVEOUT_HEAP_ID, .name = ION_SECURE_CARVEOUT_HEAP_NAME, } }; #endif Loading Loading @@ -443,6 +447,7 @@ static struct heap_types_info { MAKE_HEAP_TYPE_MAPPING(SYSTEM), MAKE_HEAP_TYPE_MAPPING(SYSTEM_CONTIG), MAKE_HEAP_TYPE_MAPPING(CARVEOUT), MAKE_HEAP_TYPE_MAPPING(SECURE_CARVEOUT), MAKE_HEAP_TYPE_MAPPING(CHUNK), MAKE_HEAP_TYPE_MAPPING(DMA), MAKE_HEAP_TYPE_MAPPING(SECURE_DMA), Loading Loading @@ -1021,6 +1026,9 @@ static struct ion_heap *msm_ion_heap_create(struct ion_platform_heap *heap_data) case ION_HEAP_TYPE_HYP_CMA: heap = ion_cma_secure_heap_create(heap_data); break; case ION_HEAP_TYPE_SECURE_CARVEOUT: heap = ion_secure_carveout_heap_create(heap_data); break; default: heap = ion_heap_create(heap_data); } Loading Loading @@ -1056,6 +1064,9 @@ static void msm_ion_heap_destroy(struct ion_heap *heap) case ION_HEAP_TYPE_HYP_CMA: ion_cma_secure_heap_destroy(heap); break; case ION_HEAP_TYPE_SECURE_CARVEOUT: ion_secure_carveout_heap_destroy(heap); break; default: ion_heap_destroy(heap); } Loading
drivers/staging/android/ion/msm_ion_priv.h +5 −1 Original line number Diff line number Diff line Loading @@ -2,7 +2,7 @@ * drivers/staging/android/ion/msm_ion_priv.h * * Copyright (C) 2011 Google, Inc. * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and Loading Loading @@ -40,6 +40,10 @@ int ion_system_secure_heap_drain(struct ion_heap *heap, void *data); struct ion_heap *ion_cma_secure_heap_create(struct ion_platform_heap *heap); void ion_cma_secure_heap_destroy(struct ion_heap *heap); struct ion_heap *ion_secure_carveout_heap_create( struct ion_platform_heap *heap); void ion_secure_carveout_heap_destroy(struct ion_heap *heap); long msm_ion_custom_ioctl(struct ion_client *client, unsigned int cmd, unsigned long arg); Loading
drivers/staging/android/uapi/msm_ion.h +3 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ enum msm_ion_heap_types { ION_HEAP_TYPE_SECURE_DMA = ION_HEAP_TYPE_MSM_START, ION_HEAP_TYPE_SYSTEM_SECURE, ION_HEAP_TYPE_HYP_CMA, ION_HEAP_TYPE_SECURE_CARVEOUT, /* * if you add a heap type here you should also add it to * heap_types_info[] in msm_ion.c Loading @@ -32,6 +33,7 @@ enum ion_heap_ids { ION_SECURE_DISPLAY_HEAP_ID = 10, ION_CP_MFC_HEAP_ID = 12, ION_SPSS_HEAP_ID = 13, /* Secure Processor ION heap */ ION_SECURE_CARVEOUT_HEAP_ID = 14, ION_CP_WB_HEAP_ID = 16, /* 8660 only */ ION_QSECOM_TA_HEAP_ID = 19, ION_CAMERA_HEAP_ID = 20, /* 8660 only */ Loading Loading @@ -133,6 +135,7 @@ enum cp_mem_usage { #define ION_IOMMU_HEAP_NAME "iommu" #define ION_MFC_HEAP_NAME "mfc" #define ION_SPSS_HEAP_NAME "spss" #define ION_SECURE_CARVEOUT_HEAP_NAME "secure_carveout" #define ION_WB_HEAP_NAME "wb" #define ION_MM_FIRMWARE_HEAP_NAME "mm_fw" #define ION_PIL1_HEAP_NAME "pil_1" Loading