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