#include "dmcu_dbg.h" #include "dmcu_mem.h" #include "soc_log.h" #include "los_dynshm.h" #include "los_memory.h" #include "shcmd.h" #include "proc.h" #include "drv_log.h" #include "los_task_pri.h" #include "shell.h" volatile mcu_dmcu_status *g_mcu_status = (volatile mcu_dmcu_status *)(MCU_CFG_CRG_BASE + MCU_FUN_STA_REG_OFFSET); mcu_dmcu_status *get_mcu_status(td_void) { return (mcu_dmcu_status *)g_mcu_status; } #if DMCU_TEST_VAM DynShmBulkMem g_iommu_text_mem = { 0 }; static td_s32 dmcu_vam_test_phy2vir(UADDR phy_addr, UADDR vir_addr) { UADDR mcu_vir_addr; td_s32 ret = LOS_DynShmAddrTranslate(phy_addr, &mcu_vir_addr, OUTER_VA_TO_INNER_VA); if (ret != TD_SUCCESS) { soc_log_err("LOS_DynShmAddrTranslate fail\n"); return TD_FAILURE; } if (mcu_vir_addr != vir_addr) { soc_log_err("fail, mcu_vir_addr:0x%llx, vir_addr:0x%llx, phy_addr:0x%llx\n", mcu_vir_addr, vir_addr, phy_addr); return TD_FAILURE; } return TD_SUCCESS; } static td_s32 dmcu_vam_test_vir2phy(UADDR phy_addr, UADDR vir_addr) { UADDR smmu_phy_addr; td_s32 ret = LOS_DynShmAddrTranslate(vir_addr, &smmu_phy_addr, INNER_VA_TO_OUTER_VA); if (ret != TD_SUCCESS) { soc_log_err("LOS_DynShmAddrTranslate fail\n"); return TD_FAILURE; } if (smmu_phy_addr != phy_addr) { soc_log_err("fail, smmu_phy_addr:0x%llx, phy_addr:0x%llx, vir_addr:0x%llx\n", smmu_phy_addr, phy_addr, vir_addr); return TD_FAILURE; } return TD_SUCCESS; } static td_s32 dmcu_vam_addr_verify(UADDR phy_addr, UADDR vir_addr, td_u32 value) { UADDR real_addr, real_addr1; td_u32 val, val1; td_s32 ret; *(volatile td_u32 *)(td_u32)(vir_addr) = value; ret = LOS_DynShmAddrTranslate(vir_addr, &real_addr, INNER_VA_TO_MEM_PA); if (ret != TD_SUCCESS) { soc_log_err("LOS_DynShmAddrTranslate fail\n"); return TD_FAILURE; } ret = LOS_DynShmAddrTranslate(phy_addr, &real_addr1, OUTER_VA_TO_MEM_PA); if (ret != TD_SUCCESS) { soc_log_err("LOS_DynShmAddrTranslate fail\n"); return TD_FAILURE; } val = *(volatile td_u32 *)(uintptr_t)(real_addr); val1 = *(volatile td_u32 *)(uintptr_t)(real_addr1); value = *(volatile td_u32 *)(td_u32)(vir_addr); if ((real_addr != real_addr1) || (val != val1) || (val != value)) { soc_log_err("vir2real addr test fail!!! real_addr:0x%llx, real_addr1:0x%llx, val:%x, val1:%x, value:%x\n", real_addr, real_addr1, val, val1, value); return TD_FAILURE; } ret = dmcu_vam_test_phy2vir(phy_addr, vir_addr); ret |= dmcu_vam_test_vir2phy(phy_addr, vir_addr); if (ret != TD_SUCCESS) { soc_log_err("vir2phy addr test fail\n"); return TD_FAILURE; } return TD_SUCCESS; } static td_s32 dmcu_vam_mmap_test(UADDR phy_addr, td_u32 length) { td_u32 vir_addr; td_s32 ret; ret = LOS_DynShmMap(phy_addr, length, DMCU_IOMMU_NOSEC_NOCACHE, &vir_addr); if (ret != TD_SUCCESS) { soc_log_err("LOS_DynShmMap fail, ret:%#x\n", ret); return TD_FAILURE; } ret = dmcu_vam_addr_verify(phy_addr, vir_addr, DMCU_DEFAULT_WRITE_VALUE); if (ret != TD_SUCCESS) { LOS_DynShmUnmap(vir_addr, length); soc_log_err("dmcu_vam_addr_verify fail\n"); return TD_FAILURE; } ret = LOS_DynShmUnmap(vir_addr, length); if (ret != TD_SUCCESS) { soc_log_err("LOS_DynShmUnmap fail\n"); return TD_FAILURE; } return TD_SUCCESS; } static td_s32 dmcu_vam_pool_verify(td_u32 length) { UADDR real_addr; td_s32 ret = TD_SUCCESS; td_s32 max = length / SIZE_8K; for (td_s32 i = 0; i < max - 1; i++) { void *vir_addr = dmcu_pool_mem_malloc(SIZE_8K); if (vir_addr == NULL) { soc_log_err("dmcu_pool_mem_malloc fail\n"); return TD_FAILURE; } *(volatile td_u32 *)(vir_addr) = DMCU_DEFAULT_WRITE_VALUE + i; ret = LOS_DynShmAddrTranslate((UADDR)(UINTPTR)vir_addr, &real_addr, INNER_VA_TO_MEM_PA); if (ret != TD_SUCCESS) { dmcu_pool_mem_free(vir_addr); soc_log_err("LOS_DynShmAddrTranslate fail\n"); return TD_FAILURE; } td_u32 val = *(volatile td_u32 *)(uintptr_t)(real_addr); if (val != DMCU_DEFAULT_WRITE_VALUE + i) { soc_log_err("write val:0x%x, read val:0x%x, vir_addr:%p, real_addr:0x%llx\n", DMCU_DEFAULT_WRITE_VALUE + i, val, vir_addr, real_addr); dmcu_pool_mem_free(vir_addr); return TD_FAILURE; } ret = dmcu_pool_mem_free(vir_addr); if (ret != TD_SUCCESS) { soc_log_err("dmcu_pool_mem_free fail\n"); return TD_FAILURE; } } return TD_SUCCESS; } static td_s32 dmcu_vam_pool_test(UADDR phy_addr, td_u32 length) { UADDR vir_addr; td_s32 ret = dmcu_pool_mem_init(phy_addr, length, DMCU_IOMMU_NOSEC_NOCACHE, &vir_addr); if (ret != TD_SUCCESS) { soc_log_err("dmcu_pool_mem_init fail\n"); return TD_FAILURE; } ret = dmcu_vam_pool_verify(length); if (ret != TD_SUCCESS) { dmcu_pool_mem_deinit(vir_addr, length); soc_log_err("dmcu_vam_pool_verify fail\n"); return TD_FAILURE; } ret = dmcu_pool_mem_deinit(vir_addr, length); if (ret != TD_SUCCESS) { soc_log_err("dmcu_pool_mem_deinit fail\n"); return TD_FAILURE; } return TD_SUCCESS; } static td_s32 dmcu_vam_bulk_test(td_u32 size, td_u32 type) { DynShmBulkMem mem = { 0 }; td_s32 ret = TD_SUCCESS; volatile td_u32 *test_ptr = NULL; mem.size = size; mem.type = type; mem.name = "bulk_test"; void *vir_addr = LOS_DynShmBulkMalloc(&mem); if (vir_addr == NULL) { soc_log_err("LOS_DynShmBulkMalloc fail\n"); return TD_FAILURE; } for (int i = 0; i < size / sizeof(td_u32); i++) { test_ptr = (volatile td_u32 *)(td_u32)(mem.virAddr) + i; *test_ptr = i + 1; soc_log_info("test_ptr[%d]: ptr:%p, val:0x%x\n", i, test_ptr, *test_ptr); } soc_log_info("phyAddr:0x%llx, virAddr:0x%llx\n", mem.phyAddr, mem.virAddr); ret = LOS_DynShmBulkFree(&mem); if (ret != TD_SUCCESS) { soc_log_err("LOS_DynShmBulkFree fail, ret:%x\n", ret); return TD_FAILURE; } return TD_SUCCESS; } static td_void dmcu_iommu_print_help(td_void) { osal_proc_echo( "echo shell iommu_test 0 >/proc/msp/dmcu iommu test help.\n"); osal_proc_echo("echo shell iommu_test 1 0x1000 0 >/proc/msp/dmcu iommu malloc " "test. param1:[1:malloc] param2:[mem_size] param3:[mem_type]\n"); osal_proc_echo("echo shell iommu_test 2 >/proc/msp/dmcu iommu free test. " " param1:[2:free]\n"); osal_proc_echo("echo shell iommu_test 3 phyAddr 0x1000 1 >/proc/msp/dmcu iommu map test. " " param1:[3:map] param2:[mem_addr] param3:[mem_size] param4:[test_count]\n"); osal_proc_echo("echo shell iommu_test 4 phyAddr 0x1000 1 >/proc/msp/dmcu iommu pool test. " " param1:[4:pool] param2:[mem_addr] param3:[mem_size] param4:[test_count]\n"); osal_proc_echo("echo shell iommu_test 5 0x1000 0 1 >/proc/msp/dmcu iommu bulk test. " " param1:[5:bulk] param2:[mem_size] param3:[mem_type] param4:[test_count]\n"); return; } static td_void dmcu_iommu_test_print_help(td_s32 argc, const char **argv) { dmcu_proc_draw_double_line("iommu", PROC_SHELL_LENGTH); dmcu_iommu_print_help(); dmcu_proc_draw_double_line("", PROC_SHELL_LENGTH); return; } static td_void dmcu_iommu_map_test(td_s32 argc, const char **argv) { td_s32 index = 0; td_u32 loop_count = MEM_TEST_DEFAULT_LOOP; td_u32 phyaddr = osal_strtoul(argv[PRARM_1], NULL, 0); td_u32 length = osal_strtoul(argv[PRARM_2], NULL, 0); if (argc == MEM_TEST_ARGC_MAX_LEN) { loop_count = osal_strtoul(argv[PRARM_3], NULL, 0); } for (index = 0; index < loop_count; index++) { td_s32 ret = dmcu_vam_mmap_test(phyaddr, length); if (ret != TD_SUCCESS) { soc_log_err("dmcu_vam_mmap_test fail, loop_count: %d\n", index); return; } } dmcu_proc_draw_double_line("iommu_mmap", PROC_IOMMU_LENGTH); osal_proc_echo("|%-14s :%-10s |%-10s :%-11d |%-10s :0x%-20llx |%-10s :0x%-20llx |\n", "test_status", "success", "loop", index, "phyAddr", g_iommu_text_mem.phyAddr, "virAddr", g_iommu_text_mem.virAddr); dmcu_proc_draw_double_line("", PROC_IOMMU_LENGTH); return; } static td_void dmcu_iommu_pool_test(td_s32 argc, const char **argv) { td_s32 index = 0; td_u32 loop_count = MEM_TEST_DEFAULT_LOOP; td_u32 phyaddr = osal_strtoul(argv[PRARM_1], NULL, 0); td_u32 length = osal_strtoul(argv[PRARM_2], NULL, 0); if (argc == MEM_TEST_ARGC_MAX_LEN) { loop_count = osal_strtoul(argv[PRARM_3], NULL, 0); } for (index = 0; index < loop_count; index++) { td_s32 ret = dmcu_vam_pool_test(phyaddr, length); if (ret != TD_SUCCESS) { soc_log_err("dmcu_vam_pool_test fail, loop_count: %d\n", index); return; } } dmcu_proc_draw_double_line("iommu_pool", PROC_IOMMU_LENGTH); osal_proc_echo("|%-14s :%-10s |%-10s :%-11d |%-10s :0x%-20llx |%-10s :0x%-20llx |\n", "test_status", "success", "loop", index, "phyAddr", g_iommu_text_mem.phyAddr, "virAddr", g_iommu_text_mem.virAddr); dmcu_proc_draw_double_line("", PROC_IOMMU_LENGTH); return; } static td_void dmcu_iommu_bulk_test(td_s32 argc, const char **argv) { td_s32 index = 0; td_u32 loop_count = MEM_TEST_DEFAULT_LOOP; td_s32 ret = TD_SUCCESS; td_u32 size = osal_strtoul(argv[PRARM_1], NULL, 0); td_u32 num = osal_strtoul(argv[PRARM_2], NULL, 0); if (argc == MEM_TEST_ARGC_MAX_LEN) { loop_count = osal_strtoul(argv[PRARM_3], NULL, 0); } for (index = 0; index < loop_count; index++) { ret = dmcu_vam_bulk_test(size, num); if (ret != TD_SUCCESS) { soc_log_err("lite_Vam_test_bulk fail, loop_count: %d\n", index); return; } } dmcu_proc_draw_double_line("iommu_bulk", PROC_IOMMU_LENGTH); osal_proc_echo("|%-14s :%-10s |%-10s :%-11d |%-10s :0x%-20llx |%-10s :0x%-20llx |\n", "test_status", "success", "loop", index, "phyAddr", g_iommu_text_mem.phyAddr, "virAddr", g_iommu_text_mem.virAddr); dmcu_proc_draw_double_line("", PROC_IOMMU_LENGTH); return; } static td_void dmcu_iommu_malloc_test(td_s32 argc, const char **argv) { void *vir_addr = TD_NULL; td_u32 size = osal_strtoul(argv[PRARM_1], NULL, 0); td_u32 type = osal_strtoul(argv[PRARM_2], NULL, 0); if (g_iommu_text_mem.virAddr != 0) { soc_log_err("dmcu iommu has been malloc, Do not malloc repeatedly\n"); return; } g_iommu_text_mem.size = size; g_iommu_text_mem.type = type; g_iommu_text_mem.name = "bulk_test"; vir_addr = LOS_DynShmBulkMalloc(&g_iommu_text_mem); if (vir_addr == NULL) { soc_log_err("LOS_DynShmBulkMalloc fail\n"); return; } dmcu_proc_draw_double_line("iommu_malloc", PROC_IOMMU_LENGTH); osal_proc_echo("|%-14s :%-10s |%-10s :%-11d |%-10s :0x%-20llx |%-10s :0x%-20llx |\n", "test_status", "success", "loop", 1, "phyAddr", g_iommu_text_mem.phyAddr, "virAddr", g_iommu_text_mem.virAddr); dmcu_proc_draw_double_line("", PROC_IOMMU_LENGTH); return; } static td_void dmcu_iommu_free_test(td_s32 argc, const char **argv) { td_s32 ret = TD_SUCCESS; if ((g_iommu_text_mem.virAddr == 0) || (g_iommu_text_mem.phyAddr == 0)) { soc_log_err("LOS_DynShmBulkFree fail, Apply for memory first.\n"); return; } ret = LOS_DynShmBulkFree(&g_iommu_text_mem); if (ret != TD_SUCCESS) { soc_log_err("LOS_DynShmBulkFree fail, ret:%x\n", ret); return; } g_iommu_text_mem.virAddr = 0; dmcu_proc_draw_double_line("iommu_free", PROC_IOMMU_LENGTH); osal_proc_echo("|%-14s :%-10s |%-10s :%-11d |%-10s :0x%-20llx |%-10s :0x%-20x |\n", "test_status", "success", "loop", 1, "phyAddr", g_iommu_text_mem.phyAddr, "virAddr", g_iommu_text_mem.virAddr); dmcu_proc_draw_double_line("", PROC_IOMMU_LENGTH); return; } static dmcu_test_cmd_function g_dmcu_test_cmd_function[] = { {DMCU_CMD_HELP, dmcu_iommu_test_print_help}, {DMCU_CMD_MALLOC, dmcu_iommu_malloc_test}, {DMCU_CMD_FREE, dmcu_iommu_free_test}, {DMCU_CMD_MAP, dmcu_iommu_map_test}, {DMCU_CMD_POOL, dmcu_iommu_pool_test}, {DMCU_CMD_BULK, dmcu_iommu_bulk_test}, }; td_u32 dmcu_iommu_test(td_s32 argc, const char **argv) { td_u32 i; td_u32 cmd_num = sizeof(g_dmcu_test_cmd_function) / sizeof(dmcu_test_cmd_function); if (argc < ARGS_NUM || argv == NULL) { soc_log_err("argc:%d failed \n", argc); dmcu_iommu_test_print_help(argc, argv); return 0; } td_u32 cmd = osal_strtoul(argv[0], NULL, 0); if (cmd < DMCU_CMD_TEST_MAX) { for (i = 0; i < cmd_num; i++) { if (cmd == g_dmcu_test_cmd_function[i].cmd) { g_dmcu_test_cmd_function[i].handler(argc, argv); break; } } } else { soc_log_err("invalid cmd\n"); } return 0; } SHELLCMD_ENTRY(test_shell_cmd, CMD_TYPE_STD, "iommu_test", XARGS, (CmdCallBackFunc)dmcu_iommu_test); /* shell proc */ int dmcu_cmd_proc_read_test(td_void *seqfile, td_void *private) { dmcu_proc_draw_double_line("shell_read", PROC_SHELL_LENGTH); dmcu_proc_draw_double_line("", PROC_SHELL_LENGTH); return TD_SUCCESS; } td_s32 dmcu_cmd_proc_iommu_test(unsigned int argc, char (*argv)[PROC_CMD_SINGEL_LENGTH_MAX], td_void *private) { UINTPTR user_cmd_para[CMD_PARAM_MAX_COUNT] = { 0 }; for (int i = 0; i < (argc - 1); i++) { user_cmd_para[i] = (UINTPTR)&argv[i + 1]; } dmcu_iommu_test(argc - 1, (const char **)user_cmd_para); return TD_SUCCESS; } td_s32 dmcu_cmd_proc_help(unsigned int argc, char (*argv)[PROC_CMD_SINGEL_LENGTH_MAX], td_void *private) { dmcu_proc_draw_double_line("shell_help", PROC_SHELL_LENGTH); osal_proc_echo("echo module cmd param1 param2 param3 param4 path explanation\n"); osal_proc_echo("echo shell help >/proc/msp/dmcu\n"); dmcu_iommu_print_help(); osal_proc_echo("echo shell himm addr value >/proc/msp/dmcu memory/reg " "write. param1:[write addr] param2:[write length]\n"); osal_proc_echo("echo shell himd addr length >/proc/msp/dmcu memory/reg read. " " param1:[read addr] param2:[read length]\n"); osal_proc_echo( "echo shell hwi >/proc/msp/dmcu get interrupt info.\n"); osal_proc_echo( "echo shell task >/proc/msp/dmcu get task info.\n"); osal_proc_echo("echo shell task stack task_id >/proc/msp/dmcu get task stack " "info by id. param1:[stack] param2:[task_id]\n"); osal_proc_echo("echo shell task stack all >/proc/msp/dmcu get task stack " "all info. param1:[stack] param2:[all]\n"); osal_proc_echo("echo shell prt2arm 0 >/proc/msp/dmcu set proc print " "to arm. param1:[off: 0 / on: 1]\n"); osal_proc_echo("echo shell proc_info >/proc/msp/dmcu print proc " "register info.\n"); dmcu_proc_draw_double_line("", PROC_SHELL_LENGTH); return TD_SUCCESS; } td_s32 dmcu_cmd_proc_himm(unsigned int argc, char (*argv)[PROC_CMD_SINGEL_LENGTH_MAX], td_void *private) { if (argc != 3) { /* 3 is param count; cmd + addr + value */ soc_log_err("invalid param himm