1fb2f18f8Sesaxe /*
2fb2f18f8Sesaxe * CDDL HEADER START
3fb2f18f8Sesaxe *
4fb2f18f8Sesaxe * The contents of this file are subject to the terms of the
5fb2f18f8Sesaxe * Common Development and Distribution License (the "License").
6fb2f18f8Sesaxe * You may not use this file except in compliance with the License.
7fb2f18f8Sesaxe *
8fb2f18f8Sesaxe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fb2f18f8Sesaxe * or http://www.opensolaris.org/os/licensing.
10fb2f18f8Sesaxe * See the License for the specific language governing permissions
11fb2f18f8Sesaxe * and limitations under the License.
12fb2f18f8Sesaxe *
13fb2f18f8Sesaxe * When distributing Covered Code, include this CDDL HEADER in each
14fb2f18f8Sesaxe * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fb2f18f8Sesaxe * If applicable, add the following below this CDDL HEADER, with the
16fb2f18f8Sesaxe * fields enclosed by brackets "[]" replaced with your own identifying
17fb2f18f8Sesaxe * information: Portions Copyright [yyyy] [name of copyright owner]
18fb2f18f8Sesaxe *
19fb2f18f8Sesaxe * CDDL HEADER END
20fb2f18f8Sesaxe */
21fb2f18f8Sesaxe /*
220e751525SEric Saxe * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23fb2f18f8Sesaxe * Use is subject to license terms.
24fb2f18f8Sesaxe */
25fb2f18f8Sesaxe
26fb2f18f8Sesaxe #include <sys/systm.h>
27fb2f18f8Sesaxe #include <sys/types.h>
28fb2f18f8Sesaxe #include <sys/param.h>
29fb2f18f8Sesaxe #include <sys/thread.h>
30fb2f18f8Sesaxe #include <sys/cpuvar.h>
31fb2f18f8Sesaxe #include <sys/cpupart.h>
32fb2f18f8Sesaxe #include <sys/kmem.h>
33fb2f18f8Sesaxe #include <sys/cmn_err.h>
34fb2f18f8Sesaxe #include <sys/kstat.h>
35fb2f18f8Sesaxe #include <sys/processor.h>
36fb2f18f8Sesaxe #include <sys/disp.h>
37fb2f18f8Sesaxe #include <sys/group.h>
38fb2f18f8Sesaxe #include <sys/pg.h>
39fb2f18f8Sesaxe
40fb2f18f8Sesaxe /*
41fb2f18f8Sesaxe * Processor groups
42fb2f18f8Sesaxe *
43fb2f18f8Sesaxe * With the introduction of Chip Multi-Threaded (CMT) processor architectures,
44fb2f18f8Sesaxe * it is no longer necessarily true that a given physical processor module
45fb2f18f8Sesaxe * will present itself as a single schedulable entity (cpu_t). Rather, each
46fb2f18f8Sesaxe * chip and/or processor core may present itself as one or more "logical" CPUs.
47fb2f18f8Sesaxe *
48fb2f18f8Sesaxe * The logical CPUs presented may share physical components such as caches,
49fb2f18f8Sesaxe * data pipes, execution pipelines, FPUs, etc. It is advantageous to have the
50fb2f18f8Sesaxe * kernel be aware of the relationships existing between logical CPUs so that
51fb2f18f8Sesaxe * the appropriate optmizations may be employed.
52fb2f18f8Sesaxe *
53fb2f18f8Sesaxe * The processor group abstraction represents a set of logical CPUs that
54fb2f18f8Sesaxe * generally share some sort of physical or characteristic relationship.
55fb2f18f8Sesaxe *
56fb2f18f8Sesaxe * In the case of a physical sharing relationship, the CPUs in the group may
57fb2f18f8Sesaxe * share a pipeline, cache or floating point unit. In the case of a logical
58fb2f18f8Sesaxe * relationship, a PG may represent the set of CPUs in a processor set, or the
59fb2f18f8Sesaxe * set of CPUs running at a particular clock speed.
60fb2f18f8Sesaxe *
61fb2f18f8Sesaxe * The generic processor group structure, pg_t, contains the elements generic
62fb2f18f8Sesaxe * to a group of CPUs. Depending on the nature of the CPU relationship
63fb2f18f8Sesaxe * (LOGICAL or PHYSICAL), a pointer to a pg may be recast to a "view" of that
64fb2f18f8Sesaxe * PG where more specific data is represented.
65fb2f18f8Sesaxe *
66fb2f18f8Sesaxe * As an example, a PG representing a PHYSICAL relationship, may be recast to
67fb2f18f8Sesaxe * a pghw_t, where data further describing the hardware sharing relationship
68fb2f18f8Sesaxe * is maintained. See pghw.c and pghw.h for details on physical PGs.
69fb2f18f8Sesaxe *
70fb2f18f8Sesaxe * At this time a more specialized casting of a PG representing a LOGICAL
71fb2f18f8Sesaxe * relationship has not been implemented, but the architecture allows for this
72fb2f18f8Sesaxe * in the future.
73fb2f18f8Sesaxe *
74fb2f18f8Sesaxe * Processor Group Classes
75fb2f18f8Sesaxe *
76fb2f18f8Sesaxe * Processor group consumers may wish to maintain and associate specific
77fb2f18f8Sesaxe * data with the PGs they create. For this reason, a mechanism for creating
78fb2f18f8Sesaxe * class specific PGs exists. Classes may overload the default functions for
79fb2f18f8Sesaxe * creating, destroying, and associating CPUs with PGs, and may also register
80fb2f18f8Sesaxe * class specific callbacks to be invoked when the CPU related system
81fb2f18f8Sesaxe * configuration changes. Class specific data is stored/associated with
82fb2f18f8Sesaxe * PGs by incorporating the pg_t (or pghw_t, as appropriate), as the first
83fb2f18f8Sesaxe * element of a class specific PG object. In memory, such a structure may look
84fb2f18f8Sesaxe * like:
85fb2f18f8Sesaxe *
86fb2f18f8Sesaxe * ----------------------- - - -
87fb2f18f8Sesaxe * | common | | | | <--(pg_t *)
88fb2f18f8Sesaxe * ----------------------- | | -
89fb2f18f8Sesaxe * | HW specific | | | <-----(pghw_t *)
90fb2f18f8Sesaxe * ----------------------- | -
91fb2f18f8Sesaxe * | class specific | | <-------(pg_cmt_t *)
92fb2f18f8Sesaxe * ----------------------- -
93fb2f18f8Sesaxe *
94fb2f18f8Sesaxe * Access to the PG class specific data can be had by casting a pointer to
95fb2f18f8Sesaxe * it's class specific view.
96fb2f18f8Sesaxe */
97fb2f18f8Sesaxe
98fb2f18f8Sesaxe static pg_t *pg_alloc_default(pg_class_t);
99fb2f18f8Sesaxe static void pg_free_default(pg_t *);
1000e751525SEric Saxe static void pg_null_op();
101fb2f18f8Sesaxe
102fb2f18f8Sesaxe /*
103fb2f18f8Sesaxe * Bootstrap CPU specific PG data
104fb2f18f8Sesaxe * See pg_cpu_bootstrap()
105fb2f18f8Sesaxe */
106fb2f18f8Sesaxe static cpu_pg_t bootstrap_pg_data;
107fb2f18f8Sesaxe
108fb2f18f8Sesaxe /*
109fb2f18f8Sesaxe * Bitset of allocated PG ids (they are sequential)
110fb2f18f8Sesaxe * and the next free id in the set.
111fb2f18f8Sesaxe */
112fb2f18f8Sesaxe static bitset_t pg_id_set;
113*b885580bSAlexander Kolbasov
114*b885580bSAlexander Kolbasov /*
115*b885580bSAlexander Kolbasov * ID space starts from 1 to assume that root has ID 0;
116*b885580bSAlexander Kolbasov */
117*b885580bSAlexander Kolbasov static pgid_t pg_id_next = 1;
118fb2f18f8Sesaxe
119fb2f18f8Sesaxe /*
120fb2f18f8Sesaxe * Default and externed PG ops vectors
121fb2f18f8Sesaxe */
122fb2f18f8Sesaxe static struct pg_ops pg_ops_default = {
123fb2f18f8Sesaxe pg_alloc_default, /* alloc */
124fb2f18f8Sesaxe pg_free_default, /* free */
125fb2f18f8Sesaxe NULL, /* cpu_init */
126fb2f18f8Sesaxe NULL, /* cpu_fini */
127fb2f18f8Sesaxe NULL, /* cpu_active */
128fb2f18f8Sesaxe NULL, /* cpu_inactive */
129fb2f18f8Sesaxe NULL, /* cpupart_in */
130fb2f18f8Sesaxe NULL, /* cpupart_out */
131fb2f18f8Sesaxe NULL, /* cpupart_move */
132fb2f18f8Sesaxe NULL, /* cpu_belongs */
1330e751525SEric Saxe NULL, /* policy_name */
1340e751525SEric Saxe };
1350e751525SEric Saxe
1360e751525SEric Saxe static struct pg_cb_ops pg_cb_ops_default = {
1370e751525SEric Saxe pg_null_op, /* thread_swtch */
1380e751525SEric Saxe pg_null_op, /* thread_remain */
139fb2f18f8Sesaxe };
140fb2f18f8Sesaxe
141fb2f18f8Sesaxe /*
142fb2f18f8Sesaxe * Class specific PG allocation callbacks
143fb2f18f8Sesaxe */
144fb2f18f8Sesaxe #define PG_ALLOC(class) \
145fb2f18f8Sesaxe (pg_classes[class].pgc_ops->alloc ? \
146fb2f18f8Sesaxe pg_classes[class].pgc_ops->alloc() : \
147fb2f18f8Sesaxe pg_classes[pg_default_cid].pgc_ops->alloc())
148fb2f18f8Sesaxe
149fb2f18f8Sesaxe #define PG_FREE(pg) \
150fb2f18f8Sesaxe ((pg)->pg_class->pgc_ops->free ? \
151fb2f18f8Sesaxe (pg)->pg_class->pgc_ops->free(pg) : \
152fb2f18f8Sesaxe pg_classes[pg_default_cid].pgc_ops->free(pg)) \
153fb2f18f8Sesaxe
154fb2f18f8Sesaxe
155fb2f18f8Sesaxe /*
1560e751525SEric Saxe * Class specific PG policy name
1570e751525SEric Saxe */
1580e751525SEric Saxe #define PG_POLICY_NAME(pg) \
1590e751525SEric Saxe ((pg)->pg_class->pgc_ops->policy_name ? \
1600e751525SEric Saxe (pg)->pg_class->pgc_ops->policy_name(pg) : NULL) \
1610e751525SEric Saxe
1620e751525SEric Saxe /*
163fb2f18f8Sesaxe * Class specific membership test callback
164fb2f18f8Sesaxe */
165fb2f18f8Sesaxe #define PG_CPU_BELONGS(pg, cp) \
166fb2f18f8Sesaxe ((pg)->pg_class->pgc_ops->cpu_belongs ? \
167fb2f18f8Sesaxe (pg)->pg_class->pgc_ops->cpu_belongs(pg, cp) : 0) \
168fb2f18f8Sesaxe
169fb2f18f8Sesaxe /*
170fb2f18f8Sesaxe * CPU configuration callbacks
171fb2f18f8Sesaxe */
17247ab0c7cSEric Saxe #define PG_CPU_INIT(class, cp, cpu_pg) \
173fb2f18f8Sesaxe { \
174fb2f18f8Sesaxe if (pg_classes[class].pgc_ops->cpu_init) \
17547ab0c7cSEric Saxe pg_classes[class].pgc_ops->cpu_init(cp, cpu_pg); \
176fb2f18f8Sesaxe }
177fb2f18f8Sesaxe
17847ab0c7cSEric Saxe #define PG_CPU_FINI(class, cp, cpu_pg) \
179fb2f18f8Sesaxe { \
180fb2f18f8Sesaxe if (pg_classes[class].pgc_ops->cpu_fini) \
18147ab0c7cSEric Saxe pg_classes[class].pgc_ops->cpu_fini(cp, cpu_pg); \
182fb2f18f8Sesaxe }
183fb2f18f8Sesaxe
184fb2f18f8Sesaxe #define PG_CPU_ACTIVE(class, cp) \
185fb2f18f8Sesaxe { \
186fb2f18f8Sesaxe if (pg_classes[class].pgc_ops->cpu_active) \
187fb2f18f8Sesaxe pg_classes[class].pgc_ops->cpu_active(cp); \
188fb2f18f8Sesaxe }
189fb2f18f8Sesaxe
190fb2f18f8Sesaxe #define PG_CPU_INACTIVE(class, cp) \
191fb2f18f8Sesaxe { \
192fb2f18f8Sesaxe if (pg_classes[class].pgc_ops->cpu_inactive) \
193fb2f18f8Sesaxe pg_classes[class].pgc_ops->cpu_inactive(cp); \
194fb2f18f8Sesaxe }
195fb2f18f8Sesaxe
196fb2f18f8Sesaxe /*
197fb2f18f8Sesaxe * CPU / cpupart configuration callbacks
198fb2f18f8Sesaxe */
199fb2f18f8Sesaxe #define PG_CPUPART_IN(class, cp, pp) \
200fb2f18f8Sesaxe { \
201fb2f18f8Sesaxe if (pg_classes[class].pgc_ops->cpupart_in) \
202fb2f18f8Sesaxe pg_classes[class].pgc_ops->cpupart_in(cp, pp); \
203fb2f18f8Sesaxe }
204fb2f18f8Sesaxe
205fb2f18f8Sesaxe #define PG_CPUPART_OUT(class, cp, pp) \
206fb2f18f8Sesaxe { \
207fb2f18f8Sesaxe if (pg_classes[class].pgc_ops->cpupart_out) \
208fb2f18f8Sesaxe pg_classes[class].pgc_ops->cpupart_out(cp, pp); \
209fb2f18f8Sesaxe }
210fb2f18f8Sesaxe
211fb2f18f8Sesaxe #define PG_CPUPART_MOVE(class, cp, old, new) \
212fb2f18f8Sesaxe { \
213fb2f18f8Sesaxe if (pg_classes[class].pgc_ops->cpupart_move) \
214fb2f18f8Sesaxe pg_classes[class].pgc_ops->cpupart_move(cp, old, new); \
215fb2f18f8Sesaxe }
216fb2f18f8Sesaxe
217fb2f18f8Sesaxe
218fb2f18f8Sesaxe
219fb2f18f8Sesaxe static pg_class_t *pg_classes;
220fb2f18f8Sesaxe static int pg_nclasses;
221fb2f18f8Sesaxe
222fb2f18f8Sesaxe static pg_cid_t pg_default_cid;
223fb2f18f8Sesaxe
224fb2f18f8Sesaxe /*
2250e751525SEric Saxe * Initialze common PG subsystem.
226fb2f18f8Sesaxe */
227fb2f18f8Sesaxe void
pg_init(void)228fb2f18f8Sesaxe pg_init(void)
229fb2f18f8Sesaxe {
2300e751525SEric Saxe extern void pg_cmt_class_init();
231ad7a79fdSEric Saxe extern void pg_cmt_cpu_startup();
2320e751525SEric Saxe
233fb2f18f8Sesaxe pg_default_cid =
234fb2f18f8Sesaxe pg_class_register("default", &pg_ops_default, PGR_LOGICAL);
2350e751525SEric Saxe
2360e751525SEric Saxe /*
2370e751525SEric Saxe * Initialize classes to allow them to register with the framework
2380e751525SEric Saxe */
2390e751525SEric Saxe pg_cmt_class_init();
2400e751525SEric Saxe
2410e751525SEric Saxe pg_cpu0_init();
242ad7a79fdSEric Saxe pg_cmt_cpu_startup(CPU);
243fb2f18f8Sesaxe }
244fb2f18f8Sesaxe
245fb2f18f8Sesaxe /*
246fb2f18f8Sesaxe * Perform CPU 0 initialization
247fb2f18f8Sesaxe */
248fb2f18f8Sesaxe void
pg_cpu0_init(void)249fb2f18f8Sesaxe pg_cpu0_init(void)
250fb2f18f8Sesaxe {
251fb2f18f8Sesaxe extern void pghw_physid_create();
252fb2f18f8Sesaxe
253fb2f18f8Sesaxe /*
254fb2f18f8Sesaxe * Create the physical ID cache for the boot CPU
255fb2f18f8Sesaxe */
256fb2f18f8Sesaxe pghw_physid_create(CPU);
257fb2f18f8Sesaxe
258fb2f18f8Sesaxe /*
259fb2f18f8Sesaxe * pg_cpu_* require that cpu_lock be held
260fb2f18f8Sesaxe */
261fb2f18f8Sesaxe mutex_enter(&cpu_lock);
262fb2f18f8Sesaxe
263023e71deSHaik Aftandilian (void) pg_cpu_init(CPU, B_FALSE);
264fb2f18f8Sesaxe pg_cpupart_in(CPU, &cp_default);
265fb2f18f8Sesaxe pg_cpu_active(CPU);
266fb2f18f8Sesaxe
267fb2f18f8Sesaxe mutex_exit(&cpu_lock);
268fb2f18f8Sesaxe }
269fb2f18f8Sesaxe
270fb2f18f8Sesaxe /*
271a6604450Sesaxe * Invoked when topology for CPU0 changes
272a6604450Sesaxe * post pg_cpu0_init().
273a6604450Sesaxe *
274a6604450Sesaxe * Currently happens as a result of null_proc_lpa
275a6604450Sesaxe * on Starcat.
276a6604450Sesaxe */
277a6604450Sesaxe void
pg_cpu0_reinit(void)278a6604450Sesaxe pg_cpu0_reinit(void)
279a6604450Sesaxe {
280a6604450Sesaxe mutex_enter(&cpu_lock);
281a6604450Sesaxe pg_cpu_inactive(CPU);
282a6604450Sesaxe pg_cpupart_out(CPU, &cp_default);
283023e71deSHaik Aftandilian pg_cpu_fini(CPU, NULL);
284a6604450Sesaxe
285023e71deSHaik Aftandilian (void) pg_cpu_init(CPU, B_FALSE);
286a6604450Sesaxe pg_cpupart_in(CPU, &cp_default);
287a6604450Sesaxe pg_cpu_active(CPU);
288a6604450Sesaxe mutex_exit(&cpu_lock);
289a6604450Sesaxe }
290a6604450Sesaxe
291a6604450Sesaxe /*
292fb2f18f8Sesaxe * Register a new PG class
293fb2f18f8Sesaxe */
294fb2f18f8Sesaxe pg_cid_t
pg_class_register(char * name,struct pg_ops * ops,pg_relation_t relation)295fb2f18f8Sesaxe pg_class_register(char *name, struct pg_ops *ops, pg_relation_t relation)
296fb2f18f8Sesaxe {
297fb2f18f8Sesaxe pg_class_t *newclass;
298fb2f18f8Sesaxe pg_class_t *classes_old;
299fb2f18f8Sesaxe id_t cid;
300fb2f18f8Sesaxe
301fb2f18f8Sesaxe mutex_enter(&cpu_lock);
302fb2f18f8Sesaxe
303fb2f18f8Sesaxe /*
304fb2f18f8Sesaxe * Allocate a new pg_class_t in the pg_classes array
305fb2f18f8Sesaxe */
306fb2f18f8Sesaxe if (pg_nclasses == 0) {
307fb2f18f8Sesaxe pg_classes = kmem_zalloc(sizeof (pg_class_t), KM_SLEEP);
308fb2f18f8Sesaxe } else {
309fb2f18f8Sesaxe classes_old = pg_classes;
310fb2f18f8Sesaxe pg_classes =
311fb2f18f8Sesaxe kmem_zalloc(sizeof (pg_class_t) * (pg_nclasses + 1),
312fb2f18f8Sesaxe KM_SLEEP);
313fb2f18f8Sesaxe (void) kcopy(classes_old, pg_classes,
314fb2f18f8Sesaxe sizeof (pg_class_t) * pg_nclasses);
315fb2f18f8Sesaxe kmem_free(classes_old, sizeof (pg_class_t) * pg_nclasses);
316fb2f18f8Sesaxe }
317fb2f18f8Sesaxe
318fb2f18f8Sesaxe cid = pg_nclasses++;
319fb2f18f8Sesaxe newclass = &pg_classes[cid];
320fb2f18f8Sesaxe
321fb2f18f8Sesaxe (void) strncpy(newclass->pgc_name, name, PG_CLASS_NAME_MAX);
322fb2f18f8Sesaxe newclass->pgc_id = cid;
323fb2f18f8Sesaxe newclass->pgc_ops = ops;
324fb2f18f8Sesaxe newclass->pgc_relation = relation;
325fb2f18f8Sesaxe
326fb2f18f8Sesaxe mutex_exit(&cpu_lock);
327fb2f18f8Sesaxe
328fb2f18f8Sesaxe return (cid);
329fb2f18f8Sesaxe }
330fb2f18f8Sesaxe
331fb2f18f8Sesaxe /*
332fb2f18f8Sesaxe * Try to find an existing pg in set in which to place cp.
333fb2f18f8Sesaxe * Returns the pg if found, and NULL otherwise.
334fb2f18f8Sesaxe * In the event that the CPU could belong to multiple
335fb2f18f8Sesaxe * PGs in the set, the first matching PG will be returned.
336fb2f18f8Sesaxe */
337fb2f18f8Sesaxe pg_t *
pg_cpu_find_pg(cpu_t * cp,group_t * set)338fb2f18f8Sesaxe pg_cpu_find_pg(cpu_t *cp, group_t *set)
339fb2f18f8Sesaxe {
340fb2f18f8Sesaxe pg_t *pg;
341fb2f18f8Sesaxe group_iter_t i;
342fb2f18f8Sesaxe
343fb2f18f8Sesaxe group_iter_init(&i);
344fb2f18f8Sesaxe while ((pg = group_iterate(set, &i)) != NULL) {
345fb2f18f8Sesaxe /*
346fb2f18f8Sesaxe * Ask the class if the CPU belongs here
347fb2f18f8Sesaxe */
348fb2f18f8Sesaxe if (PG_CPU_BELONGS(pg, cp))
349fb2f18f8Sesaxe return (pg);
350fb2f18f8Sesaxe }
351fb2f18f8Sesaxe return (NULL);
352fb2f18f8Sesaxe }
353fb2f18f8Sesaxe
354fb2f18f8Sesaxe /*
355fb2f18f8Sesaxe * Iterate over the CPUs in a PG after initializing
356fb2f18f8Sesaxe * the iterator with PG_CPU_ITR_INIT()
357fb2f18f8Sesaxe */
358fb2f18f8Sesaxe cpu_t *
pg_cpu_next(pg_cpu_itr_t * itr)359fb2f18f8Sesaxe pg_cpu_next(pg_cpu_itr_t *itr)
360fb2f18f8Sesaxe {
361fb2f18f8Sesaxe cpu_t *cpu;
362fb2f18f8Sesaxe pg_t *pg = itr->pg;
363fb2f18f8Sesaxe
364fb2f18f8Sesaxe cpu = group_iterate(&pg->pg_cpus, &itr->position);
365fb2f18f8Sesaxe return (cpu);
366fb2f18f8Sesaxe }
367fb2f18f8Sesaxe
368fb2f18f8Sesaxe /*
3690e751525SEric Saxe * Test if a given PG contains a given CPU
3700e751525SEric Saxe */
3710e751525SEric Saxe boolean_t
pg_cpu_find(pg_t * pg,cpu_t * cp)3720e751525SEric Saxe pg_cpu_find(pg_t *pg, cpu_t *cp)
3730e751525SEric Saxe {
3740e751525SEric Saxe if (group_find(&pg->pg_cpus, cp) == (uint_t)-1)
3750e751525SEric Saxe return (B_FALSE);
3760e751525SEric Saxe
3770e751525SEric Saxe return (B_TRUE);
3780e751525SEric Saxe }
3790e751525SEric Saxe
3800e751525SEric Saxe /*
3810e751525SEric Saxe * Set the PGs callbacks to the default
3820e751525SEric Saxe */
3830e751525SEric Saxe void
pg_callback_set_defaults(pg_t * pg)3840e751525SEric Saxe pg_callback_set_defaults(pg_t *pg)
3850e751525SEric Saxe {
3860e751525SEric Saxe bcopy(&pg_cb_ops_default, &pg->pg_cb, sizeof (struct pg_cb_ops));
3870e751525SEric Saxe }
3880e751525SEric Saxe
3890e751525SEric Saxe /*
390fb2f18f8Sesaxe * Create a PG of a given class.
391fb2f18f8Sesaxe * This routine may block.
392fb2f18f8Sesaxe */
393fb2f18f8Sesaxe pg_t *
pg_create(pg_cid_t cid)394fb2f18f8Sesaxe pg_create(pg_cid_t cid)
395fb2f18f8Sesaxe {
396fb2f18f8Sesaxe pg_t *pg;
397fb2f18f8Sesaxe pgid_t id;
398fb2f18f8Sesaxe
399fb2f18f8Sesaxe ASSERT(MUTEX_HELD(&cpu_lock));
400fb2f18f8Sesaxe
401fb2f18f8Sesaxe /*
402fb2f18f8Sesaxe * Call the class specific PG allocation routine
403fb2f18f8Sesaxe */
404fb2f18f8Sesaxe pg = PG_ALLOC(cid);
405fb2f18f8Sesaxe pg->pg_class = &pg_classes[cid];
406fb2f18f8Sesaxe pg->pg_relation = pg->pg_class->pgc_relation;
407fb2f18f8Sesaxe
408fb2f18f8Sesaxe /*
409fb2f18f8Sesaxe * Find the next free sequential pg id
410fb2f18f8Sesaxe */
411fb2f18f8Sesaxe do {
412fb2f18f8Sesaxe if (pg_id_next >= bitset_capacity(&pg_id_set))
413fb2f18f8Sesaxe bitset_resize(&pg_id_set, pg_id_next + 1);
414fb2f18f8Sesaxe id = pg_id_next++;
415fb2f18f8Sesaxe } while (bitset_in_set(&pg_id_set, id));
416fb2f18f8Sesaxe
417fb2f18f8Sesaxe pg->pg_id = id;
418fb2f18f8Sesaxe bitset_add(&pg_id_set, pg->pg_id);
419fb2f18f8Sesaxe
420fb2f18f8Sesaxe /*
421fb2f18f8Sesaxe * Create the PG's CPU group
422fb2f18f8Sesaxe */
423fb2f18f8Sesaxe group_create(&pg->pg_cpus);
424fb2f18f8Sesaxe
4250e751525SEric Saxe /*
4260e751525SEric Saxe * Initialize the events ops vector
4270e751525SEric Saxe */
4280e751525SEric Saxe pg_callback_set_defaults(pg);
4290e751525SEric Saxe
430fb2f18f8Sesaxe return (pg);
431fb2f18f8Sesaxe }
432fb2f18f8Sesaxe
433fb2f18f8Sesaxe /*
434fb2f18f8Sesaxe * Destroy a PG.
435fb2f18f8Sesaxe * This routine may block.
436fb2f18f8Sesaxe */
437fb2f18f8Sesaxe void
pg_destroy(pg_t * pg)438fb2f18f8Sesaxe pg_destroy(pg_t *pg)
439fb2f18f8Sesaxe {
440fb2f18f8Sesaxe ASSERT(MUTEX_HELD(&cpu_lock));
441fb2f18f8Sesaxe
442fb2f18f8Sesaxe group_destroy(&pg->pg_cpus);
443fb2f18f8Sesaxe
444fb2f18f8Sesaxe /*
445fb2f18f8Sesaxe * Unassign the pg_id
446fb2f18f8Sesaxe */
447fb2f18f8Sesaxe if (pg_id_next > pg->pg_id)
448fb2f18f8Sesaxe pg_id_next = pg->pg_id;
449fb2f18f8Sesaxe bitset_del(&pg_id_set, pg->pg_id);
450fb2f18f8Sesaxe
451fb2f18f8Sesaxe /*
452fb2f18f8Sesaxe * Invoke the class specific de-allocation routine
453fb2f18f8Sesaxe */
454fb2f18f8Sesaxe PG_FREE(pg);
455fb2f18f8Sesaxe }
456fb2f18f8Sesaxe
457fb2f18f8Sesaxe /*
458fb2f18f8Sesaxe * Add the CPU "cp" to processor group "pg"
459fb2f18f8Sesaxe * This routine may block.
460fb2f18f8Sesaxe */
461fb2f18f8Sesaxe void
pg_cpu_add(pg_t * pg,cpu_t * cp,cpu_pg_t * cpu_pg)46247ab0c7cSEric Saxe pg_cpu_add(pg_t *pg, cpu_t *cp, cpu_pg_t *cpu_pg)
463fb2f18f8Sesaxe {
464fb2f18f8Sesaxe int err;
465fb2f18f8Sesaxe
466fb2f18f8Sesaxe ASSERT(MUTEX_HELD(&cpu_lock));
467fb2f18f8Sesaxe
468fb2f18f8Sesaxe /* This adds the CPU to the PG's CPU group */
469fb2f18f8Sesaxe err = group_add(&pg->pg_cpus, cp, GRP_RESIZE);
470fb2f18f8Sesaxe ASSERT(err == 0);
471fb2f18f8Sesaxe
47247ab0c7cSEric Saxe /*
47347ab0c7cSEric Saxe * The CPU should be referencing the bootstrap PG data still
47447ab0c7cSEric Saxe * at this point, since this routine may block causing us to
47547ab0c7cSEric Saxe * enter the dispatcher.
47647ab0c7cSEric Saxe */
4771a77c24bSEric Saxe ASSERT(pg_cpu_is_bootstrapped(cp));
47847ab0c7cSEric Saxe
479fb2f18f8Sesaxe /* This adds the PG to the CPUs PG group */
48047ab0c7cSEric Saxe err = group_add(&cpu_pg->pgs, pg, GRP_RESIZE);
481fb2f18f8Sesaxe ASSERT(err == 0);
482fb2f18f8Sesaxe }
483fb2f18f8Sesaxe
484fb2f18f8Sesaxe /*
485fb2f18f8Sesaxe * Remove "cp" from "pg".
486fb2f18f8Sesaxe * This routine may block.
487fb2f18f8Sesaxe */
488fb2f18f8Sesaxe void
pg_cpu_delete(pg_t * pg,cpu_t * cp,cpu_pg_t * cpu_pg)48947ab0c7cSEric Saxe pg_cpu_delete(pg_t *pg, cpu_t *cp, cpu_pg_t *cpu_pg)
490fb2f18f8Sesaxe {
491fb2f18f8Sesaxe int err;
492fb2f18f8Sesaxe
493fb2f18f8Sesaxe ASSERT(MUTEX_HELD(&cpu_lock));
494fb2f18f8Sesaxe
495fb2f18f8Sesaxe /* Remove the CPU from the PG */
496fb2f18f8Sesaxe err = group_remove(&pg->pg_cpus, cp, GRP_RESIZE);
497fb2f18f8Sesaxe ASSERT(err == 0);
498fb2f18f8Sesaxe
49947ab0c7cSEric Saxe /*
50047ab0c7cSEric Saxe * The CPU should be referencing the bootstrap PG data still
50147ab0c7cSEric Saxe * at this point, since this routine may block causing us to
50247ab0c7cSEric Saxe * enter the dispatcher.
50347ab0c7cSEric Saxe */
5041a77c24bSEric Saxe ASSERT(pg_cpu_is_bootstrapped(cp));
50547ab0c7cSEric Saxe
506fb2f18f8Sesaxe /* Remove the PG from the CPU's PG group */
50747ab0c7cSEric Saxe err = group_remove(&cpu_pg->pgs, pg, GRP_RESIZE);
508fb2f18f8Sesaxe ASSERT(err == 0);
509fb2f18f8Sesaxe }
510fb2f18f8Sesaxe
511fb2f18f8Sesaxe /*
512fb2f18f8Sesaxe * Allocate a CPU's PG data. This hangs off struct cpu at cpu_pg
513fb2f18f8Sesaxe */
514fb2f18f8Sesaxe static cpu_pg_t *
pg_cpu_data_alloc(void)515fb2f18f8Sesaxe pg_cpu_data_alloc(void)
516fb2f18f8Sesaxe {
517fb2f18f8Sesaxe cpu_pg_t *pgd;
518fb2f18f8Sesaxe
519fb2f18f8Sesaxe pgd = kmem_zalloc(sizeof (cpu_pg_t), KM_SLEEP);
520fb2f18f8Sesaxe group_create(&pgd->pgs);
521fb2f18f8Sesaxe group_create(&pgd->cmt_pgs);
522fb2f18f8Sesaxe
523fb2f18f8Sesaxe return (pgd);
524fb2f18f8Sesaxe }
525fb2f18f8Sesaxe
526fb2f18f8Sesaxe /*
527fb2f18f8Sesaxe * Free the CPU's PG data.
528fb2f18f8Sesaxe */
529fb2f18f8Sesaxe static void
pg_cpu_data_free(cpu_pg_t * pgd)530fb2f18f8Sesaxe pg_cpu_data_free(cpu_pg_t *pgd)
531fb2f18f8Sesaxe {
532fb2f18f8Sesaxe group_destroy(&pgd->pgs);
533fb2f18f8Sesaxe group_destroy(&pgd->cmt_pgs);
534fb2f18f8Sesaxe kmem_free(pgd, sizeof (cpu_pg_t));
535fb2f18f8Sesaxe }
536fb2f18f8Sesaxe
537fb2f18f8Sesaxe /*
538023e71deSHaik Aftandilian * Called when either a new CPU is coming into the system (either
539023e71deSHaik Aftandilian * via booting or DR) or when the CPU's PG data is being recalculated.
540023e71deSHaik Aftandilian * Allocate its PG data, and notify all registered classes about
541fb2f18f8Sesaxe * the new CPU.
542fb2f18f8Sesaxe *
543023e71deSHaik Aftandilian * If "deferred_init" is B_TRUE, the CPU's PG data will be allocated
544023e71deSHaik Aftandilian * and returned, but the "bootstrap" structure will be left in place.
545023e71deSHaik Aftandilian * The deferred_init option is used when all CPUs in the system are
546023e71deSHaik Aftandilian * using the bootstrap structure as part of the process of recalculating
547023e71deSHaik Aftandilian * all PG data. The caller must replace the bootstrap structure with the
548023e71deSHaik Aftandilian * allocated PG data before pg_cpu_active is called.
549023e71deSHaik Aftandilian *
550fb2f18f8Sesaxe * This routine may block.
551fb2f18f8Sesaxe */
552023e71deSHaik Aftandilian cpu_pg_t *
pg_cpu_init(cpu_t * cp,boolean_t deferred_init)553023e71deSHaik Aftandilian pg_cpu_init(cpu_t *cp, boolean_t deferred_init)
554fb2f18f8Sesaxe {
555fb2f18f8Sesaxe pg_cid_t i;
55647ab0c7cSEric Saxe cpu_pg_t *cpu_pg;
557fb2f18f8Sesaxe
558fb2f18f8Sesaxe ASSERT(MUTEX_HELD(&cpu_lock));
559fb2f18f8Sesaxe
560fb2f18f8Sesaxe /*
561fb2f18f8Sesaxe * Allocate and size the per CPU pg data
56247ab0c7cSEric Saxe *
56347ab0c7cSEric Saxe * The CPU's PG data will be populated by the various
56447ab0c7cSEric Saxe * PG classes during the invocation of the PG_CPU_INIT()
56547ab0c7cSEric Saxe * callback below.
56647ab0c7cSEric Saxe *
56747ab0c7cSEric Saxe * Since the we could block and enter the dispatcher during
56847ab0c7cSEric Saxe * this process, the CPU will continue to reference the bootstrap
56947ab0c7cSEric Saxe * PG data until all the initialization completes.
570fb2f18f8Sesaxe */
5711a77c24bSEric Saxe ASSERT(pg_cpu_is_bootstrapped(cp));
57247ab0c7cSEric Saxe
57347ab0c7cSEric Saxe cpu_pg = pg_cpu_data_alloc();
574fb2f18f8Sesaxe
575fb2f18f8Sesaxe /*
576fb2f18f8Sesaxe * Notify all registered classes about the new CPU
577fb2f18f8Sesaxe */
578fb2f18f8Sesaxe for (i = 0; i < pg_nclasses; i++)
57947ab0c7cSEric Saxe PG_CPU_INIT(i, cp, cpu_pg);
58047ab0c7cSEric Saxe
58147ab0c7cSEric Saxe /*
58247ab0c7cSEric Saxe * The CPU's PG data is now ready to use.
58347ab0c7cSEric Saxe */
584023e71deSHaik Aftandilian if (deferred_init == B_FALSE)
58547ab0c7cSEric Saxe cp->cpu_pg = cpu_pg;
586023e71deSHaik Aftandilian
587023e71deSHaik Aftandilian return (cpu_pg);
588fb2f18f8Sesaxe }
589fb2f18f8Sesaxe
590fb2f18f8Sesaxe /*
591023e71deSHaik Aftandilian * Either this CPU is being deleted from the system or its PG data is
592023e71deSHaik Aftandilian * being recalculated. Notify the classes and free up the CPU's PG data.
593023e71deSHaik Aftandilian *
594023e71deSHaik Aftandilian * If "cpu_pg_deferred" is non-NULL, it points to the CPU's PG data and
595023e71deSHaik Aftandilian * serves to indicate that this CPU is already using the bootstrap
596023e71deSHaik Aftandilian * stucture. Used as part of the process to recalculate the PG data for
597023e71deSHaik Aftandilian * all CPUs in the system.
598fb2f18f8Sesaxe */
599fb2f18f8Sesaxe void
pg_cpu_fini(cpu_t * cp,cpu_pg_t * cpu_pg_deferred)600023e71deSHaik Aftandilian pg_cpu_fini(cpu_t *cp, cpu_pg_t *cpu_pg_deferred)
601fb2f18f8Sesaxe {
602fb2f18f8Sesaxe pg_cid_t i;
60347ab0c7cSEric Saxe cpu_pg_t *cpu_pg;
604fb2f18f8Sesaxe
605fb2f18f8Sesaxe ASSERT(MUTEX_HELD(&cpu_lock));
606fb2f18f8Sesaxe
607023e71deSHaik Aftandilian if (cpu_pg_deferred == NULL) {
60847ab0c7cSEric Saxe cpu_pg = cp->cpu_pg;
60947ab0c7cSEric Saxe
610fb2f18f8Sesaxe /*
611fb2f18f8Sesaxe * This can happen if the CPU coming into the system
612fb2f18f8Sesaxe * failed to power on.
613fb2f18f8Sesaxe */
6141a77c24bSEric Saxe if (cpu_pg == NULL || pg_cpu_is_bootstrapped(cp))
615fb2f18f8Sesaxe return;
616fb2f18f8Sesaxe
61747ab0c7cSEric Saxe /*
61847ab0c7cSEric Saxe * Have the CPU reference the bootstrap PG data to survive
61947ab0c7cSEric Saxe * the dispatcher should it block from here on out.
62047ab0c7cSEric Saxe */
6211a77c24bSEric Saxe pg_cpu_bootstrap(cp);
622023e71deSHaik Aftandilian } else {
623023e71deSHaik Aftandilian ASSERT(pg_cpu_is_bootstrapped(cp));
624023e71deSHaik Aftandilian cpu_pg = cpu_pg_deferred;
625023e71deSHaik Aftandilian }
626fb2f18f8Sesaxe
62747ab0c7cSEric Saxe for (i = 0; i < pg_nclasses; i++)
62847ab0c7cSEric Saxe PG_CPU_FINI(i, cp, cpu_pg);
62947ab0c7cSEric Saxe
63047ab0c7cSEric Saxe pg_cpu_data_free(cpu_pg);
631fb2f18f8Sesaxe }
632fb2f18f8Sesaxe
633fb2f18f8Sesaxe /*
634fb2f18f8Sesaxe * This CPU is becoming active (online)
635fb2f18f8Sesaxe * This routine may not block as it is called from paused CPUs
636fb2f18f8Sesaxe * context.
637fb2f18f8Sesaxe */
638fb2f18f8Sesaxe void
pg_cpu_active(cpu_t * cp)639fb2f18f8Sesaxe pg_cpu_active(cpu_t *cp)
640fb2f18f8Sesaxe {
641fb2f18f8Sesaxe pg_cid_t i;
642fb2f18f8Sesaxe
643fb2f18f8Sesaxe ASSERT(MUTEX_HELD(&cpu_lock));
644fb2f18f8Sesaxe
645fb2f18f8Sesaxe /*
646fb2f18f8Sesaxe * Notify all registered classes about the new CPU
647fb2f18f8Sesaxe */
648fb2f18f8Sesaxe for (i = 0; i < pg_nclasses; i++)
649fb2f18f8Sesaxe PG_CPU_ACTIVE(i, cp);
650fb2f18f8Sesaxe }
651fb2f18f8Sesaxe
652fb2f18f8Sesaxe /*
653fb2f18f8Sesaxe * This CPU is going inactive (offline)
654fb2f18f8Sesaxe * This routine may not block, as it is called from paused
655fb2f18f8Sesaxe * CPUs context.
656fb2f18f8Sesaxe */
657fb2f18f8Sesaxe void
pg_cpu_inactive(cpu_t * cp)658fb2f18f8Sesaxe pg_cpu_inactive(cpu_t *cp)
659fb2f18f8Sesaxe {
660fb2f18f8Sesaxe pg_cid_t i;
661fb2f18f8Sesaxe
662fb2f18f8Sesaxe ASSERT(MUTEX_HELD(&cpu_lock));
663fb2f18f8Sesaxe
664fb2f18f8Sesaxe /*
665fb2f18f8Sesaxe * Notify all registered classes about the new CPU
666fb2f18f8Sesaxe */
667fb2f18f8Sesaxe for (i = 0; i < pg_nclasses; i++)
668fb2f18f8Sesaxe PG_CPU_INACTIVE(i, cp);
669fb2f18f8Sesaxe }
670fb2f18f8Sesaxe
671fb2f18f8Sesaxe /*
672fb2f18f8Sesaxe * Invoked when the CPU is about to move into the partition
673fb2f18f8Sesaxe * This routine may block.
674fb2f18f8Sesaxe */
675fb2f18f8Sesaxe void
pg_cpupart_in(cpu_t * cp,cpupart_t * pp)676fb2f18f8Sesaxe pg_cpupart_in(cpu_t *cp, cpupart_t *pp)
677fb2f18f8Sesaxe {
678fb2f18f8Sesaxe int i;
679fb2f18f8Sesaxe
680fb2f18f8Sesaxe ASSERT(MUTEX_HELD(&cpu_lock));
681fb2f18f8Sesaxe
682fb2f18f8Sesaxe /*
683fb2f18f8Sesaxe * Notify all registered classes that the
684fb2f18f8Sesaxe * CPU is about to enter the CPU partition
685fb2f18f8Sesaxe */
686fb2f18f8Sesaxe for (i = 0; i < pg_nclasses; i++)
687fb2f18f8Sesaxe PG_CPUPART_IN(i, cp, pp);
688fb2f18f8Sesaxe }
689fb2f18f8Sesaxe
690fb2f18f8Sesaxe /*
691fb2f18f8Sesaxe * Invoked when the CPU is about to move out of the partition
692fb2f18f8Sesaxe * This routine may block.
693fb2f18f8Sesaxe */
694fb2f18f8Sesaxe /*ARGSUSED*/
695fb2f18f8Sesaxe void
pg_cpupart_out(cpu_t * cp,cpupart_t * pp)696fb2f18f8Sesaxe pg_cpupart_out(cpu_t *cp, cpupart_t *pp)
697fb2f18f8Sesaxe {
698fb2f18f8Sesaxe int i;
699fb2f18f8Sesaxe
700fb2f18f8Sesaxe ASSERT(MUTEX_HELD(&cpu_lock));
701fb2f18f8Sesaxe
702fb2f18f8Sesaxe /*
703fb2f18f8Sesaxe * Notify all registered classes that the
704fb2f18f8Sesaxe * CPU is about to leave the CPU partition
705fb2f18f8Sesaxe */
706fb2f18f8Sesaxe for (i = 0; i < pg_nclasses; i++)
707fb2f18f8Sesaxe PG_CPUPART_OUT(i, cp, pp);
708fb2f18f8Sesaxe }
709fb2f18f8Sesaxe
710fb2f18f8Sesaxe /*
711fb2f18f8Sesaxe * Invoked when the CPU is *moving* partitions.
712fb2f18f8Sesaxe *
713fb2f18f8Sesaxe * This routine may not block, as it is called from paused CPUs
714fb2f18f8Sesaxe * context.
715fb2f18f8Sesaxe */
716fb2f18f8Sesaxe void
pg_cpupart_move(cpu_t * cp,cpupart_t * oldpp,cpupart_t * newpp)717fb2f18f8Sesaxe pg_cpupart_move(cpu_t *cp, cpupart_t *oldpp, cpupart_t *newpp)
718fb2f18f8Sesaxe {
719fb2f18f8Sesaxe int i;
720fb2f18f8Sesaxe
721fb2f18f8Sesaxe ASSERT(MUTEX_HELD(&cpu_lock));
722fb2f18f8Sesaxe
723fb2f18f8Sesaxe /*
724fb2f18f8Sesaxe * Notify all registered classes that the
725fb2f18f8Sesaxe * CPU is about to leave the CPU partition
726fb2f18f8Sesaxe */
727fb2f18f8Sesaxe for (i = 0; i < pg_nclasses; i++)
728fb2f18f8Sesaxe PG_CPUPART_MOVE(i, cp, oldpp, newpp);
729fb2f18f8Sesaxe }
730fb2f18f8Sesaxe
731fb2f18f8Sesaxe /*
7320e751525SEric Saxe * Return a class specific string describing a policy implemented
7330e751525SEric Saxe * across this PG
7340e751525SEric Saxe */
7350e751525SEric Saxe char *
pg_policy_name(pg_t * pg)7360e751525SEric Saxe pg_policy_name(pg_t *pg)
7370e751525SEric Saxe {
7380e751525SEric Saxe char *str;
7390e751525SEric Saxe if ((str = PG_POLICY_NAME(pg)) != NULL)
7400e751525SEric Saxe return (str);
7410e751525SEric Saxe
7420e751525SEric Saxe return ("N/A");
7430e751525SEric Saxe }
7440e751525SEric Saxe
7450e751525SEric Saxe /*
746fb2f18f8Sesaxe * Provide the specified CPU a bootstrap pg
747fb2f18f8Sesaxe * This is needed to allow sane behaviour if any PG consuming
748fb2f18f8Sesaxe * code needs to deal with a partially initialized CPU
749fb2f18f8Sesaxe */
750fb2f18f8Sesaxe void
pg_cpu_bootstrap(cpu_t * cp)751fb2f18f8Sesaxe pg_cpu_bootstrap(cpu_t *cp)
752fb2f18f8Sesaxe {
753fb2f18f8Sesaxe cp->cpu_pg = &bootstrap_pg_data;
754fb2f18f8Sesaxe }
755fb2f18f8Sesaxe
7561a77c24bSEric Saxe /*
7571a77c24bSEric Saxe * Return non-zero if the specified CPU is bootstrapped,
7581a77c24bSEric Saxe * which means it's CPU specific PG data has not yet been
7591a77c24bSEric Saxe * fully constructed.
7601a77c24bSEric Saxe */
7611a77c24bSEric Saxe int
pg_cpu_is_bootstrapped(cpu_t * cp)7621a77c24bSEric Saxe pg_cpu_is_bootstrapped(cpu_t *cp)
7631a77c24bSEric Saxe {
7641a77c24bSEric Saxe return (cp->cpu_pg == &bootstrap_pg_data);
7651a77c24bSEric Saxe }
7661a77c24bSEric Saxe
767fb2f18f8Sesaxe /*ARGSUSED*/
768fb2f18f8Sesaxe static pg_t *
pg_alloc_default(pg_class_t class)769fb2f18f8Sesaxe pg_alloc_default(pg_class_t class)
770fb2f18f8Sesaxe {
771fb2f18f8Sesaxe return (kmem_zalloc(sizeof (pg_t), KM_SLEEP));
772fb2f18f8Sesaxe }
773fb2f18f8Sesaxe
774fb2f18f8Sesaxe /*ARGSUSED*/
775fb2f18f8Sesaxe static void
pg_free_default(struct pg * pg)776fb2f18f8Sesaxe pg_free_default(struct pg *pg)
777fb2f18f8Sesaxe {
778fb2f18f8Sesaxe kmem_free(pg, sizeof (pg_t));
779fb2f18f8Sesaxe }
7800e751525SEric Saxe
7810e751525SEric Saxe static void
pg_null_op()7820e751525SEric Saxe pg_null_op()
7830e751525SEric Saxe {
7840e751525SEric Saxe }
7850e751525SEric Saxe
7860e751525SEric Saxe /*
7870e751525SEric Saxe * Invoke the "thread switch" callback for each of the CPU's PGs
7880e751525SEric Saxe * This is invoked from the dispatcher swtch() routine, which is called
7890e751525SEric Saxe * when a thread running an a CPU should switch to another thread.
7900e751525SEric Saxe * "cp" is the CPU on which the thread switch is happening
7910e751525SEric Saxe * "now" is an unscaled hrtime_t timestamp taken in swtch()
7920e751525SEric Saxe * "old" and "new" are the outgoing and incoming threads, respectively.
7930e751525SEric Saxe */
7940e751525SEric Saxe void
pg_ev_thread_swtch(struct cpu * cp,hrtime_t now,kthread_t * old,kthread_t * new)7950e751525SEric Saxe pg_ev_thread_swtch(struct cpu *cp, hrtime_t now, kthread_t *old, kthread_t *new)
7960e751525SEric Saxe {
7970e751525SEric Saxe int i, sz;
7980e751525SEric Saxe group_t *grp;
7990e751525SEric Saxe pg_t *pg;
8000e751525SEric Saxe
8010e751525SEric Saxe grp = &cp->cpu_pg->pgs;
8020e751525SEric Saxe sz = GROUP_SIZE(grp);
8030e751525SEric Saxe for (i = 0; i < sz; i++) {
8040e751525SEric Saxe pg = GROUP_ACCESS(grp, i);
8050e751525SEric Saxe pg->pg_cb.thread_swtch(pg, cp, now, old, new);
8060e751525SEric Saxe }
8070e751525SEric Saxe }
8080e751525SEric Saxe
8090e751525SEric Saxe /*
8100e751525SEric Saxe * Invoke the "thread remain" callback for each of the CPU's PGs.
8110e751525SEric Saxe * This is called from the dispatcher's swtch() routine when a thread
8120e751525SEric Saxe * running on the CPU "cp" is switching to itself, which can happen as an
8130e751525SEric Saxe * artifact of the thread's timeslice expiring.
8140e751525SEric Saxe */
8150e751525SEric Saxe void
pg_ev_thread_remain(struct cpu * cp,kthread_t * t)8160e751525SEric Saxe pg_ev_thread_remain(struct cpu *cp, kthread_t *t)
8170e751525SEric Saxe {
8180e751525SEric Saxe int i, sz;
8190e751525SEric Saxe group_t *grp;
8200e751525SEric Saxe pg_t *pg;
8210e751525SEric Saxe
8220e751525SEric Saxe grp = &cp->cpu_pg->pgs;
8230e751525SEric Saxe sz = GROUP_SIZE(grp);
8240e751525SEric Saxe for (i = 0; i < sz; i++) {
8250e751525SEric Saxe pg = GROUP_ACCESS(grp, i);
8260e751525SEric Saxe pg->pg_cb.thread_remain(pg, cp, t);
8270e751525SEric Saxe }
8280e751525SEric Saxe }
829