// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Copyright (c) 2019 Amlogic, Inc. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define CONFIG_AMFC_TEST 0 #define TABLE_SRC 0 #define TABLE_DST 1 #if CONFIG_AMFC_TEST #include #include static unsigned long total_sw_compressed_size; static unsigned long total_hw_compressed_size; static unsigned long total_hw_compress_time; static unsigned long total_hw_decompress_time; static unsigned long total_hw_self_decompress_time; bool self; int table_test_mask; static struct amfc_cmd_list test_acl1 __attribute__((aligned(64))); static struct amfc_cmd_list test_acl2 __attribute__((aligned(64))); #endif #define HW_VERSION_10 0x100 #define HW_VERSION_11 0x101 #define HW_VERSION_12 0x102 static unsigned int hw_version; int amfc_init(void) { unsigned int value; cpu_id_t cpu_id = get_cpu_id(); switch (cpu_id.family_id) { case MESON_CPU_MAJOR_ID_S7D: if (cpu_id.chip_rev == 0x0A) { // 500MHz writel(0 | (1 << 6) | (5 << 7), CLKCTRL_AMFC_CLK_CTRL); break; } case MESON_CPU_MAJOR_ID_S6: // 666MHz writel(0 | (1 << 6) | (4 << 7), CLKCTRL_AMFC_CLK_CTRL); break; case MESON_CPU_MAJOR_ID_T6D: case MESON_CPU_MAJOR_ID_T6W: case MESON_CPU_MAJOR_ID_T6X: // 666MHz writel(0 | (1 << 8) | (1 << 9), CLKCTRL_AMFC_CLK_CTRL); break; case MESON_CPU_MAJOR_ID_A9: case MESON_CPU_MAJOR_ID_C5: // 666MHz writel(0 | (1 << 8) | (4 << 9), CLKCTRL_AMFC_CLK_CTRL); break; default: printf("unsupported CPU id:%x\n", cpu_id.family_id); return -1; } hw_version = readl(AMFC_GL_VERSION); printf("AMFC VLSI version:%x, feature:%x\n", readl(AMFC_GL_VERSION), readl(AMFC_GL_CMD1_FEATURE)); writel(0, AMFC_GL_CMD0_CONTROL); writel(0, AMFC_GL_CMD1_CONTROL); writel(3, AMFC_GL_CMD0_IRQCLR); writel(3, AMFC_GL_CMD1_IRQCLR); writel(0, AMFC_GL_MISC); // cmd0/1 mixed mode writel((2 << 6) | (2 << 4) | (1 << 1) | (1), AMFC_CODEC_CTRL); writel(1, AMFC_ZSTD_MODE_MISC); value = readl(AMFC_WR_MIF_CTRL); value &= ~(0x7 << 8); value |= (2 << 8); writel(value, AMFC_WR_MIF_CTRL); value = readl(AMFC_RD_MIF_CTRL); value &= ~(0x7 << 8); value |= (2 << 8); writel(value, AMFC_RD_MIF_CTRL); return 0; } static struct amfc_cmd_list acl __attribute__((aligned(64))); static int page_table_mode = 0; static int log_en = 0; static void dump_addr(void *buf, unsigned int size) { int i; unsigned int *p = (unsigned int *)buf; printf("%s addr:%px, size:%d\n", __func__, buf, size); for (i = 0; i < size / 4; i += 4) { printf("%px: %08x %08x %08x %08x\n", p + i, p[i], p[i + 1], p[i + 2], p[i + 3]); } } static int build_tables(unsigned int *table, unsigned long base, ssize_t size, int type) { int i, count, need_reverse = 0; unsigned long tmp, end = base + size - 1; if (!table || size < PAGE_SIZE) return -1; if ((base & ~PAGE_MASK) && hw_version < HW_VERSION_11) { printf("%s, base:%lx not align to %d\n", __func__, base, PAGE_SIZE); return -1; } /* physical contiguous in uboot */ count = (end >> PAGE_SHIFT) - (base >> PAGE_SHIFT) + 1; /* * type and page_table_mode for test * page_table_mode = 1 --> src/dst all sequence table * page_table_mode = 2 --> src sequence/dst reverse * page_table_mode = 3 --> src reverse/dst sequence * page_table_mode = 4 --> src/dst all reverse table * page_table_mode = 5 --> dst sequence table/src not use page_table, * for EROFS test */ if ((page_table_mode == 2 && type == TABLE_DST) || (page_table_mode == 3 && type == TABLE_SRC) || (page_table_mode == 4)) need_reverse = 1; if (need_reverse) base += (count - 1) * PAGE_SIZE; for (i = 0; i < count; i++) { tmp = ((base >> PAGE_SHIFT) << 6) | 1; table[i] = tmp; if (need_reverse) base -= PAGE_SIZE; else base += PAGE_SIZE; } flush_dcache_range((unsigned long)table, (unsigned long)table + count * 4); return 0; } #define ADDR_SRC 0 #define ADDR_DST 1 static void set_up_addr(struct amfc_cmd_list *acl, unsigned long addr, int type) { unsigned int low, high = 0; low = addr & 0xffffffff; #ifdef CONFIG_64BIT high = (addr >> 32) & 0xf; #endif switch (type) { case ADDR_SRC: acl->src_addr = low; acl->src_addr_h = high; break; case ADDR_DST: acl->dst_addr = low; acl->dst_addr_h = high; break; default: break; } } /* * src: source buffer that need decompress * dst: destination buffer that need store * src_size: size of source buffer * dst_size: size for destination buffer, caller should make sure * dst size is enough * stream: stream mode support, 0: disable, 1: enable * return value: decompressed size if success, negative value if failed */ int amfc_decompress(void *src, void *dst, ssize_t src_size, ssize_t dst_size, int stream) { unsigned int *src_table = NULL, *dst_table = NULL, *tmp; int table_size; unsigned int status, off; int cmd_time; int timeout = ((src_size + PAGE_SIZE) / PAGE_SIZE) * 100 + 5000; unsigned long inv_end = (unsigned long)dst + dst_size; unsigned long secmon_start = readl(SYSCTRL_SEC_STATUS_REG17) + (1 << 20); int ret; if (!src || !dst || src_size < 0 || dst_size < 0) return -1; if (log_en) printf("%s, acl:%p, src:%p, dst:%p, src size:%ld, dst size:%ld\n", __func__, &acl, src, dst, (long)src_size, (long)dst_size); /* setup command list */ memset(&acl, 0, sizeof(acl)); acl.src_size = src_size; acl.dst_size = dst_size; if (page_table_mode && src_size >= PAGE_SIZE) { table_size = sizeof(int) * (src_size / PAGE_SIZE) + PAGE_SIZE * 2; src_table = malloc(table_size); if (!src_table) return -ENOMEM; tmp = (unsigned int *)(((unsigned long)src_table + PAGE_SIZE) & PAGE_MASK); if (hw_version > HW_VERSION_10) { off = (unsigned long)src & (~PAGE_MASK); acl.link_addr |= off << 16; } build_tables(tmp, (unsigned long)src, src_size, TABLE_SRC); set_up_addr(&acl, virt_to_phys(tmp), ADDR_SRC); acl.src_scatter = 1; if (log_en) printf("%s, table_size:%d, src_table:%p, tmp:%p\n", __func__, table_size, src_table, tmp); } else { set_up_addr(&acl, virt_to_phys(src), ADDR_SRC); } if (page_table_mode && dst_size >= PAGE_SIZE) { table_size = sizeof(int) * (dst_size / PAGE_SIZE) + PAGE_SIZE * 2; dst_table = malloc(table_size); if (!dst_table) return -ENOMEM; tmp = (unsigned int *)(((unsigned long)dst_table + PAGE_SIZE) & PAGE_MASK); if (hw_version > HW_VERSION_10) { off = (unsigned long)dst & (~PAGE_MASK); acl.link_addr |= off; } build_tables(tmp, (unsigned long)dst, dst_size, TABLE_DST); set_up_addr(&acl, virt_to_phys(tmp), ADDR_DST); acl.dst_scatter = 1; if (log_en) printf("%s, table_size:%d, dst_table:%p, tmp:%p\n", __func__, table_size, dst_table, tmp); } else { set_up_addr(&acl, virt_to_phys(dst), ADDR_DST); } acl.stream = stream ? 1 : 0; acl.algorithm = ALGORITHM_ZSTD; acl.end = 1; acl.compress = CMD_DECOMPRESS; acl.owner = 1; acl.status = 0xffffffff; flush_dcache_range((unsigned long)src, (unsigned long)src + src_size); flush_dcache_range((unsigned long)&acl, (unsigned long)&acl + sizeof(acl)); if (inv_end > secmon_start && (unsigned long)dst < secmon_start) inv_end = secmon_start; invalidate_dcache_range((unsigned long)dst, inv_end); /* sw reset */ writel(0x80000000, AMFC_GL_CMD1_CONTROL); writel(0x03, AMFC_GL_CMD1_IRQCLR); writel((unsigned long)&acl >> ADDR_SHIFT, AMFC_GL_CMD1_DESC_BASE0_ADDR); /* trigger */ writel(1, AMFC_GL_CMD1_CONTROL); cmd_time = get_time(); /* wait for done or error */ while (1) { status = readl(AMFC_GL_CMD1_STATUS); if ((status & AMFC_IRQ_MASK)) break; if (get_time() - cmd_time > timeout) { printf("time out\n"); break; } } cmd_time = get_time() - cmd_time; invalidate_dcache_range((unsigned long)dst, inv_end); invalidate_dcache_range((unsigned long)&acl, (unsigned long)&acl + sizeof(acl)); status = readl(AMFC_GL_CMD1_STATUS); if (!(status & AMFC_ERROR_MASK)) { #if CONFIG_AMFC_TEST if (self) total_hw_self_decompress_time += readl(AMFC_CMD1_TIME_MEASURE); else total_hw_decompress_time += readl(AMFC_CMD1_TIME_MEASURE); #endif writel(0x01, AMFC_GL_CMD1_IRQCLR); if (log_en) printf("decompress done:%x %x, size:%d, cycles:%d, time:%d us\n", acl.status, status, acl.result_size, readl(AMFC_CMD1_TIME_MEASURE), cmd_time); if (stream) ret = acl.result_size & ~(0x80000000); else ret = acl.result_size; if (ret <= 0) { ret = -EINVAL; dump_addr((void *)AMFC_GL_VERSION, 300); dump_addr((void *)&acl, 32); dump_addr((void *)src, 32); dump_addr((void *)dst, 32); dump_addr((void *)(long)acl.src_addr, 32); dump_addr((void *)(long)acl.dst_addr, 32); writel(0x03, AMFC_GL_CMD1_IRQCLR); } } else { printf("decompress failed:%x %x, time:%d us, acl:%p, src:%p, dst:%p, src_size:%ld, dst_size:%ld, timeout:%d\n", acl.status, readl(AMFC_GL_CMD1_STATUS), readl(AMFC_CMD1_TIME_MEASURE), &acl, src, dst, (long)src_size, (long)dst_size, timeout); dump_addr((void *)0xfe024000, 300); dump_addr((void *)&acl, 32); dump_addr((void *)src, 32); dump_addr((void *)dst, 32); writel(0x03, AMFC_GL_CMD1_IRQCLR); ret = -EINVAL; } if (src_table) free(src_table); if (dst_table) free(dst_table); return ret; } int amfc_compress(void *src, void *dst, ssize_t src_size, ssize_t dst_size) { #ifdef CONFIG_AMFC_COMPRESS unsigned int *src_table = NULL, *dst_table = NULL, *tmp; int table_size; unsigned int status, off; int cmd_time; int timeout = ((src_size + PAGE_SIZE) / PAGE_SIZE) * 20 + 5000; int ret; if (log_en) printf("%s, acl:%p, src:%p, dst:%p, src sizs:%ld, dst size:%ld\n", __func__, &acl, src, dst, src_size, dst_size); /* setup command list */ memset(&acl, 0, sizeof(acl)); acl.src_size = src_size; acl.dst_size = dst_size; if (page_table_mode && src_size > PAGE_SIZE) { table_size = sizeof(int) * (src_size / PAGE_SIZE) + PAGE_SIZE * 2; src_table = malloc(table_size); if (!src_table) return -ENOMEM; tmp = (unsigned int *)(((unsigned long)src_table + PAGE_SIZE) & PAGE_MASK); if (hw_version > HW_VERSION_10) { off = (unsigned long)src & (~PAGE_MASK); acl.link_addr |= (off << 16); } build_tables(tmp, (unsigned long)src, src_size, TABLE_SRC); set_up_addr(&acl, virt_to_phys(tmp), ADDR_SRC); acl.src_scatter = 1; if (log_en) printf("%s, table_size:%d, src_table:%p, tmp:%p\n", __func__, table_size, src_table, tmp); } else { set_up_addr(&acl, virt_to_phys(src), ADDR_SRC); } if (page_table_mode && dst_size > PAGE_SIZE) { table_size = sizeof(int) * (dst_size / PAGE_SIZE) + PAGE_SIZE * 2; dst_table = malloc(table_size); if (!dst_table) return -ENOMEM; tmp = (unsigned int *)(((unsigned long)dst_table + PAGE_SIZE) & PAGE_MASK); if (hw_version > HW_VERSION_10) { off = (unsigned long)dst & (~PAGE_MASK); acl.link_addr |= off; } build_tables(tmp, (unsigned long)dst, dst_size, TABLE_DST); set_up_addr(&acl, virt_to_phys(tmp), ADDR_DST); acl.dst_scatter = 1; #if CONFIG_AMFC_TEST if (table_test_mask) tmp[2] = 0; #endif if (log_en) printf("%s, table_size:%d, dst_table:%p, tmp:%p\n", __func__, table_size, dst_table, tmp); } else { set_up_addr(&acl, virt_to_phys(dst), ADDR_DST); } acl.algorithm = ALGORITHM_ZSTD; acl.end = 1; acl.compress = CMD_COMPRESS; acl.owner = 1; acl.status = 0xffffffff; flush_dcache_range((unsigned long)src, (unsigned long)src + src_size); flush_dcache_range((unsigned long)&acl, (unsigned long)&acl + sizeof(acl)); invalidate_dcache_range((unsigned long)dst, (unsigned long)dst + dst_size); /* SW reset */ writel(0x80000000, AMFC_GL_CMD0_CONTROL); writel(0x03, AMFC_GL_CMD0_IRQCLR); writel((unsigned long)&acl >> ADDR_SHIFT, AMFC_GL_CMD0_DESC_BASE0_ADDR); /* trigger */ writel(1, AMFC_GL_CMD0_CONTROL); cmd_time = get_time(); // wait for done or error while (1) { status = readl(AMFC_GL_CMD0_STATUS); if ((status & AMFC_IRQ_MASK)) break; if (get_time() - cmd_time > timeout) { printf("time out\n"); break; } } cmd_time = get_time() - cmd_time; invalidate_dcache_range((unsigned long)dst, (unsigned long)dst + dst_size); invalidate_dcache_range((unsigned long)&acl, (unsigned long)&acl + sizeof(acl)); status = readl(AMFC_GL_CMD0_STATUS); if (!(status & AMFC_ERROR_MASK)) { #if CONFIG_AMFC_TEST total_hw_compress_time += readl(AMFC_CMD0_TIME_MEASURE); #endif writel(0x01, AMFC_GL_CMD0_IRQCLR); if (log_en) printf("compress done:%x %x, size:%d, cycles:%d, time:%d us\n", acl.status, status, acl.result_size, readl(AMFC_CMD0_TIME_MEASURE), cmd_time); ret = acl.result_size; } else { printf("compress failed:%x %x, time:%d us, acl:%p, src:%p, dst:%p, src_size:%ld, dst_size:%ld, timeout:%d\n", acl.status, readl(AMFC_GL_CMD0_STATUS), readl(AMFC_CMD0_TIME_MEASURE), &acl, src, dst, src_size, dst_size, timeout); dump_addr((void *)AMFC_GL_VERSION, 300); dump_addr((void *)&acl, 32); dump_addr((void *)src, 32); dump_addr((void *)dst, 32); writel(0x03, AMFC_GL_CMD0_IRQCLR); ret = -EINVAL; } return ret; #else return -ENODEV; #endif } #if CONFIG_AMFC_TEST #define EROFS_MAX_SIZE (PAGE_SIZE * 64) struct pack_file { char *name; int type; unsigned int size; unsigned int offset; }; /* * one raw file and different compressed args files */ struct pack_file test_files[] = { {"compress/521-new-log-2023-08-18_10_53_51.log", 0, 10858121, 0}, {"amfc_4m4k_level1/compress/521-new-log-2023-08-18_10_53_51.log.zsd", 1, 1076412, 10858496}, {"amfc_4m4k_level3/compress/521-new-log-2023-08-18_10_53_51.log.zsd", 1, 1212912, 11935744}, {"amfc_4m4k_level22/compress/521-new-log-2023-08-18_10_53_51.log.zsd", 1, 704301, 13152256}, {"amfc_4m128k_level1/compress/521-new-log-2023-08-18_10_53_51.log.zsd", 1, 926383, 13856768}, {"amfc_4m128k_level3/compress/521-new-log-2023-08-18_10_53_51.log.zsd", 1, 1057632, 14786560}, {"amfc_4m128k_level22/compress/521-new-log-2023-08-18_10_53_51.log.zsd", 1, 610781, 15847424}, {"compress/android_r_anon.bin", 0, 16777216, 16461824}, {"amfc_4m4k_level1/compress/android_r_anon.bin.zsd", 1, 4557912, 33243136}, {"amfc_4m4k_level3/compress/android_r_anon.bin.zsd", 1, 4353752, 37801984}, {"amfc_4m4k_level22/compress/android_r_anon.bin.zsd", 1, 3796876, 42156032}, {"amfc_4m128k_level1/compress/android_r_anon.bin.zsd", 1, 4800941, 45953024}, {"amfc_4m128k_level3/compress/android_r_anon.bin.zsd", 1, 4510906, 50757632}, {"amfc_4m128k_level22/compress/android_r_anon.bin.zsd", 1, 3784060, 55271424}, {"compress/DroidLogicTvInput.apk", 0, 10823186, 59056128}, {"amfc_4m4k_level1/compress/DroidLogicTvInput.apk.zsd", 1, 5880370, 69881856}, {"amfc_4m4k_level3/compress/DroidLogicTvInput.apk.zsd", 1, 5659473, 75763712}, {"amfc_4m4k_level22/compress/DroidLogicTvInput.apk.zsd", 1, 5260621, 81424384}, {"amfc_4m128k_level1/compress/DroidLogicTvInput.apk.zsd", 1, 5932553, 86687744}, {"amfc_4m128k_level3/compress/DroidLogicTvInput.apk.zsd", 1, 5698327, 92622848}, {"amfc_4m128k_level22/compress/DroidLogicTvInput.apk.zsd", 1, 5145713, 98324480}, {"compress/droidlogic-tv.jar", 0, 477934, 103473152}, {"amfc_4m4k_level1/compress/droidlogic-tv.jar.zsd", 1, 194111, 103952384}, {"amfc_4m4k_level3/compress/droidlogic-tv.jar.zsd", 1, 184103, 104148992}, {"amfc_4m4k_level22/compress/droidlogic-tv.jar.zsd", 1, 158674, 104333312}, {"amfc_4m128k_level1/compress/droidlogic-tv.jar.zsd", 1, 202254, 104493056}, {"amfc_4m128k_level3/compress/droidlogic-tv.jar.zsd", 1, 189089, 104697856}, {"amfc_4m128k_level22/compress/droidlogic-tv.jar.zsd", 1, 155530, 104890368}, {"compress/framework-res.apk", 0, 49495950, 105046016}, {"amfc_4m4k_level1/compress/framework-res.apk.zsd", 1, 16369915, 154542080}, {"amfc_4m4k_level3/compress/framework-res.apk.zsd", 1, 16087772, 170913792}, {"amfc_4m4k_level22/compress/framework-res.apk.zsd", 1, 15306909, 187002880}, {"amfc_4m128k_level1/compress/framework-res.apk.zsd", 1, 16283236, 202313728}, {"amfc_4m128k_level3/compress/framework-res.apk.zsd", 1, 15961873, 218599424}, {"amfc_4m128k_level22/compress/framework-res.apk.zsd", 1, 15155446, 234561536}, {"compress/Image_1", 0, 22347776, 249720832}, {"amfc_4m4k_level1/compress/Image_1.zsd", 1, 10684238, 272072704}, {"amfc_4m4k_level3/compress/Image_1.zsd", 1, 9889053, 282759168}, {"amfc_4m4k_level22/compress/Image_1.zsd", 1, 8067883, 292651008}, {"amfc_4m128k_level1/compress/Image_1.zsd", 1, 10509407, 300720128}, {"amfc_4m128k_level3/compress/Image_1.zsd", 1, 9685857, 311230464}, {"amfc_4m128k_level22/compress/Image_1.zsd", 1, 7817946, 320917504}, {"compress/NotoColorEmoji.ttf", 0, 2961984, 328736768}, {"amfc_4m4k_level1/compress/NotoColorEmoji.ttf.zsd", 1, 1794329, 331702272}, {"amfc_4m4k_level3/compress/NotoColorEmoji.ttf.zsd", 1, 1721225, 333500416}, {"amfc_4m4k_level22/compress/NotoColorEmoji.ttf.zsd", 1, 1542996, 335224832}, {"amfc_4m128k_level1/compress/NotoColorEmoji.ttf.zsd", 1, 1811509, 336769024}, {"amfc_4m128k_level3/compress/NotoColorEmoji.ttf.zsd", 1, 1723016, 338583552}, {"amfc_4m128k_level22/compress/NotoColorEmoji.ttf.zsd", 1, 1498439, 340307968}, {"compress/uImage", 0, 11194624, 341807104}, {"amfc_4m4k_level1/compress/uImage.zsd", 1, 11166211, 353005568}, {"amfc_4m4k_level3/compress/uImage.zsd", 1, 11163633, 364175360}, {"amfc_4m4k_level22/compress/uImage.zsd", 1, 11156644, 375341056}, {"amfc_4m128k_level1/compress/uImage.zsd", 1, 11170371, 386498560}, {"amfc_4m128k_level3/compress/uImage.zsd", 1, 11167452, 397672448}, {"amfc_4m128k_level22/compress/uImage.zsd", 1, 11149718, 408842240}, {"compress/zero.bin", 0, 2097152, 419995648}, {"amfc_4m4k_level1/compress/zero.bin.zsd", 1, 2070, 422096896}, {"amfc_4m4k_level3/compress/zero.bin.zsd", 1, 2069, 422100992}, {"amfc_4m4k_level22/compress/zero.bin.zsd", 1, 2068, 422105088}, {"amfc_4m128k_level1/compress/zero.bin.zsd", 1, 87, 422109184}, {"amfc_4m128k_level3/compress/zero.bin.zsd", 1, 86, 422113280}, {"amfc_4m128k_level22/compress/zero.bin.zsd", 1, 85, 422117376}, {} }; /* * pack file test for performance and data consistent. * test file and above array are generated by scripts * You need preload packed test file to a ddr address and then * use command like: * * s7_pxp# amfc pack_test 12000000 30000000 34000000 * * dst address must not overlap with base + file_size * dst2 address must not overlap with dst 1 */ static void amfc_pack_test(unsigned long base, void *dst, void *dst2) { int i, ret; struct pack_file *pack; void *src, *cur_src_addr = NULL; int cur_src_size = 0; for (i = 0; i < ARRAY_SIZE(test_files); i++) { pack = &test_files[i]; if (!pack->name) break; src = (void *)(base + pack->offset); if (!pack->type) { /* * check hw compress and hw decompress */ printf("-----------------------------\n"); printf("compress %s\n", pack->name); ret = amfc_compress(src, dst, pack->size, pack->size); cur_src_size = pack->size; cur_src_addr = src; if (ret > 0) { printf("decompress %s\n", pack->name); ret = amfc_decompress(dst, dst2, ret, pack->size, 0); ret = memcmp(dst2, src, pack->size); printf("compare %p -> %p with %d %s\n\n", dst2, cur_src_addr, cur_src_size, ret ? "FAIL!!" : "OK!!"); } else { printf("compress failed\n"); } } else { /* * check sw compressed and hw decompress */ printf("decompress %s\n", pack->name); ret = amfc_decompress(src, dst, pack->size, cur_src_size, 0); ret = memcmp(dst, cur_src_addr, cur_src_size); printf("compare %p -> %p with %d %s\n\n", dst, cur_src_addr, cur_src_size, ret ? "FAIL!!" : "OK!!"); } if (tstc()) { printf("key abort\n"); (void)getchar(); break; } } } static unsigned char test_page[EROFS_MAX_SIZE * 2] __attribute__((aligned(4096))); static int get_sw_compressed_size(void *src) { int i = 0; unsigned char *p; p = (unsigned char *)src + PAGE_SIZE - 1; while (*p == 0) { i++; p--; } return i > PAGE_SIZE ? 0 : PAGE_SIZE - i; } static void *contain_zstd_page(void *src, int cluster) { unsigned char *p = (unsigned char *)src; int i = 0; /* skip leading zero */ while ((i < cluster) && (p[i] == 0)) { i++; } if (i >= cluster) return NULL; p += i; if (p[0] == 0x28 && p[1] == 0xb5 && p[2] == 0x2f && p[3] == 0xfd) { return p; } else return NULL; } static int memcmp1(void *p1, void *p2, int size) { unsigned int *i1, *i2; int i; int ret = 0; i1 = (unsigned int *)p1; i2 = (unsigned int *)p2; for (i = 0; i < size / 4; i++) { if (i1[i] != i2[i]) { printf("i:%d, addr:%p->%p, value:%x->%x\n", i, i1, i2, i1[i], i2[i]); ret = 1; } } return ret; } /* * data is captured from Android system by * https://scgit.amlogic.com/#/c/329847/ * pattern: a raw page + a zstd compressed page interleave * * before test, you should change a captured data to hex and pre-load it * to DDR via load_mem.tcl in PXP */ static void amfc_zram_test(void *src, unsigned long size, int cmp) { unsigned long i; unsigned char *p, *z; int sw_csize, hw_csize; int no_compress = 0; int sw_decompress = 0; int hw_compress = 0; int hw_decompress = 0; int sd_error = 0; total_sw_compressed_size = 0; total_hw_compressed_size = 0; total_hw_compress_time = 0; total_hw_decompress_time = 0; total_hw_self_decompress_time = 0; for (i = 0; i < size; i += PAGE_SIZE) { p = (unsigned char *)(src + i); if (self) { // sw compressed page self = 0; z = contain_zstd_page(p, PAGE_SIZE); if (z) { sw_csize = PAGE_SIZE - (z - p); total_sw_compressed_size += sw_csize; amfc_decompress(z, test_page, sw_csize, PAGE_SIZE, 0); sw_decompress++; if (cmp && memcmp(test_page, (void *)((unsigned long)p - PAGE_SIZE), PAGE_SIZE)) { printf("hw decompress address :%p not match\n", p); } } } else { // src page self = 1; memset(test_page, 0, sizeof(test_page)); hw_csize = amfc_compress(p, test_page, PAGE_SIZE, PAGE_SIZE); hw_compress++; if (hw_csize > 0) { total_hw_compressed_size += hw_csize; amfc_decompress(test_page, test_page + PAGE_SIZE, hw_csize, PAGE_SIZE, 0); hw_decompress++; if (cmp && memcmp1(test_page + PAGE_SIZE, (void *)p, PAGE_SIZE)) { char cmd[128] = {0}; printf("hw self-decompress address :%p, size:%d not match\n", p, hw_csize); sprintf(cmd, "md %lx %x\n", (unsigned long)test_page, hw_csize / 4 + 10); run_command(cmd, 0); sd_error++; } } else { no_compress++; printf("hw compress address :%p failed\n", p); } } if (!(i & 0x3f000)) { printf("ADDR:%lx, sw_csize:%8ld, hw_csize:%8ld, hw_ctime:%8ld us, hw_dtime:%8ld, hw_sdtime:%8ld, no_comp:%4d, sw_dec_page:%5d, hw_dec_page:%5d, hw_com_page:%5d, sd_error:%d\n", (unsigned long)p, total_sw_compressed_size, total_hw_compressed_size, total_hw_compress_time, total_hw_decompress_time, total_hw_self_decompress_time, no_compress, sw_decompress, hw_decompress, hw_compress, sd_error); } if (tstc()) { printf("key abort\n"); (void)getchar(); break; } } printf("ADDR:%lx, sw_csize:%8ld, hw_csize:%8ld, hw_ctime:%8ld us, hw_dtime:%8ld, hw_sdtime:%8ld, no_comp:%4d, sw_dec_page:%5d, hw_dec_page:%5d, hw_com_page:%5d, sd_error:%d\n", (unsigned long)p, total_sw_compressed_size, total_hw_compressed_size, total_hw_compress_time, total_hw_decompress_time, total_hw_self_decompress_time, no_compress, sw_decompress, hw_decompress, hw_compress, sd_error); } static void *get_zstd_addr(void *src, int cluster, int *c_size) { unsigned char *p = (unsigned char *)src; int i = 0; unsigned long addr, remain; /* skip leading zero */ while ((i < cluster) && (p[i] == 0)) { i++; } if (i >= cluster) return NULL; p += i; if (p[0] == 0x28 && p[1] == 0xb5 && p[2] == 0x2f && p[3] == 0xfd) { if (cluster > PAGE_SIZE) { /* search next zstd page in this cluster to detect real size */ remain = cluster - i; remain &= PAGE_MASK; addr = ((unsigned long)p + PAGE_SIZE) & PAGE_MASK; while (remain) { if (contain_zstd_page((void *)addr, PAGE_SIZE)) { //printf("have zstd page addr:%lx, p:%p, i:%d, remain:%ld, cluster:%d\n", // addr, p, i, remain, cluster); break; } addr += PAGE_SIZE; remain -= PAGE_SIZE; } *c_size = addr - (unsigned long)p; //printf("addr:%lx, p:%p, i:%d, remain:%ld, cluster:%d, real size:%d\n", // addr, p, i, remain, cluster, *c_size); } else *c_size = cluster - i; return p; } else return NULL; } /* * Refer https://confluence.amlogic.com/display/SW/EROFS+with+ZSTD+and+performance+compare to * build a ZSTD supported erofs image * * before test, you should change a erofs image to hex and pre-load it * to DDR via load_mem.tcl in PXP */ static void amfc_erofs_test(void *src, unsigned long size, int pcluster, int verify) { unsigned long i, total_decompress, total_sw_csize; unsigned char *p; int hw_decompress = 0, ret, c_size; struct abuf in, out; int decompress_fail = 0; int match_fail = 0; total_decompress = 0; total_sw_csize = 0; total_hw_decompress_time = 0; self = 0; for (i = 0; i < size; i += PAGE_SIZE) { p = get_zstd_addr(src + i, pcluster, &c_size); //if (c_size < 64) { // // HW BUG: // //1, source address must align to 64 bytes, if src size is tool small, decode will hung // //2, if size set to 4k but too many leading zero, decode will hung // //3, for erofs test, page table mode must closed. // printf("skip size too small:%lx, c_size:%d\n", (unsigned long)src + i, c_size); // continue; //} if (p) { // zstd compressed page hw_decompress = amfc_decompress(p, test_page, c_size, EROFS_MAX_SIZE, 0); if (hw_decompress) { /* sw_decompress and double check */ total_decompress += hw_decompress; total_sw_csize += c_size; if (verify) { abuf_init_set(&in, p, c_size); abuf_init_set(&out, test_page + EROFS_MAX_SIZE, EROFS_MAX_SIZE); ret = zstd_decompress(&in, &out); if (ret >= 0 && ret == hw_decompress) { if (memcmp(test_page, test_page + EROFS_MAX_SIZE, ret)) { match_fail++; printf("hw decompress %p %d->%d not match\n", p, c_size, ret); } } else { printf("sw decompress %p %d %d <-> %d failed\n", p, c_size, hw_decompress, ret); } } } else { decompress_fail++; } } if (!(i & 0x3f000)) { printf("ADDR:%lx, hw_decompressed:%8ld, time:%8ld, dec failed:%4d, match failed:%4d, sw_csize:%ld\n", (unsigned long)src + i, total_decompress, total_hw_decompress_time, decompress_fail, match_fail, total_sw_csize); } if (tstc()) { printf("key abort\n"); (void)getchar(); break; } } printf("ADDR:%lx, hw_decompressed:%8ld, time:%8ld, dec failed:%4d, match failed:%4d, sw_csize:%ld\n", (unsigned long)src + i, total_decompress, total_hw_decompress_time, decompress_fail, match_fail, total_sw_csize); } static void show_acl(struct amfc_cmd_list *p_acl, int count) { int i; for (i = 0; i < count; i++) { printf("%p: %08x %08x %08x %08x %08x %08x %08x %08x\n", p_acl + i, p_acl[i].src_addr, p_acl[i].dst_addr, p_acl[i].link_addr, p_acl[i].src_size, p_acl[i].dst_size, p_acl[i].control, p_acl[i].status, p_acl[i].result_size); } } static void run_table_test(struct amfc_cmd_list *p_acl, void *src, void *dst, void *dst2, long size) { unsigned int status; int count; count = ALIGN(size, PAGE_SIZE) / PAGE_SIZE; flush_dcache_range((unsigned long)src, (unsigned long)src + size); flush_dcache_range((unsigned long)dst, (unsigned long)dst + size); flush_dcache_range((unsigned long)dst2, (unsigned long)dst2 + size); flush_dcache_range((unsigned long)p_acl, (unsigned long)p_acl + (count + 3) * sizeof(acl)); /* SW reset */ writel(0x80000000, AMFC_GL_CMD0_CONTROL); writel(0x03, AMFC_GL_CMD0_IRQCLR); writel((unsigned long)p_acl >> ADDR_SHIFT, AMFC_GL_CMD0_DESC_BASE0_ADDR); /* trigger */ writel(1, AMFC_GL_CMD0_CONTROL); // wait for done or error while (1) { status = readl(AMFC_GL_CMD0_STATUS); if ((status & AMFC_IRQ_MASK)) break; if (tstc()) { printf("key abort\n"); (void)getchar(); break; } } status = readl(AMFC_GL_CMD0_STATUS); if (!(status & AMFC_ERROR_MASK)) { writel(0x01, AMFC_GL_CMD0_IRQCLR); } else { writel(0x03, AMFC_GL_CMD0_IRQCLR); printf("test failed:%x %x\n", p_acl[0].status, readl(AMFC_GL_CMD0_STATUS)); } } /* * before test, you should change a simple text file(size > 16KB) to hex and pre-load it * to DDR via load_mem.tcl in PXP */ static void amfc_table_test(void *src, void *dst, void *dst2, unsigned long size) { struct amfc_cmd_list *p_acl, *p_raw; int count, i; count = ALIGN(size, PAGE_SIZE) / PAGE_SIZE; p_acl = malloc((count + 3) * sizeof(acl)); if (!p_acl) return; memset(dst, 0, size); p_raw = p_acl; memset(p_acl, 0, (count + 3) * sizeof(acl)); if ((unsigned long)p_acl & 0x3f) // not aligned to 64 bytes p_acl = (struct amfc_cmd_list *)(((unsigned long)p_acl + 0x40) & ~0x3f); printf("acl:%p, src:%p, dst:%p, dst2:%p, size:%ld\n", p_acl, src, dst, dst2, size); // case 1: compress src to dst by table mode for (i = 0; i < count; i++) { p_acl[i].src_addr = ((unsigned long)src + PAGE_SIZE * i); p_acl[i].dst_addr = ((unsigned long)dst + PAGE_SIZE * i); p_acl[i].link_addr = 0; p_acl[i].src_size = PAGE_SIZE; p_acl[i].dst_size = PAGE_SIZE; p_acl[i].status = 0xffffffff; p_acl[i].result_size = 0; p_acl[i].control = 0; p_acl[i].algorithm = ALGORITHM_ZSTD; p_acl[i].compress = CMD_COMPRESS; p_acl[i].owner = 1; } printf("table test case 1: compress with no end bit\n"); run_table_test(p_acl, src, dst, dst2, size); show_acl(p_acl, count); // case 2: decompress dst to dst2 by table mode for (i = 0; i < count; i++) { p_acl[i].src_addr = ((unsigned long)dst + PAGE_SIZE * i); p_acl[i].dst_addr = ((unsigned long)dst2 + PAGE_SIZE * i); p_acl[i].link_addr = 0; p_acl[i].src_size = get_sw_compressed_size(dst + PAGE_SIZE * i); p_acl[i].dst_size = PAGE_SIZE; p_acl[i].status = 0xffffffff; p_acl[i].result_size = 0; p_acl[i].control = 0; p_acl[i].algorithm = ALGORITHM_ZSTD; p_acl[i].compress = CMD_DECOMPRESS; p_acl[i].owner = 1; } p_acl[i - 1].end = 1; printf("table test case 2: decompress with end bit\n"); run_table_test(p_acl, src, dst, dst2, size); show_acl(p_acl, count); // case 3: decompress and compress interleave mode for (i = 0; i < count; i++) { if (i & 0x01) { p_acl[i].src_addr = ((unsigned long)dst + PAGE_SIZE * i); p_acl[i].dst_addr = ((unsigned long)dst2 + PAGE_SIZE * i); p_acl[i].link_addr = 0; p_acl[i].src_size = get_sw_compressed_size(dst + PAGE_SIZE * i); p_acl[i].dst_size = PAGE_SIZE; p_acl[i].status = 0xffffffff; p_acl[i].result_size = 0; p_acl[i].control = 0; p_acl[i].algorithm = ALGORITHM_ZSTD; p_acl[i].compress = CMD_DECOMPRESS; p_acl[i].owner = 1; } else { p_acl[i].src_addr = ((unsigned long)src + PAGE_SIZE * i); p_acl[i].dst_addr = ((unsigned long)dst + PAGE_SIZE * i); p_acl[i].link_addr = 0; p_acl[i].src_size = PAGE_SIZE; p_acl[i].dst_size = PAGE_SIZE; p_acl[i].status = 0xffffffff; p_acl[i].result_size = 0; p_acl[i].control = 0; p_acl[i].algorithm = ALGORITHM_ZSTD; p_acl[i].compress = CMD_COMPRESS; p_acl[i].owner = 1; } } p_acl[i - 1].end = 1; printf("table test case 3: enc/dec interleave table mode\n"); run_table_test(p_acl, src, dst, dst2, size); show_acl(p_acl, count); // case 4: bad table with no owner bit set for (i = 0; i < count; i++) { p_acl[i].src_addr = ((unsigned long)dst + PAGE_SIZE * i); p_acl[i].dst_addr = ((unsigned long)dst2 + PAGE_SIZE * i); p_acl[i].link_addr = 0; p_acl[i].src_size = get_sw_compressed_size(dst + PAGE_SIZE * i); p_acl[i].dst_size = PAGE_SIZE; p_acl[i].status = 0xffffffff; p_acl[i].result_size = 0; p_acl[i].control = 0; p_acl[i].algorithm = ALGORITHM_ZSTD; p_acl[i].compress = CMD_DECOMPRESS; if (i != 1) p_acl[i].owner = 1; } p_acl[i - 1].end = 1; printf("table test case 4: descriptor error with no owner\n"); run_table_test(p_acl, src, dst, dst2, size); show_acl(p_acl, count); // case 5: bad table with no wrong algorithm for (i = 0; i < count; i++) { p_acl[i].src_addr = ((unsigned long)dst + PAGE_SIZE * i); p_acl[i].dst_addr = ((unsigned long)dst2 + PAGE_SIZE * i); p_acl[i].link_addr = 0; p_acl[i].src_size = get_sw_compressed_size(dst + PAGE_SIZE * i); p_acl[i].dst_size = PAGE_SIZE; p_acl[i].status = 0xffffffff; p_acl[i].result_size = 0; p_acl[i].control = 0; if (i == 1) p_acl[i].algorithm = ALGORITHM_LZ4HC; else p_acl[i].algorithm = ALGORITHM_ZSTD; p_acl[i].compress = CMD_DECOMPRESS; p_acl[i].owner = 1; } p_acl[i - 1].end = 1; printf("table test case 5: descriptor error with wrong algorithm\n"); run_table_test(p_acl, src, dst, dst2, size); show_acl(p_acl, count); // case 6: bad table with zero src size for (i = 0; i < count; i++) { p_acl[i].src_addr = ((unsigned long)dst + PAGE_SIZE * i); p_acl[i].dst_addr = ((unsigned long)dst2 + PAGE_SIZE * i); p_acl[i].link_addr = 0; if (i != 1) p_acl[i].src_size = get_sw_compressed_size(dst + PAGE_SIZE * i); else p_acl[i].src_size = 0; p_acl[i].dst_size = PAGE_SIZE; p_acl[i].status = 0xffffffff; p_acl[i].result_size = 0; p_acl[i].control = 0; p_acl[i].algorithm = ALGORITHM_ZSTD; p_acl[i].compress = CMD_DECOMPRESS; p_acl[i].owner = 1; } p_acl[i - 1].end = 1; printf("table test case 6: descriptor error with zero source size\n"); run_table_test(p_acl, src, dst, dst2, size); show_acl(p_acl, count); // case 7: bad table with zero dst size for (i = 0; i < count; i++) { p_acl[i].src_addr = ((unsigned long)dst + PAGE_SIZE * i); p_acl[i].dst_addr = ((unsigned long)dst2 + PAGE_SIZE * i); p_acl[i].link_addr = 0; p_acl[i].src_size = get_sw_compressed_size(dst + PAGE_SIZE * i); if (i != 1) p_acl[i].dst_size = PAGE_SIZE; else p_acl[i].dst_size = 0; p_acl[i].status = 0xffffffff; p_acl[i].result_size = 0; p_acl[i].control = 0; p_acl[i].algorithm = ALGORITHM_ZSTD; p_acl[i].compress = CMD_DECOMPRESS; p_acl[i].owner = 1; } p_acl[i - 1].end = 1; printf("table test case 7: descriptor error with zero dst size\n"); run_table_test(p_acl, src, dst, dst2, size); show_acl(p_acl, count); // case 8: bad table with zero link address for (i = 0; i < count; i++) { p_acl[i].src_addr = ((unsigned long)dst + PAGE_SIZE * i); p_acl[i].dst_addr = ((unsigned long)dst2 + PAGE_SIZE * i); p_acl[i].link_addr = 0; p_acl[i].src_size = get_sw_compressed_size(dst + PAGE_SIZE * i); p_acl[i].dst_size = PAGE_SIZE; p_acl[i].status = 0xffffffff; p_acl[i].result_size = 0; p_acl[i].control = 0; p_acl[i].algorithm = ALGORITHM_ZSTD; p_acl[i].compress = CMD_DECOMPRESS; if (i == 1) p_acl[i].link_mode = 1; p_acl[i].owner = 1; } p_acl[i - 1].end = 1; printf("table test case 8: descriptor error with zero link address\n"); run_table_test(p_acl, src, dst, dst2, size); show_acl(p_acl, count); // case 9: bad table with dst size over flow for (i = 0; i < count; i++) { p_acl[i].src_addr = ((unsigned long)dst + PAGE_SIZE * i); p_acl[i].dst_addr = ((unsigned long)dst2 + PAGE_SIZE * i); p_acl[i].link_addr = 0; p_acl[i].src_size = get_sw_compressed_size(dst + PAGE_SIZE * i); if (i != 1) p_acl[i].dst_size = PAGE_SIZE; else p_acl[i].dst_size = 10; p_acl[i].status = 0xffffffff; p_acl[i].result_size = 0; p_acl[i].control = 0; p_acl[i].algorithm = ALGORITHM_ZSTD; p_acl[i].compress = CMD_DECOMPRESS; p_acl[i].owner = 1; } p_acl[i - 1].end = 1; printf("table test case 9: descriptor error with dst size overflow\n"); run_table_test(p_acl, src, dst, dst2, size); show_acl(p_acl, count); // case 10: bad table with decompress src size too small for (i = 0; i < count; i++) { p_acl[i].src_addr = ((unsigned long)dst + PAGE_SIZE * i); p_acl[i].dst_addr = ((unsigned long)dst2 + PAGE_SIZE * i); p_acl[i].link_addr = 0; if (i == 1) p_acl[i].src_size = 10; else p_acl[i].src_size = get_sw_compressed_size(dst + PAGE_SIZE * i); p_acl[i].dst_size = PAGE_SIZE; p_acl[i].status = 0xffffffff; p_acl[i].result_size = 0; p_acl[i].control = 0; p_acl[i].algorithm = ALGORITHM_ZSTD; p_acl[i].compress = CMD_DECOMPRESS; p_acl[i].owner = 1; } p_acl[i - 1].end = 1; printf("table test case 10: descriptor error with decompress size too small\n"); run_table_test(p_acl, src, dst, dst2, size); show_acl(p_acl, count); // case 11: bad table with compress size too small for (i = 0; i < count; i++) { p_acl[i].src_addr = ((unsigned long)src + PAGE_SIZE * i); p_acl[i].dst_addr = ((unsigned long)dst + PAGE_SIZE * i); p_acl[i].link_addr = 0; if (i == 1) p_acl[i].src_size = 2; else p_acl[i].src_size = PAGE_SIZE; p_acl[i].dst_size = PAGE_SIZE; p_acl[i].status = 0xffffffff; p_acl[i].result_size = 0; p_acl[i].control = 0; p_acl[i].algorithm = ALGORITHM_ZSTD; p_acl[i].compress = CMD_COMPRESS; p_acl[i].owner = 1; } p_acl[i - 1].end = 1; printf("table test case 11: bad table with compress size too small\n"); run_table_test(p_acl, src, dst, dst2, size); show_acl(p_acl, count); free(p_raw); } /* * before test, you should change a simple text file(size > 64KB) to hex and pre-load it * to DDR via load_mem.tcl in PXP */ static void amfc_link_test(void *src, void *dst, void *dst2, unsigned long size) { struct amfc_cmd_list *p_acl, *p_raw; int count, i; count = ALIGN(size, PAGE_SIZE) / PAGE_SIZE; p_acl = malloc((count + 3) * sizeof(acl)); if (!p_acl) return; memset(dst, 0, size); p_raw = p_acl; memset(p_acl, 0, (count + 3) * sizeof(acl)); if ((unsigned long)p_acl & 0x3f) // not aligned to 64 bytes p_acl = (struct amfc_cmd_list *)(((unsigned long)p_acl + 0x40) & ~0x3f); printf("acl:%p, src:%p, dst:%p, dst2:%p, size:%ld\n", p_acl, src, dst, dst2, size); // case 1: compress src to dst by link mode for (i = 0; i < count; i += 2) { p_acl[i].src_addr = ((unsigned long)src + PAGE_SIZE * i); p_acl[i].dst_addr = ((unsigned long)dst + PAGE_SIZE * i); p_acl[i].link_addr = ((unsigned long)&p_acl[i + 2]) >> ADDR_SHIFT; p_acl[i].src_size = PAGE_SIZE; p_acl[i].dst_size = PAGE_SIZE; p_acl[i].status = 0xffffffff; p_acl[i].result_size = 0; p_acl[i].link_mode = 1; p_acl[i].algorithm = ALGORITHM_ZSTD; p_acl[i].compress = CMD_COMPRESS; p_acl[i].owner = 1; } printf("link test case 1: compress with NULL link end\n"); run_table_test(p_acl, src, dst, dst2, size); show_acl(p_acl, count + 3); // case 2: decompress dst to dst2 by table mode memset(p_acl, 0, (count + 2 ) * sizeof(*p_acl)); for (i = 0; i < count; i += 2) { p_acl[i].src_addr = ((unsigned long)dst + PAGE_SIZE * i); p_acl[i].dst_addr = ((unsigned long)dst2 + PAGE_SIZE * i); p_acl[i].link_addr = ((unsigned long)&p_acl[i + 2]) >> ADDR_SHIFT; p_acl[i].src_size = get_sw_compressed_size(dst + PAGE_SIZE * i); p_acl[i].dst_size = PAGE_SIZE; p_acl[i].status = 0xffffffff; p_acl[i].result_size = 0; p_acl[i].link_mode = 1; p_acl[i].algorithm = ALGORITHM_ZSTD; p_acl[i].compress = CMD_DECOMPRESS; p_acl[i].owner = 1; } p_acl[i - 2].end = 1; // end but build a valid link next descriptor p_acl[i].src_addr = ((unsigned long)dst + PAGE_SIZE * i); p_acl[i].dst_addr = ((unsigned long)dst2 + PAGE_SIZE * i); p_acl[i].link_addr = 0; p_acl[i].src_size = get_sw_compressed_size(dst + PAGE_SIZE * i); p_acl[i].dst_size = PAGE_SIZE; p_acl[i].status = 0xffffffff; p_acl[i].result_size = 0; p_acl[i].link_mode = 0; p_acl[i].algorithm = ALGORITHM_ZSTD; p_acl[i].compress = CMD_DECOMPRESS; p_acl[i].owner = 1; p_acl[i].end = 1; // end printf("link test case 2: decompress with end bit but have a valid link descriptor\n"); run_table_test(p_acl, src, dst, dst2, size); show_acl(p_acl, count + 3); // case 3: decompress and compress interleave link mode memset(p_acl, 0, (count + 2 ) * sizeof(*p_acl)); for (i = 0; i < count; i += 2) { if (i & 0x02) { p_acl[i].src_addr = ((unsigned long)dst + PAGE_SIZE * i); p_acl[i].dst_addr = ((unsigned long)dst2 + PAGE_SIZE * i); p_acl[i].link_addr = ((unsigned long)&p_acl[i + 2]) >> ADDR_SHIFT; p_acl[i].src_size = get_sw_compressed_size(dst + PAGE_SIZE * i); p_acl[i].dst_size = PAGE_SIZE; p_acl[i].status = 0xffffffff; p_acl[i].result_size = 0; p_acl[i].link_mode = 1; p_acl[i].algorithm = ALGORITHM_ZSTD; p_acl[i].compress = CMD_DECOMPRESS; p_acl[i].owner = 1; } else { p_acl[i].src_addr = ((unsigned long)src + PAGE_SIZE * i); p_acl[i].dst_addr = ((unsigned long)dst + PAGE_SIZE * i); p_acl[i].link_addr = ((unsigned long)&p_acl[i + 2]) >> ADDR_SHIFT; p_acl[i].src_size = PAGE_SIZE; p_acl[i].dst_size = PAGE_SIZE; p_acl[i].status = 0xffffffff; p_acl[i].result_size = 0; p_acl[i].link_mode = 1; p_acl[i].algorithm = ALGORITHM_ZSTD; p_acl[i].compress = CMD_COMPRESS; p_acl[i].owner = 1; } } p_acl[i - 2].end = 1; p_acl[i - 2].link_mode = 0; printf("link test case 3: enc/dec interleave link mode\n"); run_table_test(p_acl, src, dst, dst2, size); show_acl(p_acl, count + 3); // case 4: valid link descriptor but link mode disabled memset(p_acl, 0, (count + 2 ) * sizeof(*p_acl)); for (i = 0; i < count; i++) { p_acl[i].src_addr = ((unsigned long)src + PAGE_SIZE * i); p_acl[i].dst_addr = ((unsigned long)dst + PAGE_SIZE * i); p_acl[i].src_size = PAGE_SIZE; p_acl[i].dst_size = PAGE_SIZE; if (!i) { // link to 3rd desc p_acl[i].link_addr = ((unsigned long)&p_acl[i + 2]) >> ADDR_SHIFT; } p_acl[i].status = 0xffffffff; p_acl[i].result_size = 0; p_acl[i].algorithm = ALGORITHM_ZSTD; p_acl[i].compress = CMD_COMPRESS; p_acl[i].owner = 1; } p_acl[i - 1].end = 1; printf("link test case 4: valid link descriptor but link mode disabled \n"); run_table_test(p_acl, src, dst, dst2, size); show_acl(p_acl, count + 3); // case 5: circular link memset(p_acl, 0, (count + 2 ) * sizeof(*p_acl)); for (i = 0; i < count; i += 2) { p_acl[i].src_addr = ((unsigned long)dst + PAGE_SIZE * i); p_acl[i].dst_addr = ((unsigned long)dst2 + PAGE_SIZE * i); p_acl[i].link_addr = ((unsigned long)&p_acl[i + 2]) >> ADDR_SHIFT; p_acl[i].src_size = get_sw_compressed_size(dst + PAGE_SIZE * i); p_acl[i].dst_size = PAGE_SIZE; p_acl[i].status = 0xffffffff; p_acl[i].result_size = 0; p_acl[i].link_mode = 1; p_acl[i].algorithm = ALGORITHM_ZSTD; p_acl[i].compress = CMD_DECOMPRESS; p_acl[i].owner = 1; } p_acl[i - 2].link_addr = ((unsigned long)&p_acl[0]) >> ADDR_SHIFT; printf("link test case 5: circular link\n"); run_table_test(p_acl, src, dst, dst2, size); show_acl(p_acl, count + 3); // case 6: table and link memset(p_acl, 0, (count + 2 ) * sizeof(*p_acl)); for (i = 0; i < count; i ++) { p_acl[i].src_addr = ((unsigned long)src + PAGE_SIZE * i); p_acl[i].dst_addr = ((unsigned long)dst + PAGE_SIZE * i); p_acl[i].src_size = PAGE_SIZE; p_acl[i].dst_size = PAGE_SIZE; p_acl[i].status = 0xffffffff; p_acl[i].result_size = 0; p_acl[i].algorithm = ALGORITHM_ZSTD; p_acl[i].compress = CMD_COMPRESS; p_acl[i].owner = 1; if (i == 2) { p_acl[i].link_addr = ((unsigned long)&p_acl[i + 4]) >> ADDR_SHIFT; p_acl[i].link_mode = 1; } } p_acl[i - 1].end = 1; printf("link test case 6: table and link\n"); run_table_test(p_acl, src, dst, dst2, size); show_acl(p_acl, count + 3); free(p_raw); } static int check_zero(void *start, int range) { unsigned char *p = (unsigned char *)start; int i; for (i = 0; i < range; i++) if (p[i]) return 1; return 0; } static void amfc_address_test(void *src, void *dst, void *dst2, int src_size) { int i, ret; void *p, *p1, *p2; char cmd_buf[128] = {}; // 1, compress dst not align test printf("==== compress dst and decompress src not aligned test\n"); for (i = 0; i < 64; i++) { p = (void *)(dst + i); memset(dst, 0, src_size + 128); memset(dst2, 0, src_size + 128); run_command("dcache flush", 0); ret = amfc_compress(src, p, src_size, src_size); if (ret > 0) { amfc_decompress(p, dst2, ret, src_size, 0); if (memcmp(src, dst2, src_size)) { printf("%s, src:%p, dst:%p, dst2:%p, ret:%d, src_size:%d, i:%d not match\n", __func__, src, p, dst2, ret, src_size, i); } p1 = p + ret; p2 = (void *)(((unsigned long)p1 + 64) & ~63); if (check_zero(dst, i)) { printf("left over write\n"); sprintf(cmd_buf, "md %lx 10\n", (long)dst); run_command(cmd_buf, 0); } if (check_zero(p1, p2 - p1)) { printf("right over write\n"); sprintf(cmd_buf, "md %lx 10\n", (long)p1); run_command(cmd_buf, 0); } } } // 2, compress src not aligned memset(dst, 0, src_size + 128); amfc_compress(src, dst, src_size, src_size); printf("==== compress src not aligned test\n"); for (i = 0; i < 64; i++) { p = (void *)(dst + src_size + i); memset(p, 0, src_size + 128); memset(dst2, 0, src_size + 128); memcpy(p, src, src_size); run_command("dcache flush", 0); ret = amfc_compress(p, dst2, src_size, src_size); if (ret > 0) { if (memcmp(dst, dst2, ret)) { printf("%s, dst:%p, dst2:%p, ret:%d, src_size:%d i:%d, not match\n", __func__, dst, dst2, ret, src_size, i); } } } // 3, decompress dest not aligned memset(dst, 0, src_size + 128); ret = amfc_compress(src, dst, src_size, src_size); printf("==== decompress dst not aligned test\n"); for (i = 0; i < 64; i++) { p = (void *)(dst2 + i); memset(dst2, 0, src_size + 128); run_command("dcache flush", 0); ret = amfc_decompress(dst, p, ret, src_size, 0); if (ret > 0) { if (memcmp(p, src, src_size)) { printf("%s, p:%p, src:%p, ret:%d, src_size:%d, i:%d not match\n", __func__, p, src, ret, src_size, i); } if (check_zero(dst2, i)) { printf("left over write\n"); sprintf(cmd_buf, "md %lx 10\n", (long)dst2); run_command(cmd_buf, 0); } p1 = p + src_size; p2 = (void *)(((unsigned long)p1 + 64) & ~63); if (check_zero(p1, p2 - p1)) { printf("right over write\n"); sprintf(cmd_buf, "md %lx 10\n", (long)p1); run_command(cmd_buf, 0); } } } } static void amfc_pagetable_test(void *src, void *dst, void *dst2, int size) { int i, j, ret; char *p = src; page_table_mode = 1; /* set to fixed pattern */ for (i = 0; i < size + PAGE_SIZE; i++) { p[i] = i & 0xff; } p = dst2; for (j = 0; j <= PAGE_SIZE; j++) { memset(dst, 0, size + PAGE_SIZE * 2); memset(dst2, 0, size + PAGE_SIZE * 3); flush_dcache_range((unsigned long)dst2, (unsigned long)dst2 + size + PAGE_SIZE * 3); ret = amfc_compress(src + j, dst + j, size + j, size + j); if (ret < 0) { printf("%d compress %p failed:%d\n", j, src + j, ret); return; } ret = amfc_decompress(dst + j, dst2 + j, ret, size + j, 0); if (ret < 0) { printf("%d decompress %p failed:%d\n", j, src + j, ret); return; } if (memcmp(src + j, dst2 + j, size + j)) { printf("%d compare %p %p not match\n", j, src + j, dst2 + j); return; } for (i = 0; i < j; i++) { if (p[i] || p[j + size + j]) { printf("%d mem overwrite %p %p\n", j, p + i, p + j + size + j); return; } } } printf("test pass \n"); } static void amfc_stream_mode_test(void *src, void *dst, void *dst2, int size) { int i, ret, src_size; char *p = src; page_table_mode = 1; /* set to fixed pattern */ for (i = 0; i < size + PAGE_SIZE; i++) { p[i] = i & 0xff; } p = dst2; src_size = amfc_compress(src, dst, size, size); if (src_size < 0) { printf("compress %p failed:%d\n", src, src_size); return; } for (i = 1; i < size; i++) { memset(dst2, 0, size + PAGE_SIZE * 3); flush_dcache_range((unsigned long)dst2, (unsigned long)dst2 + size + PAGE_SIZE * 3); ret = amfc_decompress(dst, dst2, src_size, i, 1); if (ret < -1) { printf("%d decompress %p failed:%d\n", i, src, ret); return; } if (memcmp(src, dst2, i)) { printf("%d compare %p %p not match\n", i, src, dst2); return; } if (p[i]) { printf("%d mem overwrite %p\n", i, p + i); return; } } printf("test pass \n"); } static void amfc_reset_test(unsigned long cnt) { char *p_enc_src, *p_enc_dst, *p_dec_src, *p_dec_dst; int enc_src_size, enc_dst_size, dec_src_size, dec_dst_size; int i = 0; int cmd_time; int timeout, old_log; unsigned int status, delay; unsigned long enc_time, dec_time; int fail0 = 0, fail1 = 0; old_log = log_en; p_enc_src = (char *)0x01000000; p_enc_dst = (char *)0x02000000; p_dec_src = (char *)0x03000000; p_dec_dst = (char *)0x04000000; enc_src_size = dec_dst_size = enc_dst_size = 0x01000000; timeout = ((enc_src_size + PAGE_SIZE) / PAGE_SIZE) * 100 + 5000; for (i = 0; i < p_enc_dst - p_enc_src; i++) { p_enc_src[i] = i & 0xff; } log_en = 0; enc_time = get_time(); dec_src_size = amfc_compress(p_enc_src, p_dec_src, enc_src_size, enc_dst_size); enc_time = get_time() - enc_time; if (dec_src_size < 0) printf("build test buffer failed\n"); else printf("source compressed to size:%d\n", dec_src_size); dec_time = get_time(); amfc_decompress(p_dec_src, p_dec_dst, dec_src_size, dec_dst_size, 0); dec_time = get_time() - dec_time; log_en = old_log; printf("enc time:%ld, dec_time:%ld, loop:%ld\n", enc_time, dec_time, cnt); i = 0; while (i < cnt) { /* build 2 descriptors 0 for enc, 1 for dec */ // case 1, cmd0 work and reset cmd 1 with random delay memset(&test_acl1, 0, sizeof(test_acl1)); memset(&test_acl2, 0, sizeof(test_acl2)); test_acl1.src_size = enc_src_size; test_acl1.dst_size = enc_dst_size; set_up_addr(&test_acl1, (unsigned long)p_enc_src, ADDR_SRC); set_up_addr(&test_acl1, (unsigned long)p_enc_dst, ADDR_DST); test_acl1.algorithm = ALGORITHM_ZSTD; test_acl1.end = 1; test_acl1.compress = CMD_COMPRESS; test_acl1.owner = 1; test_acl1.status = 0xffffffff; flush_dcache_range((unsigned long)p_enc_src, (unsigned long)p_enc_src + enc_src_size); flush_dcache_range((unsigned long)&test_acl1, (unsigned long)&test_acl1 + sizeof(acl)); invalidate_dcache_range((unsigned long)p_enc_dst, enc_dst_size); test_acl2.src_size = dec_src_size; test_acl2.dst_size = dec_dst_size; set_up_addr(&test_acl2, (unsigned long)p_dec_src, ADDR_SRC); set_up_addr(&test_acl2, (unsigned long)p_dec_dst, ADDR_DST); test_acl2.algorithm = ALGORITHM_ZSTD; test_acl2.end = 1; test_acl2.compress = CMD_DECOMPRESS; test_acl2.owner = 1; test_acl2.status = 0xffffffff; flush_dcache_range((unsigned long)p_dec_src, (unsigned long)p_dec_src + dec_src_size); flush_dcache_range((unsigned long)&test_acl2, (unsigned long)&test_acl2 + sizeof(acl)); invalidate_dcache_range((unsigned long)p_dec_dst, dec_dst_size); /* sw reset */ writel(0x80000000, AMFC_GL_CMD1_CONTROL); writel(0x03, AMFC_GL_CMD1_IRQCLR); writel((unsigned long)&test_acl2 >> ADDR_SHIFT, AMFC_GL_CMD1_DESC_BASE0_ADDR); /* SW reset */ writel(0x80000000, AMFC_GL_CMD0_CONTROL); writel(0x03, AMFC_GL_CMD0_IRQCLR); writel((unsigned long)&test_acl1 >> ADDR_SHIFT, AMFC_GL_CMD0_DESC_BASE0_ADDR); /* trigger 2 cmd */ writel(1, AMFC_GL_CMD0_CONTROL); writel(1, AMFC_GL_CMD1_CONTROL); delay = rand() % (enc_time + 1); udelay(delay); /* reset cmd 1 and check if cmd0 will timeout? */ writel(0x80000000, AMFC_GL_CMD1_CONTROL); cmd_time = get_time(); /* wait for done or error */ while (1) { status = readl(AMFC_GL_CMD0_STATUS); if ((status & IRQ_DONE)) { printf("%s, cmd 1 reset while cmd 0 is working, test pass, delay:%d, loop:%d\n", __func__, delay, i); break; } if ((status & IRQ_ERR)) { printf("%s, cmd 1 reset while cmd 0 is working, error occur, delay:%d, loop:%d\n", __func__, delay, i); dump_addr((void *)&test_acl1, 32); fail0++; break; } if (get_time() - cmd_time > timeout) { printf("%s, time out, cmd1 reset while cmd 0 working test failed, delay:%d, loop:%d\n", __func__, delay, i); dump_addr((void *)&test_acl1, 32); fail0++; break; } } invalidate_dcache_range((unsigned long)&test_acl1, (unsigned long)&test_acl1+ sizeof(acl)); // case 2, cmd1 work and reset cmd 0 with random delay memset(&test_acl1, 0, sizeof(test_acl1)); memset(&test_acl2, 0, sizeof(test_acl2)); test_acl1.src_size = enc_src_size; test_acl1.dst_size = enc_dst_size; set_up_addr(&test_acl1, (unsigned long)p_enc_src, ADDR_SRC); set_up_addr(&test_acl1, (unsigned long)p_enc_dst, ADDR_DST); test_acl1.algorithm = ALGORITHM_ZSTD; test_acl1.end = 1; test_acl1.compress = CMD_COMPRESS; test_acl1.owner = 1; test_acl1.status = 0xffffffff; flush_dcache_range((unsigned long)p_enc_src, (unsigned long)p_enc_src + enc_src_size); flush_dcache_range((unsigned long)&test_acl1, (unsigned long)&test_acl1 + sizeof(acl)); invalidate_dcache_range((unsigned long)p_enc_dst, enc_dst_size); test_acl2.src_size = dec_src_size; test_acl2.dst_size = dec_dst_size; set_up_addr(&test_acl2, (unsigned long)p_dec_src, ADDR_SRC); set_up_addr(&test_acl2, (unsigned long)p_dec_dst, ADDR_DST); test_acl2.algorithm = ALGORITHM_ZSTD; test_acl2.end = 1; test_acl2.compress = CMD_DECOMPRESS; test_acl2.owner = 1; test_acl2.status = 0xffffffff; flush_dcache_range((unsigned long)p_dec_src, (unsigned long)p_dec_src + dec_src_size); flush_dcache_range((unsigned long)&test_acl2, (unsigned long)&test_acl2 + sizeof(acl)); invalidate_dcache_range((unsigned long)p_dec_dst, dec_dst_size); /* sw reset */ writel(0x80000000, AMFC_GL_CMD1_CONTROL); writel(0x03, AMFC_GL_CMD1_IRQCLR); writel((unsigned long)&test_acl2 >> ADDR_SHIFT, AMFC_GL_CMD1_DESC_BASE0_ADDR); /* SW reset */ writel(0x80000000, AMFC_GL_CMD0_CONTROL); writel(0x03, AMFC_GL_CMD0_IRQCLR); writel((unsigned long)&test_acl1 >> ADDR_SHIFT, AMFC_GL_CMD0_DESC_BASE0_ADDR); /* trigger 2 cmd */ writel(1, AMFC_GL_CMD0_CONTROL); writel(1, AMFC_GL_CMD1_CONTROL); delay = rand() % (dec_time + 1); udelay(delay); /* reset cmd 0 and check if cmd1 will timeout? */ writel(0x80000000, AMFC_GL_CMD0_CONTROL); cmd_time = get_time(); /* wait for done or error */ while (1) { status = readl(AMFC_GL_CMD1_STATUS); if ((status & IRQ_DONE)) { printf("%s, cmd 0 reset while cmd 1 is working, test pass, delay:%d, loop:%d\n", __func__, delay, i); break; } if ((status & IRQ_ERR)) { printf("%s, cmd 0 reset while cmd 1 is working, error occur, delay:%d, loop:%d\n", __func__, delay, i); dump_addr((void *)&test_acl2, 32); dump_addr((void *)AMFC_GL_VERSION, AMFC_SECURE_TOP_REG - AMFC_GL_VERSION + 4); fail1++; break; } if (get_time() - cmd_time > timeout) { printf("%s, time out, cmd 0 reset while cmd 1 working test failed, delay:%d, loop:%d\n", __func__, delay, i); dump_addr((void *)&test_acl2, 32); fail1++; break; } } invalidate_dcache_range((unsigned long)&test_acl2, (unsigned long)&test_acl2+ sizeof(acl)); i++; } printf("%s, faile:%d %d, loop:%d\n", __func__, fail0, fail1, i); } static void amfc_stream_auto_reset_test(void) { char *p_enc_src, *p_enc_dst, *p_dec_src, *p_dec_dst; int enc_src_size, enc_dst_size, dec_src_size, dec_dst_size; int i = 0; int cmd_time; int timeout; unsigned int status; p_enc_src = (char *)0x01000000; p_enc_dst = (char *)0x02000000; p_dec_src = (char *)0x03000000; p_dec_dst = (char *)0x04000000; enc_src_size = dec_dst_size = enc_dst_size = 0x01000000; timeout = ((enc_src_size + PAGE_SIZE) / PAGE_SIZE) * 100 + 5000; for (i = 0; i < p_enc_dst - p_enc_src; i++) { p_enc_src[i] = i & 0xff; } dec_src_size = amfc_compress(p_enc_src, p_dec_src, enc_src_size, enc_dst_size); if (dec_src_size < 0) printf("build test buffer failed\n"); else printf("source compressed to size:%d\n", dec_src_size); /* build 2 descriptors 0 for enc, 1 for dec */ memset(&test_acl1, 0, sizeof(test_acl1)); memset(&test_acl2, 0, sizeof(test_acl2)); test_acl1.src_size = enc_src_size; test_acl1.dst_size = enc_dst_size; set_up_addr(&test_acl1, (unsigned long)p_enc_src, ADDR_SRC); set_up_addr(&test_acl1, (unsigned long)p_enc_dst, ADDR_DST); test_acl1.algorithm = ALGORITHM_ZSTD; test_acl1.end = 1; // test_acl1.stream = 1; test_acl1.compress = CMD_COMPRESS; test_acl1.owner = 1; test_acl1.status = 0xffffffff; flush_dcache_range((unsigned long)p_enc_src, (unsigned long)p_enc_src + enc_src_size); flush_dcache_range((unsigned long)&test_acl1, (unsigned long)&test_acl1 + sizeof(acl)); invalidate_dcache_range((unsigned long)p_enc_dst, enc_dst_size); test_acl2.src_size = dec_src_size; test_acl2.dst_size = 10000; set_up_addr(&test_acl2, (unsigned long)p_dec_src, ADDR_SRC); set_up_addr(&test_acl2, (unsigned long)p_dec_dst, ADDR_DST); test_acl2.algorithm = ALGORITHM_ZSTD; test_acl2.end = 1; test_acl2.stream = 1; // setup stream test_acl2.compress = CMD_DECOMPRESS; test_acl2.owner = 1; test_acl2.status = 0xffffffff; flush_dcache_range((unsigned long)p_dec_src, (unsigned long)p_dec_src + dec_src_size); flush_dcache_range((unsigned long)&test_acl2, (unsigned long)&test_acl2 + sizeof(acl)); invalidate_dcache_range((unsigned long)p_dec_dst, dec_dst_size); /* sw reset */ writel(0x80000000, AMFC_GL_CMD1_CONTROL); writel(0x03, AMFC_GL_CMD1_IRQCLR); writel((unsigned long)&test_acl2 >> ADDR_SHIFT, AMFC_GL_CMD1_DESC_BASE0_ADDR); /* SW reset */ writel(0x80000000, AMFC_GL_CMD0_CONTROL); writel(0x03, AMFC_GL_CMD0_IRQCLR); writel((unsigned long)&test_acl1 >> ADDR_SHIFT, AMFC_GL_CMD0_DESC_BASE0_ADDR); /* trigger 2 cmd */ writel(1, AMFC_GL_CMD0_CONTROL); writel(1, AMFC_GL_CMD1_CONTROL); cmd_time = get_time(); /* wait cmd1 for done or error */ while (1) { status = readl(AMFC_GL_CMD1_STATUS); if ((status & IRQ_DONE)) { if (hw_version < HW_VERSION_12) writel(0x80000000, AMFC_GL_CMD1_CONTROL); break; } if ((status & IRQ_ERR)) { printf("%s, cmd 1 stream error occur\n", __func__); break; } if (get_time() - cmd_time > timeout) { printf("%s, time out, cmd1 stream timeout\n", __func__); break; } } cmd_time = get_time(); /* wait for done or error */ while (1) { status = readl(AMFC_GL_CMD0_STATUS); if ((status & IRQ_DONE)) { printf("%s, cmd 1 stream while cmd 0 is working, test pass\n", __func__); break; } if ((status & IRQ_ERR)) { printf("%s, cmd 1 stream while cmd 0 is working, error occur\n", __func__); break; } if (get_time() - cmd_time > timeout) { printf("%s, time out, cmd1 stream while cmd 0 working test failed\n", __func__); break; } } invalidate_dcache_range((unsigned long)&test_acl1, (unsigned long)&test_acl1+ sizeof(acl)); dump_addr((void *)&test_acl1, 32); invalidate_dcache_range((unsigned long)&test_acl2, (unsigned long)&test_acl2+ sizeof(acl)); dump_addr((void *)&test_acl2, 32); } const unsigned test_data[]={ 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000, 0xb5280000 , 0x1040fd2f , 0x006cff00 , 0x30302000, 0x0002300a , 0x40f167f4 , 0x003c4400 , 0x00010000, 0x805fa7fd , 0x0000003c , 0xf7fd0001 , 0x003c1001, 0x00010000 , 0x1001f7fd , 0x0000003c , 0xf7fd0001, 0x003c1001 , 0x00010000 , 0x1001f7fd , 0x0000003c, 0xf7fd0001 , 0x003c1001 , 0x00010000 , 0x1001f7fd, 0x0000003c , 0xf7fd0001 , 0x003c1001 , 0x00010000, 0x1001f7fd , 0x0000003c , 0xf7fd0001 , 0x003c1001, 0x00010000 , 0x1001f7fd , 0x0000003c , 0xf7fd0001, 0x003c1001 , 0x00010000 , 0x1001f7fd , 0x0000003c, 0xf7fd0001 , 0x003d1001 , 0x00010000 , 0x1001f7fd, 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }; static void amfc_page_boundary_test(void) { unsigned char *p_src, *p_dst; int src_size, dst_size, ret; p_src = (unsigned char *)0x01000000; p_dst = (unsigned char *)0x02000000; src_size = 4096; dst_size = 65600; memcpy(p_src, test_data, sizeof(test_data)); page_table_mode = 1; ret = amfc_decompress(p_src, p_dst, src_size, dst_size, 0); if (ret < 0) { printf("%s, test failed, ret:%d\n", __func__, ret); } else { printf("%s, test pass, ret:%d\n", __func__, ret); } } #endif static int do_amfc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { unsigned long src; unsigned long dst; unsigned long src_size; unsigned long dst_size; int ret; if (argc < 2) return -1; if (!strcmp(argv[1], "set")) { if (argc != 4) return -1; if (!strcmp(argv[2], "page_table")) { page_table_mode = simple_strtoul(argv[3], NULL, 16); printf("set page_table_mode to:%d\n", page_table_mode); } if (!strcmp(argv[2], "log")) { log_en = simple_strtoul(argv[3], NULL, 16); printf("set log to:%d\n", log_en); } return 0; } #if CONFIG_AMFC_TEST if (!strcmp(argv[1], "pack_test")) { if (argc != 5) return -1; src = simple_strtoul(argv[2], NULL, 16); dst = simple_strtoul(argv[3], NULL, 16); src_size = simple_strtoul(argv[4], NULL, 16); amfc_pack_test(src, (void *)dst, (void *)src_size); return 0; } if (!strcmp(argv[1], "zram_test")) { if (argc != 5) return -1; src = simple_strtoul(argv[2], NULL, 16); src_size = simple_strtoul(argv[3], NULL, 16); dst_size = simple_strtoul(argv[4], NULL, 16); amfc_zram_test((void *)src, src_size, dst_size); return 0; } if (!strcmp(argv[1], "erofs_test")) { if (argc != 6) return -1; src = simple_strtoul(argv[2], NULL, 16); dst = simple_strtoul(argv[3], NULL, 16); src_size = simple_strtoul(argv[4], NULL, 16); dst_size = simple_strtoul(argv[5], NULL, 16); amfc_erofs_test((void *)src, dst, src_size, dst_size); return 0; } if (!strcmp(argv[1], "table_test")) { if (argc != 6) return -1; src = simple_strtoul(argv[2], NULL, 16); dst = simple_strtoul(argv[3], NULL, 16); src_size = simple_strtoul(argv[4], NULL, 16); dst_size = simple_strtoul(argv[5], NULL, 16); amfc_table_test((void *)src, (void *)dst, (void *)src_size, dst_size); return 0; } if (!strcmp(argv[1], "link_test")) { if (argc != 6) return -1; src = simple_strtoul(argv[2], NULL, 16); dst = simple_strtoul(argv[3], NULL, 16); src_size = simple_strtoul(argv[4], NULL, 16); dst_size = simple_strtoul(argv[5], NULL, 16); amfc_link_test((void *)src, (void *)dst, (void *)src_size, dst_size); return 0; } if (!strcmp(argv[1], "table_mask")) { if (argc != 3) return -1; table_test_mask = simple_strtoul(argv[2], NULL, 16); return 0; } if (!strcmp(argv[1], "addr_test")) { if (argc != 6) return -1; src = simple_strtoul(argv[2], NULL, 16); dst = simple_strtoul(argv[3], NULL, 16); src_size = simple_strtoul(argv[4], NULL, 16); dst_size = simple_strtoul(argv[5], NULL, 16); amfc_address_test((void *)src, (void *)dst, (void *)src_size, dst_size); return 0; } if (!strcmp(argv[1], "pagetable_test")) { if (argc != 6) return -1; src = simple_strtoul(argv[2], NULL, 16); dst = simple_strtoul(argv[3], NULL, 16); src_size = simple_strtoul(argv[4], NULL, 16); dst_size = simple_strtoul(argv[5], NULL, 16); amfc_pagetable_test((void *)src, (void *)dst, (void *)src_size, dst_size); return 0; } if (!strcmp(argv[1], "stream_test")) { if (argc != 6) return -1; src = simple_strtoul(argv[2], NULL, 16); dst = simple_strtoul(argv[3], NULL, 16); src_size = simple_strtoul(argv[4], NULL, 16); dst_size = simple_strtoul(argv[5], NULL, 16); amfc_stream_mode_test((void *)src, (void *)dst, (void *)src_size, dst_size); } if (!strcmp(argv[1], "reset_test")) { if (argc != 3) return -1; src = simple_strtoul(argv[2], NULL, 16); amfc_reset_test(src); return 0; } if (!strcmp(argv[1], "stream_auto_reset_test")) { amfc_stream_auto_reset_test(); return 0; } if (!strcmp(argv[1], "page_bound_test")) { amfc_page_boundary_test(); return 0; } #endif if (argc != 6) return -1; src = simple_strtoul(argv[2], NULL, 16); dst = simple_strtoul(argv[3], NULL, 16); src_size = simple_strtoul(argv[4], NULL, 16); dst_size = simple_strtoul(argv[5], NULL, 16); if (!strcmp(argv[1], "compress")) ret = amfc_compress((void *)src, (void *)dst, src_size, dst_size); else if (!strcmp(argv[1], "decompress")) ret = amfc_decompress((void *)src, (void *)dst, src_size, dst_size, 0); return 0; } U_BOOT_CMD( amfc, 7, 0, do_amfc, "amfc subsystem", "compress/decompress [src_addr] [dst_addr] [src_size] [dst_size]\n" "set:\n" " page_table [0/1] ---- enable/disable page table mode\n" "memcmp [src] [dst] [size] ----compare two memory region\n" "All parameters in hex value" );