1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #ifndef _LGRP_H 28*0Sstevel@tonic-gate #define _LGRP_H 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 31*0Sstevel@tonic-gate 32*0Sstevel@tonic-gate /* 33*0Sstevel@tonic-gate * locality group definitions for kernel 34*0Sstevel@tonic-gate */ 35*0Sstevel@tonic-gate 36*0Sstevel@tonic-gate #include <sys/types.h> 37*0Sstevel@tonic-gate 38*0Sstevel@tonic-gate #ifdef __cplusplus 39*0Sstevel@tonic-gate extern "C" { 40*0Sstevel@tonic-gate #endif 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate #define LGRP_NONE (-1) /* non-existent lgroup ID */ 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate 45*0Sstevel@tonic-gate typedef id_t lgrp_id_t; /* lgroup ID */ 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate #if (!defined(_KERNEL) && !defined(_KMEMUSER)) 48*0Sstevel@tonic-gate typedef struct lgrp_mem_policy_info { int opaque[2]; } lgrp_mem_policy_info_t; 49*0Sstevel@tonic-gate #endif /* !_KERNEL && !_KMEMUSER */ 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gate #if (defined(_KERNEL) || defined(_KMEMUSER)) 52*0Sstevel@tonic-gate #include <sys/cpuvar.h> 53*0Sstevel@tonic-gate #include <sys/bitmap.h> 54*0Sstevel@tonic-gate #include <sys/vnode.h> 55*0Sstevel@tonic-gate #include <vm/anon.h> 56*0Sstevel@tonic-gate #include <vm/seg.h> 57*0Sstevel@tonic-gate #include <sys/lgrp_user.h> 58*0Sstevel@tonic-gate #include <sys/param.h> 59*0Sstevel@tonic-gate 60*0Sstevel@tonic-gate typedef uint32_t lgrp_load_t; /* lgrp_loadavg type */ 61*0Sstevel@tonic-gate typedef uintptr_t lgrp_handle_t; /* lgrp handle */ 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate #define LGRP_NONE_SUCH LGRP_NONE /* non-existent lgroup ID */ 64*0Sstevel@tonic-gate /* null platform handle */ 65*0Sstevel@tonic-gate #define LGRP_NULL_HANDLE ((lgrp_handle_t)0xbadbad) 66*0Sstevel@tonic-gate #define LGRP_DEFAULT_HANDLE ((lgrp_handle_t)0xbabecafe) /* uma handle */ 67*0Sstevel@tonic-gate #define LGRP_ROOTID (0) /* root lgroup ID */ 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate /* 70*0Sstevel@tonic-gate * Maximum number of lgrps a platform may define. 71*0Sstevel@tonic-gate */ 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate #define NLGRPS_MAX 64 74*0Sstevel@tonic-gate #define NLGRP_LEAVES_MAX 24 75*0Sstevel@tonic-gate #define LGRP_LOADAVG_MAX UINT32_MAX 76*0Sstevel@tonic-gate #define LPL_RSET_MAX NLGRP_LEAVES_MAX 77*0Sstevel@tonic-gate #define LPL_RSET_ARRYSZ (LPL_RSET_MAX + 1) 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate /* 80*0Sstevel@tonic-gate * The load-average we expect for one cpu-bound thread's worth of load 81*0Sstevel@tonic-gate */ 82*0Sstevel@tonic-gate #define LGRP_LOADAVG_THREAD_MAX 65516 83*0Sstevel@tonic-gate 84*0Sstevel@tonic-gate /* 85*0Sstevel@tonic-gate * The input to the load-average generating function for one cpu-bound thread's 86*0Sstevel@tonic-gate * worth of load 87*0Sstevel@tonic-gate */ 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate #define LGRP_LOADAVG_IN_THREAD_MAX 128 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate /* 92*0Sstevel@tonic-gate * LPL actions 93*0Sstevel@tonic-gate */ 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate typedef enum { 96*0Sstevel@tonic-gate LPL_INCREMENT, 97*0Sstevel@tonic-gate LPL_DECREMENT 98*0Sstevel@tonic-gate } lpl_act_t; 99*0Sstevel@tonic-gate 100*0Sstevel@tonic-gate /* 101*0Sstevel@tonic-gate * lgroup statistics. Most of these are counters that are updated 102*0Sstevel@tonic-gate * dynamically so they are hashed to CPU buckets to reduce cache 103*0Sstevel@tonic-gate * interference. The remaining statistics are snapshots of kernel 104*0Sstevel@tonic-gate * data, so they aren't stored in the array of counter stats. 105*0Sstevel@tonic-gate * 106*0Sstevel@tonic-gate * For the hashed stats to make sense, you have to sum all the buckets for 107*0Sstevel@tonic-gate * that stat, hence macros are provided to read the stats. 108*0Sstevel@tonic-gate */ 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate #define LGRP_NUM_CPU_BUCKETS 8 /* must be power of 2 */ 111*0Sstevel@tonic-gate #define LGRP_CPU_BUCKET_MASK (LGRP_NUM_CPU_BUCKETS - 1) 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate /* 114*0Sstevel@tonic-gate * Flags for what to do with lgroup memory policy 115*0Sstevel@tonic-gate * Used for heap and stack where policy is extended to new segments added to 116*0Sstevel@tonic-gate * the end 117*0Sstevel@tonic-gate */ 118*0Sstevel@tonic-gate #define LGRP_MP_FLAG_EXTEND_UP 0x1 /* policy should extend up */ 119*0Sstevel@tonic-gate #define LGRP_MP_FLAG_EXTEND_DOWN 0x2 /* policy should extend down */ 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate #define LGRP_STAT(stats, bucket, whichstat) \ 122*0Sstevel@tonic-gate ((stats)->ls_data[bucket][whichstat]) 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate /* Return a pointer suitable for an atomic 64-bit op on the bucket */ 125*0Sstevel@tonic-gate #define LGRP_STAT_WRITE_PTR(stats, whichstat) \ 126*0Sstevel@tonic-gate (&LGRP_STAT(stats, (CPU->cpu_id) & LGRP_CPU_BUCKET_MASK, \ 127*0Sstevel@tonic-gate whichstat)) 128*0Sstevel@tonic-gate 129*0Sstevel@tonic-gate /* Sum up all the buckets and return the value in 'val' */ 130*0Sstevel@tonic-gate #define LGRP_STAT_READ(stats, whichstat, val) { \ 131*0Sstevel@tonic-gate int bkt; \ 132*0Sstevel@tonic-gate for (val = 0, bkt = 0; bkt < LGRP_NUM_CPU_BUCKETS; bkt++) \ 133*0Sstevel@tonic-gate val += LGRP_STAT(stats, bkt, whichstat); \ 134*0Sstevel@tonic-gate } 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate /* Reset all buckets for the stat to 0 */ 137*0Sstevel@tonic-gate #define LGRP_STAT_RESET(stats, stat) { \ 138*0Sstevel@tonic-gate int i; \ 139*0Sstevel@tonic-gate for (i = 0; i < LGRP_NUM_CPU_BUCKETS; i++) \ 140*0Sstevel@tonic-gate LGRP_STAT(stats, i, stat) = 0; \ 141*0Sstevel@tonic-gate } 142*0Sstevel@tonic-gate 143*0Sstevel@tonic-gate /* 144*0Sstevel@tonic-gate * Define all of the statistics that are kept for lgrp kstats, 145*0Sstevel@tonic-gate * and their corresponding text names. 146*0Sstevel@tonic-gate */ 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate typedef enum lgrp_stat_types { 149*0Sstevel@tonic-gate LGRP_NUM_MIGR, /* # migrations away from this lgrp */ 150*0Sstevel@tonic-gate LGRP_NUM_ALLOC_FAIL, /* # times alloc fails for chosen lgrp */ 151*0Sstevel@tonic-gate LGRP_PM_SRC_PGS, /* # pages migrated from this lgrp */ 152*0Sstevel@tonic-gate LGRP_PM_DEST_PGS, /* # pages migrated to this lgrp */ 153*0Sstevel@tonic-gate LGRP_PM_FAIL_ALLOC_PGS, /* # pages failed to migrate to this lgrp */ 154*0Sstevel@tonic-gate LGRP_PM_FAIL_LOCK_PGS, /* # pages failed to migrate from this lgrp */ 155*0Sstevel@tonic-gate LGRP_PMM_PGS, /* # pages marked to migrate from this lgrp */ 156*0Sstevel@tonic-gate LGRP_PMM_FAIL_PGS, /* # pages marked to migrate from this lgrp */ 157*0Sstevel@tonic-gate LGRP_NUM_DEFAULT, /* # of times default policy applied */ 158*0Sstevel@tonic-gate LGRP_NUM_NEXT, /* # of times next touch policy applied */ 159*0Sstevel@tonic-gate LGRP_NUM_RANDOM, /* # of times random policy applied */ 160*0Sstevel@tonic-gate LGRP_NUM_RANDOM_PROC, /* # of times random proc policy applied */ 161*0Sstevel@tonic-gate LGRP_NUM_RANDOM_PSET, /* # of times random pset policy applied */ 162*0Sstevel@tonic-gate LGRP_NUM_ROUNDROBIN, /* # of times round robin policy applied */ 163*0Sstevel@tonic-gate LGRP_NUM_COUNTER_STATS, /* always last */ 164*0Sstevel@tonic-gate LGRP_CTR_STATS_ALLOC = 16 /* cache-align pad - multiple of 8 */ 165*0Sstevel@tonic-gate /* always keep >= LGRP_NUM_COUNTER_STATS */ 166*0Sstevel@tonic-gate } lgrp_stat_t; 167*0Sstevel@tonic-gate 168*0Sstevel@tonic-gate typedef enum lgrp_snap_stat_types { 169*0Sstevel@tonic-gate LGRP_NUM_CPUS, /* number of CPUs */ 170*0Sstevel@tonic-gate LGRP_NUM_PG_FREE, /* # of free pages */ 171*0Sstevel@tonic-gate LGRP_NUM_PG_AVAIL, /* # of allocatable physical pages */ 172*0Sstevel@tonic-gate LGRP_NUM_PG_INSTALL, /* # of installed physical pages */ 173*0Sstevel@tonic-gate LGRP_LOADAVG, /* "load average" of this lgrp */ 174*0Sstevel@tonic-gate LGRP_NUM_SNAPSHOT_STATS /* always last */ 175*0Sstevel@tonic-gate } lgrp_snap_stat_t; 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gate #define LGRP_KSTAT_NAMES \ 178*0Sstevel@tonic-gate static char *lgrp_kstat_names[] = { \ 179*0Sstevel@tonic-gate \ 180*0Sstevel@tonic-gate /* Counter stats */ \ 181*0Sstevel@tonic-gate "lwp migrations", \ 182*0Sstevel@tonic-gate "alloc fail", \ 183*0Sstevel@tonic-gate "pages migrated from", \ 184*0Sstevel@tonic-gate "pages migrated to", \ 185*0Sstevel@tonic-gate "pages failed to migrate to", \ 186*0Sstevel@tonic-gate "pages failed to migrate from", \ 187*0Sstevel@tonic-gate "pages marked for migration", \ 188*0Sstevel@tonic-gate "pages failed to mark", \ 189*0Sstevel@tonic-gate "default policy", \ 190*0Sstevel@tonic-gate "next-touch policy", \ 191*0Sstevel@tonic-gate "random policy", \ 192*0Sstevel@tonic-gate "span process policy", \ 193*0Sstevel@tonic-gate "span psrset policy", \ 194*0Sstevel@tonic-gate "round robin policy", \ 195*0Sstevel@tonic-gate \ 196*0Sstevel@tonic-gate /* Snapshot stats */ \ 197*0Sstevel@tonic-gate "cpus", \ 198*0Sstevel@tonic-gate "pages free", \ 199*0Sstevel@tonic-gate "pages avail", \ 200*0Sstevel@tonic-gate "pages installed", \ 201*0Sstevel@tonic-gate "load average" \ 202*0Sstevel@tonic-gate } 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate #define LGRP_NUM_STATS ((int)LGRP_NUM_COUNTER_STATS + \ 205*0Sstevel@tonic-gate (int)LGRP_NUM_SNAPSHOT_STATS) 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate /* 208*0Sstevel@tonic-gate * The contents of this structure are opaque and should only be 209*0Sstevel@tonic-gate * accessed through the LGRP_STAT macro. 210*0Sstevel@tonic-gate */ 211*0Sstevel@tonic-gate struct lgrp_stats { 212*0Sstevel@tonic-gate int64_t ls_data[LGRP_NUM_CPU_BUCKETS][LGRP_CTR_STATS_ALLOC]; 213*0Sstevel@tonic-gate }; 214*0Sstevel@tonic-gate 215*0Sstevel@tonic-gate /* The kernel's version of a bitmap of lgroups */ 216*0Sstevel@tonic-gate typedef uint64_t klgrpset_t; 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate /* 219*0Sstevel@tonic-gate * This really belongs in memnode.h, but it must be defined here to avoid 220*0Sstevel@tonic-gate * recursive inclusion problems. Note that memnode.h includes this header. 221*0Sstevel@tonic-gate */ 222*0Sstevel@tonic-gate typedef uint64_t mnodeset_t; 223*0Sstevel@tonic-gate 224*0Sstevel@tonic-gate /* 225*0Sstevel@tonic-gate * lgroup structure 226*0Sstevel@tonic-gate * 227*0Sstevel@tonic-gate * Visible to generic code and contains the lgroup ID, CPUs in this lgroup, 228*0Sstevel@tonic-gate * and a platform handle used to identify this lgroup to the lgroup platform 229*0Sstevel@tonic-gate * support code 230*0Sstevel@tonic-gate */ 231*0Sstevel@tonic-gate typedef struct lgrp { 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gate lgrp_id_t lgrp_id; /* which lgroup */ 234*0Sstevel@tonic-gate int lgrp_latency; 235*0Sstevel@tonic-gate lgrp_handle_t lgrp_plathand; /* handle for platform calls */ 236*0Sstevel@tonic-gate struct lgrp *lgrp_parent; /* parent lgroup */ 237*0Sstevel@tonic-gate uint_t lgrp_reserved1; /* filler */ 238*0Sstevel@tonic-gate uint_t lgrp_childcnt; /* number of children lgroups */ 239*0Sstevel@tonic-gate klgrpset_t lgrp_children; /* children lgroups */ 240*0Sstevel@tonic-gate klgrpset_t lgrp_leaves; /* (direct decendant) leaf lgroups */ 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate /* 243*0Sstevel@tonic-gate * set of lgroups containing a given type of resource 244*0Sstevel@tonic-gate * at this level of locality 245*0Sstevel@tonic-gate */ 246*0Sstevel@tonic-gate klgrpset_t lgrp_set[LGRP_RSRC_COUNT]; 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate mnodeset_t lgrp_mnodes; /* set of memory nodes in this lgroup */ 249*0Sstevel@tonic-gate uint_t lgrp_nmnodes; /* number of memnodes */ 250*0Sstevel@tonic-gate uint_t lgrp_reserved2; /* filler */ 251*0Sstevel@tonic-gate 252*0Sstevel@tonic-gate struct cpu *lgrp_cpu; /* pointer to a cpu may be null */ 253*0Sstevel@tonic-gate uint_t lgrp_cpucnt; /* number of cpus in this lgrp */ 254*0Sstevel@tonic-gate uint_t lgrp_chipcnt; 255*0Sstevel@tonic-gate struct chip *lgrp_chips; /* pointer to chips in this lgrp */ 256*0Sstevel@tonic-gate kstat_t *lgrp_kstat; /* per-lgrp kstats */ 257*0Sstevel@tonic-gate } lgrp_t; 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate /* 260*0Sstevel@tonic-gate * lgroup load average structure 261*0Sstevel@tonic-gate */ 262*0Sstevel@tonic-gate 263*0Sstevel@tonic-gate typedef struct lgrp_ld { 264*0Sstevel@tonic-gate lgrp_load_t lpl_loadavg; /* load average */ 265*0Sstevel@tonic-gate uint_t lpl_ncpu; /* how many cpus */ 266*0Sstevel@tonic-gate lgrp_id_t lpl_lgrpid; /* which group this lpl part of */ 267*0Sstevel@tonic-gate lgrp_t *lpl_lgrp; /* ptr to lpl's lgrp */ 268*0Sstevel@tonic-gate struct lgrp_ld *lpl_parent; /* lpl of parent lgrp */ 269*0Sstevel@tonic-gate struct cpu *lpl_cpus; /* list of cpus in lpl */ 270*0Sstevel@tonic-gate /* NULL for non-leaf lgrps */ 271*0Sstevel@tonic-gate uint_t lpl_nrset; /* no. of leaf lpls for lgrp */ 272*0Sstevel@tonic-gate int lpl_hint; /* where to start looking in parent */ 273*0Sstevel@tonic-gate hrtime_t lpl_homed_time; /* time of last homing to this lpl */ 274*0Sstevel@tonic-gate struct lgrp_ld *lpl_rset[LPL_RSET_ARRYSZ]; /* leaf lpls for lgrp */ 275*0Sstevel@tonic-gate /* contains ptr to self for leaf lgrp */ 276*0Sstevel@tonic-gate } lpl_t; 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate /* 279*0Sstevel@tonic-gate * 1 << LGRP_MAX_EFFECT_SHFT == lgrp_loadavg_max_effect 280*0Sstevel@tonic-gate */ 281*0Sstevel@tonic-gate #define LGRP_MAX_EFFECT_SHFT 16 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gate /* 284*0Sstevel@tonic-gate * Operations handled by lgrp_config() 285*0Sstevel@tonic-gate */ 286*0Sstevel@tonic-gate typedef enum lgrp_config_flag { 287*0Sstevel@tonic-gate LGRP_CONFIG_NOP, 288*0Sstevel@tonic-gate LGRP_CONFIG_CPU_ADD, 289*0Sstevel@tonic-gate LGRP_CONFIG_CPU_DEL, 290*0Sstevel@tonic-gate LGRP_CONFIG_CPU_ONLINE, 291*0Sstevel@tonic-gate LGRP_CONFIG_CPU_OFFLINE, 292*0Sstevel@tonic-gate LGRP_CONFIG_CPUPART_ADD, 293*0Sstevel@tonic-gate LGRP_CONFIG_CPUPART_DEL, 294*0Sstevel@tonic-gate LGRP_CONFIG_MEM_ADD, 295*0Sstevel@tonic-gate LGRP_CONFIG_MEM_DEL, 296*0Sstevel@tonic-gate LGRP_CONFIG_MEM_RENAME, 297*0Sstevel@tonic-gate LGRP_CONFIG_GEN_UPDATE, 298*0Sstevel@tonic-gate LGRP_CONFIG_FLATTEN, 299*0Sstevel@tonic-gate LGRP_CONFIG_LATENCY_CHANGE 300*0Sstevel@tonic-gate } lgrp_config_flag_t; 301*0Sstevel@tonic-gate 302*0Sstevel@tonic-gate /* 303*0Sstevel@tonic-gate * Memory allocation policies 304*0Sstevel@tonic-gate */ 305*0Sstevel@tonic-gate typedef enum lgrp_mem_policy { 306*0Sstevel@tonic-gate LGRP_MEM_POLICY_DEFAULT, 307*0Sstevel@tonic-gate LGRP_MEM_POLICY_NEXT, /* near LWP to next touch */ 308*0Sstevel@tonic-gate LGRP_MEM_POLICY_RANDOM_PROC, /* randomly across process */ 309*0Sstevel@tonic-gate LGRP_MEM_POLICY_RANDOM_PSET, /* randomly across processor set */ 310*0Sstevel@tonic-gate LGRP_MEM_POLICY_RANDOM, /* randomly across all lgroups */ 311*0Sstevel@tonic-gate LGRP_MEM_POLICY_ROUNDROBIN, /* round robin across all lgroups */ 312*0Sstevel@tonic-gate LGRP_MEM_POLICY_NEXT_CPU, /* Near next CPU to touch memory */ 313*0Sstevel@tonic-gate LGRP_NUM_MEM_POLICIES 314*0Sstevel@tonic-gate } lgrp_mem_policy_t; 315*0Sstevel@tonic-gate 316*0Sstevel@tonic-gate /* 317*0Sstevel@tonic-gate * Search scopes for finding resouces 318*0Sstevel@tonic-gate */ 319*0Sstevel@tonic-gate typedef enum lgrp_res_ss { 320*0Sstevel@tonic-gate LGRP_SRCH_LOCAL, /* Search local lgroup only */ 321*0Sstevel@tonic-gate LGRP_SRCH_HIER /* Search entire hierarchy */ 322*0Sstevel@tonic-gate } lgrp_res_ss_t; 323*0Sstevel@tonic-gate 324*0Sstevel@tonic-gate /* 325*0Sstevel@tonic-gate * Cookie used for lgrp mnode selection 326*0Sstevel@tonic-gate */ 327*0Sstevel@tonic-gate typedef struct lgrp_mnode_cookie { 328*0Sstevel@tonic-gate lgrp_t *lmc_lgrp; /* lgrp under consideration */ 329*0Sstevel@tonic-gate mnodeset_t lmc_nodes; /* nodes not yet tried in lgrp */ 330*0Sstevel@tonic-gate int lmc_cnt; /* how many nodes in untried set */ 331*0Sstevel@tonic-gate mnodeset_t lmc_tried; /* nodes already tried */ 332*0Sstevel@tonic-gate int lmc_ntried; /* how many nodes in tried set */ 333*0Sstevel@tonic-gate lgrp_res_ss_t lmc_scope; /* consider non-local nodes? */ 334*0Sstevel@tonic-gate ushort_t lmc_rand; /* a "random" number */ 335*0Sstevel@tonic-gate } lgrp_mnode_cookie_t; 336*0Sstevel@tonic-gate 337*0Sstevel@tonic-gate /* 338*0Sstevel@tonic-gate * Information needed to implement memory allocation policy 339*0Sstevel@tonic-gate */ 340*0Sstevel@tonic-gate typedef struct lgrp_mem_policy_info { 341*0Sstevel@tonic-gate int mem_policy; /* memory allocation policy */ 342*0Sstevel@tonic-gate int mem_reserved; /* reserved */ 343*0Sstevel@tonic-gate } lgrp_mem_policy_info_t; 344*0Sstevel@tonic-gate 345*0Sstevel@tonic-gate /* 346*0Sstevel@tonic-gate * Shared memory policy segment 347*0Sstevel@tonic-gate */ 348*0Sstevel@tonic-gate typedef struct lgrp_shm_policy_seg { 349*0Sstevel@tonic-gate u_offset_t shm_off; /* offset into shared object */ 350*0Sstevel@tonic-gate size_t shm_size; /* size of segment */ 351*0Sstevel@tonic-gate lgrp_mem_policy_info_t shm_policy; /* memory allocation policy */ 352*0Sstevel@tonic-gate avl_node_t shm_tree; /* AVL tree */ 353*0Sstevel@tonic-gate } lgrp_shm_policy_seg_t; 354*0Sstevel@tonic-gate 355*0Sstevel@tonic-gate /* 356*0Sstevel@tonic-gate * Shared memory locality info 357*0Sstevel@tonic-gate */ 358*0Sstevel@tonic-gate typedef struct lgrp_shm_locality { 359*0Sstevel@tonic-gate size_t loc_count; /* reference count */ 360*0Sstevel@tonic-gate avl_tree_t *loc_tree; /* policy segment tree */ 361*0Sstevel@tonic-gate krwlock_t loc_lock; /* protects tree */ 362*0Sstevel@tonic-gate } lgrp_shm_locality_t; 363*0Sstevel@tonic-gate 364*0Sstevel@tonic-gate /* 365*0Sstevel@tonic-gate * Queries that may be made to determine lgroup memory size 366*0Sstevel@tonic-gate */ 367*0Sstevel@tonic-gate typedef enum { 368*0Sstevel@tonic-gate LGRP_MEM_SIZE_FREE, /* number of free pages */ 369*0Sstevel@tonic-gate LGRP_MEM_SIZE_AVAIL, /* number of pages in phys_avail */ 370*0Sstevel@tonic-gate LGRP_MEM_SIZE_INSTALL /* number of pages in phys_install */ 371*0Sstevel@tonic-gate } lgrp_mem_query_t; 372*0Sstevel@tonic-gate 373*0Sstevel@tonic-gate /* 374*0Sstevel@tonic-gate * Argument for the memory copy-rename operation, contains the source and the 375*0Sstevel@tonic-gate * destination platform handles. 376*0Sstevel@tonic-gate */ 377*0Sstevel@tonic-gate typedef struct lgrp_config_mem_rename { 378*0Sstevel@tonic-gate lgrp_handle_t lmem_rename_from; 379*0Sstevel@tonic-gate lgrp_handle_t lmem_rename_to; 380*0Sstevel@tonic-gate } lgrp_config_mem_rename_t; 381*0Sstevel@tonic-gate 382*0Sstevel@tonic-gate /* Macro to clear an lgroup bitmap */ 383*0Sstevel@tonic-gate #define klgrpset_clear(klgrpset) \ 384*0Sstevel@tonic-gate (klgrpset) = (klgrpset_t)0 385*0Sstevel@tonic-gate 386*0Sstevel@tonic-gate /* Macro to fill an lgroup bitmap */ 387*0Sstevel@tonic-gate #define klgrpset_fill(klgrpset) \ 388*0Sstevel@tonic-gate (klgrpset) = (klgrpset_t)(-1) 389*0Sstevel@tonic-gate 390*0Sstevel@tonic-gate /* Macro to add an lgroup to an lgroup bitmap */ 391*0Sstevel@tonic-gate #define klgrpset_add(klgrpset, lgrpid) \ 392*0Sstevel@tonic-gate (klgrpset) |= ((klgrpset_t)1 << (lgrpid)) 393*0Sstevel@tonic-gate 394*0Sstevel@tonic-gate /* Macro to delete an lgroup from an lgroup bitmap */ 395*0Sstevel@tonic-gate #define klgrpset_del(klgrpset, lgrpid) \ 396*0Sstevel@tonic-gate (klgrpset) &= ~((klgrpset_t)1 << (lgrpid)) 397*0Sstevel@tonic-gate 398*0Sstevel@tonic-gate /* Macro to copy a klgrpset into another klgrpset */ 399*0Sstevel@tonic-gate #define klgrpset_copy(klgrpset_to, klgrpset_from) \ 400*0Sstevel@tonic-gate (klgrpset_to) = (klgrpset_from) 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gate /* Macro to perform an 'and' operation on a pair of lgroup bitmaps */ 403*0Sstevel@tonic-gate #define klgrpset_and(klgrpset_rslt, klgrpset_arg) \ 404*0Sstevel@tonic-gate (klgrpset_rslt) &= (klgrpset_arg) 405*0Sstevel@tonic-gate 406*0Sstevel@tonic-gate /* Macro to perform an 'or' operation on a pair of lgroup bitmaps */ 407*0Sstevel@tonic-gate #define klgrpset_or(klgrpset_rslt, klgrpset_arg) \ 408*0Sstevel@tonic-gate (klgrpset_rslt) |= (klgrpset_arg) 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate /* Macro to perform a 'diff' operation on a pair of lgroup bitmaps */ 411*0Sstevel@tonic-gate #define klgrpset_diff(klgrpset_rslt, klgrpset_arg) \ 412*0Sstevel@tonic-gate (klgrpset_rslt) &= ~(klgrpset_arg) 413*0Sstevel@tonic-gate 414*0Sstevel@tonic-gate /* Macro to check if an lgroup is a member of an lgrpset */ 415*0Sstevel@tonic-gate #define klgrpset_ismember(klgrpset, lgrpid) \ 416*0Sstevel@tonic-gate ((klgrpset) & ((klgrpset_t)1 << (lgrpid))) 417*0Sstevel@tonic-gate 418*0Sstevel@tonic-gate /* Macro to check if an lgroup bitmap is empty */ 419*0Sstevel@tonic-gate #define klgrpset_isempty(klgrpset) \ 420*0Sstevel@tonic-gate ((klgrpset) == (klgrpset_t)0) 421*0Sstevel@tonic-gate 422*0Sstevel@tonic-gate /* Macro to check if two lgrpsets intersect */ 423*0Sstevel@tonic-gate #define klgrpset_intersects(klgrpset1, klgrpset2) \ 424*0Sstevel@tonic-gate ((klgrpset1) & (klgrpset2)) 425*0Sstevel@tonic-gate 426*0Sstevel@tonic-gate /* Macro to count the number of members in an lgrpset */ 427*0Sstevel@tonic-gate #define klgrpset_nlgrps(klgrpset, count) \ 428*0Sstevel@tonic-gate { \ 429*0Sstevel@tonic-gate lgrp_id_t lgrpid; \ 430*0Sstevel@tonic-gate for (lgrpid = 0, count = 0; lgrpid <= lgrp_alloc_max; lgrpid++) {\ 431*0Sstevel@tonic-gate if (klgrpset_ismember(klgrpset, lgrpid)) \ 432*0Sstevel@tonic-gate count++; \ 433*0Sstevel@tonic-gate } \ 434*0Sstevel@tonic-gate } 435*0Sstevel@tonic-gate 436*0Sstevel@tonic-gate /* Macro to get total memory size (in bytes) of a given set of lgroups */ 437*0Sstevel@tonic-gate #define klgrpset_totalsize(klgrpset, size) \ 438*0Sstevel@tonic-gate { \ 439*0Sstevel@tonic-gate lgrp_handle_t hand; \ 440*0Sstevel@tonic-gate lgrp_id_t lgrpid; \ 441*0Sstevel@tonic-gate \ 442*0Sstevel@tonic-gate for (lgrpid = 0, size = 0; lgrpid <= lgrp_alloc_max; lgrpid++) {\ 443*0Sstevel@tonic-gate if (klgrpset_ismember(klgrpset, lgrpid) && \ 444*0Sstevel@tonic-gate lgrp_table[lgrpid]) { \ 445*0Sstevel@tonic-gate hand = lgrp_table[lgrpid]->lgrp_plathand; \ 446*0Sstevel@tonic-gate size += lgrp_plat_mem_size(hand, \ 447*0Sstevel@tonic-gate LGRP_MEM_SIZE_AVAIL) * PAGESIZE; \ 448*0Sstevel@tonic-gate } \ 449*0Sstevel@tonic-gate } \ 450*0Sstevel@tonic-gate } 451*0Sstevel@tonic-gate 452*0Sstevel@tonic-gate /* 453*0Sstevel@tonic-gate * Does this lgroup exist? 454*0Sstevel@tonic-gate */ 455*0Sstevel@tonic-gate #define LGRP_EXISTS(lgrp) \ 456*0Sstevel@tonic-gate (lgrp != NULL && lgrp->lgrp_id != LGRP_NONE) 457*0Sstevel@tonic-gate 458*0Sstevel@tonic-gate /* 459*0Sstevel@tonic-gate * Initialize an lgrp_mnode_cookie 460*0Sstevel@tonic-gate */ 461*0Sstevel@tonic-gate #define LGRP_MNODE_COOKIE_INIT(c, lgrp, scope) \ 462*0Sstevel@tonic-gate { \ 463*0Sstevel@tonic-gate bzero(&(c), sizeof (lgrp_mnode_cookie_t)); \ 464*0Sstevel@tonic-gate (&(c))->lmc_lgrp = lgrp; \ 465*0Sstevel@tonic-gate (&(c))->lmc_nodes = lgrp->lgrp_mnodes; \ 466*0Sstevel@tonic-gate (&(c))->lmc_cnt = lgrp->lgrp_nmnodes; \ 467*0Sstevel@tonic-gate (&(c))->lmc_scope = scope; \ 468*0Sstevel@tonic-gate (&(c))->lmc_rand = (ushort_t)gethrtime_unscaled() >> 4; \ 469*0Sstevel@tonic-gate } 470*0Sstevel@tonic-gate 471*0Sstevel@tonic-gate /* 472*0Sstevel@tonic-gate * Upgrade cookie scope from LGRP_SRCH_LOCAL to LGRP_SRCH_HIER. 473*0Sstevel@tonic-gate */ 474*0Sstevel@tonic-gate #define LGRP_MNODE_COOKIE_UPGRADE(c) \ 475*0Sstevel@tonic-gate { \ 476*0Sstevel@tonic-gate ASSERT((&(c))->lmc_scope == LGRP_SRCH_LOCAL); \ 477*0Sstevel@tonic-gate (&(c))->lmc_scope = LGRP_SRCH_HIER; \ 478*0Sstevel@tonic-gate } 479*0Sstevel@tonic-gate 480*0Sstevel@tonic-gate /* 481*0Sstevel@tonic-gate * Macro to see whether memory allocation policy can be reapplied 482*0Sstevel@tonic-gate */ 483*0Sstevel@tonic-gate #define LGRP_MEM_POLICY_REAPPLICABLE(p) \ 484*0Sstevel@tonic-gate (p == LGRP_MEM_POLICY_NEXT) 485*0Sstevel@tonic-gate 486*0Sstevel@tonic-gate /* 487*0Sstevel@tonic-gate * Return true if lgrp has CPU resources in the cpupart 488*0Sstevel@tonic-gate */ 489*0Sstevel@tonic-gate #define LGRP_CPUS_IN_PART(lgrpid, cpupart) \ 490*0Sstevel@tonic-gate (cpupart->cp_lgrploads[lgrpid].lpl_ncpu > 0) 491*0Sstevel@tonic-gate 492*0Sstevel@tonic-gate extern int lgrp_alloc_max; 493*0Sstevel@tonic-gate extern lgrp_t *lgrp_table[NLGRPS_MAX]; /* indexed by lgrp_id */ 494*0Sstevel@tonic-gate extern int nlgrps; /* number of lgroups in machine */ 495*0Sstevel@tonic-gate extern int nlgrpsmax; /* max number of lgroups on platform */ 496*0Sstevel@tonic-gate extern lgrp_gen_t lgrp_gen; /* generation of lgroup hierarchy */ 497*0Sstevel@tonic-gate extern int lgrp_initialized; /* single-CPU initialization done */ 498*0Sstevel@tonic-gate extern int lgrp_topo_initialized; /* lgrp topology constructed */ 499*0Sstevel@tonic-gate extern lgrp_t *lgrp_root; /* root lgroup */ 500*0Sstevel@tonic-gate extern unsigned int lgrp_topo_levels; 501*0Sstevel@tonic-gate extern lpl_t *lpl_bootstrap; /* bootstrap lpl for non-active CPUs */ 502*0Sstevel@tonic-gate 503*0Sstevel@tonic-gate 504*0Sstevel@tonic-gate /* generic interfaces */ 505*0Sstevel@tonic-gate 506*0Sstevel@tonic-gate /* 507*0Sstevel@tonic-gate * lgroup management 508*0Sstevel@tonic-gate */ 509*0Sstevel@tonic-gate int lgrp_optimizations(void); 510*0Sstevel@tonic-gate void lgrp_init(void); 511*0Sstevel@tonic-gate void lgrp_setup(void); 512*0Sstevel@tonic-gate lgrp_t *lgrp_create(void); 513*0Sstevel@tonic-gate void lgrp_destroy(lgrp_t *); 514*0Sstevel@tonic-gate void lgrp_config(lgrp_config_flag_t, uintptr_t, uintptr_t); 515*0Sstevel@tonic-gate lgrp_t *lgrp_hand_to_lgrp(lgrp_handle_t); 516*0Sstevel@tonic-gate 517*0Sstevel@tonic-gate /* 518*0Sstevel@tonic-gate * lgroup stats 519*0Sstevel@tonic-gate */ 520*0Sstevel@tonic-gate void lgrp_kstat_create(struct cpu *); 521*0Sstevel@tonic-gate void lgrp_kstat_destroy(struct cpu *); 522*0Sstevel@tonic-gate void lgrp_stat_add(lgrp_id_t, lgrp_stat_t, int64_t); 523*0Sstevel@tonic-gate int64_t lgrp_stat_read(lgrp_id_t, lgrp_stat_t); 524*0Sstevel@tonic-gate 525*0Sstevel@tonic-gate /* 526*0Sstevel@tonic-gate * lgroup memory 527*0Sstevel@tonic-gate */ 528*0Sstevel@tonic-gate lgrp_mem_policy_t lgrp_madv_to_policy(uchar_t, size_t, int); 529*0Sstevel@tonic-gate pgcnt_t lgrp_mem_size(lgrp_id_t, lgrp_mem_query_t); 530*0Sstevel@tonic-gate lgrp_t *lgrp_mem_choose(struct seg *, caddr_t, size_t); 531*0Sstevel@tonic-gate int lgrp_memnode_choose(lgrp_mnode_cookie_t *); 532*0Sstevel@tonic-gate lgrp_mem_policy_t lgrp_mem_policy_default(size_t, int); 533*0Sstevel@tonic-gate int lgrp_mnode_update(klgrpset_t, klgrpset_t *); 534*0Sstevel@tonic-gate lgrp_t *lgrp_pfn_to_lgrp(pfn_t); 535*0Sstevel@tonic-gate lgrp_t *lgrp_phys_to_lgrp(u_longlong_t); /* used by numat driver */ 536*0Sstevel@tonic-gate int lgrp_privm_policy_set(lgrp_mem_policy_t, lgrp_mem_policy_info_t *, 537*0Sstevel@tonic-gate size_t); 538*0Sstevel@tonic-gate void lgrp_shm_policy_init(struct anon_map *, vnode_t *); 539*0Sstevel@tonic-gate void lgrp_shm_policy_fini(struct anon_map *, vnode_t *); 540*0Sstevel@tonic-gate lgrp_mem_policy_info_t *lgrp_shm_policy_get(struct anon_map *, ulong_t, 541*0Sstevel@tonic-gate vnode_t *, u_offset_t); 542*0Sstevel@tonic-gate int lgrp_shm_policy_set(lgrp_mem_policy_t, struct anon_map *, ulong_t, 543*0Sstevel@tonic-gate vnode_t *, u_offset_t, size_t); 544*0Sstevel@tonic-gate 545*0Sstevel@tonic-gate /* 546*0Sstevel@tonic-gate * Used by numat driver 547*0Sstevel@tonic-gate */ 548*0Sstevel@tonic-gate int lgrp_query_cpu(processorid_t, lgrp_id_t *); 549*0Sstevel@tonic-gate int lgrp_query_load(processorid_t, lgrp_load_t *); 550*0Sstevel@tonic-gate 551*0Sstevel@tonic-gate /* 552*0Sstevel@tonic-gate * lgroup thread placement 553*0Sstevel@tonic-gate */ 554*0Sstevel@tonic-gate lpl_t *lgrp_affinity_best(kthread_t *, struct cpupart *, lgrp_id_t); 555*0Sstevel@tonic-gate void lgrp_affinity_init(lgrp_affinity_t **); 556*0Sstevel@tonic-gate void lgrp_affinity_free(lgrp_affinity_t **); 557*0Sstevel@tonic-gate lpl_t *lgrp_choose(kthread_t *t, struct cpupart *); 558*0Sstevel@tonic-gate lgrp_t *lgrp_home_lgrp(void); 559*0Sstevel@tonic-gate lgrp_id_t lgrp_home_id(kthread_t *); 560*0Sstevel@tonic-gate void lgrp_loadavg(lpl_t *, uint_t, int); 561*0Sstevel@tonic-gate void lgrp_move_thread(kthread_t *, lpl_t *, int); 562*0Sstevel@tonic-gate 563*0Sstevel@tonic-gate /* 564*0Sstevel@tonic-gate * lgroup topology 565*0Sstevel@tonic-gate */ 566*0Sstevel@tonic-gate int lgrp_leaf_add(lgrp_t *, lgrp_t **, int, klgrpset_t *); 567*0Sstevel@tonic-gate int lgrp_leaf_delete(lgrp_t *, lgrp_t **, int, klgrpset_t *); 568*0Sstevel@tonic-gate int lgrp_rsets_empty(klgrpset_t *); 569*0Sstevel@tonic-gate int lgrp_rsets_member(klgrpset_t *, lgrp_id_t); 570*0Sstevel@tonic-gate int lgrp_topo_flatten(int, lgrp_t **, int, klgrpset_t *); 571*0Sstevel@tonic-gate int lgrp_topo_ht_limit(void); 572*0Sstevel@tonic-gate int lgrp_topo_ht_limit_default(void); 573*0Sstevel@tonic-gate int lgrp_topo_ht_limit_set(int); 574*0Sstevel@tonic-gate int lgrp_topo_update(lgrp_t **, int, klgrpset_t *); 575*0Sstevel@tonic-gate 576*0Sstevel@tonic-gate /* 577*0Sstevel@tonic-gate * lpl topology 578*0Sstevel@tonic-gate */ 579*0Sstevel@tonic-gate void lpl_topo_bootstrap(lpl_t *, int); 580*0Sstevel@tonic-gate int lpl_topo_flatten(int); 581*0Sstevel@tonic-gate int lpl_topo_verify(struct cpupart *); 582*0Sstevel@tonic-gate 583*0Sstevel@tonic-gate 584*0Sstevel@tonic-gate /* platform interfaces */ 585*0Sstevel@tonic-gate void lgrp_plat_init(void); 586*0Sstevel@tonic-gate void lgrp_plat_main_init(void); 587*0Sstevel@tonic-gate lgrp_t *lgrp_plat_alloc(lgrp_id_t lgrpid); 588*0Sstevel@tonic-gate void lgrp_plat_config(lgrp_config_flag_t, uintptr_t); 589*0Sstevel@tonic-gate lgrp_handle_t lgrp_plat_cpu_to_hand(processorid_t); 590*0Sstevel@tonic-gate lgrp_handle_t lgrp_plat_pfn_to_hand(pfn_t); 591*0Sstevel@tonic-gate int lgrp_plat_max_lgrps(void); 592*0Sstevel@tonic-gate pgcnt_t lgrp_plat_mem_size(lgrp_handle_t, lgrp_mem_query_t); 593*0Sstevel@tonic-gate int lgrp_plat_latency(lgrp_handle_t, lgrp_handle_t); 594*0Sstevel@tonic-gate lgrp_handle_t lgrp_plat_root_hand(void); 595*0Sstevel@tonic-gate void lgrp_plat_probe(void); 596*0Sstevel@tonic-gate void lgrp_plat_build_topo(void); 597*0Sstevel@tonic-gate 598*0Sstevel@tonic-gate #endif /* _KERNEL && _KMEMUSER */ 599*0Sstevel@tonic-gate 600*0Sstevel@tonic-gate #ifdef __cplusplus 601*0Sstevel@tonic-gate } 602*0Sstevel@tonic-gate #endif 603*0Sstevel@tonic-gate 604*0Sstevel@tonic-gate #endif /* _LGRP_H */ 605