413 lines
11 KiB
C
413 lines
11 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
/*
|
|
* Copyright (c) 2019 MediaTek Inc.
|
|
*/
|
|
|
|
/*
|
|
* GenieZone (hypervisor-based seucrity platform) enables hardware protected
|
|
* and isolated security execution environment, includes
|
|
* 1. GZ hypervisor
|
|
* 2. Hypervisor-TEE OS (built-in Trusty OS)
|
|
* 3. Drivers (ex: debug, communication and interrupt) for GZ and
|
|
* hypervisor-TEE OS
|
|
* 4. GZ and hypervisor-TEE and GZ framework (supporting multiple TEE
|
|
* ecosystem, ex: M-TEE, Trusty, GlobalPlatform, ...)
|
|
*/
|
|
|
|
|
|
#include "gz_shmem_ut.h"
|
|
#include <linux/string.h>
|
|
#include <linux/slab.h>
|
|
#include <kree/system.h>
|
|
#include <kree/mem.h>
|
|
#include <tz_cross/trustzone.h>
|
|
#include <tz_cross/ta_test.h>
|
|
#include <tz_cross/ta_system.h>
|
|
#include "unittest.h"
|
|
|
|
#define KREE_DEBUG(fmt...) pr_info("[SM_kUT]" fmt)
|
|
#define KREE_INFO(fmt...) pr_info("[SM_kUT]" fmt)
|
|
#define KREE_ERR(fmt...) pr_info("[SM_kUT][ERR]" fmt)
|
|
|
|
INIT_UNITTESTS;
|
|
|
|
#define mem_srv_name "com.mediatek.geniezone.srv.mem"
|
|
#define echo_srv_name "com.mediatek.geniezone.srv.echo"
|
|
|
|
int verify_data(char *buf, int size, char ch)
|
|
{
|
|
int i;
|
|
int cnt = 0;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
if (buf[i] != ch)
|
|
return TZ_RESULT_ERROR_GENERIC;
|
|
cnt++;
|
|
}
|
|
|
|
//KREE_DEBUG("[%s]char:%c @buf(0x%llx,sz=0x%x),cnt=0x%x\n",
|
|
//__func__, ch, (uint64_t) buf, size, cnt);
|
|
|
|
return TZ_RESULT_SUCCESS;
|
|
}
|
|
|
|
/*update shmem data in GZ*/
|
|
int upt_data_in_GZ(int32_t mem_hd, int shm_size, int numOfPA)
|
|
{
|
|
union MTEEC_PARAM param[4];
|
|
uint32_t paramTypes;
|
|
KREE_SESSION_HANDLE echo_sn; /*for echo service */
|
|
int ret = TZ_RESULT_SUCCESS;
|
|
|
|
ret = KREE_CreateSession(echo_srv_name, &echo_sn);
|
|
if (ret != TZ_RESULT_SUCCESS) {
|
|
KREE_ERR("echo_sn create fail\n");
|
|
return ret;
|
|
}
|
|
|
|
param[0].value.a = mem_hd;
|
|
param[1].value.a = numOfPA;
|
|
param[1].value.b = shm_size;
|
|
paramTypes = TZ_ParamTypes3
|
|
(TZPT_VALUE_INPUT, TZPT_VALUE_INPUT, TZPT_VALUE_OUTPUT);
|
|
ret = KREE_TeeServiceCall(echo_sn,
|
|
TZCMD_SHARED_MEM_TEST, paramTypes, param); /*5588*/
|
|
if (ret != TZ_RESULT_SUCCESS)
|
|
KREE_ERR("[%s]echo[0x5588] fail(0x%x)\n", __func__, ret);
|
|
|
|
ret = KREE_CloseSession(echo_sn);
|
|
if (ret != TZ_RESULT_SUCCESS) {
|
|
KREE_ERR("echo_sn close fail\n");
|
|
return ret;
|
|
}
|
|
|
|
//KREE_DEBUG("[%s] upt shmem hd=0x%x, sz=0x%x, num_PA=0x%x\n",
|
|
// __func__, mem_hd, shm_size, numOfPA);
|
|
return ret;
|
|
}
|
|
|
|
TZ_RESULT shmem_test_continuous(void)
|
|
{
|
|
int sz = 4272; /*can update for test*/
|
|
|
|
int aligned_sz = (int) PAGE_ALIGN(sz);
|
|
int sz_order = 0;
|
|
char *buf = NULL;
|
|
int num_PA = 0;
|
|
uint64_t pa = 0;
|
|
KREE_SESSION_HANDLE mem_sn = 0;
|
|
KREE_SHAREDMEM_HANDLE mem_hd;
|
|
KREE_SHAREDMEM_PARAM shm_param;
|
|
TZ_RESULT ret = TZ_RESULT_SUCCESS;
|
|
|
|
TEST_BEGIN("==> shmem test continuous case");
|
|
RESET_UNITTESTS;
|
|
|
|
num_PA = sz / PAGE_SIZE;
|
|
if ((sz % PAGE_SIZE) != 0)
|
|
num_PA++;
|
|
|
|
//buf = kmalloc(sz, GFP_KERNEL);
|
|
sz_order = get_order(aligned_sz);
|
|
buf = (char *)__get_free_pages(GFP_KERNEL, sz_order);
|
|
if (!buf) {
|
|
KREE_ERR("[%s] buf kmalloc fail.\n", __func__);
|
|
ret = TZ_RESULT_ERROR_OUT_OF_MEMORY;
|
|
goto out;
|
|
}
|
|
|
|
pa = (uint64_t) virt_to_phys((void *)buf);
|
|
|
|
if ((pa % PAGE_SIZE) != 0) {
|
|
KREE_ERR("[%s] buf PA(0x%llx) !aligned, stop UT\n",
|
|
__func__, pa);
|
|
ret = TZ_RESULT_ERROR_BAD_PARAMETERS;
|
|
goto out_free_buf;
|
|
}
|
|
|
|
KREE_DEBUG("[%s]sz=%d, aligned_sz=%d, PA=%llx, num_PA=%d\n",
|
|
__func__, sz, aligned_sz, pa, num_PA);
|
|
|
|
memset(buf, 'a', sz); /*init data */
|
|
ret = verify_data(buf, sz, 'a');
|
|
CHECK_EQ(ret, TZ_RESULT_SUCCESS, "verify buf (bf)");
|
|
if (ret != TZ_RESULT_SUCCESS) {
|
|
KREE_ERR("[%s]buf (bf) fail(%d)\n", __func__, ret);
|
|
goto out_free_buf;
|
|
}
|
|
|
|
shm_param.buffer = (void *)pa;
|
|
shm_param.size = sz;
|
|
shm_param.region_id = 0;
|
|
shm_param.mapAry = NULL; /*continuous pages */
|
|
|
|
/*create session*/
|
|
ret = KREE_CreateSession(mem_srv_name, &mem_sn);
|
|
CHECK_EQ(ret, TZ_RESULT_SUCCESS, "create mem_sn");
|
|
if (ret != TZ_RESULT_SUCCESS) {
|
|
KREE_ERR("CreateSession fail(%d)\n", mem_sn);
|
|
goto out_free_buf;
|
|
}
|
|
|
|
/*reg shared mem */
|
|
ret = KREE_RegisterSharedmem(mem_sn, &mem_hd, &shm_param);
|
|
CHECK_EQ(ret, TZ_RESULT_SUCCESS, "reg shmem");
|
|
if (ret != TZ_RESULT_SUCCESS) {
|
|
KREE_ERR("[%s]Reg Shmem fail(0x%x)\n", __func__, ret);
|
|
goto out_create_mem_sn;
|
|
}
|
|
|
|
KREE_DEBUG("[%s]sz=%d, &buf=%llx, PA=%llx, num_PA=%d, hd=0x%x\n",
|
|
__func__, sz, (uint64_t) buf, pa, num_PA, mem_hd);
|
|
|
|
/*update shmem data in GZ side */
|
|
ret = upt_data_in_GZ(mem_hd, sz, num_PA);
|
|
CHECK_EQ(ret, TZ_RESULT_SUCCESS, "upt shmem in GZ");
|
|
if (ret != TZ_RESULT_SUCCESS) {
|
|
KREE_ERR("upt shmem fail (ret=%d)\n", ret);
|
|
goto out_unreg_shmem;
|
|
}
|
|
|
|
/*verify updated data:b (changed in GZ) */
|
|
ret = verify_data(buf, sz, 'b');
|
|
CHECK_EQ(ret, TZ_RESULT_SUCCESS, "verify buf (af)");
|
|
if (ret != TZ_RESULT_SUCCESS) {
|
|
KREE_ERR("[%s]buf (af) fail(%d)\n", __func__, ret);
|
|
goto out_unreg_shmem;
|
|
}
|
|
|
|
out_unreg_shmem:
|
|
/*unreg shared mem */
|
|
ret = KREE_UnregisterSharedmem(mem_sn, mem_hd);
|
|
CHECK_EQ(ret, TZ_RESULT_SUCCESS, "unreg shmem");
|
|
if (ret != TZ_RESULT_SUCCESS)
|
|
KREE_ERR("Unreg Shmem fail: hd=0x%x(%d)\n", mem_hd, ret);
|
|
|
|
out_create_mem_sn:
|
|
/*close session */
|
|
ret = KREE_CloseSession(mem_sn);
|
|
CHECK_EQ(ret, TZ_RESULT_SUCCESS, "close mem_sn");
|
|
if (ret != TZ_RESULT_SUCCESS)
|
|
KREE_ERR("mem_sn close fail\n");
|
|
|
|
out_free_buf:
|
|
/*free test shmem region */
|
|
if (buf)
|
|
free_pages((unsigned long)buf, sz_order);
|
|
//kfree(buf); /*w kmalloc()*/
|
|
|
|
out:
|
|
KREE_DEBUG("[%s] test end\n", __func__);
|
|
|
|
TEST_END;
|
|
REPORT_UNITTESTS;
|
|
return ret;
|
|
}
|
|
|
|
TZ_RESULT shmem_test_discontinuous(void)
|
|
{
|
|
int sz1 = 8192, sz2 = 12288; /*can update for test*/
|
|
|
|
int aligned_sz1 = (int) PAGE_ALIGN(sz1);
|
|
int aligned_sz2 = (int) PAGE_ALIGN(sz2);
|
|
int sz1_order = 0, sz2_order = 0;
|
|
char *buf1 = NULL, *buf2 = NULL;
|
|
int num_PA1 = 0, num_PA2 = 0, num_PA;
|
|
int num_PA1_div = 0, num_PA2_div = 0;
|
|
int num_PA1_mod = 0, num_PA2_mod = 0;
|
|
|
|
uint64_t pa1 = 0, pa2 = 0;
|
|
uint64_t *paAry = NULL;
|
|
KREE_SESSION_HANDLE mem_sn = 0;
|
|
KREE_SHAREDMEM_HANDLE mem_hd;
|
|
KREE_SHAREDMEM_PARAM shm_param;
|
|
TZ_RESULT ret = TZ_RESULT_SUCCESS;
|
|
int m = 0, idx = 1;
|
|
|
|
TEST_BEGIN("==> shmem test discontinuous case");
|
|
RESET_UNITTESTS;
|
|
|
|
num_PA1_div = sz1 / ((int) PAGE_SIZE);
|
|
num_PA1_mod = sz1 % ((int) PAGE_SIZE);
|
|
num_PA1 = (num_PA1_mod != 0) ? (num_PA1_div + 1) : num_PA1_div;
|
|
|
|
num_PA2_div = sz2 / ((int) PAGE_SIZE);
|
|
num_PA2_mod = sz2 % ((int) PAGE_SIZE);
|
|
num_PA2 = (num_PA2_mod != 0) ? (num_PA2_div + 1) : num_PA2_div;
|
|
|
|
num_PA = (num_PA1 + num_PA2);
|
|
|
|
//buf1 = kmalloc(sz1, GFP_KERNEL);
|
|
sz1_order = get_order(aligned_sz1);
|
|
buf1 = (char *)__get_free_pages(GFP_KERNEL, sz1_order);
|
|
if (!buf1) {
|
|
KREE_ERR("[%s] buf1 kmalloc fail.\n", __func__);
|
|
ret = TZ_RESULT_ERROR_OUT_OF_MEMORY;
|
|
goto out;
|
|
}
|
|
|
|
memset(buf1, 'a', sz1); /*init data */
|
|
ret = verify_data(buf1, sz1, 'a');
|
|
CHECK_EQ(ret, TZ_RESULT_SUCCESS, "verify buf1 (bf)");
|
|
if (ret != TZ_RESULT_SUCCESS) {
|
|
KREE_ERR("[%s]buf1 (bf) fail(%d)\n", __func__, ret);
|
|
goto out_free_buf1;
|
|
}
|
|
|
|
//buf2 = kmalloc(sz2, GFP_KERNEL);
|
|
sz2_order = get_order(aligned_sz2);
|
|
buf2 = (char *)__get_free_pages(GFP_KERNEL, sz2_order);
|
|
if (!buf2) {
|
|
KREE_ERR("[%s] buf2 kmalloc fail.\n", __func__);
|
|
ret = TZ_RESULT_ERROR_OUT_OF_MEMORY;
|
|
goto out_free_buf1;
|
|
}
|
|
|
|
memset(buf2, 'a', sz2); /*init data */
|
|
ret = verify_data(buf2, sz2, 'a');
|
|
CHECK_EQ(ret, TZ_RESULT_SUCCESS, "verify buf2 (bf)");
|
|
if (ret != TZ_RESULT_SUCCESS) {
|
|
KREE_ERR("[%s]buf2 (bf) fail(%d)\n", __func__, ret);
|
|
goto out_free_buf2;
|
|
}
|
|
|
|
pa1 = (uint64_t) virt_to_phys((void *)buf1);
|
|
pa2 = (uint64_t) virt_to_phys((void *)buf2);
|
|
|
|
if ((pa1 % PAGE_SIZE) != 0) {
|
|
KREE_ERR("[%s] buf1 PA(0x%llx) !aligned, stop UT\n",
|
|
__func__, pa1);
|
|
ret = TZ_RESULT_ERROR_BAD_PARAMETERS;
|
|
goto out_free_buf2;
|
|
}
|
|
|
|
if ((pa2 % PAGE_SIZE) != 0) {
|
|
KREE_ERR("[%s] buf2 PA(0x%llx) !aligned, stop UT\n",
|
|
__func__, pa2);
|
|
ret = TZ_RESULT_ERROR_BAD_PARAMETERS;
|
|
goto out_free_buf2;
|
|
}
|
|
|
|
paAry = kmalloc((num_PA + 1) * sizeof(uint64_t), GFP_KERNEL);
|
|
if (!paAry) {
|
|
KREE_DEBUG("[%s]paAry kmalloc fail.\n", __func__);
|
|
goto out_free_buf2;
|
|
}
|
|
paAry[0] = num_PA;
|
|
|
|
for (m = 0; m < num_PA1; m++)
|
|
paAry[idx++] = pa1 + (uint64_t) (m) * (uint64_t) PAGE_SIZE;
|
|
|
|
for (m = 0; m < num_PA2; m++)
|
|
paAry[idx++] = pa2 + (uint64_t) (m) * (uint64_t) PAGE_SIZE;
|
|
|
|
/*for debug */
|
|
//for (m = 0; m < idx; m++)
|
|
// KREE_DEBUG("paAry[%d]=0x%llx\n", m, paAry[m]);
|
|
|
|
shm_param.buffer = NULL;
|
|
shm_param.size = (num_PA1 + num_PA2) * (uint32_t) PAGE_SIZE;
|
|
shm_param.region_id = 0;
|
|
shm_param.mapAry = (void *)paAry; /*discountinuous pages*/
|
|
|
|
/*create session*/
|
|
ret = KREE_CreateSession(mem_srv_name, &mem_sn);
|
|
CHECK_EQ(ret, TZ_RESULT_SUCCESS, "create mem_sn");
|
|
if (ret != TZ_RESULT_SUCCESS) {
|
|
KREE_ERR("CreateSession fail(%d)\n", mem_sn);
|
|
goto out_free_paAry;
|
|
}
|
|
|
|
/*reg shared mem */
|
|
ret = KREE_RegisterSharedmem(mem_sn, &mem_hd, &shm_param);
|
|
CHECK_EQ(ret, TZ_RESULT_SUCCESS, "reg shmem");
|
|
if (ret != TZ_RESULT_SUCCESS) {
|
|
KREE_ERR("[%s]Reg Shmem fail(0x%x)\n", __func__, ret);
|
|
goto out_create_mem_sn;
|
|
}
|
|
|
|
KREE_DEBUG("[%s]sz1=%d, &buf1=%llx, PA1=%llx, num_PA1=%d, hd=0x%x\n",
|
|
__func__, sz1, (uint64_t) buf1, pa1, num_PA1, mem_hd);
|
|
|
|
KREE_DEBUG("[%s]sz2=%d, &buf2=%llx, PA2=%llx, num_PA2=%d, hd=0x%x\n",
|
|
__func__, sz2, (uint64_t) buf2, pa2, num_PA2, mem_hd);
|
|
|
|
/*update shmem data in GZ side */
|
|
ret = upt_data_in_GZ(mem_hd, (sz1 + sz2), num_PA);
|
|
CHECK_EQ(ret, TZ_RESULT_SUCCESS, "upt shmem in GZ");
|
|
if (ret != TZ_RESULT_SUCCESS) {
|
|
KREE_ERR("upt shmem fail (ret=%d)\n", ret);
|
|
goto out_unreg_shmem;
|
|
}
|
|
|
|
/*verify updated data:b (changed in GZ) */
|
|
ret = verify_data(buf1, sz1, 'b');
|
|
CHECK_EQ(ret, TZ_RESULT_SUCCESS, "verify buf1 (af)");
|
|
if (ret != TZ_RESULT_SUCCESS) {
|
|
KREE_ERR("[%s]buf1 (af) fail(%d)\n", __func__, ret);
|
|
goto out_unreg_shmem;
|
|
}
|
|
|
|
ret = verify_data(buf2, sz2, 'b');
|
|
CHECK_EQ(ret, TZ_RESULT_SUCCESS, "verify buf2 (af)");
|
|
if (ret != TZ_RESULT_SUCCESS) {
|
|
KREE_ERR("[%s]buf2 (af) fail(%d)\n", __func__, ret);
|
|
goto out_unreg_shmem;
|
|
}
|
|
|
|
out_unreg_shmem:
|
|
/*unreg shared mem */
|
|
ret = KREE_UnregisterSharedmem(mem_sn, mem_hd);
|
|
CHECK_EQ(ret, TZ_RESULT_SUCCESS, "unreg shmem");
|
|
if (ret != TZ_RESULT_SUCCESS)
|
|
KREE_ERR("Unreg Shmem fail: hd=0x%x(%d)\n", mem_hd, ret);
|
|
|
|
out_create_mem_sn:
|
|
/*close session */
|
|
ret = KREE_CloseSession(mem_sn);
|
|
CHECK_EQ(ret, TZ_RESULT_SUCCESS, "close mem_sn");
|
|
if (ret != TZ_RESULT_SUCCESS)
|
|
KREE_ERR("mem_sn close fail\n");
|
|
|
|
out_free_paAry:
|
|
if (paAry)
|
|
kfree(paAry);
|
|
|
|
out_free_buf2:
|
|
/*free test shmem region */
|
|
if (buf2)
|
|
free_pages((unsigned long)buf2, sz2_order);
|
|
//kfree(buf2);
|
|
|
|
out_free_buf1:
|
|
/*free test shmem region */
|
|
if (buf1)
|
|
free_pages((unsigned long)buf1, sz1_order);
|
|
//kfree(buf1);
|
|
|
|
out:
|
|
KREE_DEBUG("[%s] test end\n", __func__);
|
|
|
|
TEST_END;
|
|
REPORT_UNITTESTS;
|
|
return ret;
|
|
}
|
|
|
|
DEFINE_MUTEX(shmem_ut_mutex);
|
|
int gz_test_shm(void *arg)
|
|
{
|
|
mutex_lock(&shmem_ut_mutex);
|
|
|
|
/*case1: test continuous region*/
|
|
shmem_test_continuous();
|
|
|
|
/*case2: test discontinuous region*/
|
|
shmem_test_discontinuous();
|
|
|
|
mutex_unlock(&shmem_ut_mutex);
|
|
|
|
return TZ_RESULT_SUCCESS;
|
|
}
|
|
|