Merge "msm: kgsl: Support global secure memory objects"

This commit is contained in:
qctecmdr 2020-01-07 15:23:35 -08:00 • committed by Gerrit - the friendly Code Review server
commit db96989477
12 changed files with 175 additions and 242 deletions

View file

@ -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);

View file

@ -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 <linux/delay.h>
@ -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,

View file

@ -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 <linux/of.h>
@ -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,

View file

@ -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);

View file

@ -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;

View file

@ -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 <linux/sched/clock.h>
@ -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)

View file

@ -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;

View file

@ -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 */

View file

@ -71,16 +71,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,
@ -89,15 +91,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
@ -116,49 +201,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)
{
@ -776,6 +818,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;
@ -788,7 +831,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);
@ -1052,6 +1102,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;
@ -1076,6 +1127,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);
@ -2197,13 +2254,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);
@ -2424,7 +2474,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,
};

View file

@ -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)
{

View file

@ -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

View file

@ -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;
/*