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
test_ptr_compress_params(void * base,uint64_t mem_sz,unsigned int align_exp,unsigned int num_ptrs,bool use_32_bit)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
test_ptr_compress(void)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