1// vi:set ft=cpp: -*- Mode: C++ -*- 2 3#pragma once 4 5#include <l4/sys/consts.h> 6 7namespace L4 { 8 9 /** 10 * Round a value down so the given number of lsb is zero. 11 * 12 * \tparam T The type of the value (shall be some integral type. 13 * \param val The value where the given lsb shall be masked. 14 * \param order the number of least significant bits (lsb) to mask. 15 * \return val with order lsb masked to zero. 16 */ 17 template<typename T> 18 constexpr T trunc_order(T val, unsigned char order) 19 { 20 return val & ((~T(0)) << order); 21 } 22 23 /** 24 * Round a value up so the given number of lsb is zero. 25 * 26 * \tparam T The type of the value (shall be some integral type. 27 * \param val The value to rund up to the next multiple of 2^order. 28 * \param order order (2^order) to round up to. 29 * \return val rounded up to the next 2^order. 30 */ 31 template<typename T> 32 constexpr T round_order(T val, unsigned char order) 33 { 34 return (val + (T(1) << order) - T(1)) & ((~T(0)) << order); 35 } 36 37 template<typename T> 38 constexpr T trunc_page(T val) 39 { 40 return trunc_order(val, L4_PAGESHIFT); 41 } 42 43 template<typename T> 44 constexpr T round_page(T val) 45 { 46 return round_order(val, L4_PAGESHIFT); 47 } 48 49 template<typename T> 50 inline unsigned char 51 max_order(unsigned char order, T addr, 52 T min_addr, T max_addr, 53 T hotspot = T(0)) 54 { 55 while (order < 30 /* limit to 1GB flexpages */) 56 { 57 T mask; 58 T base = trunc_order(addr, order + 1); 59 if (base < min_addr) 60 return order; 61 62 if (base + (T(1) << (order + 1)) - T(1) > max_addr - T(1)) 63 return order; 64 65 mask = ~((~T(0)) << (order + 1)); 66 if (hotspot == ~T(0) || ((addr ^ hotspot) & mask)) 67 break; 68 69 ++order; 70 } 71 72 return order; 73 } 74 75} 76