1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #include <stdio.h> 6 #include <inttypes.h> 7 #include <string.h> 8 #include <math.h> 9 #include <rte_common.h> 10 #include <rte_bitops.h> 11 #include <rte_hexdump.h> 12 #include <rte_pause.h> 13 14 #include "test.h" 15 16 #define MAX_NUM 1 << 20 17 18 #define FAIL(x)\ 19 {printf(x "() test failed!\n");\ 20 return -1;} 21 22 /* this is really a sanity check */ 23 static int 24 test_macros(int __rte_unused unused_parm) 25 { 26 #define SMALLER 0x1000U 27 #define BIGGER 0x2000U 28 #define PTR_DIFF BIGGER - SMALLER 29 30 uintptr_t unused = 0; 31 unsigned int smaller = SMALLER, bigger = BIGGER; 32 uint32_t arr[3]; 33 34 RTE_SET_USED(unused); 35 36 RTE_SWAP(smaller, bigger); 37 RTE_TEST_ASSERT(smaller == BIGGER && bigger == SMALLER, 38 "RTE_SWAP"); 39 RTE_TEST_ASSERT_EQUAL((uintptr_t)RTE_PTR_ADD(SMALLER, PTR_DIFF), BIGGER, 40 "RTE_PTR_ADD"); 41 RTE_TEST_ASSERT_EQUAL((uintptr_t)RTE_PTR_SUB(BIGGER, PTR_DIFF), SMALLER, 42 "RTE_PTR_SUB"); 43 RTE_TEST_ASSERT_EQUAL(RTE_PTR_DIFF(BIGGER, SMALLER), PTR_DIFF, 44 "RTE_PTR_DIFF"); 45 RTE_TEST_ASSERT_EQUAL(RTE_MAX(SMALLER, BIGGER), BIGGER, 46 "RTE_MAX"); 47 RTE_TEST_ASSERT_EQUAL(RTE_MIN(SMALLER, BIGGER), SMALLER, 48 "RTE_MIN"); 49 50 RTE_TEST_ASSERT_EQUAL(RTE_PTR_ADD(arr + 1, sizeof(arr[0])), &arr[2], 51 "RTE_PTR_ADD(expr, x)"); 52 RTE_TEST_ASSERT_EQUAL(RTE_PTR_SUB(arr + 1, sizeof(arr[0])), &arr[0], 53 "RTE_PTR_SUB(expr, x)"); 54 RTE_TEST_ASSERT_EQUAL(RTE_PTR_ALIGN_FLOOR(arr + 2, 4), &arr[2], 55 "RTE_PTR_ALIGN_FLOOR(expr, x)"); 56 RTE_TEST_ASSERT_EQUAL(RTE_PTR_ALIGN_CEIL(arr + 2, 4), &arr[2], 57 "RTE_PTR_ALIGN_CEIL(expr, x)"); 58 RTE_TEST_ASSERT_EQUAL(RTE_PTR_ALIGN(arr + 2, 4), &arr[2], 59 "RTE_PTR_ALIGN(expr, x)"); 60 61 RTE_TEST_ASSERT_EQUAL( 62 RTE_PTR_ALIGN_FLOOR(RTE_PTR_ADD(&arr[1], 1), 4), &arr[1], 63 "RTE_PTR_ALIGN_FLOOR(x < y/2, y)"); 64 RTE_TEST_ASSERT_EQUAL( 65 RTE_PTR_ALIGN_FLOOR(RTE_PTR_ADD(&arr[1], 3), 4), &arr[1], 66 "RTE_PTR_ALIGN_FLOOR(x > y/2, y)"); 67 RTE_TEST_ASSERT_EQUAL( 68 RTE_PTR_ALIGN_CEIL(RTE_PTR_ADD(&arr[1], 3), 4), &arr[2], 69 "RTE_PTR_ALIGN_CEIL(x < y/2, y)"); 70 RTE_TEST_ASSERT_EQUAL( 71 RTE_PTR_ALIGN_CEIL(RTE_PTR_ADD(&arr[1], 1), 4), &arr[2], 72 "RTE_PTR_ALIGN_CEIL(x > y/2, y)"); 73 74 RTE_TEST_ASSERT(strncmp(RTE_STR(test), "test", sizeof("test")) == 0, 75 "RTE_STR"); 76 77 return 0; 78 } 79 80 static int 81 test_bsf(void) 82 { 83 uint32_t shift, pos; 84 85 /* safe versions should be able to handle 0 */ 86 if (rte_bsf32_safe(0, &pos) != 0) 87 FAIL("rte_bsf32_safe"); 88 if (rte_bsf64_safe(0, &pos) != 0) 89 FAIL("rte_bsf64_safe"); 90 91 for (shift = 0; shift < 63; shift++) { 92 uint32_t val32; 93 uint64_t val64; 94 95 val64 = 1ULL << shift; 96 if ((uint32_t)rte_bsf64(val64) != shift) 97 FAIL("rte_bsf64"); 98 if (rte_bsf64_safe(val64, &pos) != 1) 99 FAIL("rte_bsf64_safe"); 100 if (pos != shift) 101 FAIL("rte_bsf64_safe"); 102 103 if (shift > 31) 104 continue; 105 106 val32 = 1U << shift; 107 if ((uint32_t)rte_bsf32(val32) != shift) 108 FAIL("rte_bsf32"); 109 if (rte_bsf32_safe(val32, &pos) != 1) 110 FAIL("rte_bsf32_safe"); 111 if (pos != shift) 112 FAIL("rte_bsf32_safe"); 113 } 114 115 return 0; 116 } 117 118 static int 119 test_misc(void) 120 { 121 char memdump[] = "memdump_test"; 122 123 rte_memdump(stdout, "test", memdump, sizeof(memdump)); 124 rte_hexdump(stdout, "test", memdump, sizeof(memdump)); 125 126 rte_pause(); 127 128 return 0; 129 } 130 131 static int 132 test_align(void) 133 { 134 #define FAIL_ALIGN(x, i, p)\ 135 {printf(x "() test failed: %u %u\n", i, p);\ 136 return -1;} 137 #define FAIL_ALIGN64(x, j, q)\ 138 {printf(x "() test failed: %"PRIu64" %"PRIu64"\n", j, q);\ 139 return -1; } 140 #define ERROR_FLOOR(res, i, pow) \ 141 (res % pow) || /* check if not aligned */ \ 142 ((res / pow) != (i / pow)) /* check if correct alignment */ 143 #define ERROR_CEIL(res, i, pow) \ 144 (res % pow) || /* check if not aligned */ \ 145 ((i % pow) == 0 ? /* check if ceiling is invoked */ \ 146 val / pow != i / pow : /* if aligned */ \ 147 val / pow != (i / pow) + 1) /* if not aligned, hence +1 */ 148 149 uint32_t i, p, val; 150 uint64_t j, q; 151 152 for (i = 1, p = 1; i <= MAX_NUM; i ++) { 153 if (rte_align32pow2(i) != p) 154 FAIL_ALIGN("rte_align32pow2", i, p); 155 if (i == p) 156 p <<= 1; 157 } 158 159 for (i = 1, p = 1; i <= MAX_NUM; i++) { 160 if (rte_align32prevpow2(i) != p) 161 FAIL_ALIGN("rte_align32prevpow2", i, p); 162 if (rte_is_power_of_2(i + 1)) 163 p = i + 1; 164 } 165 166 for (j = 1, q = 1; j <= MAX_NUM ; j++) { 167 if (rte_align64pow2(j) != q) 168 FAIL_ALIGN64("rte_align64pow2", j, q); 169 if (j == q) 170 q <<= 1; 171 } 172 173 for (j = 1, q = 1; j <= MAX_NUM ; j++) { 174 if (rte_align64prevpow2(j) != q) 175 FAIL_ALIGN64("rte_align64prevpow2", j, q); 176 if (rte_is_power_of_2(j + 1)) 177 q = j + 1; 178 } 179 180 for (p = 2; p <= MAX_NUM; p <<= 1) { 181 182 if (!rte_is_power_of_2(p)) 183 FAIL("rte_is_power_of_2"); 184 185 for (i = 1; i <= MAX_NUM; i++) { 186 /* align floor */ 187 if (RTE_ALIGN_FLOOR((uintptr_t)i, p) % p) 188 FAIL_ALIGN("RTE_ALIGN_FLOOR", i, p); 189 190 val = RTE_PTR_ALIGN_FLOOR((uintptr_t) i, p); 191 if (ERROR_FLOOR(val, i, p)) 192 FAIL_ALIGN("RTE_PTR_ALIGN_FLOOR", i, p); 193 194 val = RTE_ALIGN_FLOOR(i, p); 195 if (ERROR_FLOOR(val, i, p)) 196 FAIL_ALIGN("RTE_ALIGN_FLOOR", i, p); 197 198 /* align ceiling */ 199 val = RTE_PTR_ALIGN((uintptr_t) i, p); 200 if (ERROR_CEIL(val, i, p)) 201 FAIL_ALIGN("RTE_PTR_ALIGN", i, p); 202 203 val = RTE_ALIGN(i, p); 204 if (ERROR_CEIL(val, i, p)) 205 FAIL_ALIGN("RTE_ALIGN", i, p); 206 207 val = RTE_ALIGN_CEIL(i, p); 208 if (ERROR_CEIL(val, i, p)) 209 FAIL_ALIGN("RTE_ALIGN_CEIL", i, p); 210 211 val = RTE_PTR_ALIGN_CEIL((uintptr_t)i, p); 212 if (ERROR_CEIL(val, i, p)) 213 FAIL_ALIGN("RTE_PTR_ALIGN_CEIL", i, p); 214 215 /* by this point we know that val is aligned to p */ 216 if (!rte_is_aligned((void*)(uintptr_t) val, p)) 217 FAIL("rte_is_aligned"); 218 } 219 } 220 221 for (p = 1; p <= MAX_NUM / 2; p++) { 222 for (i = 1; i <= MAX_NUM / 2; i++) { 223 val = RTE_ALIGN_MUL_CEIL(i, p); 224 if (val % p != 0 || val < i) 225 FAIL_ALIGN("RTE_ALIGN_MUL_CEIL", i, p); 226 val = RTE_ALIGN_MUL_FLOOR(i, p); 227 if (val % p != 0 || val > i) 228 FAIL_ALIGN("RTE_ALIGN_MUL_FLOOR", i, p); 229 val = RTE_ALIGN_MUL_NEAR(i, p); 230 if (val % p != 0 || ((val != RTE_ALIGN_MUL_CEIL(i, p)) 231 & (val != RTE_ALIGN_MUL_FLOOR(i, p)))) 232 FAIL_ALIGN("RTE_ALIGN_MUL_NEAR", i, p); 233 } 234 } 235 236 return 0; 237 } 238 239 static int 240 test_log2(void) 241 { 242 uint32_t i, base, compare; 243 const uint32_t max = 0x10000; 244 const uint32_t step = 1; 245 246 compare = rte_log2_u32(0); 247 if (compare != 0) { 248 printf("Wrong rte_log2_u32(0) val %x, expected 0\n", compare); 249 return TEST_FAILED; 250 } 251 252 compare = rte_log2_u64(0); 253 if (compare != 0) { 254 printf("Wrong rte_log2_u64(0) val %x, expected 0\n", compare); 255 return TEST_FAILED; 256 } 257 258 for (i = 1; i < max; i = i + step) { 259 uint64_t i64; 260 261 /* extend range for 64-bit */ 262 i64 = (uint64_t)i << 32; 263 base = (uint32_t)ceilf(log2(i64)); 264 compare = rte_log2_u64(i64); 265 if (base != compare) { 266 printf("Wrong rte_log2_u64(%" PRIx64 ") val %x, expected %x\n", 267 i64, compare, base); 268 return TEST_FAILED; 269 } 270 271 base = (uint32_t)ceilf(log2((uint32_t)i)); 272 compare = rte_log2_u32((uint32_t)i); 273 if (base != compare) { 274 printf("Wrong rte_log2_u32(%x) val %x, expected %x\n", 275 i, compare, base); 276 return TEST_FAILED; 277 } 278 compare = rte_log2_u64((uint64_t)i); 279 if (base != compare) { 280 printf("Wrong rte_log2_u64(%x) val %x, expected %x\n", 281 i, compare, base); 282 return TEST_FAILED; 283 } 284 } 285 return 0; 286 } 287 288 static int 289 test_fls(void) 290 { 291 struct fls_test_vector { 292 uint32_t arg; 293 int rc; 294 }; 295 int expected, rc; 296 uint32_t i, arg; 297 298 const struct fls_test_vector test[] = { 299 {0x0, 0}, 300 {0x1, 1}, 301 {0x4000, 15}, 302 {0x80000000, 32}, 303 }; 304 305 for (i = 0; i < RTE_DIM(test); i++) { 306 uint64_t arg64; 307 308 arg = test[i].arg; 309 rc = rte_fls_u32(arg); 310 expected = test[i].rc; 311 if (rc != expected) { 312 printf("Wrong rte_fls_u32(0x%x) rc=%d, expected=%d\n", 313 arg, rc, expected); 314 return TEST_FAILED; 315 } 316 /* 64-bit version */ 317 arg = test[i].arg; 318 rc = rte_fls_u64(arg); 319 expected = test[i].rc; 320 if (rc != expected) { 321 printf("Wrong rte_fls_u64(0x%x) rc=%d, expected=%d\n", 322 arg, rc, expected); 323 return TEST_FAILED; 324 } 325 /* 64-bit version shifted by 32 bits */ 326 arg64 = (uint64_t)test[i].arg << 32; 327 rc = rte_fls_u64(arg64); 328 /* don't shift zero */ 329 expected = test[i].rc == 0 ? 0 : test[i].rc + 32; 330 if (rc != expected) { 331 printf("Wrong rte_fls_u64(0x%" PRIx64 ") rc=%d, expected=%d\n", 332 arg64, rc, expected); 333 return TEST_FAILED; 334 } 335 } 336 337 return 0; 338 } 339 340 static int 341 test_common(void) 342 { 343 int ret = 0; 344 ret |= test_align(); 345 ret |= test_macros(0); 346 ret |= test_misc(); 347 ret |= test_bsf(); 348 ret |= test_log2(); 349 ret |= test_fls(); 350 351 return ret; 352 } 353 354 REGISTER_FAST_TEST(common_autotest, true, true, test_common); 355