1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2024 Arm Limited 3 */ 4 5 #include "test.h" 6 #include <stdint.h> 7 #include <string.h> 8 9 #include <rte_ptr_compress.h> 10 11 #define MAX_ALIGN_EXPONENT 3 12 #define MAX_PTRS 16 13 #define NUM_BASES 2 14 #define NUM_REGIONS 4 15 #define MAX_32BIT_REGION ((uint64_t)UINT32_MAX + 1) 16 #define MAX_16BIT_REGION (UINT16_MAX + 1) 17 18 static int 19 test_ptr_compress_params( 20 void *base, 21 uint64_t mem_sz, 22 unsigned int align_exp, 23 unsigned int num_ptrs, 24 bool use_32_bit) 25 { 26 unsigned int i; 27 unsigned int align = 1 << align_exp; 28 void *ptrs[MAX_PTRS] = {0}; 29 void *ptrs_out[MAX_PTRS] = {0}; 30 uint32_t offsets32[MAX_PTRS] = {0}; 31 uint16_t offsets16[MAX_PTRS] = {0}; 32 33 for (i = 0; i < num_ptrs; i++) { 34 /* make pointers point at memory in steps of align */ 35 /* alternate steps from the start and end of memory region */ 36 if ((i & 1) == 1) 37 ptrs[i] = (char *)base + mem_sz - i * align; 38 else 39 ptrs[i] = (char *)base + i * align; 40 } 41 42 if (use_32_bit) { 43 rte_ptr_compress_32_shift( 44 base, ptrs, offsets32, num_ptrs, align_exp); 45 rte_ptr_decompress_32_shift(base, offsets32, ptrs_out, num_ptrs, 46 align_exp); 47 } else { 48 rte_ptr_compress_16_shift( 49 base, ptrs, offsets16, num_ptrs, align_exp); 50 rte_ptr_decompress_16_shift(base, offsets16, ptrs_out, num_ptrs, 51 align_exp); 52 } 53 54 TEST_ASSERT_BUFFERS_ARE_EQUAL(ptrs, ptrs_out, sizeof(void *) * num_ptrs, 55 "Decompressed pointers corrupted\nbase pointer: %p, " 56 "memory region size: %" PRIu64 ", alignment exponent: %u, " 57 "num of pointers: %u, using %s offsets", 58 base, mem_sz, align_exp, num_ptrs, 59 use_32_bit ? "32-bit" : "16-bit"); 60 61 return 0; 62 } 63 64 static int 65 test_ptr_compress(void) 66 { 67 unsigned int j, k, n; 68 int ret = 0; 69 /* the test is run with multiple memory regions and base addresses */ 70 void * const bases[NUM_BASES] = { (void *)0, (void *)UINT16_MAX }; 71 /* maximum size for pointers aligned by consecutive powers of 2 */ 72 const uint64_t region_sizes_16[NUM_REGIONS] = { 73 MAX_16BIT_REGION, 74 MAX_16BIT_REGION * 2, 75 MAX_16BIT_REGION * 4, 76 MAX_16BIT_REGION * 8, 77 }; 78 const uint64_t region_sizes_32[NUM_REGIONS] = { 79 MAX_32BIT_REGION, 80 MAX_32BIT_REGION * 2, 81 MAX_32BIT_REGION * 4, 82 MAX_32BIT_REGION * 8, 83 }; 84 85 /* main test compresses and decompresses arrays of pointers 86 * and compares the array before and after to verify that 87 * pointers are successfully decompressed 88 */ 89 90 for (j = 0; j < NUM_REGIONS; j++) { 91 for (k = 0; k < NUM_BASES; k++) { 92 for (n = 1; n < MAX_PTRS; n++) { 93 ret |= test_ptr_compress_params( 94 bases[k], 95 region_sizes_16[j], 96 j /* exponent of alignment */, 97 n, 98 false 99 ); 100 ret |= test_ptr_compress_params( 101 bases[k], 102 region_sizes_32[j], 103 j /* exponent of alignment */, 104 n, 105 true 106 ); 107 if (ret != 0) 108 return ret; 109 } 110 } 111 } 112 113 /* verify helper macro computations */ 114 115 n = RTE_PTR_COMPRESS_BITS_NEEDED_FOR_POINTER_WITHIN_RANGE(0); 116 TEST_ASSERT_EQUAL(n, 1, 117 "RTE_PTR_COMPRESS_BITS_NEEDED_FOR_POINTER_WITHIN_RANGE " 118 "macro computation incorrect\n"); 119 120 n = RTE_PTR_COMPRESS_BITS_NEEDED_FOR_POINTER_WITHIN_RANGE(1); 121 TEST_ASSERT_EQUAL(n, 1, 122 "RTE_PTR_COMPREtopSS_BITS_REQUIRED_TO_STORE_VALUE " 123 "macro computation incorrect\n"); 124 125 n = RTE_PTR_COMPRESS_BITS_NEEDED_FOR_POINTER_WITHIN_RANGE(MAX_16BIT_REGION); 126 TEST_ASSERT_EQUAL(n, 16, 127 "RTE_PTR_COMPRESS_BITS_NEEDED_FOR_POINTER_WITHIN_RANGE " 128 "macro computation incorrect\n"); 129 130 n = RTE_PTR_COMPRESS_BITS_NEEDED_FOR_POINTER_WITHIN_RANGE(MAX_32BIT_REGION); 131 TEST_ASSERT_EQUAL(n, 32, 132 "RTE_PTR_COMPRESS_BITS_NEEDED_FOR_POINTER_WITHIN_RANGE " 133 "macro computation incorrect\n"); 134 135 n = RTE_PTR_COMPRESS_BIT_SHIFT_FROM_ALIGNMENT(0); 136 TEST_ASSERT_EQUAL(n, 0, 137 "RTE_PTR_COMPRESS_BIT_SHIFT_FROM_ALIGNMENT " 138 "macro computation incorrect\n"); 139 140 n = RTE_PTR_COMPRESS_BIT_SHIFT_FROM_ALIGNMENT(1); 141 TEST_ASSERT_EQUAL(n, 0, 142 "RTE_PTR_COMPRESS_BIT_SHIFT_FROM_ALIGNMENT " 143 "macro computation incorrect\n"); 144 145 n = RTE_PTR_COMPRESS_BIT_SHIFT_FROM_ALIGNMENT(2); 146 TEST_ASSERT_EQUAL(n, 1, 147 "RTE_PTR_COMPRESS_BIT_SHIFT_FROM_ALIGNMENT " 148 "macro computation incorrect\n"); 149 150 n = RTE_PTR_COMPRESS_BIT_SHIFT_FROM_ALIGNMENT(3); 151 TEST_ASSERT_EQUAL(n, 0, 152 "RTE_PTR_COMPRESS_BIT_SHIFT_FROM_ALIGNMENT " 153 "macro computation incorrect\n"); 154 155 n = RTE_PTR_COMPRESS_BIT_SHIFT_FROM_ALIGNMENT(4); 156 TEST_ASSERT_EQUAL(n, 2, 157 "RTE_PTR_COMPRESS_BIT_SHIFT_FROM_ALIGNMENT " 158 "macro computation incorrect\n"); 159 160 ret = RTE_PTR_COMPRESS_CAN_COMPRESS_16_SHIFT(MAX_16BIT_REGION, 1); 161 TEST_ASSERT_EQUAL(ret, 1, 162 "RTE_PTR_COMPRESS_CAN_COMPRESS_16_SHIFT " 163 "macro computation incorrect\n"); 164 165 ret = RTE_PTR_COMPRESS_CAN_COMPRESS_16_SHIFT(MAX_16BIT_REGION + 1, 1); 166 TEST_ASSERT_EQUAL(ret, 0, 167 "RTE_PTR_COMPRESS_CAN_COMPRESS_16_SHIFT " 168 "macro computation incorrect\n"); 169 170 ret = RTE_PTR_COMPRESS_CAN_COMPRESS_16_SHIFT(MAX_16BIT_REGION + 1, 2); 171 TEST_ASSERT_EQUAL(ret, 1, 172 "RTE_PTR_COMPRESS_CAN_COMPRESS_16_SHIFT " 173 "macro computation incorrect\n"); 174 175 ret = RTE_PTR_COMPRESS_CAN_COMPRESS_32_SHIFT(MAX_32BIT_REGION, 1); 176 TEST_ASSERT_EQUAL(ret, 1, 177 "RTE_PTR_COMPRESS_CAN_COMPRESS_32_SHIFT " 178 "macro computation incorrect\n"); 179 180 ret = RTE_PTR_COMPRESS_CAN_COMPRESS_32_SHIFT(MAX_32BIT_REGION + 1, 1); 181 TEST_ASSERT_EQUAL(ret, 0, 182 "RTE_PTR_COMPRESS_CAN_COMPRESS_32_SHIFT " 183 "macro computation incorrect\n"); 184 185 ret = RTE_PTR_COMPRESS_CAN_COMPRESS_32_SHIFT(MAX_32BIT_REGION + 1, 2); 186 TEST_ASSERT_EQUAL(ret, 1, 187 "RTE_PTR_COMPRESS_CAN_COMPRESS_32_SHIFT " 188 "macro computation incorrect\n"); 189 190 return 0; 191 } 192 193 REGISTER_FAST_TEST(ptr_compress_autotest, true, true, test_ptr_compress); 194