1210284Sjmallett/***********************license start***************
2232812Sjmallett * Copyright (c) 2003-2010  Cavium Inc. (support@cavium.com). All rights
3215990Sjmallett * reserved.
4210284Sjmallett *
5210284Sjmallett *
6215990Sjmallett * Redistribution and use in source and binary forms, with or without
7215990Sjmallett * modification, are permitted provided that the following conditions are
8215990Sjmallett * met:
9210284Sjmallett *
10215990Sjmallett *   * Redistributions of source code must retain the above copyright
11215990Sjmallett *     notice, this list of conditions and the following disclaimer.
12210284Sjmallett *
13215990Sjmallett *   * Redistributions in binary form must reproduce the above
14215990Sjmallett *     copyright notice, this list of conditions and the following
15215990Sjmallett *     disclaimer in the documentation and/or other materials provided
16215990Sjmallett *     with the distribution.
17215990Sjmallett
18232812Sjmallett *   * Neither the name of Cavium Inc. nor the names of
19215990Sjmallett *     its contributors may be used to endorse or promote products
20215990Sjmallett *     derived from this software without specific prior written
21215990Sjmallett *     permission.
22215990Sjmallett
23215990Sjmallett * This Software, including technical data, may be subject to U.S. export  control
24215990Sjmallett * laws, including the U.S. Export Administration Act and its  associated
25215990Sjmallett * regulations, and may be subject to export or import  regulations in other
26215990Sjmallett * countries.
27215990Sjmallett
28215990Sjmallett * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29232812Sjmallett * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
30215990Sjmallett * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
31215990Sjmallett * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
32215990Sjmallett * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
33215990Sjmallett * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
34215990Sjmallett * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
35215990Sjmallett * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
36215990Sjmallett * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE  RISK ARISING OUT OF USE OR
37215990Sjmallett * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38210284Sjmallett ***********************license end**************************************/
39210284Sjmallett
40210284Sjmallett
41210284Sjmallett
42210284Sjmallett
43210284Sjmallett
44210284Sjmallett
45215990Sjmallett
46210284Sjmallett/**
47210284Sjmallett * @file
48210284Sjmallett *
49210284Sjmallett * Module to support operations on bitmap of cores. Coremask can be used to
50210284Sjmallett * select a specific core, a group of cores, or all available cores, for
51210284Sjmallett * initialization and differentiation of roles within a single shared binary
52210284Sjmallett * executable image.
53210284Sjmallett *
54232812Sjmallett * <hr>$Revision: 70030 $<hr>
55210284Sjmallett *
56210284Sjmallett */
57210284Sjmallett
58210284Sjmallett
59210284Sjmallett#ifndef __CVMX_COREMASK_H__
60210284Sjmallett#define __CVMX_COREMASK_H__
61210284Sjmallett
62210284Sjmallett#include "cvmx-asm.h"
63210284Sjmallett
64210284Sjmallett#ifdef	__cplusplus
65210284Sjmallettextern "C" {
66210284Sjmallett#endif
67210284Sjmallett
68232812Sjmalletttypedef uint64_t cvmx_coremask_holder_t;	/* basic type to hold the
69232812Sjmallett						   coremask bits */
70232812Sjmallett
71232812Sjmallett#define CVMX_COREMASK_HLDRSZ ((int)(sizeof(cvmx_coremask_holder_t) * 8))
72232812Sjmallett						/* bits per holder */
73232812Sjmallett
74232812Sjmallett#define CVMX_COREMASK_BMPSZ ((int)(CVMX_MAX_CORES / CVMX_COREMASK_HLDRSZ + 1))
75232812Sjmallett						/* bit map size */
76232812Sjmallett
77210284Sjmallett/*
78232812Sjmallett * The macro pair implement a way to iterate active cores in the mask.
79232812Sjmallett * @param fec_pcm points to the coremask.
80232812Sjmallett * @param fec_ppid is the active core's id.
81232812Sjmallett */
82232812Sjmallett#define CVMX_COREMASK_FOR_EACH_CORE_BEGIN(fec_pcm, fec_ppid)		\
83232812Sjmallett    do {								\
84232812Sjmallett    	int fec_i, fec_j;						\
85232812Sjmallett    				 					\
86232812Sjmallett	for (fec_i = 0; fec_i < CVMX_COREMASK_BMPSZ; fec_i++)		\
87232812Sjmallett	{								\
88232812Sjmallett	    for (fec_j = 0; fec_j < CVMX_COREMASK_HLDRSZ; fec_j++)	\
89232812Sjmallett	    { 								\
90232812Sjmallett		if (((cvmx_coremask_holder_t)1 << fec_j) & 		\
91232812Sjmallett		    (fec_pcm)->coremask_bitmap[fec_i])			\
92232812Sjmallett		{							\
93232812Sjmallett	            fec_ppid = fec_i * CVMX_COREMASK_HLDRSZ + fec_j;
94232812Sjmallett
95232812Sjmallett
96232812Sjmallett#define CVMX_COREMASK_FOR_EACH_CORE_END					\
97232812Sjmallett		}							\
98232812Sjmallett	    }								\
99232812Sjmallett	}								\
100232812Sjmallett   } while (0)
101232812Sjmallett
102232812Sjmallettstruct cvmx_coremask {
103232812Sjmallett    /*
104232812Sjmallett     * Big-endian. Array elems of larger indices represent cores of
105232812Sjmallett     * bigger ids. So do MSBs within a cvmx_coremask_holder_t. Ditto
106232812Sjmallett     * MSbs within a byte.
107232812Sjmallett     */
108232812Sjmallett    cvmx_coremask_holder_t coremask_bitmap[CVMX_COREMASK_BMPSZ];
109232812Sjmallett};
110232812Sjmallett
111232812Sjmallett/*
112232812Sjmallett * Is ``core'' set in the coremask?
113232812Sjmallett *
114232812Sjmallett * @param pcm is the pointer to the coremask.
115232812Sjmallett * @param core
116232812Sjmallett * @return 1 if core is set and 0 if not.
117232812Sjmallett */
118232812Sjmallettstatic inline int cvmx_coremask_is_set_core(struct cvmx_coremask *pcm,
119232812Sjmallett    int core)
120232812Sjmallett{
121232812Sjmallett    int n, i;
122232812Sjmallett
123232812Sjmallett    n = core % CVMX_COREMASK_HLDRSZ;
124232812Sjmallett    i = core / CVMX_COREMASK_HLDRSZ;
125232812Sjmallett
126232812Sjmallett    return (int)((pcm->coremask_bitmap[i] & (1ull << n)) != 0);
127232812Sjmallett}
128232812Sjmallett
129232812Sjmallett/*
130232812Sjmallett * Set ``core'' in the coremask.
131232812Sjmallett *
132232812Sjmallett * @param pcm is the pointer to the coremask.
133232812Sjmallett * @param core
134232812Sjmallett * @return 0.
135232812Sjmallett */
136232812Sjmallettstatic inline int cvmx_coremask_set_core(struct cvmx_coremask *pcm,
137232812Sjmallett    int core)
138232812Sjmallett{
139232812Sjmallett    int n, i;
140232812Sjmallett
141232812Sjmallett    n = core % CVMX_COREMASK_HLDRSZ;
142232812Sjmallett    i = core / CVMX_COREMASK_HLDRSZ;
143232812Sjmallett    pcm->coremask_bitmap[i] |= (1ull << n);
144232812Sjmallett
145232812Sjmallett    return 0;
146232812Sjmallett}
147232812Sjmallett
148232812Sjmallett/*
149232812Sjmallett * Clear ``core'' from the coremask.
150232812Sjmallett *
151232812Sjmallett * @param pcm is the pointer to the coremask.
152232812Sjmallett * @param core
153232812Sjmallett * @return 0.
154232812Sjmallett */
155232812Sjmallettstatic inline int cvmx_coremask_clear_core(struct cvmx_coremask *pcm,
156232812Sjmallett    int core)
157232812Sjmallett{
158232812Sjmallett    int n, i;
159232812Sjmallett
160232812Sjmallett    n = core % CVMX_COREMASK_HLDRSZ;
161232812Sjmallett    i = core / CVMX_COREMASK_HLDRSZ;
162232812Sjmallett    pcm->coremask_bitmap[i] &= ~(1ull << n);
163232812Sjmallett
164232812Sjmallett    return 0;
165232812Sjmallett}
166232812Sjmallett
167232812Sjmallett/*
168232812Sjmallett * Clear the coremask.
169232812Sjmallett *
170232812Sjmallett * @param pcm is the pointer to the coremask.
171232812Sjmallett * @return 0.
172232812Sjmallett */
173232812Sjmallettstatic inline int cvmx_coremask_clear_all(struct cvmx_coremask *pcm)
174232812Sjmallett{
175232812Sjmallett    int i;
176232812Sjmallett
177232812Sjmallett    for (i = 0; i < CVMX_COREMASK_BMPSZ; i++)
178232812Sjmallett        pcm->coremask_bitmap[i] = 0;
179232812Sjmallett
180232812Sjmallett    return 0;
181232812Sjmallett}
182232812Sjmallett
183232812Sjmallett/*
184232812Sjmallett * Is the current core the first in the coremask?
185232812Sjmallett *
186232812Sjmallett * @param pcm is the pointer to the coremask.
187232812Sjmallett * @return 1 for yes and 0 for no.
188232812Sjmallett */
189232812Sjmallettstatic inline int cvmx_coremask_first_core_bmp(struct cvmx_coremask *pcm)
190232812Sjmallett{
191232812Sjmallett     int n, i;
192232812Sjmallett
193232812Sjmallett     n = (int) cvmx_get_core_num();
194232812Sjmallett     for (i = 0; i < CVMX_COREMASK_BMPSZ; i++)
195232812Sjmallett     {
196232812Sjmallett         if (pcm->coremask_bitmap[i])
197232812Sjmallett         {
198232812Sjmallett             if (n == 0 && pcm->coremask_bitmap[i] & 1)
199232812Sjmallett                 return 1;
200232812Sjmallett
201232812Sjmallett             if (n >= CVMX_COREMASK_HLDRSZ)
202232812Sjmallett                 return 0;
203232812Sjmallett
204232812Sjmallett             return ((((1ull << n) - 1) & pcm->coremask_bitmap[i]) == 0);
205232812Sjmallett         }
206232812Sjmallett         else
207232812Sjmallett             n -= CVMX_COREMASK_HLDRSZ;
208232812Sjmallett     }
209232812Sjmallett
210232812Sjmallett     return 0;
211232812Sjmallett}
212232812Sjmallett
213232812Sjmallett/*
214232812Sjmallett * Is the current core a member of the coremask?
215232812Sjmallett *
216232812Sjmallett * @param pcm is the pointer to the coremask.
217232812Sjmallett * @return 1 for yes and 0 for no.
218232812Sjmallett */
219232812Sjmallettstatic inline int cvmx_coremask_is_member_bmp(struct cvmx_coremask *pcm)
220232812Sjmallett{
221232812Sjmallett    return cvmx_coremask_is_set_core(pcm, (int)cvmx_get_core_num());
222232812Sjmallett}
223232812Sjmallett
224232812Sjmallett/*
225210284Sjmallett * coremask is simply unsigned int (32 bits).
226210284Sjmallett *
227210284Sjmallett * NOTE: supports up to 32 cores maximum.
228210284Sjmallett *
229210284Sjmallett * union of coremasks is simply bitwise-or.
230210284Sjmallett * intersection of coremasks is simply bitwise-and.
231210284Sjmallett *
232210284Sjmallett */
233210284Sjmallett
234210284Sjmallett#define  CVMX_COREMASK_MAX  0xFFFFFFFFu    /* maximum supported mask */
235210284Sjmallett
236210284Sjmallett
237210284Sjmallett/**
238210284Sjmallett * Compute coremask for a specific core.
239210284Sjmallett *
240210284Sjmallett * @param  core_id  The core ID
241210284Sjmallett *
242210284Sjmallett * @return  coremask for a specific core
243210284Sjmallett *
244210284Sjmallett */
245210284Sjmallettstatic inline unsigned int cvmx_coremask_core(unsigned int core_id)
246210284Sjmallett{
247210284Sjmallett    return (1u << core_id);
248210284Sjmallett}
249210284Sjmallett
250210284Sjmallett/**
251210284Sjmallett * Compute coremask for num_cores cores starting with core 0.
252210284Sjmallett *
253210284Sjmallett * @param  num_cores  number of cores
254210284Sjmallett *
255210284Sjmallett * @return  coremask for num_cores cores
256210284Sjmallett *
257210284Sjmallett */
258210284Sjmallettstatic inline unsigned int cvmx_coremask_numcores(unsigned int num_cores)
259210284Sjmallett{
260232812Sjmallett    return (CVMX_COREMASK_MAX >> (CVMX_MAX_CORES - num_cores));
261210284Sjmallett}
262210284Sjmallett
263210284Sjmallett/**
264210284Sjmallett * Compute coremask for a range of cores from core low to core high.
265210284Sjmallett *
266210284Sjmallett * @param  low   first core in the range
267210284Sjmallett * @param  high  last core in the range
268210284Sjmallett *
269210284Sjmallett * @return  coremask for the range of cores
270210284Sjmallett *
271210284Sjmallett */
272210284Sjmallettstatic inline unsigned int cvmx_coremask_range(unsigned int low, unsigned int high)
273210284Sjmallett{
274232812Sjmallett    return ((CVMX_COREMASK_MAX >> (CVMX_MAX_CORES - 1 - high + low)) << low);
275210284Sjmallett}
276210284Sjmallett
277210284Sjmallett
278210284Sjmallett/**
279210284Sjmallett * Test to see if current core is a member of coremask.
280210284Sjmallett *
281210284Sjmallett * @param  coremask  the coremask to test against
282210284Sjmallett *
283210284Sjmallett * @return  1 if current core is a member of coremask, 0 otherwise
284210284Sjmallett *
285210284Sjmallett */
286210284Sjmallettstatic inline int cvmx_coremask_is_member(unsigned int coremask)
287210284Sjmallett{
288210284Sjmallett    return ((cvmx_coremask_core(cvmx_get_core_num()) & coremask) != 0);
289210284Sjmallett}
290210284Sjmallett
291210284Sjmallett/**
292210284Sjmallett * Test to see if current core is first core in coremask.
293210284Sjmallett *
294210284Sjmallett * @param  coremask  the coremask to test against
295210284Sjmallett *
296210284Sjmallett * @return  1 if current core is first core in the coremask, 0 otherwise
297210284Sjmallett *
298210284Sjmallett */
299210284Sjmallettstatic inline int cvmx_coremask_first_core(unsigned int coremask)
300210284Sjmallett{
301210284Sjmallett    return cvmx_coremask_is_member(coremask)
302210284Sjmallett        && ((cvmx_get_core_num() == 0) ||
303210284Sjmallett            ((cvmx_coremask_numcores(cvmx_get_core_num()) & coremask) == 0));
304210284Sjmallett}
305210284Sjmallett
306210284Sjmallett/**
307210284Sjmallett * Wait (stall) until all cores in the given coremask has reached this point
308210284Sjmallett * in the program execution before proceeding.
309210284Sjmallett *
310210284Sjmallett * @param  coremask  the group of cores performing the barrier sync
311210284Sjmallett *
312210284Sjmallett */
313210284Sjmallettextern void cvmx_coremask_barrier_sync(unsigned int coremask);
314210284Sjmallett
315210284Sjmallett#ifdef	__cplusplus
316210284Sjmallett}
317210284Sjmallett#endif
318210284Sjmallett
319210284Sjmallett#endif /* __CVMX_COREMASK_H__ */
320