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 /* 22fb2f18f8Sesaxe * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23fb2f18f8Sesaxe * Use is subject to license terms. 24fb2f18f8Sesaxe */ 25fb2f18f8Sesaxe 26fb2f18f8Sesaxe #pragma ident "%Z%%M% %I% %E% SMI" 27fb2f18f8Sesaxe 28fb2f18f8Sesaxe #include <sys/systm.h> 29fb2f18f8Sesaxe #include <sys/types.h> 30fb2f18f8Sesaxe #include <sys/param.h> 31fb2f18f8Sesaxe #include <sys/thread.h> 32fb2f18f8Sesaxe #include <sys/cpuvar.h> 33fb2f18f8Sesaxe #include <sys/cpupart.h> 34fb2f18f8Sesaxe #include <sys/kmem.h> 35fb2f18f8Sesaxe #include <sys/cmn_err.h> 36fb2f18f8Sesaxe #include <sys/kstat.h> 37fb2f18f8Sesaxe #include <sys/processor.h> 38fb2f18f8Sesaxe #include <sys/disp.h> 39fb2f18f8Sesaxe #include <sys/group.h> 40fb2f18f8Sesaxe #include <sys/pg.h> 41fb2f18f8Sesaxe 42fb2f18f8Sesaxe /* 43fb2f18f8Sesaxe * Processor groups 44fb2f18f8Sesaxe * 45fb2f18f8Sesaxe * With the introduction of Chip Multi-Threaded (CMT) processor architectures, 46fb2f18f8Sesaxe * it is no longer necessarily true that a given physical processor module 47fb2f18f8Sesaxe * will present itself as a single schedulable entity (cpu_t). Rather, each 48fb2f18f8Sesaxe * chip and/or processor core may present itself as one or more "logical" CPUs. 49fb2f18f8Sesaxe * 50fb2f18f8Sesaxe * The logical CPUs presented may share physical components such as caches, 51fb2f18f8Sesaxe * data pipes, execution pipelines, FPUs, etc. It is advantageous to have the 52fb2f18f8Sesaxe * kernel be aware of the relationships existing between logical CPUs so that 53fb2f18f8Sesaxe * the appropriate optmizations may be employed. 54fb2f18f8Sesaxe * 55fb2f18f8Sesaxe * The processor group abstraction represents a set of logical CPUs that 56fb2f18f8Sesaxe * generally share some sort of physical or characteristic relationship. 57fb2f18f8Sesaxe * 58fb2f18f8Sesaxe * In the case of a physical sharing relationship, the CPUs in the group may 59fb2f18f8Sesaxe * share a pipeline, cache or floating point unit. In the case of a logical 60fb2f18f8Sesaxe * relationship, a PG may represent the set of CPUs in a processor set, or the 61fb2f18f8Sesaxe * set of CPUs running at a particular clock speed. 62fb2f18f8Sesaxe * 63fb2f18f8Sesaxe * The generic processor group structure, pg_t, contains the elements generic 64fb2f18f8Sesaxe * to a group of CPUs. Depending on the nature of the CPU relationship 65fb2f18f8Sesaxe * (LOGICAL or PHYSICAL), a pointer to a pg may be recast to a "view" of that 66fb2f18f8Sesaxe * PG where more specific data is represented. 67fb2f18f8Sesaxe * 68fb2f18f8Sesaxe * As an example, a PG representing a PHYSICAL relationship, may be recast to 69fb2f18f8Sesaxe * a pghw_t, where data further describing the hardware sharing relationship 70fb2f18f8Sesaxe * is maintained. See pghw.c and pghw.h for details on physical PGs. 71fb2f18f8Sesaxe * 72fb2f18f8Sesaxe * At this time a more specialized casting of a PG representing a LOGICAL 73fb2f18f8Sesaxe * relationship has not been implemented, but the architecture allows for this 74fb2f18f8Sesaxe * in the future. 75fb2f18f8Sesaxe * 76fb2f18f8Sesaxe * Processor Group Classes 77fb2f18f8Sesaxe * 78fb2f18f8Sesaxe * Processor group consumers may wish to maintain and associate specific 79fb2f18f8Sesaxe * data with the PGs they create. For this reason, a mechanism for creating 80fb2f18f8Sesaxe * class specific PGs exists. Classes may overload the default functions for 81fb2f18f8Sesaxe * creating, destroying, and associating CPUs with PGs, and may also register 82fb2f18f8Sesaxe * class specific callbacks to be invoked when the CPU related system 83fb2f18f8Sesaxe * configuration changes. Class specific data is stored/associated with 84fb2f18f8Sesaxe * PGs by incorporating the pg_t (or pghw_t, as appropriate), as the first 85fb2f18f8Sesaxe * element of a class specific PG object. In memory, such a structure may look 86fb2f18f8Sesaxe * like: 87fb2f18f8Sesaxe * 88fb2f18f8Sesaxe * ----------------------- - - - 89fb2f18f8Sesaxe * | common | | | | <--(pg_t *) 90fb2f18f8Sesaxe * ----------------------- | | - 91fb2f18f8Sesaxe * | HW specific | | | <-----(pghw_t *) 92fb2f18f8Sesaxe * ----------------------- | - 93fb2f18f8Sesaxe * | class specific | | <-------(pg_cmt_t *) 94fb2f18f8Sesaxe * ----------------------- - 95fb2f18f8Sesaxe * 96fb2f18f8Sesaxe * Access to the PG class specific data can be had by casting a pointer to 97fb2f18f8Sesaxe * it's class specific view. 98fb2f18f8Sesaxe */ 99fb2f18f8Sesaxe 100fb2f18f8Sesaxe static pg_t *pg_alloc_default(pg_class_t); 101fb2f18f8Sesaxe static void pg_free_default(pg_t *); 102fb2f18f8Sesaxe 103fb2f18f8Sesaxe /* 104fb2f18f8Sesaxe * Bootstrap CPU specific PG data 105fb2f18f8Sesaxe * See pg_cpu_bootstrap() 106fb2f18f8Sesaxe */ 107fb2f18f8Sesaxe static cpu_pg_t bootstrap_pg_data; 108fb2f18f8Sesaxe 109fb2f18f8Sesaxe /* 110fb2f18f8Sesaxe * Bitset of allocated PG ids (they are sequential) 111fb2f18f8Sesaxe * and the next free id in the set. 112fb2f18f8Sesaxe */ 113fb2f18f8Sesaxe static bitset_t pg_id_set; 114fb2f18f8Sesaxe static pgid_t pg_id_next = 0; 115fb2f18f8Sesaxe 116fb2f18f8Sesaxe /* 117fb2f18f8Sesaxe * Default and externed PG ops vectors 118fb2f18f8Sesaxe */ 119fb2f18f8Sesaxe static struct pg_ops pg_ops_default = { 120fb2f18f8Sesaxe pg_alloc_default, /* alloc */ 121fb2f18f8Sesaxe pg_free_default, /* free */ 122fb2f18f8Sesaxe NULL, /* cpu_init */ 123fb2f18f8Sesaxe NULL, /* cpu_fini */ 124fb2f18f8Sesaxe NULL, /* cpu_active */ 125fb2f18f8Sesaxe NULL, /* cpu_inactive */ 126fb2f18f8Sesaxe NULL, /* cpupart_in */ 127fb2f18f8Sesaxe NULL, /* cpupart_out */ 128fb2f18f8Sesaxe NULL, /* cpupart_move */ 129fb2f18f8Sesaxe NULL, /* cpu_belongs */ 130fb2f18f8Sesaxe }; 131fb2f18f8Sesaxe 132fb2f18f8Sesaxe /* 133fb2f18f8Sesaxe * Class specific PG allocation callbacks 134fb2f18f8Sesaxe */ 135fb2f18f8Sesaxe #define PG_ALLOC(class) \ 136fb2f18f8Sesaxe (pg_classes[class].pgc_ops->alloc ? \ 137fb2f18f8Sesaxe pg_classes[class].pgc_ops->alloc() : \ 138fb2f18f8Sesaxe pg_classes[pg_default_cid].pgc_ops->alloc()) 139fb2f18f8Sesaxe 140fb2f18f8Sesaxe #define PG_FREE(pg) \ 141fb2f18f8Sesaxe ((pg)->pg_class->pgc_ops->free ? \ 142fb2f18f8Sesaxe (pg)->pg_class->pgc_ops->free(pg) : \ 143fb2f18f8Sesaxe pg_classes[pg_default_cid].pgc_ops->free(pg)) \ 144fb2f18f8Sesaxe 145fb2f18f8Sesaxe 146fb2f18f8Sesaxe /* 147fb2f18f8Sesaxe * Class specific membership test callback 148fb2f18f8Sesaxe */ 149fb2f18f8Sesaxe #define PG_CPU_BELONGS(pg, cp) \ 150fb2f18f8Sesaxe ((pg)->pg_class->pgc_ops->cpu_belongs ? \ 151fb2f18f8Sesaxe (pg)->pg_class->pgc_ops->cpu_belongs(pg, cp) : 0) \ 152fb2f18f8Sesaxe 153fb2f18f8Sesaxe /* 154fb2f18f8Sesaxe * CPU configuration callbacks 155fb2f18f8Sesaxe */ 156fb2f18f8Sesaxe #define PG_CPU_INIT(class, cp) \ 157fb2f18f8Sesaxe { \ 158fb2f18f8Sesaxe if (pg_classes[class].pgc_ops->cpu_init) \ 159fb2f18f8Sesaxe pg_classes[class].pgc_ops->cpu_init(cp); \ 160fb2f18f8Sesaxe } 161fb2f18f8Sesaxe 162fb2f18f8Sesaxe #define PG_CPU_FINI(class, cp) \ 163fb2f18f8Sesaxe { \ 164fb2f18f8Sesaxe if (pg_classes[class].pgc_ops->cpu_fini) \ 165fb2f18f8Sesaxe pg_classes[class].pgc_ops->cpu_fini(cp); \ 166fb2f18f8Sesaxe } 167fb2f18f8Sesaxe 168fb2f18f8Sesaxe #define PG_CPU_ACTIVE(class, cp) \ 169fb2f18f8Sesaxe { \ 170fb2f18f8Sesaxe if (pg_classes[class].pgc_ops->cpu_active) \ 171fb2f18f8Sesaxe pg_classes[class].pgc_ops->cpu_active(cp); \ 172fb2f18f8Sesaxe } 173fb2f18f8Sesaxe 174fb2f18f8Sesaxe #define PG_CPU_INACTIVE(class, cp) \ 175fb2f18f8Sesaxe { \ 176fb2f18f8Sesaxe if (pg_classes[class].pgc_ops->cpu_inactive) \ 177fb2f18f8Sesaxe pg_classes[class].pgc_ops->cpu_inactive(cp); \ 178fb2f18f8Sesaxe } 179fb2f18f8Sesaxe 180fb2f18f8Sesaxe /* 181fb2f18f8Sesaxe * CPU / cpupart configuration callbacks 182fb2f18f8Sesaxe */ 183fb2f18f8Sesaxe #define PG_CPUPART_IN(class, cp, pp) \ 184fb2f18f8Sesaxe { \ 185fb2f18f8Sesaxe if (pg_classes[class].pgc_ops->cpupart_in) \ 186fb2f18f8Sesaxe pg_classes[class].pgc_ops->cpupart_in(cp, pp); \ 187fb2f18f8Sesaxe } 188fb2f18f8Sesaxe 189fb2f18f8Sesaxe #define PG_CPUPART_OUT(class, cp, pp) \ 190fb2f18f8Sesaxe { \ 191fb2f18f8Sesaxe if (pg_classes[class].pgc_ops->cpupart_out) \ 192fb2f18f8Sesaxe pg_classes[class].pgc_ops->cpupart_out(cp, pp); \ 193fb2f18f8Sesaxe } 194fb2f18f8Sesaxe 195fb2f18f8Sesaxe #define PG_CPUPART_MOVE(class, cp, old, new) \ 196fb2f18f8Sesaxe { \ 197fb2f18f8Sesaxe if (pg_classes[class].pgc_ops->cpupart_move) \ 198fb2f18f8Sesaxe pg_classes[class].pgc_ops->cpupart_move(cp, old, new); \ 199fb2f18f8Sesaxe } 200fb2f18f8Sesaxe 201fb2f18f8Sesaxe 202fb2f18f8Sesaxe 203fb2f18f8Sesaxe static pg_class_t *pg_classes; 204fb2f18f8Sesaxe static int pg_nclasses; 205fb2f18f8Sesaxe 206fb2f18f8Sesaxe static pg_cid_t pg_default_cid; 207fb2f18f8Sesaxe 208fb2f18f8Sesaxe /* 209fb2f18f8Sesaxe * Initialze common PG subsystem. Perform CPU 0 initialization 210fb2f18f8Sesaxe */ 211fb2f18f8Sesaxe void 212fb2f18f8Sesaxe pg_init(void) 213fb2f18f8Sesaxe { 214fb2f18f8Sesaxe pg_default_cid = 215fb2f18f8Sesaxe pg_class_register("default", &pg_ops_default, PGR_LOGICAL); 216fb2f18f8Sesaxe } 217fb2f18f8Sesaxe 218fb2f18f8Sesaxe /* 219fb2f18f8Sesaxe * Perform CPU 0 initialization 220fb2f18f8Sesaxe */ 221fb2f18f8Sesaxe void 222fb2f18f8Sesaxe pg_cpu0_init(void) 223fb2f18f8Sesaxe { 224fb2f18f8Sesaxe extern void pghw_physid_create(); 225fb2f18f8Sesaxe 226fb2f18f8Sesaxe /* 227fb2f18f8Sesaxe * Create the physical ID cache for the boot CPU 228fb2f18f8Sesaxe */ 229fb2f18f8Sesaxe pghw_physid_create(CPU); 230fb2f18f8Sesaxe 231fb2f18f8Sesaxe /* 232fb2f18f8Sesaxe * pg_cpu_* require that cpu_lock be held 233fb2f18f8Sesaxe */ 234fb2f18f8Sesaxe mutex_enter(&cpu_lock); 235fb2f18f8Sesaxe 236fb2f18f8Sesaxe pg_cpu_init(CPU); 237fb2f18f8Sesaxe pg_cpupart_in(CPU, &cp_default); 238fb2f18f8Sesaxe pg_cpu_active(CPU); 239fb2f18f8Sesaxe 240fb2f18f8Sesaxe mutex_exit(&cpu_lock); 241fb2f18f8Sesaxe } 242fb2f18f8Sesaxe 243fb2f18f8Sesaxe /* 244*a6604450Sesaxe * Invoked when topology for CPU0 changes 245*a6604450Sesaxe * post pg_cpu0_init(). 246*a6604450Sesaxe * 247*a6604450Sesaxe * Currently happens as a result of null_proc_lpa 248*a6604450Sesaxe * on Starcat. 249*a6604450Sesaxe */ 250*a6604450Sesaxe void 251*a6604450Sesaxe pg_cpu0_reinit(void) 252*a6604450Sesaxe { 253*a6604450Sesaxe mutex_enter(&cpu_lock); 254*a6604450Sesaxe pg_cpu_inactive(CPU); 255*a6604450Sesaxe pg_cpupart_out(CPU, &cp_default); 256*a6604450Sesaxe pg_cpu_fini(CPU); 257*a6604450Sesaxe 258*a6604450Sesaxe pg_cpu_init(CPU); 259*a6604450Sesaxe pg_cpupart_in(CPU, &cp_default); 260*a6604450Sesaxe pg_cpu_active(CPU); 261*a6604450Sesaxe mutex_exit(&cpu_lock); 262*a6604450Sesaxe } 263*a6604450Sesaxe 264*a6604450Sesaxe /* 265fb2f18f8Sesaxe * Register a new PG class 266fb2f18f8Sesaxe */ 267fb2f18f8Sesaxe pg_cid_t 268fb2f18f8Sesaxe pg_class_register(char *name, struct pg_ops *ops, pg_relation_t relation) 269fb2f18f8Sesaxe { 270fb2f18f8Sesaxe pg_class_t *newclass; 271fb2f18f8Sesaxe pg_class_t *classes_old; 272fb2f18f8Sesaxe id_t cid; 273fb2f18f8Sesaxe 274fb2f18f8Sesaxe mutex_enter(&cpu_lock); 275fb2f18f8Sesaxe 276fb2f18f8Sesaxe /* 277fb2f18f8Sesaxe * Allocate a new pg_class_t in the pg_classes array 278fb2f18f8Sesaxe */ 279fb2f18f8Sesaxe if (pg_nclasses == 0) { 280fb2f18f8Sesaxe pg_classes = kmem_zalloc(sizeof (pg_class_t), KM_SLEEP); 281fb2f18f8Sesaxe } else { 282fb2f18f8Sesaxe classes_old = pg_classes; 283fb2f18f8Sesaxe pg_classes = 284fb2f18f8Sesaxe kmem_zalloc(sizeof (pg_class_t) * (pg_nclasses + 1), 285fb2f18f8Sesaxe KM_SLEEP); 286fb2f18f8Sesaxe (void) kcopy(classes_old, pg_classes, 287fb2f18f8Sesaxe sizeof (pg_class_t) * pg_nclasses); 288fb2f18f8Sesaxe kmem_free(classes_old, sizeof (pg_class_t) * pg_nclasses); 289fb2f18f8Sesaxe } 290fb2f18f8Sesaxe 291fb2f18f8Sesaxe cid = pg_nclasses++; 292fb2f18f8Sesaxe newclass = &pg_classes[cid]; 293fb2f18f8Sesaxe 294fb2f18f8Sesaxe (void) strncpy(newclass->pgc_name, name, PG_CLASS_NAME_MAX); 295fb2f18f8Sesaxe newclass->pgc_id = cid; 296fb2f18f8Sesaxe newclass->pgc_ops = ops; 297fb2f18f8Sesaxe newclass->pgc_relation = relation; 298fb2f18f8Sesaxe 299fb2f18f8Sesaxe mutex_exit(&cpu_lock); 300fb2f18f8Sesaxe 301fb2f18f8Sesaxe return (cid); 302fb2f18f8Sesaxe } 303fb2f18f8Sesaxe 304fb2f18f8Sesaxe /* 305fb2f18f8Sesaxe * Try to find an existing pg in set in which to place cp. 306fb2f18f8Sesaxe * Returns the pg if found, and NULL otherwise. 307fb2f18f8Sesaxe * In the event that the CPU could belong to multiple 308fb2f18f8Sesaxe * PGs in the set, the first matching PG will be returned. 309fb2f18f8Sesaxe */ 310fb2f18f8Sesaxe pg_t * 311fb2f18f8Sesaxe pg_cpu_find_pg(cpu_t *cp, group_t *set) 312fb2f18f8Sesaxe { 313fb2f18f8Sesaxe pg_t *pg; 314fb2f18f8Sesaxe group_iter_t i; 315fb2f18f8Sesaxe 316fb2f18f8Sesaxe group_iter_init(&i); 317fb2f18f8Sesaxe while ((pg = group_iterate(set, &i)) != NULL) { 318fb2f18f8Sesaxe /* 319fb2f18f8Sesaxe * Ask the class if the CPU belongs here 320fb2f18f8Sesaxe */ 321fb2f18f8Sesaxe if (PG_CPU_BELONGS(pg, cp)) 322fb2f18f8Sesaxe return (pg); 323fb2f18f8Sesaxe } 324fb2f18f8Sesaxe return (NULL); 325fb2f18f8Sesaxe } 326fb2f18f8Sesaxe 327fb2f18f8Sesaxe /* 328fb2f18f8Sesaxe * Iterate over the CPUs in a PG after initializing 329fb2f18f8Sesaxe * the iterator with PG_CPU_ITR_INIT() 330fb2f18f8Sesaxe */ 331fb2f18f8Sesaxe cpu_t * 332fb2f18f8Sesaxe pg_cpu_next(pg_cpu_itr_t *itr) 333fb2f18f8Sesaxe { 334fb2f18f8Sesaxe cpu_t *cpu; 335fb2f18f8Sesaxe pg_t *pg = itr->pg; 336fb2f18f8Sesaxe 337fb2f18f8Sesaxe cpu = group_iterate(&pg->pg_cpus, &itr->position); 338fb2f18f8Sesaxe return (cpu); 339fb2f18f8Sesaxe } 340fb2f18f8Sesaxe 341fb2f18f8Sesaxe /* 342fb2f18f8Sesaxe * Create a PG of a given class. 343fb2f18f8Sesaxe * This routine may block. 344fb2f18f8Sesaxe */ 345fb2f18f8Sesaxe pg_t * 346fb2f18f8Sesaxe pg_create(pg_cid_t cid) 347fb2f18f8Sesaxe { 348fb2f18f8Sesaxe pg_t *pg; 349fb2f18f8Sesaxe pgid_t id; 350fb2f18f8Sesaxe 351fb2f18f8Sesaxe ASSERT(MUTEX_HELD(&cpu_lock)); 352fb2f18f8Sesaxe 353fb2f18f8Sesaxe /* 354fb2f18f8Sesaxe * Call the class specific PG allocation routine 355fb2f18f8Sesaxe */ 356fb2f18f8Sesaxe pg = PG_ALLOC(cid); 357fb2f18f8Sesaxe pg->pg_class = &pg_classes[cid]; 358fb2f18f8Sesaxe pg->pg_relation = pg->pg_class->pgc_relation; 359fb2f18f8Sesaxe 360fb2f18f8Sesaxe /* 361fb2f18f8Sesaxe * Find the next free sequential pg id 362fb2f18f8Sesaxe */ 363fb2f18f8Sesaxe do { 364fb2f18f8Sesaxe if (pg_id_next >= bitset_capacity(&pg_id_set)) 365fb2f18f8Sesaxe bitset_resize(&pg_id_set, pg_id_next + 1); 366fb2f18f8Sesaxe id = pg_id_next++; 367fb2f18f8Sesaxe } while (bitset_in_set(&pg_id_set, id)); 368fb2f18f8Sesaxe 369fb2f18f8Sesaxe pg->pg_id = id; 370fb2f18f8Sesaxe bitset_add(&pg_id_set, pg->pg_id); 371fb2f18f8Sesaxe 372fb2f18f8Sesaxe /* 373fb2f18f8Sesaxe * Create the PG's CPU group 374fb2f18f8Sesaxe */ 375fb2f18f8Sesaxe group_create(&pg->pg_cpus); 376fb2f18f8Sesaxe 377fb2f18f8Sesaxe return (pg); 378fb2f18f8Sesaxe } 379fb2f18f8Sesaxe 380fb2f18f8Sesaxe /* 381fb2f18f8Sesaxe * Destroy a PG. 382fb2f18f8Sesaxe * This routine may block. 383fb2f18f8Sesaxe */ 384fb2f18f8Sesaxe void 385fb2f18f8Sesaxe pg_destroy(pg_t *pg) 386fb2f18f8Sesaxe { 387fb2f18f8Sesaxe ASSERT(MUTEX_HELD(&cpu_lock)); 388fb2f18f8Sesaxe 389fb2f18f8Sesaxe group_destroy(&pg->pg_cpus); 390fb2f18f8Sesaxe 391fb2f18f8Sesaxe /* 392fb2f18f8Sesaxe * Unassign the pg_id 393fb2f18f8Sesaxe */ 394fb2f18f8Sesaxe if (pg_id_next > pg->pg_id) 395fb2f18f8Sesaxe pg_id_next = pg->pg_id; 396fb2f18f8Sesaxe bitset_del(&pg_id_set, pg->pg_id); 397fb2f18f8Sesaxe 398fb2f18f8Sesaxe /* 399fb2f18f8Sesaxe * Invoke the class specific de-allocation routine 400fb2f18f8Sesaxe */ 401fb2f18f8Sesaxe PG_FREE(pg); 402fb2f18f8Sesaxe } 403fb2f18f8Sesaxe 404fb2f18f8Sesaxe /* 405fb2f18f8Sesaxe * Add the CPU "cp" to processor group "pg" 406fb2f18f8Sesaxe * This routine may block. 407fb2f18f8Sesaxe */ 408fb2f18f8Sesaxe void 409fb2f18f8Sesaxe pg_cpu_add(pg_t *pg, cpu_t *cp) 410fb2f18f8Sesaxe { 411fb2f18f8Sesaxe int err; 412fb2f18f8Sesaxe 413fb2f18f8Sesaxe ASSERT(MUTEX_HELD(&cpu_lock)); 414fb2f18f8Sesaxe 415fb2f18f8Sesaxe /* This adds the CPU to the PG's CPU group */ 416fb2f18f8Sesaxe err = group_add(&pg->pg_cpus, cp, GRP_RESIZE); 417fb2f18f8Sesaxe ASSERT(err == 0); 418fb2f18f8Sesaxe 419fb2f18f8Sesaxe /* This adds the PG to the CPUs PG group */ 420fb2f18f8Sesaxe ASSERT(cp->cpu_pg != &bootstrap_pg_data); 421fb2f18f8Sesaxe err = group_add(&cp->cpu_pg->pgs, pg, GRP_RESIZE); 422fb2f18f8Sesaxe ASSERT(err == 0); 423fb2f18f8Sesaxe } 424fb2f18f8Sesaxe 425fb2f18f8Sesaxe /* 426fb2f18f8Sesaxe * Remove "cp" from "pg". 427fb2f18f8Sesaxe * This routine may block. 428fb2f18f8Sesaxe */ 429fb2f18f8Sesaxe void 430fb2f18f8Sesaxe pg_cpu_delete(pg_t *pg, cpu_t *cp) 431fb2f18f8Sesaxe { 432fb2f18f8Sesaxe int err; 433fb2f18f8Sesaxe 434fb2f18f8Sesaxe ASSERT(MUTEX_HELD(&cpu_lock)); 435fb2f18f8Sesaxe 436fb2f18f8Sesaxe /* Remove the CPU from the PG */ 437fb2f18f8Sesaxe err = group_remove(&pg->pg_cpus, cp, GRP_RESIZE); 438fb2f18f8Sesaxe ASSERT(err == 0); 439fb2f18f8Sesaxe 440fb2f18f8Sesaxe /* Remove the PG from the CPU's PG group */ 441fb2f18f8Sesaxe ASSERT(cp->cpu_pg != &bootstrap_pg_data); 442fb2f18f8Sesaxe err = group_remove(&cp->cpu_pg->pgs, pg, GRP_RESIZE); 443fb2f18f8Sesaxe ASSERT(err == 0); 444fb2f18f8Sesaxe } 445fb2f18f8Sesaxe 446fb2f18f8Sesaxe /* 447fb2f18f8Sesaxe * Allocate a CPU's PG data. This hangs off struct cpu at cpu_pg 448fb2f18f8Sesaxe */ 449fb2f18f8Sesaxe static cpu_pg_t * 450fb2f18f8Sesaxe pg_cpu_data_alloc(void) 451fb2f18f8Sesaxe { 452fb2f18f8Sesaxe cpu_pg_t *pgd; 453fb2f18f8Sesaxe 454fb2f18f8Sesaxe pgd = kmem_zalloc(sizeof (cpu_pg_t), KM_SLEEP); 455fb2f18f8Sesaxe group_create(&pgd->pgs); 456fb2f18f8Sesaxe group_create(&pgd->cmt_pgs); 457fb2f18f8Sesaxe 458fb2f18f8Sesaxe return (pgd); 459fb2f18f8Sesaxe } 460fb2f18f8Sesaxe 461fb2f18f8Sesaxe /* 462fb2f18f8Sesaxe * Free the CPU's PG data. 463fb2f18f8Sesaxe */ 464fb2f18f8Sesaxe static void 465fb2f18f8Sesaxe pg_cpu_data_free(cpu_pg_t *pgd) 466fb2f18f8Sesaxe { 467fb2f18f8Sesaxe group_destroy(&pgd->pgs); 468fb2f18f8Sesaxe group_destroy(&pgd->cmt_pgs); 469fb2f18f8Sesaxe kmem_free(pgd, sizeof (cpu_pg_t)); 470fb2f18f8Sesaxe } 471fb2f18f8Sesaxe 472fb2f18f8Sesaxe /* 473fb2f18f8Sesaxe * A new CPU is coming into the system, either via booting or DR. 474fb2f18f8Sesaxe * Allocate it's PG data, and notify all registered classes about 475fb2f18f8Sesaxe * the new CPU. 476fb2f18f8Sesaxe * 477fb2f18f8Sesaxe * This routine may block. 478fb2f18f8Sesaxe */ 479fb2f18f8Sesaxe void 480fb2f18f8Sesaxe pg_cpu_init(cpu_t *cp) 481fb2f18f8Sesaxe { 482fb2f18f8Sesaxe pg_cid_t i; 483fb2f18f8Sesaxe 484fb2f18f8Sesaxe ASSERT(MUTEX_HELD(&cpu_lock)); 485fb2f18f8Sesaxe 486fb2f18f8Sesaxe /* 487fb2f18f8Sesaxe * Allocate and size the per CPU pg data 488fb2f18f8Sesaxe */ 489fb2f18f8Sesaxe cp->cpu_pg = pg_cpu_data_alloc(); 490fb2f18f8Sesaxe 491fb2f18f8Sesaxe /* 492fb2f18f8Sesaxe * Notify all registered classes about the new CPU 493fb2f18f8Sesaxe */ 494fb2f18f8Sesaxe for (i = 0; i < pg_nclasses; i++) 495fb2f18f8Sesaxe PG_CPU_INIT(i, cp); 496fb2f18f8Sesaxe } 497fb2f18f8Sesaxe 498fb2f18f8Sesaxe /* 499fb2f18f8Sesaxe * This CPU is being deleted from the system. Notify the classes 500fb2f18f8Sesaxe * and free up the CPU's PG data. 501fb2f18f8Sesaxe */ 502fb2f18f8Sesaxe void 503fb2f18f8Sesaxe pg_cpu_fini(cpu_t *cp) 504fb2f18f8Sesaxe { 505fb2f18f8Sesaxe pg_cid_t i; 506fb2f18f8Sesaxe 507fb2f18f8Sesaxe ASSERT(MUTEX_HELD(&cpu_lock)); 508fb2f18f8Sesaxe 509fb2f18f8Sesaxe /* 510fb2f18f8Sesaxe * This can happen if the CPU coming into the system 511fb2f18f8Sesaxe * failed to power on. 512fb2f18f8Sesaxe */ 513fb2f18f8Sesaxe if (cp->cpu_pg == NULL || 514fb2f18f8Sesaxe cp->cpu_pg == &bootstrap_pg_data) 515fb2f18f8Sesaxe return; 516fb2f18f8Sesaxe 517fb2f18f8Sesaxe for (i = 0; i < pg_nclasses; i++) 518fb2f18f8Sesaxe PG_CPU_FINI(i, cp); 519fb2f18f8Sesaxe 520fb2f18f8Sesaxe pg_cpu_data_free(cp->cpu_pg); 521fb2f18f8Sesaxe cp->cpu_pg = NULL; 522fb2f18f8Sesaxe } 523fb2f18f8Sesaxe 524fb2f18f8Sesaxe /* 525fb2f18f8Sesaxe * This CPU is becoming active (online) 526fb2f18f8Sesaxe * This routine may not block as it is called from paused CPUs 527fb2f18f8Sesaxe * context. 528fb2f18f8Sesaxe */ 529fb2f18f8Sesaxe void 530fb2f18f8Sesaxe pg_cpu_active(cpu_t *cp) 531fb2f18f8Sesaxe { 532fb2f18f8Sesaxe pg_cid_t i; 533fb2f18f8Sesaxe 534fb2f18f8Sesaxe ASSERT(MUTEX_HELD(&cpu_lock)); 535fb2f18f8Sesaxe 536fb2f18f8Sesaxe /* 537fb2f18f8Sesaxe * Notify all registered classes about the new CPU 538fb2f18f8Sesaxe */ 539fb2f18f8Sesaxe for (i = 0; i < pg_nclasses; i++) 540fb2f18f8Sesaxe PG_CPU_ACTIVE(i, cp); 541fb2f18f8Sesaxe } 542fb2f18f8Sesaxe 543fb2f18f8Sesaxe /* 544fb2f18f8Sesaxe * This CPU is going inactive (offline) 545fb2f18f8Sesaxe * This routine may not block, as it is called from paused 546fb2f18f8Sesaxe * CPUs context. 547fb2f18f8Sesaxe */ 548fb2f18f8Sesaxe void 549fb2f18f8Sesaxe pg_cpu_inactive(cpu_t *cp) 550fb2f18f8Sesaxe { 551fb2f18f8Sesaxe pg_cid_t i; 552fb2f18f8Sesaxe 553fb2f18f8Sesaxe ASSERT(MUTEX_HELD(&cpu_lock)); 554fb2f18f8Sesaxe 555fb2f18f8Sesaxe /* 556fb2f18f8Sesaxe * Notify all registered classes about the new CPU 557fb2f18f8Sesaxe */ 558fb2f18f8Sesaxe for (i = 0; i < pg_nclasses; i++) 559fb2f18f8Sesaxe PG_CPU_INACTIVE(i, cp); 560fb2f18f8Sesaxe } 561fb2f18f8Sesaxe 562fb2f18f8Sesaxe /* 563fb2f18f8Sesaxe * Invoked when the CPU is about to move into the partition 564fb2f18f8Sesaxe * This routine may block. 565fb2f18f8Sesaxe */ 566fb2f18f8Sesaxe void 567fb2f18f8Sesaxe pg_cpupart_in(cpu_t *cp, cpupart_t *pp) 568fb2f18f8Sesaxe { 569fb2f18f8Sesaxe int i; 570fb2f18f8Sesaxe 571fb2f18f8Sesaxe ASSERT(MUTEX_HELD(&cpu_lock)); 572fb2f18f8Sesaxe 573fb2f18f8Sesaxe /* 574fb2f18f8Sesaxe * Notify all registered classes that the 575fb2f18f8Sesaxe * CPU is about to enter the CPU partition 576fb2f18f8Sesaxe */ 577fb2f18f8Sesaxe for (i = 0; i < pg_nclasses; i++) 578fb2f18f8Sesaxe PG_CPUPART_IN(i, cp, pp); 579fb2f18f8Sesaxe } 580fb2f18f8Sesaxe 581fb2f18f8Sesaxe /* 582fb2f18f8Sesaxe * Invoked when the CPU is about to move out of the partition 583fb2f18f8Sesaxe * This routine may block. 584fb2f18f8Sesaxe */ 585fb2f18f8Sesaxe /*ARGSUSED*/ 586fb2f18f8Sesaxe void 587fb2f18f8Sesaxe pg_cpupart_out(cpu_t *cp, cpupart_t *pp) 588fb2f18f8Sesaxe { 589fb2f18f8Sesaxe int i; 590fb2f18f8Sesaxe 591fb2f18f8Sesaxe ASSERT(MUTEX_HELD(&cpu_lock)); 592fb2f18f8Sesaxe 593fb2f18f8Sesaxe /* 594fb2f18f8Sesaxe * Notify all registered classes that the 595fb2f18f8Sesaxe * CPU is about to leave the CPU partition 596fb2f18f8Sesaxe */ 597fb2f18f8Sesaxe for (i = 0; i < pg_nclasses; i++) 598fb2f18f8Sesaxe PG_CPUPART_OUT(i, cp, pp); 599fb2f18f8Sesaxe } 600fb2f18f8Sesaxe 601fb2f18f8Sesaxe /* 602fb2f18f8Sesaxe * Invoked when the CPU is *moving* partitions. 603fb2f18f8Sesaxe * 604fb2f18f8Sesaxe * This routine may not block, as it is called from paused CPUs 605fb2f18f8Sesaxe * context. 606fb2f18f8Sesaxe */ 607fb2f18f8Sesaxe void 608fb2f18f8Sesaxe pg_cpupart_move(cpu_t *cp, cpupart_t *oldpp, cpupart_t *newpp) 609fb2f18f8Sesaxe { 610fb2f18f8Sesaxe int i; 611fb2f18f8Sesaxe 612fb2f18f8Sesaxe ASSERT(MUTEX_HELD(&cpu_lock)); 613fb2f18f8Sesaxe 614fb2f18f8Sesaxe /* 615fb2f18f8Sesaxe * Notify all registered classes that the 616fb2f18f8Sesaxe * CPU is about to leave the CPU partition 617fb2f18f8Sesaxe */ 618fb2f18f8Sesaxe for (i = 0; i < pg_nclasses; i++) 619fb2f18f8Sesaxe PG_CPUPART_MOVE(i, cp, oldpp, newpp); 620fb2f18f8Sesaxe } 621fb2f18f8Sesaxe 622fb2f18f8Sesaxe /* 623fb2f18f8Sesaxe * Provide the specified CPU a bootstrap pg 624fb2f18f8Sesaxe * This is needed to allow sane behaviour if any PG consuming 625fb2f18f8Sesaxe * code needs to deal with a partially initialized CPU 626fb2f18f8Sesaxe */ 627fb2f18f8Sesaxe void 628fb2f18f8Sesaxe pg_cpu_bootstrap(cpu_t *cp) 629fb2f18f8Sesaxe { 630fb2f18f8Sesaxe cp->cpu_pg = &bootstrap_pg_data; 631fb2f18f8Sesaxe } 632fb2f18f8Sesaxe 633fb2f18f8Sesaxe /*ARGSUSED*/ 634fb2f18f8Sesaxe static pg_t * 635fb2f18f8Sesaxe pg_alloc_default(pg_class_t class) 636fb2f18f8Sesaxe { 637fb2f18f8Sesaxe return (kmem_zalloc(sizeof (pg_t), KM_SLEEP)); 638fb2f18f8Sesaxe } 639fb2f18f8Sesaxe 640fb2f18f8Sesaxe /*ARGSUSED*/ 641fb2f18f8Sesaxe static void 642fb2f18f8Sesaxe pg_free_default(struct pg *pg) 643fb2f18f8Sesaxe { 644fb2f18f8Sesaxe kmem_free(pg, sizeof (pg_t)); 645fb2f18f8Sesaxe } 646