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 (IS_ENABLED(DEBUG))
745 cvmx_coremask_print(pcm);
746 }
747
748 struct cvmx_coremask *octeon_get_available_coremask(struct cvmx_coremask *pcm);
749
750 int validate_coremask(struct cvmx_coremask *pcm);
751
752 #endif /* __CVMX_COREMASK_H__ */
753