1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * An extensible bitmap is a bitmap that supports an
4 * arbitrary number of bits.  Extensible bitmaps are
5 * used to represent sets of values, such as types,
6 * roles, categories, and classes.
7 *
8 * Each extensible bitmap is implemented as a linked
9 * list of bitmap nodes, where each bitmap node has
10 * an explicitly specified starting bit position within
11 * the total bitmap.
12 *
13 * Author : Stephen Smalley, <stephen.smalley.work@gmail.com>
14 */
15
16#ifndef _SS_EBITMAP_H_
17#define _SS_EBITMAP_H_
18
19#include <net/netlabel.h>
20
21#ifdef CONFIG_64BIT
22#define EBITMAP_NODE_SIZE 64
23#else
24#define EBITMAP_NODE_SIZE 32
25#endif
26
27#define EBITMAP_UNIT_NUMS                                     \
28	((EBITMAP_NODE_SIZE - sizeof(void *) - sizeof(u32)) / \
29	 sizeof(unsigned long))
30#define EBITMAP_UNIT_SIZE BITS_PER_LONG
31#define EBITMAP_SIZE	  (EBITMAP_UNIT_NUMS * EBITMAP_UNIT_SIZE)
32#define EBITMAP_BIT	  1ULL
33#define EBITMAP_SHIFT_UNIT_SIZE(x) \
34	(((x) >> EBITMAP_UNIT_SIZE / 2) >> EBITMAP_UNIT_SIZE / 2)
35
36struct ebitmap_node {
37	struct ebitmap_node *next;
38	unsigned long maps[EBITMAP_UNIT_NUMS];
39	u32 startbit;
40};
41
42struct ebitmap {
43	struct ebitmap_node *node; /* first node in the bitmap */
44	u32 highbit; /* highest position in the total bitmap */
45};
46
47#define ebitmap_length(e) ((e)->highbit)
48
49static inline unsigned int ebitmap_start_positive(const struct ebitmap *e,
50						  struct ebitmap_node **n)
51{
52	unsigned int ofs;
53
54	for (*n = e->node; *n; *n = (*n)->next) {
55		ofs = find_first_bit((*n)->maps, EBITMAP_SIZE);
56		if (ofs < EBITMAP_SIZE)
57			return (*n)->startbit + ofs;
58	}
59	return ebitmap_length(e);
60}
61
62static inline void ebitmap_init(struct ebitmap *e)
63{
64	memset(e, 0, sizeof(*e));
65}
66
67static inline unsigned int ebitmap_next_positive(const struct ebitmap *e,
68						 struct ebitmap_node **n,
69						 unsigned int bit)
70{
71	unsigned int ofs;
72
73	ofs = find_next_bit((*n)->maps, EBITMAP_SIZE, bit - (*n)->startbit + 1);
74	if (ofs < EBITMAP_SIZE)
75		return ofs + (*n)->startbit;
76
77	for (*n = (*n)->next; *n; *n = (*n)->next) {
78		ofs = find_first_bit((*n)->maps, EBITMAP_SIZE);
79		if (ofs < EBITMAP_SIZE)
80			return ofs + (*n)->startbit;
81	}
82	return ebitmap_length(e);
83}
84
85#define EBITMAP_NODE_INDEX(node, bit) \
86	(((bit) - (node)->startbit) / EBITMAP_UNIT_SIZE)
87#define EBITMAP_NODE_OFFSET(node, bit) \
88	(((bit) - (node)->startbit) % EBITMAP_UNIT_SIZE)
89
90static inline int ebitmap_node_get_bit(const struct ebitmap_node *n,
91				       unsigned int bit)
92{
93	unsigned int index = EBITMAP_NODE_INDEX(n, bit);
94	unsigned int ofs = EBITMAP_NODE_OFFSET(n, bit);
95
96	BUG_ON(index >= EBITMAP_UNIT_NUMS);
97	if ((n->maps[index] & (EBITMAP_BIT << ofs)))
98		return 1;
99	return 0;
100}
101
102static inline void ebitmap_node_set_bit(struct ebitmap_node *n,
103					unsigned int bit)
104{
105	unsigned int index = EBITMAP_NODE_INDEX(n, bit);
106	unsigned int ofs = EBITMAP_NODE_OFFSET(n, bit);
107
108	BUG_ON(index >= EBITMAP_UNIT_NUMS);
109	n->maps[index] |= (EBITMAP_BIT << ofs);
110}
111
112static inline void ebitmap_node_clr_bit(struct ebitmap_node *n,
113					unsigned int bit)
114{
115	unsigned int index = EBITMAP_NODE_INDEX(n, bit);
116	unsigned int ofs = EBITMAP_NODE_OFFSET(n, bit);
117
118	BUG_ON(index >= EBITMAP_UNIT_NUMS);
119	n->maps[index] &= ~(EBITMAP_BIT << ofs);
120}
121
122#define ebitmap_for_each_positive_bit(e, n, bit)      \
123	for ((bit) = ebitmap_start_positive(e, &(n)); \
124	     (bit) < ebitmap_length(e);               \
125	     (bit) = ebitmap_next_positive(e, &(n), bit))
126
127int ebitmap_cmp(const struct ebitmap *e1, const struct ebitmap *e2);
128int ebitmap_cpy(struct ebitmap *dst, const struct ebitmap *src);
129int ebitmap_and(struct ebitmap *dst, const struct ebitmap *e1,
130		const struct ebitmap *e2);
131int ebitmap_contains(const struct ebitmap *e1, const struct ebitmap *e2,
132		     u32 last_e2bit);
133int ebitmap_get_bit(const struct ebitmap *e, unsigned long bit);
134int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value);
135void ebitmap_destroy(struct ebitmap *e);
136int ebitmap_read(struct ebitmap *e, void *fp);
137int ebitmap_write(const struct ebitmap *e, void *fp);
138u32 ebitmap_hash(const struct ebitmap *e, u32 hash);
139
140#ifdef CONFIG_NETLABEL
141int ebitmap_netlbl_export(struct ebitmap *ebmap,
142			  struct netlbl_lsm_catmap **catmap);
143int ebitmap_netlbl_import(struct ebitmap *ebmap,
144			  struct netlbl_lsm_catmap *catmap);
145#else
146static inline int ebitmap_netlbl_export(struct ebitmap *ebmap,
147					struct netlbl_lsm_catmap **catmap)
148{
149	return -ENOMEM;
150}
151static inline int ebitmap_netlbl_import(struct ebitmap *ebmap,
152					struct netlbl_lsm_catmap *catmap)
153{
154	return -ENOMEM;
155}
156#endif
157
158#endif /* _SS_EBITMAP_H_ */
159