1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Copyright (C) 2020 Marvell International Ltd.
4  */
5 
6 /**
7  * Module to support operations on bitmap of cores. Coremask can be used to
8  * select a specific core, a group of cores, or all available cores, for
9  * initialization and differentiation of roles within a single shared binary
10  * executable image.
11  *
12  * The core numbers used in this file are the same value as what is found in
13  * the COP0_EBASE register and the rdhwr 0 instruction.
14  *
15  * For the CN78XX and other multi-node environments the core numbers are not
16  * contiguous.  The core numbers for the CN78XX are as follows:
17  *
18  * Node 0:	Cores 0 - 47
19  * Node 1:	Cores 128 - 175
20  * Node 2:	Cores 256 - 303
21  * Node 3:	Cores 384 - 431
22  *
23  * The coremask environment generally tries to be node agnostic in order to
24  * provide future compatibility if more cores are added to future processors
25  * or more nodes are supported.
26  */
27 
28 #ifndef __CVMX_COREMASK_H__
29 #define __CVMX_COREMASK_H__
30 
31 #include "cvmx-regs.h"
32 
33 /* bits per holder */
34 #define CVMX_COREMASK_HLDRSZ	((int)(sizeof(u64) * 8))
35 
36 /** Maximum allowed cores per node */
37 #define CVMX_COREMASK_MAX_CORES_PER_NODE	(1 << CVMX_NODE_NO_SHIFT)
38 
39 /** Maximum number of bits actually used in the coremask */
40 #define CVMX_MAX_USED_CORES_BMP	(1 << (CVMX_NODE_NO_SHIFT + CVMX_NODE_BITS))
41 
42 /* the number of valid bits in and the mask of the most significant holder */
43 #define CVMX_COREMASK_MSHLDR_NBITS			\
44 	(CVMX_MIPS_MAX_CORES % CVMX_COREMASK_HLDRSZ)
45 
46 #define CVMX_COREMASK_MSHLDR_MASK				\
47 	((CVMX_COREMASK_MSHLDR_NBITS) ?				\
48 	 (((u64)1 << CVMX_COREMASK_MSHLDR_NBITS) - 1) :		\
49 	 ((u64)-1))
50 
51 /* cvmx_coremask size in u64 */
52 #define CVMX_COREMASK_BMPSZ					\
53 	((int)(CVMX_MIPS_MAX_CORES / CVMX_COREMASK_HLDRSZ +	\
54 	       (CVMX_COREMASK_MSHLDR_NBITS != 0)))
55 
56 #define CVMX_COREMASK_USED_BMPSZ				\
57 	(CVMX_MAX_USED_CORES_BMP / CVMX_COREMASK_HLDRSZ)
58 
59 #define CVMX_COREMASK_BMP_NODE_CORE_IDX(node, core)			\
60 	((((node) << CVMX_NODE_NO_SHIFT) + (core)) / CVMX_COREMASK_HLDRSZ)
61 /**
62  * Maximum available coremask.
63  */
64 #define CVMX_COREMASK_MAX				\
65 	{ {						\
66 			0x0000FFFFFFFFFFFF, 0,		\
67 				0x0000FFFFFFFFFFFF, 0,	\
68 				0x0000FFFFFFFFFFFF, 0,	\
69 				0x0000FFFFFFFFFFFF, 0,	\
70 				0, 0,			\
71 				0, 0,			\
72 				0, 0,			\
73 				0, 0} }
74 
75 /**
76  * Empty coremask
77  */
78 #define CVMX_COREMASK_EMPTY					\
79 	{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }
80 
81 struct cvmx_coremask {
82 	u64 coremask_bitmap[CVMX_COREMASK_BMPSZ];
83 };
84 
85 /**
86  * Macro to iterate through all available cores in a coremask
87  *
88  * @param core - core variable to use to iterate
89  * @param pcm - pointer to core mask
90  *
91  * Use this like a for statement
92  */
93 #define cvmx_coremask_for_each_core(core, pcm)			\
94 	for ((core) = -1;					\
95 	     (core) = cvmx_coremask_next_core((core), pcm),	\
96 		     (core) >= 0;)
97 
98 /**
99  * Given a node and node mask, return the next available node.
100  *
101  * @param node		starting node number
102  * @param node_mask	node mask to use to find the next node
103  *
104  * @return next node number or -1 if no more nodes are available
105  */
cvmx_coremask_next_node(int node,u8 node_mask)106 static inline int cvmx_coremask_next_node(int node, u8 node_mask)
107 {
108 	int next_offset;
109 
110 	next_offset = __builtin_ffs(node_mask >> (node + 1));
111 	if (next_offset == 0)
112 		return -1;
113 	else
114 		return node + next_offset;
115 }
116 
117 /**
118  * Iterate through all nodes in a node mask
119  *
120  * @param node		node iterator variable
121  * @param node_mask	mask to use for iterating
122  *
123  * Use this like a for statement
124  */
125 #define cvmx_coremask_for_each_node(node, node_mask)		\
126 	for ((node) = __builtin_ffs(node_mask) - 1;		\
127 	     (node) >= 0 && (node) < CVMX_MAX_NODES;		\
128 	     (node) = cvmx_coremask_next_node(node, node_mask))
129 
130 /**
131  * Is ``core'' set in the coremask?
132  *
133  * @param pcm is the pointer to the coremask.
134  * @param core
135  * @return 1 if core is set and 0 if not.
136  */
cvmx_coremask_is_core_set(const struct cvmx_coremask * pcm,int core)137 static inline int cvmx_coremask_is_core_set(const struct cvmx_coremask *pcm,
138 					    int core)
139 {
140 	int n, i;
141 
142 	n = core % CVMX_COREMASK_HLDRSZ;
143 	i = core / CVMX_COREMASK_HLDRSZ;
144 
145 	return (pcm->coremask_bitmap[i] & ((u64)1 << n)) != 0;
146 }
147 
148 /**
149  * Is ``current core'' set in the coremask?
150  *
151  * @param pcm is the pointer to the coremask.
152  * @return 1 if core is set and 0 if not.
153  */
cvmx_coremask_is_self_set(const struct cvmx_coremask * pcm)154 static inline int cvmx_coremask_is_self_set(const struct cvmx_coremask *pcm)
155 {
156 	return cvmx_coremask_is_core_set(pcm, (int)cvmx_get_core_num());
157 }
158 
159 /**
160  * Is coremask empty?
161  * @param pcm is the pointer to the coremask.
162  * @return 1 if *pcm is empty (all zeros), 0 if not empty.
163  */
cvmx_coremask_is_empty(const struct cvmx_coremask * pcm)164 static inline int cvmx_coremask_is_empty(const struct cvmx_coremask *pcm)
165 {
166 	int i;
167 
168 	for (i = 0; i < CVMX_COREMASK_USED_BMPSZ; i++)
169 		if (pcm->coremask_bitmap[i] != 0)
170 			return 0;
171 
172 	return 1;
173 }
174 
175 /**
176  * Set ``core'' in the coremask.
177  *
178  * @param pcm is the pointer to the coremask.
179  * @param core
180  * @return 0.
181  */
cvmx_coremask_set_core(struct cvmx_coremask * pcm,int core)182 static inline int cvmx_coremask_set_core(struct cvmx_coremask *pcm, int core)
183 {
184 	int n, i;
185 
186 	n = core % CVMX_COREMASK_HLDRSZ;
187 	i = core / CVMX_COREMASK_HLDRSZ;
188 	pcm->coremask_bitmap[i] |= ((u64)1 << n);
189 
190 	return 0;
191 }
192 
193 /**
194  * Set ``current core'' in the coremask.
195  *
196  * @param pcm is the pointer to the coremask.
197  * @return 0.
198  */
cvmx_coremask_set_self(struct cvmx_coremask * pcm)199 static inline int cvmx_coremask_set_self(struct cvmx_coremask *pcm)
200 {
201 	return cvmx_coremask_set_core(pcm, (int)cvmx_get_core_num());
202 }
203 
204 /**
205  * Clear ``core'' from the coremask.
206  *
207  * @param pcm is the pointer to the coremask.
208  * @param core
209  * @return 0.
210  */
cvmx_coremask_clear_core(struct cvmx_coremask * pcm,int core)211 static inline int cvmx_coremask_clear_core(struct cvmx_coremask *pcm, int core)
212 {
213 	int n, i;
214 
215 	n = core % CVMX_COREMASK_HLDRSZ;
216 	i = core / CVMX_COREMASK_HLDRSZ;
217 	pcm->coremask_bitmap[i] &= ~((u64)1 << n);
218 
219 	return 0;
220 }
221 
222 /**
223  * Clear ``current core'' from the coremask.
224  *
225  * @param pcm is the pointer to the coremask.
226  * @return 0.
227  */
cvmx_coremask_clear_self(struct cvmx_coremask * pcm)228 static inline int cvmx_coremask_clear_self(struct cvmx_coremask *pcm)
229 {
230 	return cvmx_coremask_clear_core(pcm, cvmx_get_core_num());
231 }
232 
233 /**
234  * Toggle ``core'' in the coremask.
235  *
236  * @param pcm is the pointer to the coremask.
237  * @param core
238  * @return 0.
239  */
cvmx_coremask_toggle_core(struct cvmx_coremask * pcm,int core)240 static inline int cvmx_coremask_toggle_core(struct cvmx_coremask *pcm, int core)
241 {
242 	int n, i;
243 
244 	n = core % CVMX_COREMASK_HLDRSZ;
245 	i = core / CVMX_COREMASK_HLDRSZ;
246 	pcm->coremask_bitmap[i] ^= ((u64)1 << n);
247 
248 	return 0;
249 }
250 
251 /**
252  * Toggle ``current core'' in the coremask.
253  *
254  * @param pcm is the pointer to the coremask.
255  * @return 0.
256  */
cvmx_coremask_toggle_self(struct cvmx_coremask * pcm)257 static inline int cvmx_coremask_toggle_self(struct cvmx_coremask *pcm)
258 {
259 	return cvmx_coremask_toggle_core(pcm, cvmx_get_core_num());
260 }
261 
262 /**
263  * Set the lower 64-bit of the coremask.
264  * @param pcm	pointer to coremask
265  * @param coremask_64	64-bit coremask to apply to the first node (0)
266  */
cvmx_coremask_set64(struct cvmx_coremask * pcm,u64 coremask_64)267 static inline void cvmx_coremask_set64(struct cvmx_coremask *pcm,
268 				       u64 coremask_64)
269 {
270 	pcm->coremask_bitmap[0] = coremask_64;
271 }
272 
273 /**
274  * Set the 64-bit of the coremask for a particular node.
275  * @param pcm	pointer to coremask
276  * @param node	node to set
277  * @param coremask_64	64-bit coremask to apply to the specified node
278  */
cvmx_coremask_set64_node(struct cvmx_coremask * pcm,u8 node,u64 coremask_64)279 static inline void cvmx_coremask_set64_node(struct cvmx_coremask *pcm,
280 					    u8 node,
281 					    u64 coremask_64)
282 {
283 	pcm->coremask_bitmap[CVMX_COREMASK_BMP_NODE_CORE_IDX(node, 0)] =
284 		coremask_64;
285 }
286 
287 /**
288  * Gets the lower 64-bits of the coremask
289  *
290  * @param[in] pcm - pointer to coremask
291  * @return 64-bit coremask for the first node
292  */
cvmx_coremask_get64(const struct cvmx_coremask * pcm)293 static inline u64 cvmx_coremask_get64(const struct cvmx_coremask *pcm)
294 {
295 	return pcm->coremask_bitmap[0];
296 }
297 
298 /**
299  * Gets the lower 64-bits of the coremask for the specified node
300  *
301  * @param[in] pcm - pointer to coremask
302  * @param node - node to get coremask for
303  * @return 64-bit coremask for the first node
304  */
cvmx_coremask_get64_node(const struct cvmx_coremask * pcm,u8 node)305 static inline u64 cvmx_coremask_get64_node(const struct cvmx_coremask *pcm,
306 					   u8 node)
307 {
308 	return pcm->coremask_bitmap[CVMX_COREMASK_BMP_NODE_CORE_IDX(node, 0)];
309 }
310 
311 /**
312  * Gets the lower 32-bits of the coremask for compatibility
313  *
314  * @param[in] pcm - pointer to coremask
315  * @return 32-bit coremask for the first node
316  * @deprecated This function is to maintain compatibility with older
317  *             SDK applications and may disappear at some point.
318  * This function is not compatible with the CN78XX or any other
319  * Octeon device with more than 32 cores.
320  */
cvmx_coremask_get32(const struct cvmx_coremask * pcm)321 static inline u32 cvmx_coremask_get32(const struct cvmx_coremask *pcm)
322 {
323 	return pcm->coremask_bitmap[0] & 0xffffffff;
324 }
325 
326 /*
327  * cvmx_coremask_cmp() returns an integer less than, equal to, or
328  * greater than zero if *pcm1 is found, respectively, to be less than,
329  * to match, or be greater than *pcm2.
330  */
cvmx_coremask_cmp(const struct cvmx_coremask * pcm1,const struct cvmx_coremask * pcm2)331 static inline int cvmx_coremask_cmp(const struct cvmx_coremask *pcm1,
332 				    const struct cvmx_coremask *pcm2)
333 {
334 	int i;
335 
336 	/* Start from highest node for arithemtically correct result */
337 	for (i = CVMX_COREMASK_USED_BMPSZ - 1; i >= 0; i--)
338 		if (pcm1->coremask_bitmap[i] != pcm2->coremask_bitmap[i]) {
339 			return (pcm1->coremask_bitmap[i] >
340 				pcm2->coremask_bitmap[i]) ? 1 : -1;
341 		}
342 
343 	return 0;
344 }
345 
346 /*
347  * cvmx_coremask_OPx(pcm1, pcm2[, pcm3]), where OPx can be
348  * - and
349  * - or
350  * - xor
351  * - not
352  * ...
353  * For binary operators, pcm3 <-- pcm1 OPX pcm2.
354  * For unaries, pcm2 <-- OPx pcm1.
355  */
356 #define CVMX_COREMASK_BINARY_DEFUN(binary_op, op)		\
357 	static inline int cvmx_coremask_##binary_op(		\
358 		struct cvmx_coremask *pcm1,				\
359 		const struct cvmx_coremask *pcm2,			\
360 		const struct cvmx_coremask *pcm3)			\
361 	{							\
362 		int i;						\
363 								\
364 		for (i = 0; i < CVMX_COREMASK_USED_BMPSZ; i++)	\
365 			pcm1->coremask_bitmap[i] =		\
366 				pcm2->coremask_bitmap[i]	\
367 				op				\
368 				pcm3->coremask_bitmap[i];	\
369 								\
370 		return 0;					\
371 	}
372 
373 #define CVMX_COREMASK_UNARY_DEFUN(unary_op, op)			\
374 	static inline int cvmx_coremask_##unary_op(		\
375 		struct cvmx_coremask *pcm1,				\
376 		const struct cvmx_coremask *pcm2)			\
377 	{							\
378 		int i;						\
379 								\
380 		for (i = 0; i < CVMX_COREMASK_USED_BMPSZ; i++)	\
381 			pcm1->coremask_bitmap[i] =		\
382 				op				\
383 				pcm2->coremask_bitmap[i];	\
384 								\
385 		return 0;					\
386 	}
387 
388 /* cvmx_coremask_and(pcm1, pcm2, pcm3): pcm1 = pmc2 & pmc3 */
389 CVMX_COREMASK_BINARY_DEFUN(and, &)
390 /* cvmx_coremask_or(pcm1, pcm2, pcm3): pcm1 = pmc2 | pmc3  */
391 CVMX_COREMASK_BINARY_DEFUN(or, |)
392 /* cvmx_coremask_xor(pcm1, pcm2, pcm3): pcm1 = pmc2 ^ pmc3 */
393 CVMX_COREMASK_BINARY_DEFUN(xor, ^)
394 /* cvmx_coremask_maskoff(pcm1, pcm2, pcm3): pcm1 = pmc2 & ~pmc3 */
395 CVMX_COREMASK_BINARY_DEFUN(maskoff, & ~)
396 /* cvmx_coremask_not(pcm1, pcm2): pcm1 = ~pcm2       */
397 CVMX_COREMASK_UNARY_DEFUN(not, ~)
398 /* cvmx_coremask_fill(pcm1, pcm2): pcm1 = -1      */
399 CVMX_COREMASK_UNARY_DEFUN(fill, -1 |)
400 /* cvmx_coremask_clear(pcm1, pcm2): pcm1 = 0     */
401 CVMX_COREMASK_UNARY_DEFUN(clear, 0 &)
402 /* cvmx_coremask_dup(pcm1, pcm2): pcm1 = pcm2       */
403 CVMX_COREMASK_UNARY_DEFUN(dup, +)
404 
405 /*
406  * Macros using the unary functions defined w/
407  * CVMX_COREMASK_UNARY_DEFUN
408  * - set *pcm to its complement
409  * - set all bits in *pcm to 0
410  * - set all (valid) bits in *pcm to 1
411  */
412 #define cvmx_coremask_complement(pcm)	cvmx_coremask_not(pcm, pcm)
413 /* On clear, even clear the unused bits */
414 #define cvmx_coremask_clear_all(pcm)					\
415 	*(pcm) = (struct cvmx_coremask)CVMX_COREMASK_EMPTY
416 #define cvmx_coremask_set_all(pcm)	cvmx_coremask_fill(pcm, NULL)
417 
418 /*
419  * convert a string of hex digits to struct cvmx_coremask
420  *
421  * @param pcm
422  * @param hexstr can be
423  *	- "[1-9A-Fa-f][0-9A-Fa-f]*", or
424  *	- "-1" to set the bits for all the cores.
425  * return
426  *	 0 for success,
427  *	-1 for string too long (i.e., hexstr takes more bits than
428  *	   CVMX_MIPS_MAX_CORES),
429  *	-2 for conversion problems from hex string to an unsigned
430  *	   long long, e.g., non-hex char in hexstr, and
431  *	-3 for hexstr starting with '0'.
432  * NOTE:
433  *	This function clears the bitmask in *pcm before the conversion.
434  */
435 int cvmx_coremask_str2bmp(struct cvmx_coremask *pcm, char *hexstr);
436 
437 /*
438  * convert a struct cvmx_coremask to a string of hex digits
439  *
440  * @param pcm
441  * @param hexstr is "[1-9A-Fa-f][0-9A-Fa-f]*"
442  *
443  * return 0.
444  */
445 int cvmx_coremask_bmp2str(const struct cvmx_coremask *pcm, char *hexstr);
446 
447 /*
448  * Returns the index of the lowest bit in a coremask holder.
449  */
cvmx_coremask_lowest_bit(u64 h)450 static inline int cvmx_coremask_lowest_bit(u64 h)
451 {
452 	return __builtin_ctzll(h);
453 }
454 
455 /*
456  * Returns the 0-based index of the highest bit in a coremask holder.
457  */
cvmx_coremask_highest_bit(u64 h)458 static inline int cvmx_coremask_highest_bit(u64 h)
459 {
460 	return (64 - __builtin_clzll(h) - 1);
461 }
462 
463 /**
464  * Returns the last core within the coremask and -1 when the coremask
465  * is empty.
466  *
467  * @param[in] pcm - pointer to coremask
468  * @returns last core set in the coremask or -1 if all clear
469  *
470  */
cvmx_coremask_get_last_core(const struct cvmx_coremask * pcm)471 static inline int cvmx_coremask_get_last_core(const struct cvmx_coremask *pcm)
472 {
473 	int i;
474 	int found = -1;
475 
476 	for (i = 0; i < CVMX_COREMASK_USED_BMPSZ; i++) {
477 		if (pcm->coremask_bitmap[i])
478 			found = i;
479 	}
480 
481 	if (found == -1)
482 		return -1;
483 
484 	return found * CVMX_COREMASK_HLDRSZ +
485 		cvmx_coremask_highest_bit(pcm->coremask_bitmap[found]);
486 }
487 
488 /**
489  * Returns the first core within the coremask and -1 when the coremask
490  * is empty.
491  *
492  * @param[in] pcm - pointer to coremask
493  * @returns first core set in the coremask or -1 if all clear
494  *
495  */
cvmx_coremask_get_first_core(const struct cvmx_coremask * pcm)496 static inline int cvmx_coremask_get_first_core(const struct cvmx_coremask *pcm)
497 {
498 	int i;
499 
500 	for (i = 0; i < CVMX_COREMASK_USED_BMPSZ; i++)
501 		if (pcm->coremask_bitmap[i])
502 			break;
503 
504 	if (i == CVMX_COREMASK_USED_BMPSZ)
505 		return -1;
506 
507 	return i * CVMX_COREMASK_HLDRSZ +
508 		cvmx_coremask_lowest_bit(pcm->coremask_bitmap[i]);
509 }
510 
511 /**
512  * Given a core and coremask, return the next available core in the coremask
513  * or -1 if none are available.
514  *
515  * @param core - starting core to check (can be -1 for core 0)
516  * @param pcm - pointer to coremask to check for the next core.
517  *
518  * @return next core following the core parameter or -1 if no more cores.
519  */
cvmx_coremask_next_core(int core,const struct cvmx_coremask * pcm)520 static inline int cvmx_coremask_next_core(int core,
521 					  const struct cvmx_coremask *pcm)
522 {
523 	int n, i;
524 
525 	core++;
526 	n = core % CVMX_COREMASK_HLDRSZ;
527 	i = core / CVMX_COREMASK_HLDRSZ;
528 
529 	if (pcm->coremask_bitmap[i] != 0) {
530 		for (; n < CVMX_COREMASK_HLDRSZ; n++)
531 			if (pcm->coremask_bitmap[i] & (1ULL << n))
532 				return ((i * CVMX_COREMASK_HLDRSZ) + n);
533 	}
534 
535 	for (i = i + 1; i < CVMX_COREMASK_USED_BMPSZ; i++) {
536 		if (pcm->coremask_bitmap[i] != 0)
537 			return (i * CVMX_COREMASK_HLDRSZ) +
538 				cvmx_coremask_lowest_bit(pcm->coremask_bitmap[i]);
539 	}
540 	return -1;
541 }
542 
543 /**
544  * Compute coremask for count cores starting with start_core.
545  * Note that the coremask for multi-node processors may have
546  * gaps.
547  *
548  * @param[out]  pcm        pointer to core mask data structure
549  * @param	start_core starting code number
550  * @param       count      number of cores
551  *
552  */
cvmx_coremask_set_cores(struct cvmx_coremask * pcm,unsigned int start_core,unsigned int count)553 static inline void cvmx_coremask_set_cores(struct cvmx_coremask *pcm,
554 					   unsigned int start_core,
555 					   unsigned int count)
556 {
557 	int node;
558 	int core;	/** Current core in node */
559 	int cores_in_node;
560 	int i;
561 
562 	assert(CVMX_MAX_CORES < CVMX_COREMASK_HLDRSZ);
563 	node = start_core >> CVMX_NODE_NO_SHIFT;
564 	core = start_core & ((1 << CVMX_NODE_NO_SHIFT) - 1);
565 	assert(core < CVMX_MAX_CORES);
566 
567 	cvmx_coremask_clear_all(pcm);
568 	while (count > 0) {
569 		if (count + core > CVMX_MAX_CORES)
570 			cores_in_node = CVMX_MAX_CORES - core;
571 		else
572 			cores_in_node = count;
573 
574 		i = CVMX_COREMASK_BMP_NODE_CORE_IDX(node, core);
575 		pcm->coremask_bitmap[i] = ((1ULL << cores_in_node) - 1) << core;
576 		count -= cores_in_node;
577 		core = 0;
578 		node++;
579 	}
580 }
581 
582 /**
583  * Makes a copy of a coremask
584  *
585  * @param[out] dest - pointer to destination coremask
586  * @param[in]  src  - pointer to source coremask
587  */
cvmx_coremask_copy(struct cvmx_coremask * dest,const struct cvmx_coremask * src)588 static inline void cvmx_coremask_copy(struct cvmx_coremask *dest,
589 				      const struct cvmx_coremask *src)
590 {
591 	memcpy(dest, src, sizeof(*dest));
592 }
593 
594 /**
595  * Test to see if the specified core is first core in coremask.
596  *
597  * @param[in]  pcm  pointer to the coremask to test against
598  * @param[in]  core core to check
599  *
600  * @return  1 if the core is first core in the coremask, 0 otherwise
601  *
602  */
cvmx_coremask_is_core_first_core(const struct cvmx_coremask * pcm,unsigned int core)603 static inline int cvmx_coremask_is_core_first_core(const struct cvmx_coremask *pcm,
604 						   unsigned int core)
605 {
606 	int n, i;
607 
608 	n = core / CVMX_COREMASK_HLDRSZ;
609 
610 	for (i = 0; i < n; i++)
611 		if (pcm->coremask_bitmap[i] != 0)
612 			return 0;
613 
614 	/* From now on we only care about the core number within an entry */
615 	core &= (CVMX_COREMASK_HLDRSZ - 1);
616 	if (__builtin_ffsll(pcm->coremask_bitmap[n]) < (core + 1))
617 		return 0;
618 
619 	return (__builtin_ffsll(pcm->coremask_bitmap[n]) == core + 1);
620 }
621 
622 /*
623  * NOTE:
624  * cvmx_coremask_is_first_core() was retired due to improper usage.
625  * For inquiring about the current core being the initializing
626  * core for an application, use cvmx_is_init_core().
627  * For simply inquring if the current core is numerically
628  * lowest in a given mask, use :
629  *	cvmx_coremask_is_core_first_core( pcm, dvmx_get_core_num())
630  */
631 
632 /**
633  * Returns the number of 1 bits set in a coremask
634  *
635  * @param[in] pcm - pointer to core mask
636  *
637  * @return number of bits set in the coremask
638  */
cvmx_coremask_get_core_count(const struct cvmx_coremask * pcm)639 static inline int cvmx_coremask_get_core_count(const struct cvmx_coremask *pcm)
640 {
641 	int i;
642 	int count = 0;
643 
644 	for (i = 0; i < CVMX_COREMASK_USED_BMPSZ; i++)
645 		count += __builtin_popcountll(pcm->coremask_bitmap[i]);
646 
647 	return count;
648 }
649 
650 /**
651  * For multi-node systems, return the node a core belongs to.
652  *
653  * @param core - core number (0-1023)
654  *
655  * @return node number core belongs to
656  */
cvmx_coremask_core_to_node(int core)657 static inline int cvmx_coremask_core_to_node(int core)
658 {
659 	return (core >> CVMX_NODE_NO_SHIFT) & CVMX_NODE_MASK;
660 }
661 
662 /**
663  * Given a core number on a multi-node system, return the core number for a
664  * particular node.
665  *
666  * @param core - global core number
667  *
668  * @returns core number local to the node.
669  */
cvmx_coremask_core_on_node(int core)670 static inline int cvmx_coremask_core_on_node(int core)
671 {
672 	return (core & ((1 << CVMX_NODE_NO_SHIFT) - 1));
673 }
674 
675 /**
676  * Returns if one coremask is a subset of another coremask
677  *
678  * @param main - main coremask to test
679  * @param subset - subset coremask to test
680  *
681  * @return 0 if the subset contains cores not in the main coremask or 1 if
682  *         the subset is fully contained in the main coremask.
683  */
cvmx_coremask_is_subset(const struct cvmx_coremask * main,const struct cvmx_coremask * subset)684 static inline int cvmx_coremask_is_subset(const struct cvmx_coremask *main,
685 					  const struct cvmx_coremask *subset)
686 {
687 	int i;
688 
689 	for (i = 0; i < CVMX_COREMASK_USED_BMPSZ; i++)
690 		if ((main->coremask_bitmap[i] & subset->coremask_bitmap[i]) !=
691 		    subset->coremask_bitmap[i])
692 			return 0;
693 	return 1;
694 }
695 
696 /**
697  * Returns if one coremask intersects another coremask
698  *
699  * @param c1 - main coremask to test
700  * @param c2 - subset coremask to test
701  *
702  * @return 1 if coremask c1 intersects coremask c2, 0 if they are exclusive
703  */
cvmx_coremask_intersects(const struct cvmx_coremask * c1,const struct cvmx_coremask * c2)704 static inline int cvmx_coremask_intersects(const struct cvmx_coremask *c1,
705 					   const struct cvmx_coremask *c2)
706 {
707 	int i;
708 
709 	for (i = 0; i < CVMX_COREMASK_USED_BMPSZ; i++)
710 		if ((c1->coremask_bitmap[i] & c2->coremask_bitmap[i]) != 0)
711 			return 1;
712 	return 0;
713 }
714 
715 /**
716  * Masks a single node of a coremask
717  *
718  * @param pcm - coremask to mask [inout]
719  * @param node       - node number to mask against
720  */
cvmx_coremask_mask_node(struct cvmx_coremask * pcm,int node)721 static inline void cvmx_coremask_mask_node(struct cvmx_coremask *pcm, int node)
722 {
723 	int i;
724 
725 	for (i = 0; i < CVMX_COREMASK_BMP_NODE_CORE_IDX(node, 0); i++)
726 		pcm->coremask_bitmap[i] = 0;
727 
728 	for (i = CVMX_COREMASK_BMP_NODE_CORE_IDX(node + 1, 0);
729 	     i < CVMX_COREMASK_USED_BMPSZ; i++)
730 		pcm->coremask_bitmap[i] = 0;
731 }
732 
733 /**
734  * Prints out a coremask in the form of node X: 0x... 0x...
735  *
736  * @param[in] pcm - pointer to core mask
737  *
738  * @return nothing
739  */
740 void cvmx_coremask_print(const struct cvmx_coremask *pcm);
741 
cvmx_coremask_dprint(const struct cvmx_coremask * pcm)742 static inline void cvmx_coremask_dprint(const struct cvmx_coremask *pcm)
743 {
744 #if defined(DEBUG)
745 	cvmx_coremask_print(pcm);
746 #endif
747 }
748 
749 struct cvmx_coremask *octeon_get_available_coremask(struct cvmx_coremask *pcm);
750 
751 int validate_coremask(struct cvmx_coremask *pcm);
752 
753 #endif /* __CVMX_COREMASK_H__ */
754