cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

generic-radix-tree.h (6527B)


      1#ifndef _LINUX_GENERIC_RADIX_TREE_H
      2#define _LINUX_GENERIC_RADIX_TREE_H
      3
      4/**
      5 * DOC: Generic radix trees/sparse arrays
      6 *
      7 * Very simple and minimalistic, supporting arbitrary size entries up to
      8 * PAGE_SIZE.
      9 *
     10 * A genradix is defined with the type it will store, like so:
     11 *
     12 * static GENRADIX(struct foo) foo_genradix;
     13 *
     14 * The main operations are:
     15 *
     16 * - genradix_init(radix) - initialize an empty genradix
     17 *
     18 * - genradix_free(radix) - free all memory owned by the genradix and
     19 *   reinitialize it
     20 *
     21 * - genradix_ptr(radix, idx) - gets a pointer to the entry at idx, returning
     22 *   NULL if that entry does not exist
     23 *
     24 * - genradix_ptr_alloc(radix, idx, gfp) - gets a pointer to an entry,
     25 *   allocating it if necessary
     26 *
     27 * - genradix_for_each(radix, iter, p) - iterate over each entry in a genradix
     28 *
     29 * The radix tree allocates one page of entries at a time, so entries may exist
     30 * that were never explicitly allocated - they will be initialized to all
     31 * zeroes.
     32 *
     33 * Internally, a genradix is just a radix tree of pages, and indexing works in
     34 * terms of byte offsets. The wrappers in this header file use sizeof on the
     35 * type the radix contains to calculate a byte offset from the index - see
     36 * __idx_to_offset.
     37 */
     38
     39#include <asm/page.h>
     40#include <linux/bug.h>
     41#include <linux/log2.h>
     42#include <linux/math.h>
     43#include <linux/types.h>
     44
     45struct genradix_root;
     46
     47struct __genradix {
     48	struct genradix_root		*root;
     49};
     50
     51/*
     52 * NOTE: currently, sizeof(_type) must not be larger than PAGE_SIZE:
     53 */
     54
     55#define __GENRADIX_INITIALIZER					\
     56	{							\
     57		.tree = {					\
     58			.root = NULL,				\
     59		}						\
     60	}
     61
     62/*
     63 * We use a 0 size array to stash the type we're storing without taking any
     64 * space at runtime - then the various accessor macros can use typeof() to get
     65 * to it for casts/sizeof - we also force the alignment so that storing a type
     66 * with a ridiculous alignment doesn't blow up the alignment or size of the
     67 * genradix.
     68 */
     69
     70#define GENRADIX(_type)						\
     71struct {							\
     72	struct __genradix	tree;				\
     73	_type			type[0] __aligned(1);		\
     74}
     75
     76#define DEFINE_GENRADIX(_name, _type)				\
     77	GENRADIX(_type) _name = __GENRADIX_INITIALIZER
     78
     79/**
     80 * genradix_init - initialize a genradix
     81 * @_radix:	genradix to initialize
     82 *
     83 * Does not fail
     84 */
     85#define genradix_init(_radix)					\
     86do {								\
     87	*(_radix) = (typeof(*_radix)) __GENRADIX_INITIALIZER;	\
     88} while (0)
     89
     90void __genradix_free(struct __genradix *);
     91
     92/**
     93 * genradix_free: free all memory owned by a genradix
     94 * @_radix: the genradix to free
     95 *
     96 * After freeing, @_radix will be reinitialized and empty
     97 */
     98#define genradix_free(_radix)	__genradix_free(&(_radix)->tree)
     99
    100static inline size_t __idx_to_offset(size_t idx, size_t obj_size)
    101{
    102	if (__builtin_constant_p(obj_size))
    103		BUILD_BUG_ON(obj_size > PAGE_SIZE);
    104	else
    105		BUG_ON(obj_size > PAGE_SIZE);
    106
    107	if (!is_power_of_2(obj_size)) {
    108		size_t objs_per_page = PAGE_SIZE / obj_size;
    109
    110		return (idx / objs_per_page) * PAGE_SIZE +
    111			(idx % objs_per_page) * obj_size;
    112	} else {
    113		return idx * obj_size;
    114	}
    115}
    116
    117#define __genradix_cast(_radix)		(typeof((_radix)->type[0]) *)
    118#define __genradix_obj_size(_radix)	sizeof((_radix)->type[0])
    119#define __genradix_idx_to_offset(_radix, _idx)			\
    120	__idx_to_offset(_idx, __genradix_obj_size(_radix))
    121
    122void *__genradix_ptr(struct __genradix *, size_t);
    123
    124/**
    125 * genradix_ptr - get a pointer to a genradix entry
    126 * @_radix:	genradix to access
    127 * @_idx:	index to fetch
    128 *
    129 * Returns a pointer to entry at @_idx, or NULL if that entry does not exist.
    130 */
    131#define genradix_ptr(_radix, _idx)				\
    132	(__genradix_cast(_radix)				\
    133	 __genradix_ptr(&(_radix)->tree,			\
    134			__genradix_idx_to_offset(_radix, _idx)))
    135
    136void *__genradix_ptr_alloc(struct __genradix *, size_t, gfp_t);
    137
    138/**
    139 * genradix_ptr_alloc - get a pointer to a genradix entry, allocating it
    140 *			if necessary
    141 * @_radix:	genradix to access
    142 * @_idx:	index to fetch
    143 * @_gfp:	gfp mask
    144 *
    145 * Returns a pointer to entry at @_idx, or NULL on allocation failure
    146 */
    147#define genradix_ptr_alloc(_radix, _idx, _gfp)			\
    148	(__genradix_cast(_radix)				\
    149	 __genradix_ptr_alloc(&(_radix)->tree,			\
    150			__genradix_idx_to_offset(_radix, _idx),	\
    151			_gfp))
    152
    153struct genradix_iter {
    154	size_t			offset;
    155	size_t			pos;
    156};
    157
    158/**
    159 * genradix_iter_init - initialize a genradix_iter
    160 * @_radix:	genradix that will be iterated over
    161 * @_idx:	index to start iterating from
    162 */
    163#define genradix_iter_init(_radix, _idx)			\
    164	((struct genradix_iter) {				\
    165		.pos	= (_idx),				\
    166		.offset	= __genradix_idx_to_offset((_radix), (_idx)),\
    167	})
    168
    169void *__genradix_iter_peek(struct genradix_iter *, struct __genradix *, size_t);
    170
    171/**
    172 * genradix_iter_peek - get first entry at or above iterator's current
    173 *			position
    174 * @_iter:	a genradix_iter
    175 * @_radix:	genradix being iterated over
    176 *
    177 * If no more entries exist at or above @_iter's current position, returns NULL
    178 */
    179#define genradix_iter_peek(_iter, _radix)			\
    180	(__genradix_cast(_radix)				\
    181	 __genradix_iter_peek(_iter, &(_radix)->tree,		\
    182			      PAGE_SIZE / __genradix_obj_size(_radix)))
    183
    184static inline void __genradix_iter_advance(struct genradix_iter *iter,
    185					   size_t obj_size)
    186{
    187	iter->offset += obj_size;
    188
    189	if (!is_power_of_2(obj_size) &&
    190	    (iter->offset & (PAGE_SIZE - 1)) + obj_size > PAGE_SIZE)
    191		iter->offset = round_up(iter->offset, PAGE_SIZE);
    192
    193	iter->pos++;
    194}
    195
    196#define genradix_iter_advance(_iter, _radix)			\
    197	__genradix_iter_advance(_iter, __genradix_obj_size(_radix))
    198
    199#define genradix_for_each_from(_radix, _iter, _p, _start)	\
    200	for (_iter = genradix_iter_init(_radix, _start);	\
    201	     (_p = genradix_iter_peek(&_iter, _radix)) != NULL;	\
    202	     genradix_iter_advance(&_iter, _radix))
    203
    204/**
    205 * genradix_for_each - iterate over entry in a genradix
    206 * @_radix:	genradix to iterate over
    207 * @_iter:	a genradix_iter to track current position
    208 * @_p:		pointer to genradix entry type
    209 *
    210 * On every iteration, @_p will point to the current entry, and @_iter.pos
    211 * will be the current entry's index.
    212 */
    213#define genradix_for_each(_radix, _iter, _p)			\
    214	genradix_for_each_from(_radix, _iter, _p, 0)
    215
    216int __genradix_prealloc(struct __genradix *, size_t, gfp_t);
    217
    218/**
    219 * genradix_prealloc - preallocate entries in a generic radix tree
    220 * @_radix:	genradix to preallocate
    221 * @_nr:	number of entries to preallocate
    222 * @_gfp:	gfp mask
    223 *
    224 * Returns 0 on success, -ENOMEM on failure
    225 */
    226#define genradix_prealloc(_radix, _nr, _gfp)			\
    227	 __genradix_prealloc(&(_radix)->tree,			\
    228			__genradix_idx_to_offset(_radix, _nr + 1),\
    229			_gfp)
    230
    231
    232#endif /* _LINUX_GENERIC_RADIX_TREE_H */