// vi:set ft=cpp: -*- Mode: C++ -*- #pragma once #include namespace L4 { /** * Round a value down so the given number of lsb is zero. * * \tparam T The type of the value (shall be some integral type. * \param val The value where the given lsb shall be masked. * \param order the number of least significant bits (lsb) to mask. * \return val with order lsb masked to zero. */ template constexpr T trunc_order(T val, unsigned char order) { return val & ((~T(0)) << order); } /** * Round a value up so the given number of lsb is zero. * * \tparam T The type of the value (shall be some integral type. * \param val The value to rund up to the next multiple of 2^order. * \param order order (2^order) to round up to. * \return val rounded up to the next 2^order. */ template constexpr T round_order(T val, unsigned char order) { return (val + (T(1) << order) - T(1)) & ((~T(0)) << order); } template constexpr T trunc_page(T val) { return trunc_order(val, L4_PAGESHIFT); } template constexpr T round_page(T val) { return round_order(val, L4_PAGESHIFT); } template inline unsigned char max_order(unsigned char order, T addr, T min_addr, T max_addr, T hotspot = T(0)) { while (order < 30 /* limit to 1GB flexpages */) { T mask; T base = trunc_order(addr, order + 1); if (base < min_addr) return order; if (base + (T(1) << (order + 1)) - T(1) > max_addr - T(1)) return order; mask = ~((~T(0)) << (order + 1)); if (hotspot == ~T(0) || ((addr ^ hotspot) & mask)) break; ++order; } return order; } }