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