From: shipeng.sun Date: Mon, 23 Dec 2019 08:59:53 +0000 (+0800) Subject: codec_mm: add protect secure memory in codec_mm [1/1] X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=1449764189322a0dc8c866ab4cf4ed22530a7c35;p=GitHub%2FLineageOS%2FG12%2Fandroid_kernel_amlogic_linux-4.9.git codec_mm: add protect secure memory in codec_mm [1/1] PD#SWPL-17811 Problem: add protect secure memory in codec_mm Solution: add protect secure memory protect in codec_mm and add flags to change old mode to debug Verify: Android Q + franklin Test: 1. If tvp_mode set to 0 can be compatibility with old mode. 2. In tvp_mode 1, if no protect tvp, the play will full screen mosaic Change-Id: Ie3b04c0a06377610f9a5a18fdec2feba70ba2f8d Signed-off-by: shipeng.sun --- diff --git a/drivers/amlogic/media/common/codec_mm/codec_mm.c b/drivers/amlogic/media/common/codec_mm/codec_mm.c index 1583f455c91f..1c8c8d810821 100644 --- a/drivers/amlogic/media/common/codec_mm/codec_mm.c +++ b/drivers/amlogic/media/common/codec_mm/codec_mm.c @@ -47,6 +47,7 @@ #include #include #include +#include #define TVP_POOL_NAME "TVP_POOL" #define CMA_RES_POOL_NAME "CMA_RES" @@ -111,6 +112,12 @@ static int default_tvp_4k_size; static int default_cma_res_size; #define TVP_MAX_SLOT 8 +/* + *tvp_mode == 0 means protect secure memory in secmem ta + *tvp_mode == 1 means use protect secure memory in codec_mm + */ +static u32 tvp_mode; + struct extpool_mgt_s { struct gen_pool *gen_pool[TVP_MAX_SLOT]; struct codec_mm_s *mm[TVP_MAX_SLOT]; @@ -151,6 +158,9 @@ struct codec_mm_mgt_s { /*1:for 1080p,2:for 4k */ int fastplay_enable; spinlock_t lock; + atomic_t tvp_user_count; + /* for tvp operator used */ + struct mutex tvp_protect_lock; }; #define PHY_OFF() offsetof(struct codec_mm_s, phy_addr) @@ -158,13 +168,27 @@ struct codec_mm_mgt_s { #define VADDR_OFF() offsetof(struct codec_mm_s, vbuffer) #define VAL_OFF_VAL(mem, off) (*(unsigned long *)((unsigned long)(mem) + off)) +static int codec_mm_extpool_pool_release(struct extpool_mgt_s *tvp_pool); + static struct codec_mm_mgt_s *get_mem_mgt(void) { static struct codec_mm_mgt_s mgt; static int inited; + int ret = 0; + int handle = 0; if (!inited) { memset(&mgt, 0, sizeof(struct codec_mm_mgt_s)); + /*If tee_protect_tvp_mem is not implement + *will return 0xFFFFFFF we used to init use + *which mode + */ + ret = tee_protect_tvp_mem(0, 0, &handle); + if (ret == 0xFFFFFFFF) + tvp_mode = 0; + else + tvp_mode = 1; + mutex_init(&mgt.tvp_protect_lock); inited++; } return &mgt; @@ -619,10 +643,32 @@ static int codec_mm_alloc_in( } } +static int codec_mm_tvp_pool_unprotect(struct extpool_mgt_s *tvp_pool) +{ + struct codec_mm_mgt_s *mgt = get_mem_mgt(); + int ret = -1; + int i = 0; + + if (mgt->tvp_pool.alloced_size <= 0) { + for (i = 0; i < tvp_pool->slot_num; i++) { + pr_info("unprotect tvp %d handle is %d\n", + i, tvp_pool->mm[i]->tvp_handle); + if (tvp_pool->mm[i]->tvp_handle > 0) { + tee_unprotect_tvp_mem( + tvp_pool->mm[i]->tvp_handle); + tvp_pool->mm[i]->tvp_handle = -1; + } + } + ret = 0; + } + return ret; +} + static void codec_mm_free_in(struct codec_mm_mgt_s *mgt, struct codec_mm_s *mem) { unsigned long flags; + if (mem->from_flags == AMPORTS_MEM_FLAGS_FROM_GET_FROM_CMA) { if (mem->flags & CODEC_MM_FLAGS_FOR_PHYS_VMAPED) codec_mm_unmap_phyaddr(mem->vbuffer); @@ -672,6 +718,15 @@ static void codec_mm_free_in(struct codec_mm_mgt_s *mgt, } spin_unlock_irqrestore(&mgt->lock, flags); + if ((mem->from_flags == AMPORTS_MEM_FLAGS_FROM_GET_FROM_TVP) && + (tvp_mode == 1)) { + mutex_lock(&mgt->tvp_protect_lock); + if (atomic_read(&mgt->tvp_user_count) == 0) { + if (codec_mm_tvp_pool_unprotect(&mgt->tvp_pool) == 0) + codec_mm_extpool_pool_release(&mgt->tvp_pool); + } + mutex_unlock(&mgt->tvp_protect_lock); + } return; } @@ -1035,10 +1090,32 @@ static int codec_mm_init_tvp_pool( return -1; } tvp_pool->gen_pool[tvp_pool->slot_num] = pool; + mm->tvp_handle = -1; tvp_pool->mm[tvp_pool->slot_num] = mm; return 0; } +static int codec_mm_tvp_pool_protect(struct extpool_mgt_s *tvp_pool) +{ + int ret = 0; + int i = 0; + + for (i = 0; i < tvp_pool->slot_num; i++) { + if (tvp_pool->mm[i]->tvp_handle == -1) { + ret = tee_protect_tvp_mem( + (uint32_t)tvp_pool->mm[i]->phy_addr, + (uint32_t)tvp_pool->mm[i]->buffer_size, + &tvp_pool->mm[i]->tvp_handle); + pr_info("protect tvp %d %d ret %d\n", + i, tvp_pool->mm[i]->tvp_handle, ret); + } else { + pr_info("protect tvp %d %d ret %d\n", + i, tvp_pool->mm[i]->tvp_handle, ret); + } + } + return ret; +} + int codec_mm_extpool_pool_alloc( struct extpool_mgt_s *tvp_pool, int size, int memflags, int for_tvp) @@ -1144,6 +1221,8 @@ int codec_mm_extpool_pool_alloc( alloced_finished: if (alloced_size > 0) tvp_pool->total_size = alloced_size; + if (tvp_mode == 1 && for_tvp) + codec_mm_tvp_pool_protect(tvp_pool); mutex_unlock(&tvp_pool->pool_lock); return alloced_size; } @@ -1234,7 +1313,7 @@ static int codec_mm_tvp_get_mem_resource(ulong *res, int victor_size) struct codec_mm_mgt_s *mgt = get_mem_mgt(); struct extpool_mgt_s *tvp_pool = &mgt->tvp_pool; int i; - + mutex_lock(&tvp_pool->pool_lock); for (i = 0; i < tvp_pool->slot_num && i < victor_size / 2; i++) { if (tvp_pool->mm[i]) { res[2 * i] = tvp_pool->mm[i]->phy_addr; @@ -1242,6 +1321,7 @@ static int codec_mm_tvp_get_mem_resource(ulong *res, int victor_size) tvp_pool->mm[i]->buffer_size - 1; } } + mutex_unlock(&tvp_pool->pool_lock); return i; } @@ -1252,6 +1332,7 @@ static int codec_mm_is_in_tvp_region(ulong phy_addr) int i; int in = 0, in2 = 0; + mutex_lock(&tvp_pool->pool_lock); for (i = 0; i < tvp_pool->slot_num; i++) { if (tvp_pool->mm[i]) { in = tvp_pool->mm[i]->phy_addr <= phy_addr; @@ -1263,6 +1344,7 @@ static int codec_mm_is_in_tvp_region(ulong phy_addr) in = 0; } } + mutex_unlock(&tvp_pool->pool_lock); return in; } @@ -1818,8 +1900,11 @@ static ssize_t tvp_enable_help_show(struct class *class, ssize_t size = 0; struct codec_mm_mgt_s *mgt = get_mem_mgt(); - - size += sprintf(buf, "tvp_flag=%d\n", mgt->tvp_enable); + mutex_lock(&mgt->tvp_protect_lock); + size += sprintf(buf, "tvp_flag=%d\n", + (tvp_mode << 4) + mgt->tvp_enable); + size += sprintf(buf + size, "tvp ref count=%d\n", + atomic_read(&mgt->tvp_user_count)); size += sprintf(buf + size, "tvp enable help:\n"); size += sprintf(buf + size, "echo n > tvp_enable\n"); size += sprintf(buf + size, "0: disable tvp(tvp size to 0)\n"); @@ -1827,6 +1912,7 @@ static ssize_t tvp_enable_help_show(struct class *class, "1: enable tvp for 1080p playing(use default size)\n"); size += sprintf(buf + size, "2: enable tvp for 4k playing(use default 4k size)\n"); + mutex_unlock(&mgt->tvp_protect_lock); return size; } @@ -1843,35 +1929,73 @@ static ssize_t tvp_enable_store(struct class *class, ret = kstrtoint(buf, 0, &val); if (ret != 0) return -EINVAL; - /* - always free all scatter cache for - tvp changes. - */ - codec_mm_keeper_free_all_keep(2); - codec_mm_scatter_free_all_ignorecache(3); - switch (val) { - case 0: - ret = codec_mm_extpool_pool_release(&mgt->tvp_pool); - mgt->tvp_enable = 0; - pr_info("disalbe tvp\n"); - break; - case 1: - codec_mm_extpool_pool_alloc( - &mgt->tvp_pool, - default_tvp_size, 0, 1); - mgt->tvp_enable = 1; - pr_info("enable tvp for 1080p\n"); - break; - case 2: - codec_mm_extpool_pool_alloc( - &mgt->tvp_pool, - default_tvp_4k_size, 0, 1); - mgt->tvp_enable = 2; - pr_info("enable tvp for 4k\n"); - break; - default: - pr_err("unknown cmd! %d\n", val); + mutex_lock(&mgt->tvp_protect_lock); + if (tvp_mode == 0) { + /* + * always free all scatter cache for + * tvp changes. + */ + codec_mm_keeper_free_all_keep(2); + codec_mm_scatter_free_all_ignorecache(3); + switch (val) { + case 0: + ret = codec_mm_extpool_pool_release(&mgt->tvp_pool); + mgt->tvp_enable = 0; + pr_info("disalbe tvp\n"); + break; + case 1: + codec_mm_extpool_pool_alloc( + &mgt->tvp_pool, + default_tvp_size, 0, 1); + mgt->tvp_enable = 1; + pr_info("enable tvp for 1080p\n"); + break; + case 2: + codec_mm_extpool_pool_alloc( + &mgt->tvp_pool, + default_tvp_4k_size, 0, 1); + mgt->tvp_enable = 2; + pr_info("enable tvp for 4k\n"); + break; + default: + pr_err("unknown cmd! %d\n", val); + } + } else { + switch (val) { + case 0: + if (atomic_dec_and_test(&mgt->tvp_user_count)) { + if (codec_mm_tvp_pool_unprotect + (&mgt->tvp_pool) == 0) { + ret = codec_mm_extpool_pool_release + (&mgt->tvp_pool); + mgt->tvp_enable = 0; + pr_info("disalbe tvp\n"); + mutex_unlock(&mgt->tvp_protect_lock); + return size; + } + } + if (atomic_read(&mgt->tvp_user_count) < 0) + atomic_set(&mgt->tvp_user_count, 0); + pr_info("tvp_user_count is %d\n", + atomic_read(&mgt->tvp_user_count)); + break; + case 1: + case 2: + ret = atomic_add_return(1, &mgt->tvp_user_count); + if (ret == 1) { + codec_mm_extpool_pool_alloc( + &mgt->tvp_pool, + default_tvp_4k_size, 0, 1); + mgt->tvp_enable = 2; + } + pr_info("tvp_user_count is %d\n", + atomic_read(&mgt->tvp_user_count)); + break; + default: + pr_err("unknown cmd! %d\n", val); + } } + mutex_unlock(&mgt->tvp_protect_lock); return size; } @@ -2326,3 +2450,5 @@ module_param(debug_sc_mode, uint, 0664); MODULE_PARM_DESC(debug_sc_mode, "\n debug scatter module\n"); module_param(debug_keep_mode, uint, 0664); MODULE_PARM_DESC(debug_keep_mode, "\n debug keep module\n"); +module_param(tvp_mode, uint, 0664); +MODULE_PARM_DESC(tvp_mode, "\n tvp module\n"); diff --git a/include/linux/amlogic/media/codec_mm/codec_mm.h b/include/linux/amlogic/media/codec_mm/codec_mm.h index 7108cb4a79d0..d2ad64013821 100644 --- a/include/linux/amlogic/media/codec_mm/codec_mm.h +++ b/include/linux/amlogic/media/codec_mm/codec_mm.h @@ -112,6 +112,7 @@ struct codec_mm_s { int mem_id; int next_bit; struct list_head list; + u32 tvp_handle; }; struct codec_mm_s *codec_mm_alloc(const char *owner, int size, int align2n, int memflags);