mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 05:39:54 -04:00
Merge "msm: kgsl: Support global secure memory objects"
This commit is contained in:
commit
db96989477
12 changed files with 175 additions and 242 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in a new issue