1*7c5b184dSJason Gunthorpe /* SPDX-License-Identifier: GPL-2.0-only */ 2*7c5b184dSJason Gunthorpe /* 3*7c5b184dSJason Gunthorpe * Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES 4*7c5b184dSJason Gunthorpe * 5*7c5b184dSJason Gunthorpe * Helper macros for working with log2 values 6*7c5b184dSJason Gunthorpe * 7*7c5b184dSJason Gunthorpe */ 8*7c5b184dSJason Gunthorpe #ifndef __GENERIC_PT_LOG2_H 9*7c5b184dSJason Gunthorpe #define __GENERIC_PT_LOG2_H 10*7c5b184dSJason Gunthorpe #include <linux/bitops.h> 11*7c5b184dSJason Gunthorpe #include <linux/limits.h> 12*7c5b184dSJason Gunthorpe 13*7c5b184dSJason Gunthorpe /* Compute a */ 14*7c5b184dSJason Gunthorpe #define log2_to_int_t(type, a_lg2) ((type)(((type)1) << (a_lg2))) 15*7c5b184dSJason Gunthorpe static_assert(log2_to_int_t(unsigned int, 0) == 1); 16*7c5b184dSJason Gunthorpe 17*7c5b184dSJason Gunthorpe /* Compute a - 1 (aka all low bits set) */ 18*7c5b184dSJason Gunthorpe #define log2_to_max_int_t(type, a_lg2) ((type)(log2_to_int_t(type, a_lg2) - 1)) 19*7c5b184dSJason Gunthorpe 20*7c5b184dSJason Gunthorpe /* Compute a / b */ 21*7c5b184dSJason Gunthorpe #define log2_div_t(type, a, b_lg2) ((type)(((type)a) >> (b_lg2))) 22*7c5b184dSJason Gunthorpe static_assert(log2_div_t(unsigned int, 4, 2) == 1); 23*7c5b184dSJason Gunthorpe 24*7c5b184dSJason Gunthorpe /* 25*7c5b184dSJason Gunthorpe * Compute: 26*7c5b184dSJason Gunthorpe * a / c == b / c 27*7c5b184dSJason Gunthorpe * aka the high bits are equal 28*7c5b184dSJason Gunthorpe */ 29*7c5b184dSJason Gunthorpe #define log2_div_eq_t(type, a, b, c_lg2) \ 30*7c5b184dSJason Gunthorpe (log2_div_t(type, (a) ^ (b), c_lg2) == 0) 31*7c5b184dSJason Gunthorpe static_assert(log2_div_eq_t(unsigned int, 1, 1, 2)); 32*7c5b184dSJason Gunthorpe 33*7c5b184dSJason Gunthorpe /* Compute a % b */ 34*7c5b184dSJason Gunthorpe #define log2_mod_t(type, a, b_lg2) \ 35*7c5b184dSJason Gunthorpe ((type)(((type)a) & log2_to_max_int_t(type, b_lg2))) 36*7c5b184dSJason Gunthorpe static_assert(log2_mod_t(unsigned int, 1, 2) == 1); 37*7c5b184dSJason Gunthorpe 38*7c5b184dSJason Gunthorpe /* 39*7c5b184dSJason Gunthorpe * Compute: 40*7c5b184dSJason Gunthorpe * a % b == b - 1 41*7c5b184dSJason Gunthorpe * aka the low bits are all 1s 42*7c5b184dSJason Gunthorpe */ 43*7c5b184dSJason Gunthorpe #define log2_mod_eq_max_t(type, a, b_lg2) \ 44*7c5b184dSJason Gunthorpe (log2_mod_t(type, a, b_lg2) == log2_to_max_int_t(type, b_lg2)) 45*7c5b184dSJason Gunthorpe static_assert(log2_mod_eq_max_t(unsigned int, 3, 2)); 46*7c5b184dSJason Gunthorpe 47*7c5b184dSJason Gunthorpe /* 48*7c5b184dSJason Gunthorpe * Return a value such that: 49*7c5b184dSJason Gunthorpe * a / b == ret / b 50*7c5b184dSJason Gunthorpe * ret % b == val 51*7c5b184dSJason Gunthorpe * aka set the low bits to val. val must be < b 52*7c5b184dSJason Gunthorpe */ 53*7c5b184dSJason Gunthorpe #define log2_set_mod_t(type, a, val, b_lg2) \ 54*7c5b184dSJason Gunthorpe ((((type)(a)) & (~log2_to_max_int_t(type, b_lg2))) | ((type)(val))) 55*7c5b184dSJason Gunthorpe static_assert(log2_set_mod_t(unsigned int, 3, 1, 2) == 1); 56*7c5b184dSJason Gunthorpe 57*7c5b184dSJason Gunthorpe /* Return a value such that: 58*7c5b184dSJason Gunthorpe * a / b == ret / b 59*7c5b184dSJason Gunthorpe * ret % b == b - 1 60*7c5b184dSJason Gunthorpe * aka set the low bits to all 1s 61*7c5b184dSJason Gunthorpe */ 62*7c5b184dSJason Gunthorpe #define log2_set_mod_max_t(type, a, b_lg2) \ 63*7c5b184dSJason Gunthorpe (((type)(a)) | log2_to_max_int_t(type, b_lg2)) 64*7c5b184dSJason Gunthorpe static_assert(log2_set_mod_max_t(unsigned int, 2, 2) == 3); 65*7c5b184dSJason Gunthorpe 66*7c5b184dSJason Gunthorpe /* Compute a * b */ 67*7c5b184dSJason Gunthorpe #define log2_mul_t(type, a, b_lg2) ((type)(((type)a) << (b_lg2))) 68*7c5b184dSJason Gunthorpe static_assert(log2_mul_t(unsigned int, 2, 2) == 8); 69*7c5b184dSJason Gunthorpe 70*7c5b184dSJason Gunthorpe #define _dispatch_sz(type, fn, a) \ 71*7c5b184dSJason Gunthorpe (sizeof(type) == 4 ? fn##32((u32)a) : fn##64(a)) 72*7c5b184dSJason Gunthorpe 73*7c5b184dSJason Gunthorpe /* 74*7c5b184dSJason Gunthorpe * Return the highest value such that: 75*7c5b184dSJason Gunthorpe * fls_t(u32, 0) == 0 76*7c5b184dSJason Gunthorpe * fls_t(u3, 1) == 1 77*7c5b184dSJason Gunthorpe * a >= log2_to_int(ret - 1) 78*7c5b184dSJason Gunthorpe * aka find last set bit 79*7c5b184dSJason Gunthorpe */ 80*7c5b184dSJason Gunthorpe static inline unsigned int fls32(u32 a) 81*7c5b184dSJason Gunthorpe { 82*7c5b184dSJason Gunthorpe return fls(a); 83*7c5b184dSJason Gunthorpe } 84*7c5b184dSJason Gunthorpe #define fls_t(type, a) _dispatch_sz(type, fls, a) 85*7c5b184dSJason Gunthorpe 86*7c5b184dSJason Gunthorpe /* 87*7c5b184dSJason Gunthorpe * Return the highest value such that: 88*7c5b184dSJason Gunthorpe * ffs_t(u32, 0) == UNDEFINED 89*7c5b184dSJason Gunthorpe * ffs_t(u32, 1) == 0 90*7c5b184dSJason Gunthorpe * log_mod(a, ret) == 0 91*7c5b184dSJason Gunthorpe * aka find first set bit 92*7c5b184dSJason Gunthorpe */ 93*7c5b184dSJason Gunthorpe static inline unsigned int __ffs32(u32 a) 94*7c5b184dSJason Gunthorpe { 95*7c5b184dSJason Gunthorpe return __ffs(a); 96*7c5b184dSJason Gunthorpe } 97*7c5b184dSJason Gunthorpe #define ffs_t(type, a) _dispatch_sz(type, __ffs, a) 98*7c5b184dSJason Gunthorpe 99*7c5b184dSJason Gunthorpe /* 100*7c5b184dSJason Gunthorpe * Return the highest value such that: 101*7c5b184dSJason Gunthorpe * ffz_t(u32, U32_MAX) == UNDEFINED 102*7c5b184dSJason Gunthorpe * ffz_t(u32, 0) == 0 103*7c5b184dSJason Gunthorpe * ffz_t(u32, 1) == 1 104*7c5b184dSJason Gunthorpe * log_mod(a, ret) == log_to_max_int(ret) 105*7c5b184dSJason Gunthorpe * aka find first zero bit 106*7c5b184dSJason Gunthorpe */ 107*7c5b184dSJason Gunthorpe static inline unsigned int ffz32(u32 a) 108*7c5b184dSJason Gunthorpe { 109*7c5b184dSJason Gunthorpe return ffz(a); 110*7c5b184dSJason Gunthorpe } 111*7c5b184dSJason Gunthorpe static inline unsigned int ffz64(u64 a) 112*7c5b184dSJason Gunthorpe { 113*7c5b184dSJason Gunthorpe if (sizeof(u64) == sizeof(unsigned long)) 114*7c5b184dSJason Gunthorpe return ffz(a); 115*7c5b184dSJason Gunthorpe 116*7c5b184dSJason Gunthorpe if ((u32)a == U32_MAX) 117*7c5b184dSJason Gunthorpe return ffz32(a >> 32) + 32; 118*7c5b184dSJason Gunthorpe return ffz32(a); 119*7c5b184dSJason Gunthorpe } 120*7c5b184dSJason Gunthorpe #define ffz_t(type, a) _dispatch_sz(type, ffz, a) 121*7c5b184dSJason Gunthorpe 122*7c5b184dSJason Gunthorpe #endif 123