From 37a1e58faa1d48127ad505a2781d7acfec124caa Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Tue, 5 Nov 2019 13:53:42 -0700 Subject: [PATCH] msm: kgsl: Support global secure memory objects Currently the few global secure memory objects are allocated in a side band fashion. Add support to kgsl_allocate_secure_global() to allow secure objects. Change-Id: Ic0dedbadc03fb462a8b8bb82a2141f1d5ddd9762 Signed-off-by: Jordan Crouse --- drivers/gpu/msm/adreno.h | 8 +- drivers/gpu/msm/adreno_a5xx.c | 46 ++------ drivers/gpu/msm/adreno_a6xx.c | 5 +- drivers/gpu/msm/adreno_a6xx.h | 3 +- drivers/gpu/msm/adreno_a6xx_preempt.c | 54 +++------ drivers/gpu/msm/adreno_ringbuffer.c | 6 +- drivers/gpu/msm/adreno_ringbuffer.h | 4 +- drivers/gpu/msm/kgsl_device.h | 4 +- drivers/gpu/msm/kgsl_iommu.c | 159 +++++++++++++++++--------- drivers/gpu/msm/kgsl_mmu.c | 10 -- drivers/gpu/msm/kgsl_mmu.h | 13 --- drivers/gpu/msm/kgsl_sharedmem.c | 111 ++++++------------ 12 files changed, 178 insertions(+), 245 deletions(-) diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index ca6c1bb5ba22..a49bf4ac1779 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2008-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2008-2020, The Linux Foundation. All rights reserved. */ #ifndef __ADRENO_H #define __ADRENO_H @@ -531,6 +531,11 @@ struct adreno_device { * @critpkts: Memory descriptor for 5xx critical packets if applicable */ struct kgsl_memdesc *critpkts; + /** + * @critpkts: Memory descriptor for 5xx secure critical packets + */ + struct kgsl_memdesc *critpkts_secure; + }; /** @@ -800,7 +805,6 @@ struct adreno_gpudev { struct adreno_device *adreno_dev, unsigned int *cmds); int (*preemption_init)(struct adreno_device *adreno_dev); - void (*preemption_close)(struct adreno_device *adreno_dev); void (*preemption_schedule)(struct adreno_device *adreno_dev); int (*preemption_context_init)(struct kgsl_context *context); void (*preemption_context_destroy)(struct kgsl_context *context); diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index 9cd39a2ba5d5..1952dcfa6d58 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. */ #include @@ -18,7 +18,6 @@ static int critical_packet_constructed; static unsigned int crit_pkts_dwords; -static struct kgsl_memdesc crit_pkts_refbuf0; static void a5xx_irq_storm_worker(struct work_struct *work); static int _read_fw2_block_header(struct kgsl_device *device, @@ -121,14 +120,6 @@ static void a5xx_platform_setup(struct adreno_device *adreno_dev) a5xx_check_features(adreno_dev); } -static void a5xx_critical_packet_destroy(struct adreno_device *adreno_dev) -{ - kgsl_iommu_unmap_global_secure_pt_entry(KGSL_DEVICE(adreno_dev), - &crit_pkts_refbuf0); - kgsl_sharedmem_free(&crit_pkts_refbuf0); - -} - static void _do_fixup(const struct adreno_critical_fixup *fixups, int count, uint64_t *gpuaddrs, unsigned int *buffer) { @@ -146,29 +137,23 @@ static void _do_fixup(const struct adreno_critical_fixup *fixups, int count, static int a5xx_critical_packet_construct(struct adreno_device *adreno_dev) { - + struct kgsl_device *device = KGSL_DEVICE(adreno_dev); unsigned int *cmds; uint64_t gpuaddrs[4]; - int ret; - adreno_dev->critpkts = kgsl_allocate_global(KGSL_DEVICE(adreno_dev), + adreno_dev->critpkts = kgsl_allocate_global(device, PAGE_SIZE * 4, 0, 0, "crit_pkts"); if (IS_ERR(adreno_dev->critpkts)) return PTR_ERR(adreno_dev->critpkts); - ret = kgsl_allocate_user(&adreno_dev->dev, &crit_pkts_refbuf0, - PAGE_SIZE, KGSL_MEMFLAGS_SECURE, 0); - if (ret) - return ret; - - ret = kgsl_iommu_map_global_secure_pt_entry(&adreno_dev->dev, - &crit_pkts_refbuf0); - if (ret) - return ret; + adreno_dev->critpkts_secure = kgsl_allocate_global(device, + PAGE_SIZE, KGSL_MEMFLAGS_SECURE, 0, "crit_pkts_secure"); + if (IS_ERR(adreno_dev->critpkts_secure)) + return PTR_ERR(adreno_dev->critpkts_secure); cmds = adreno_dev->critpkts->hostptr; - gpuaddrs[0] = crit_pkts_refbuf0.gpuaddr; + gpuaddrs[0] = adreno_dev->critpkts_secure->gpuaddr; gpuaddrs[1] = adreno_dev->critpkts->gpuaddr + PAGE_SIZE; gpuaddrs[2] = adreno_dev->critpkts->gpuaddr + (PAGE_SIZE * 2); gpuaddrs[3] = adreno_dev->critpkts->gpuaddr + (PAGE_SIZE * 3); @@ -211,23 +196,13 @@ static void a5xx_init(struct adreno_device *adreno_dev) INIT_WORK(&adreno_dev->irq_storm_work, a5xx_irq_storm_worker); - if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_CRITICAL_PACKETS)) { - int ret; + if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_CRITICAL_PACKETS)) + a5xx_critical_packet_construct(adreno_dev); - ret = a5xx_critical_packet_construct(adreno_dev); - if (ret) - a5xx_critical_packet_destroy(adreno_dev); - } a5xx_crashdump_init(adreno_dev); } -static void a5xx_remove(struct adreno_device *adreno_dev) -{ - if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_CRITICAL_PACKETS)) - a5xx_critical_packet_destroy(adreno_dev); -} - const static struct { u32 reg; u32 base; @@ -3003,7 +2978,6 @@ struct adreno_gpudev adreno_a5xx_gpudev = { .irq_trace = trace_kgsl_a5xx_irq_status, .platform_setup = a5xx_platform_setup, .init = a5xx_init, - .remove = a5xx_remove, .rb_start = a5xx_rb_start, .microcode_read = a5xx_microcode_read, .perfcounters = &a5xx_perfcounters, diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c index b1803282a2c7..63c3f3fd0855 100644 --- a/drivers/gpu/msm/adreno_a6xx.c +++ b/drivers/gpu/msm/adreno_a6xx.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -716,7 +716,7 @@ static int _preemption_init(struct adreno_device *adreno_dev, *cmds++ = 2; cmds += cp_gpuaddr(adreno_dev, cmds, - rb->secure_preemption_desc.gpuaddr); + rb->secure_preemption_desc->gpuaddr); /* Turn CP protection back ON */ if (!ADRENO_FEATURE(adreno_dev, ADRENO_APRIV)) @@ -2541,7 +2541,6 @@ struct adreno_gpudev adreno_a6xx_gpudev = { .preemption_pre_ibsubmit = a6xx_preemption_pre_ibsubmit, .preemption_post_ibsubmit = a6xx_preemption_post_ibsubmit, .preemption_init = a6xx_preemption_init, - .preemption_close = a6xx_preemption_close, .preemption_schedule = a6xx_preemption_schedule, .set_marker = a6xx_set_marker, .preemption_context_init = a6xx_preemption_context_init, diff --git a/drivers/gpu/msm/adreno_a6xx.h b/drivers/gpu/msm/adreno_a6xx.h index 07b7d5922516..b2316692b341 100644 --- a/drivers/gpu/msm/adreno_a6xx.h +++ b/drivers/gpu/msm/adreno_a6xx.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _ADRENO_A6XX_H_ @@ -251,7 +251,6 @@ void a6xx_preemption_trigger(struct adreno_device *adreno_dev); void a6xx_preemption_schedule(struct adreno_device *adreno_dev); void a6xx_preemption_start(struct adreno_device *adreno_dev); int a6xx_preemption_init(struct adreno_device *adreno_dev); -void a6xx_preemption_close(struct adreno_device *adreno_dev); unsigned int a6xx_preemption_post_ibsubmit(struct adreno_device *adreno_dev, unsigned int *cmds); diff --git a/drivers/gpu/msm/adreno_a6xx_preempt.c b/drivers/gpu/msm/adreno_a6xx_preempt.c index 920b7038352e..b6326148a74b 100644 --- a/drivers/gpu/msm/adreno_a6xx_preempt.c +++ b/drivers/gpu/msm/adreno_a6xx_preempt.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include "adreno.h" @@ -320,13 +320,13 @@ void a6xx_preemption_trigger(struct adreno_device *adreno_dev) if (adreno_gmu_fenced_write(adreno_dev, ADRENO_REG_CP_CONTEXT_SWITCH_PRIV_SECURE_RESTORE_ADDR_LO, - lower_32_bits(next->secure_preemption_desc.gpuaddr), + lower_32_bits(next->secure_preemption_desc->gpuaddr), FENCE_STATUS_WRITEDROPPED1_MASK)) goto err; if (adreno_gmu_fenced_write(adreno_dev, ADRENO_REG_CP_CONTEXT_SWITCH_PRIV_SECURE_RESTORE_ADDR_HI, - upper_32_bits(next->secure_preemption_desc.gpuaddr), + upper_32_bits(next->secure_preemption_desc->gpuaddr), FENCE_STATUS_WRITEDROPPED1_MASK)) goto err; @@ -483,7 +483,7 @@ unsigned int a6xx_preemption_pre_ibsubmit( *cmds++ = SET_PSEUDO_REGISTER_SAVE_REGISTER_PRIV_SECURE_SAVE_ADDR; cmds += cp_gpuaddr(adreno_dev, cmds, - rb->secure_preemption_desc.gpuaddr); + rb->secure_preemption_desc->gpuaddr); if (context) { @@ -594,7 +594,6 @@ static int a6xx_preemption_ringbuffer_init(struct adreno_device *adreno_dev, struct adreno_ringbuffer *rb) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); - int ret; if (IS_ERR_OR_NULL(rb->preemption_desc)) rb->preemption_desc = kgsl_allocate_global(device, @@ -603,16 +602,14 @@ static int a6xx_preemption_ringbuffer_init(struct adreno_device *adreno_dev, if (IS_ERR(rb->preemption_desc)) return PTR_ERR(rb->preemption_desc); - ret = kgsl_allocate_user(device, &rb->secure_preemption_desc, - A6XX_CP_CTXRECORD_SIZE_IN_BYTES, - KGSL_MEMFLAGS_SECURE, KGSL_MEMDESC_PRIVILEGED); - if (ret) - return ret; + if (IS_ERR_OR_NULL(rb->secure_preemption_desc)) + rb->secure_preemption_desc = kgsl_allocate_global(device, + A6XX_CP_CTXRECORD_SIZE_IN_BYTES, + KGSL_MEMFLAGS_SECURE, KGSL_MEMDESC_PRIVILEGED, + "secure_preemption_desc"); - ret = kgsl_iommu_map_global_secure_pt_entry(device, - &rb->secure_preemption_desc); - if (ret) - return ret; + if (IS_ERR(rb->secure_preemption_desc)) + return PTR_ERR(rb->secure_preemption_desc); if (IS_ERR_OR_NULL(rb->perfcounter_save_restore_desc)) rb->perfcounter_save_restore_desc = kgsl_allocate_global(device, @@ -646,27 +643,6 @@ static int a6xx_preemption_ringbuffer_init(struct adreno_device *adreno_dev, return 0; } -static void _preemption_close(struct adreno_device *adreno_dev) -{ - struct kgsl_device *device = KGSL_DEVICE(adreno_dev); - struct adreno_ringbuffer *rb; - unsigned int i; - - FOR_EACH_RINGBUFFER(adreno_dev, rb, i) { - kgsl_iommu_unmap_global_secure_pt_entry(device, - &rb->secure_preemption_desc); - kgsl_sharedmem_free(&rb->secure_preemption_desc); - } -} - -void a6xx_preemption_close(struct adreno_device *adreno_dev) -{ - if (!test_bit(ADRENO_DEVICE_PREEMPTION, &adreno_dev->priv)) - return; - - _preemption_close(adreno_dev); -} - int a6xx_preemption_init(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); @@ -685,10 +661,8 @@ int a6xx_preemption_init(struct adreno_device *adreno_dev) /* Allocate mem for storing preemption switch record */ FOR_EACH_RINGBUFFER(adreno_dev, rb, i) { ret = a6xx_preemption_ringbuffer_init(adreno_dev, rb); - if (ret) { - _preemption_close(adreno_dev); + if (ret) return ret; - } } /* Allocate mem for storing preemption smmu record */ @@ -698,10 +672,8 @@ int a6xx_preemption_init(struct adreno_device *adreno_dev) "smmu_info"); ret = PTR_ERR_OR_ZERO(iommu->smmu_info); - if (ret) { - _preemption_close(adreno_dev); + if (ret) return ret; - } set_bit(ADRENO_DEVICE_PREEMPTION, &adreno_dev->priv); return 0; diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c index 24e4da63e989..26fc4796622c 100644 --- a/drivers/gpu/msm/adreno_ringbuffer.c +++ b/drivers/gpu/msm/adreno_ringbuffer.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2002,2007-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved. */ #include @@ -326,16 +326,12 @@ static void adreno_preemption_init(struct adreno_device *adreno_dev) static void adreno_preemption_close(struct adreno_device *adreno_dev) { - struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); struct adreno_preemption *preempt = &adreno_dev->preempt; if (!ADRENO_FEATURE(adreno_dev, ADRENO_PREEMPTION)) return; del_timer(&preempt->timer); - - if (gpudev->preemption_close) - gpudev->preemption_close(adreno_dev); } int adreno_ringbuffer_probe(struct adreno_device *adreno_dev) diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h index ff9b818d5e2d..a01cbd7a2d5e 100644 --- a/drivers/gpu/msm/adreno_ringbuffer.h +++ b/drivers/gpu/msm/adreno_ringbuffer.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2002,2007-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved. */ #ifndef __ADRENO_RINGBUFFER_H #define __ADRENO_RINGBUFFER_H @@ -111,7 +111,7 @@ struct adreno_ringbuffer { struct kgsl_event_group events; struct adreno_context *drawctxt_active; struct kgsl_memdesc *preemption_desc; - struct kgsl_memdesc secure_preemption_desc; + struct kgsl_memdesc *secure_preemption_desc; struct kgsl_memdesc *perfcounter_save_restore_desc; struct kgsl_memdesc *pagetable_desc; struct adreno_dispatcher_drawqueue dispatch_q; diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h index 6a83c0437ee2..e35e373d4994 100644 --- a/drivers/gpu/msm/kgsl_device.h +++ b/drivers/gpu/msm/kgsl_device.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2002,2007-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved. */ #ifndef __KGSL_DEVICE_H #define __KGSL_DEVICE_H @@ -306,8 +306,6 @@ struct kgsl_device { struct list_head globals; /** @globlal_map: bitmap for global memory allocations */ unsigned long *global_map; - /** @global_pages: Number of pages available in the global_map */ - unsigned int global_pages; /* @qdss_desc: Memory descriptor for the QDSS region if applicable */ struct kgsl_memdesc *qdss_desc; /* @qtimer_desc: Memory descriptor for the QDSS region if applicable */ diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index 3cfa9c6d197b..ab44009a84be 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -66,16 +66,18 @@ struct kgsl_iommu_addr_entry { static struct kmem_cache *addr_entry_cache; -static int secure_global_size; - static void kgsl_iommu_unmap_globals(struct kgsl_mmu *mmu, struct kgsl_pagetable *pagetable) { struct kgsl_device *device = KGSL_MMU_DEVICE(mmu); struct kgsl_global_memdesc *md; - list_for_each_entry(md, &device->globals, node) + list_for_each_entry(md, &device->globals, node) { + if (md->memdesc.flags & KGSL_MEMFLAGS_SECURE) + continue; + kgsl_mmu_unmap(pagetable, &md->memdesc); + } } static void kgsl_iommu_map_globals(struct kgsl_mmu *mmu, @@ -84,15 +86,98 @@ static void kgsl_iommu_map_globals(struct kgsl_mmu *mmu, struct kgsl_device *device = KGSL_MMU_DEVICE(mmu); struct kgsl_global_memdesc *md; - list_for_each_entry(md, &device->globals, node) + list_for_each_entry(md, &device->globals, node) { + if (md->memdesc.flags & KGSL_MEMFLAGS_SECURE) + continue; + kgsl_mmu_map(pagetable, &md->memdesc); + } +} + +static int kgsl_iommu_get_gpuaddr(struct kgsl_pagetable *pagetable, + struct kgsl_memdesc *memdesc); + +static void kgsl_iommu_map_secure_global(struct kgsl_mmu *mmu, + struct kgsl_memdesc *memdesc) +{ + if (!mmu->securepagetable) + return; + + if (!memdesc->gpuaddr) { + int ret = kgsl_iommu_get_gpuaddr(mmu->securepagetable, + memdesc); + + if (WARN_ON(ret)) + return; + } + + kgsl_mmu_map(mmu->securepagetable, memdesc); +} + +#define KGSL_GLOBAL_MEM_PAGES (KGSL_IOMMU_GLOBAL_MEM_SIZE >> PAGE_SHIFT) + +static u64 global_get_offset(struct kgsl_device *device, u64 size, + unsigned long priv) +{ + int start = 0, bit; + + if (!device->global_map) { + device->global_map = + kcalloc(BITS_TO_LONGS(KGSL_GLOBAL_MEM_PAGES), + sizeof(unsigned long), GFP_KERNEL); + if (!device->global_map) + return (unsigned long) -ENOMEM; + } + + if (priv & KGSL_MEMDESC_RANDOM) { + u32 offset = KGSL_GLOBAL_MEM_PAGES - (size >> PAGE_SHIFT); + + start = get_random_int() % offset; + } + + while (start >= 0) { + bit = bitmap_find_next_zero_area(device->global_map, + KGSL_GLOBAL_MEM_PAGES, start, size >> PAGE_SHIFT, 0); + + if (bit < KGSL_GLOBAL_MEM_PAGES) + break; + + /* + * Later implementations might want to randomize this to reduce + * predictability + */ + start--; + } + + if (WARN_ON(start < 0)) + return (unsigned long) -ENOMEM; + + bitmap_set(device->global_map, bit, size >> PAGE_SHIFT); + + return bit << PAGE_SHIFT; } static void kgsl_iommu_map_global(struct kgsl_mmu *mmu, struct kgsl_memdesc *memdesc) { + struct kgsl_device *device = KGSL_MMU_DEVICE(mmu); struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu); + if (memdesc->flags & KGSL_MEMFLAGS_SECURE) { + kgsl_iommu_map_secure_global(mmu, memdesc); + return; + } + + if (!memdesc->gpuaddr) { + u64 offset = global_get_offset(device, memdesc->size, + memdesc->priv); + + if (IS_ERR_VALUE(offset)) + return; + + memdesc->gpuaddr = KGSL_IOMMU_GLOBAL_MEM_BASE(mmu) + offset; + } + /* * If the global pagetable hasn't been created yet, do nothing. We'll * get them all in one big swoop at create time @@ -111,49 +196,6 @@ static void kgsl_iommu_map_global(struct kgsl_mmu *mmu, kgsl_mmu_map(mmu->defaultpagetable, memdesc); } -static u64 kgsl_iommu_get_global_base(struct kgsl_mmu *mmu) -{ - return KGSL_IOMMU_GLOBAL_MEM_BASE(mmu); -} - -void kgsl_iommu_unmap_global_secure_pt_entry(struct kgsl_device *device, - struct kgsl_memdesc *memdesc) -{ - if (!kgsl_mmu_is_secured(&device->mmu) || memdesc == NULL) - return; - - /* Check if an empty memdesc got passed in */ - if ((memdesc->gpuaddr == 0) || (memdesc->size == 0)) - return; - - if (memdesc->pagetable) { - if (memdesc->pagetable->name == KGSL_MMU_SECURE_PT) - kgsl_mmu_unmap(memdesc->pagetable, memdesc); - } -} - -int kgsl_iommu_map_global_secure_pt_entry(struct kgsl_device *device, - struct kgsl_memdesc *entry) -{ - int ret = 0; - - if (!kgsl_mmu_is_secured(&device->mmu)) - return -ENOTSUPP; - - if (entry != NULL) { - struct kgsl_pagetable *pagetable = device->mmu.securepagetable; - - entry->pagetable = pagetable; - entry->gpuaddr = KGSL_IOMMU_SECURE_BASE(&device->mmu) + - secure_global_size; - - ret = kgsl_mmu_map(pagetable, entry); - if (ret == 0) - secure_global_size += entry->size; - } - return ret; -} - static void _detach_pt(struct kgsl_iommu_pt *iommu_pt, struct kgsl_iommu_context *ctx) { @@ -771,6 +813,7 @@ static void kgsl_iommu_destroy_pagetable(struct kgsl_pagetable *pt) { struct kgsl_iommu_pt *iommu_pt = pt->priv; struct kgsl_mmu *mmu = pt->mmu; + struct kgsl_device *device = KGSL_MMU_DEVICE(mmu); struct kgsl_iommu *iommu; struct kgsl_iommu_context *ctx; @@ -783,7 +826,14 @@ static void kgsl_iommu_destroy_pagetable(struct kgsl_pagetable *pt) iommu = _IOMMU_PRIV(mmu); if (pt->name == KGSL_MMU_SECURE_PT) { + struct kgsl_global_memdesc *md; + ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_SECURE]; + /* Unmap any pending secure global buffers */ + list_for_each_entry(md, &device->globals, node) { + if (md->memdesc.flags & KGSL_MEMFLAGS_SECURE) + kgsl_mmu_unmap(pt, &md->memdesc); + } } else { ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER]; kgsl_iommu_unmap_globals(mmu, pt); @@ -1035,6 +1085,7 @@ static int _init_secure_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt) struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu); struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_SECURE]; int secure_vmid = VMID_CP_PIXEL; + struct kgsl_global_memdesc *md; if (!mmu->secured) return -EPERM; @@ -1059,6 +1110,12 @@ static int _init_secure_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt) iommu_set_fault_handler(iommu_pt->domain, kgsl_iommu_fault_handler, pt); + /* Map any pending secure global buffers */ + list_for_each_entry(md, &device->globals, node) { + if (md->memdesc.flags & KGSL_MEMFLAGS_SECURE) + kgsl_iommu_map_secure_global(mmu, &md->memdesc); + } + done: if (ret) _free_pt(ctx, pt); @@ -2180,13 +2237,6 @@ static int kgsl_iommu_get_gpuaddr(struct kgsl_pagetable *pagetable, end = pt->va_end; } - /* - * When mapping secure buffers, adjust the start of the va range - * to the end of secure global buffers. - */ - if (kgsl_memdesc_is_secured(memdesc)) - start += secure_global_size; - spin_lock(&pagetable->lock); addr = _get_unmapped_area(pagetable, start, end, size, align); @@ -2407,7 +2457,6 @@ struct kgsl_mmu_ops kgsl_iommu_ops = { .mmu_pagefault_resume = kgsl_iommu_pagefault_resume, .mmu_init_pt = kgsl_iommu_init_pt, .mmu_getpagetable = kgsl_iommu_getpagetable, - .mmu_get_global_base = kgsl_iommu_get_global_base, .mmu_map_global = kgsl_iommu_map_global, .probe = kgsl_iommu_probe, }; diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c index e7411896f17c..d30d745a18f6 100644 --- a/drivers/gpu/msm/kgsl_mmu.c +++ b/drivers/gpu/msm/kgsl_mmu.c @@ -527,16 +527,6 @@ int kgsl_mmu_sparse_dummy_map(struct kgsl_pagetable *pagetable, return 0; } -u64 kgsl_mmu_get_global_base(struct kgsl_device *device) -{ - struct kgsl_mmu *mmu = &(device->mmu); - - if (MMU_OP_VALID(mmu, mmu_get_global_base)) - return mmu->mmu_ops->mmu_get_global_base(mmu); - - return 0; -} - void kgsl_mmu_map_global(struct kgsl_device *device, struct kgsl_memdesc *memdesc) { diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h index cdef06d1741d..3a77ad98e569 100644 --- a/drivers/gpu/msm/kgsl_mmu.h +++ b/drivers/gpu/msm/kgsl_mmu.h @@ -70,7 +70,6 @@ struct kgsl_mmu_ops { int (*mmu_init_pt)(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt); struct kgsl_pagetable * (*mmu_getpagetable)(struct kgsl_mmu *mmu, unsigned long name); - u64 (*mmu_get_global_base)(struct kgsl_mmu *mmu); void (*mmu_map_global)(struct kgsl_mmu *mmu, struct kgsl_memdesc *memdesc); }; @@ -163,10 +162,6 @@ int kgsl_mmu_start(struct kgsl_device *device); struct kgsl_pagetable *kgsl_mmu_getpagetable_ptbase(struct kgsl_mmu *mmu, u64 ptbase); -int kgsl_iommu_map_global_secure_pt_entry(struct kgsl_device *device, - struct kgsl_memdesc *memdesc); -void kgsl_iommu_unmap_global_secure_pt_entry(struct kgsl_device *device, - struct kgsl_memdesc *memdesc); void kgsl_print_global_pt_entries(struct seq_file *s); void kgsl_mmu_putpagetable(struct kgsl_pagetable *pagetable); @@ -338,14 +333,6 @@ kgsl_mmu_pagetable_get_contextidr(struct kgsl_pagetable *pagetable) return 0; } -/** - * kgsl_mmu_get_global_base - Return the base GPU address of the global region - * @device: A KGSL GPU device handle - * - * Return: The virtual address of the base of the global object region - */ -u64 kgsl_mmu_get_global_base(struct kgsl_device *device); - /** * kgsl_mmu_map_global - Map a memdesc as a global buffer * @device: A KGSL GPU device handle diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c index 95d1a990bd61..540b225560cc 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.c +++ b/drivers/gpu/msm/kgsl_sharedmem.c @@ -1236,56 +1236,12 @@ int kgsl_allocate_kernel(struct kgsl_device *device, return 0; } -#define KGSL_GLOBAL_MEM_SIZE (20 * SZ_1M) -#define KGSL_GLOBAL_MEM_PAGES (KGSL_GLOBAL_MEM_SIZE >> PAGE_SHIFT) - -static u64 global_get_offset(struct kgsl_device *device, u64 size, - unsigned long priv) -{ - int start = 0, bit; - - if (!device->global_map) { - device->global_map = - kcalloc(BITS_TO_LONGS(KGSL_GLOBAL_MEM_PAGES), - sizeof(unsigned long), GFP_KERNEL); - if (!device->global_map) - return (unsigned long) -ENOMEM; - - device->global_pages = KGSL_GLOBAL_MEM_PAGES; - } - - if (priv & KGSL_MEMDESC_RANDOM) { - u32 offset = device->global_pages - (size >> PAGE_SHIFT); - - start = get_random_int() % offset; - } - - while (start >= 0) { - bit = bitmap_find_next_zero_area(device->global_map, - device->global_pages, start, size >> PAGE_SHIFT, 0); - - if (bit < device->global_pages) - break; - - /* FIXME: We should randomize this */ - start--; - } - - if (WARN_ON(start < 0)) - return (unsigned long) -ENOMEM; - - bitmap_set(device->global_map, bit, size >> PAGE_SHIFT); - - return bit << PAGE_SHIFT; -} - struct kgsl_memdesc *kgsl_allocate_global_fixed(struct kgsl_device *device, const char *resource, const char *name) { struct kgsl_global_memdesc *md; u32 entry[2]; int ret; - u64 offset; if (of_property_read_u32_array(device->pdev->dev.of_node, resource, entry, 2)) @@ -1306,17 +1262,6 @@ struct kgsl_memdesc *kgsl_allocate_global_fixed(struct kgsl_device *device, return ERR_PTR(ret); } - offset = global_get_offset(device, - kgsl_memdesc_footprint(&md->memdesc), 0); - if (IS_ERR_VALUE(offset)) { - kgsl_sharedmem_free(&md->memdesc); - kfree(md); - return (void *) offset; - } - - if (!md->memdesc.gpuaddr) - md->memdesc.gpuaddr = kgsl_mmu_get_global_base(device) + offset; - md->name = name; /* @@ -1330,20 +1275,51 @@ struct kgsl_memdesc *kgsl_allocate_global_fixed(struct kgsl_device *device, return &md->memdesc; } +static struct kgsl_memdesc * +kgsl_allocate_secure_global(struct kgsl_device *device, + u64 size, u64 flags, u32 priv, const char *name) +{ + struct kgsl_global_memdesc *md; + int ret; + + md = kzalloc(sizeof(*md), GFP_KERNEL); + if (!md) + return ERR_PTR(-ENOMEM); + + priv |= KGSL_MEMDESC_GLOBAL; + + ret = kgsl_allocate_secure(device, &md->memdesc, size, flags, priv); + if (ret) { + kfree(md); + return ERR_PTR(ret); + } + + md->name = name; + + /* + * No lock here, because this function is only called during probe/init + * while the caller is holding the mutex + */ + list_add_tail(&md->node, &device->globals); + + /* + * No offset needed, we'll get an address inside of the pagetable + * normally + */ + kgsl_mmu_map_global(device, &md->memdesc); + + return &md->memdesc; +} + struct kgsl_memdesc *kgsl_allocate_global(struct kgsl_device *device, u64 size, u64 flags, u32 priv, const char *name) { int ret; struct kgsl_global_memdesc *md; - u64 offset; - - /* - * For the moment, don't allow secure to be allocated through this - * function - */ if (flags & KGSL_MEMFLAGS_SECURE) - return ERR_PTR(-EINVAL); + return kgsl_allocate_secure_global(device, size, flags, priv, + name); md = kzalloc(sizeof(*md), GFP_KERNEL); if (!md) @@ -1357,17 +1333,6 @@ struct kgsl_memdesc *kgsl_allocate_global(struct kgsl_device *device, return ERR_PTR(ret); } - offset = global_get_offset(device, - kgsl_memdesc_footprint(&md->memdesc), priv); - if (IS_ERR_VALUE(offset)) { - kgsl_sharedmem_free(&md->memdesc); - kfree(md); - return (void *) offset; - } - - if (!md->memdesc.gpuaddr) - md->memdesc.gpuaddr = kgsl_mmu_get_global_base(device) + offset; - md->name = name; /*