The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/common/os/lgrp.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * CDDL HEADER START
    3  *
    4  * The contents of this file are subject to the terms of the
    5  * Common Development and Distribution License (the "License").
    6  * You may not use this file except in compliance with the License.
    7  *
    8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
    9  * or http://www.opensolaris.org/os/licensing.
   10  * See the License for the specific language governing permissions
   11  * and limitations under the License.
   12  *
   13  * When distributing Covered Code, include this CDDL HEADER in each
   14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
   15  * If applicable, add the following below this CDDL HEADER, with the
   16  * fields enclosed by brackets "[]" replaced with your own identifying
   17  * information: Portions Copyright [yyyy] [name of copyright owner]
   18  *
   19  * CDDL HEADER END
   20  */
   21 /*
   22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
   23  * Use is subject to license terms.
   24  */
   25 
   26 /*
   27  * Basic NUMA support in terms of locality groups
   28  *
   29  * Solaris needs to know which CPUs, memory, etc. are near each other to
   30  * provide good performance on NUMA machines by optimizing for locality.
   31  * In order to do this, a new abstraction called a "locality group (lgroup)"
   32  * has been introduced to keep track of which CPU-like and memory-like hardware
   33  * resources are close to each other.  Currently, latency is the only measure
   34  * used to determine how to group hardware resources into lgroups, but this
   35  * does not limit the groupings to be based solely on latency.  Other factors
   36  * may be used to determine the groupings in the future.
   37  *
   38  * Lgroups are organized into a hieararchy or topology that represents the
   39  * latency topology of the machine.  There is always at least a root lgroup in
   40  * the system.  It represents all the hardware resources in the machine at a
   41  * latency big enough that any hardware resource can at least access any other
   42  * hardware resource within that latency.  A Uniform Memory Access (UMA)
   43  * machine is represented with one lgroup (the root).  In contrast, a NUMA
   44  * machine is represented at least by the root lgroup and some number of leaf
   45  * lgroups where the leaf lgroups contain the hardware resources within the
   46  * least latency of each other and the root lgroup still contains all the
   47  * resources in the machine.  Some number of intermediate lgroups may exist
   48  * which represent more levels of locality than just the local latency of the
   49  * leaf lgroups and the system latency of the root lgroup.  Non-leaf lgroups
   50  * (eg. root and intermediate lgroups) contain the next nearest resources to
   51  * its children lgroups.  Thus, the lgroup hierarchy from a given leaf lgroup
   52  * to the root lgroup shows the hardware resources from closest to farthest
   53  * from the leaf lgroup such that each successive ancestor lgroup contains
   54  * the next nearest resources at the next level of locality from the previous.
   55  *
   56  * The kernel uses the lgroup abstraction to know how to allocate resources
   57  * near a given process/thread.  At fork() and lwp/thread_create() time, a
   58  * "home" lgroup is chosen for a thread.  This is done by picking the lgroup
   59  * with the lowest load average.  Binding to a processor or processor set will
   60  * change the home lgroup for a thread.  The scheduler has been modified to try
   61  * to dispatch a thread on a CPU in its home lgroup.  Physical memory
   62  * allocation is lgroup aware too, so memory will be allocated from the current
   63  * thread's home lgroup if possible.  If the desired resources are not
   64  * available, the kernel traverses the lgroup hierarchy going to the parent
   65  * lgroup to find resources at the next level of locality until it reaches the
   66  * root lgroup.
   67  */
   68 
   69 #include <sys/lgrp.h>
   70 #include <sys/lgrp_user.h>
   71 #include <sys/types.h>
   72 #include <sys/mman.h>
   73 #include <sys/param.h>
   74 #include <sys/var.h>
   75 #include <sys/thread.h>
   76 #include <sys/cpuvar.h>
   77 #include <sys/cpupart.h>
   78 #include <sys/kmem.h>
   79 #include <vm/seg.h>
   80 #include <vm/seg_kmem.h>
   81 #include <vm/seg_spt.h>
   82 #include <vm/seg_vn.h>
   83 #include <vm/as.h>
   84 #include <sys/atomic.h>
   85 #include <sys/systm.h>
   86 #include <sys/errno.h>
   87 #include <sys/cmn_err.h>
   88 #include <sys/kstat.h>
   89 #include <sys/sysmacros.h>
   90 #include <sys/pg.h>
   91 #include <sys/promif.h>
   92 #include <sys/sdt.h>
   93 
   94 lgrp_gen_t      lgrp_gen = 0;           /* generation of lgroup hierarchy */
   95 lgrp_t *lgrp_table[NLGRPS_MAX]; /* table of all initialized lgrp_t structs */
   96                                 /* indexed by lgrp_id */
   97 int     nlgrps;                 /* number of lgroups in machine */
   98 int     lgrp_alloc_hint = -1;   /* hint for where to try to allocate next */
   99 int     lgrp_alloc_max = 0;     /* max lgroup ID allocated so far */
  100 
  101 /*
  102  * Kstat data for lgroups.
  103  *
  104  * Actual kstat data is collected in lgrp_stats array.
  105  * The lgrp_kstat_data array of named kstats is used to extract data from
  106  * lgrp_stats and present it to kstat framework. It is protected from partallel
  107  * modifications by lgrp_kstat_mutex. This may cause some contention when
  108  * several kstat commands run in parallel but this is not the
  109  * performance-critical path.
  110  */
  111 extern struct lgrp_stats lgrp_stats[];  /* table of per-lgrp stats */
  112 
  113 /*
  114  * Declare kstat names statically for enums as defined in the header file.
  115  */
  116 LGRP_KSTAT_NAMES;
  117 
  118 static void     lgrp_kstat_init(void);
  119 static int      lgrp_kstat_extract(kstat_t *, int);
  120 static void     lgrp_kstat_reset(lgrp_id_t);
  121 
  122 static struct kstat_named lgrp_kstat_data[LGRP_NUM_STATS];
  123 static kmutex_t lgrp_kstat_mutex;
  124 
  125 
  126 /*
  127  * max number of lgroups supported by the platform
  128  */
  129 int     nlgrpsmax = 0;
  130 
  131 /*
  132  * The root lgroup. Represents the set of resources at the system wide
  133  * level of locality.
  134  */
  135 lgrp_t          *lgrp_root = NULL;
  136 
  137 /*
  138  * During system bootstrap cp_default does not contain the list of lgrp load
  139  * averages (cp_lgrploads). The list is allocated after the first CPU is brought
  140  * on-line when cp_default is initialized by cpupart_initialize_default().
  141  * Configuring CPU0 may create a two-level topology with root and one leaf node
  142  * containing CPU0. This topology is initially constructed in a special
  143  * statically allocated 2-element lpl list lpl_bootstrap_list and later cloned
  144  * to cp_default when cp_default is initialized. The lpl_bootstrap_list is used
  145  * for all lpl operations until cp_default is fully constructed.
  146  *
  147  * The lpl_bootstrap_list is maintained by the code in lgrp.c. Every other
  148  * consumer who needs default lpl should use lpl_bootstrap which is a pointer to
  149  * the first element of lpl_bootstrap_list.
  150  *
  151  * CPUs that are added to the system, but have not yet been assigned to an
  152  * lgrp will use lpl_bootstrap as a default lpl. This is necessary because
  153  * on some architectures (x86) it's possible for the slave CPU startup thread
  154  * to enter the dispatcher or allocate memory before calling lgrp_cpu_init().
  155  */
  156 #define LPL_BOOTSTRAP_SIZE 2
  157 static lpl_t    lpl_bootstrap_list[LPL_BOOTSTRAP_SIZE];
  158 lpl_t           *lpl_bootstrap;
  159 static lpl_t    *lpl_bootstrap_rset[LPL_BOOTSTRAP_SIZE];
  160 static int      lpl_bootstrap_id2rset[LPL_BOOTSTRAP_SIZE];
  161 
  162 /*
  163  * If cp still references the bootstrap lpl, it has not yet been added to
  164  * an lgrp. lgrp_mem_choose() uses this macro to detect the case where
  165  * a thread is trying to allocate memory close to a CPU that has no lgrp.
  166  */
  167 #define LGRP_CPU_HAS_NO_LGRP(cp)        ((cp)->cpu_lpl == lpl_bootstrap)
  168 
  169 static lgrp_t   lroot;
  170 
  171 /*
  172  * Size, in bytes, beyond which random memory allocation policy is applied
  173  * to non-shared memory.  Default is the maximum size, so random memory
  174  * allocation won't be used for non-shared memory by default.
  175  */
  176 size_t  lgrp_privm_random_thresh = (size_t)(-1);
  177 
  178 /* the maximum effect that a single thread can have on it's lgroup's load */
  179 #define LGRP_LOADAVG_MAX_EFFECT(ncpu) \
  180         ((lgrp_loadavg_max_effect) / (ncpu))
  181 uint32_t        lgrp_loadavg_max_effect = LGRP_LOADAVG_THREAD_MAX;
  182 
  183 
  184 /*
  185  * Size, in bytes, beyond which random memory allocation policy is applied to
  186  * shared memory.  Default is 8MB (2 ISM pages).
  187  */
  188 size_t  lgrp_shm_random_thresh = 8*1024*1024;
  189 
  190 /*
  191  * Whether to do processor set aware memory allocation by default
  192  */
  193 int     lgrp_mem_pset_aware = 0;
  194 
  195 /*
  196  * Set the default memory allocation policy for root lgroup
  197  */
  198 lgrp_mem_policy_t       lgrp_mem_policy_root = LGRP_MEM_POLICY_RANDOM;
  199 
  200 /*
  201  * Set the default memory allocation policy.  For most platforms,
  202  * next touch is sufficient, but some platforms may wish to override
  203  * this.
  204  */
  205 lgrp_mem_policy_t       lgrp_mem_default_policy = LGRP_MEM_POLICY_NEXT;
  206 
  207 
  208 /*
  209  * lgroup CPU event handlers
  210  */
  211 static void     lgrp_cpu_init(struct cpu *);
  212 static void     lgrp_cpu_fini(struct cpu *, lgrp_id_t);
  213 static lgrp_t   *lgrp_cpu_to_lgrp(struct cpu *);
  214 
  215 /*
  216  * lgroup memory event handlers
  217  */
  218 static void     lgrp_mem_init(int, lgrp_handle_t, boolean_t);
  219 static void     lgrp_mem_fini(int, lgrp_handle_t, boolean_t);
  220 static void     lgrp_mem_rename(int, lgrp_handle_t, lgrp_handle_t);
  221 
  222 /*
  223  * lgroup CPU partition event handlers
  224  */
  225 static void     lgrp_part_add_cpu(struct cpu *, lgrp_id_t);
  226 static void     lgrp_part_del_cpu(struct cpu *);
  227 
  228 /*
  229  * lgroup framework initialization
  230  */
  231 static void     lgrp_main_init(void);
  232 static void     lgrp_main_mp_init(void);
  233 static void     lgrp_root_init(void);
  234 static void     lgrp_setup(void);
  235 
  236 /*
  237  * lpl topology
  238  */
  239 static void     lpl_init(lpl_t *, lpl_t *, lgrp_t *);
  240 static void     lpl_clear(lpl_t *);
  241 static void     lpl_leaf_insert(lpl_t *, struct cpupart *);
  242 static void     lpl_leaf_remove(lpl_t *, struct cpupart *);
  243 static void     lpl_rset_add(lpl_t *, lpl_t *);
  244 static void     lpl_rset_del(lpl_t *, lpl_t *);
  245 static int      lpl_rset_contains(lpl_t *, lpl_t *);
  246 static void     lpl_cpu_adjcnt(lpl_act_t, struct cpu *);
  247 static void     lpl_child_update(lpl_t *, struct cpupart *);
  248 static int      lpl_pick(lpl_t *, lpl_t *);
  249 static void     lpl_verify_wrapper(struct cpupart *);
  250 
  251 /*
  252  * defines for lpl topology verifier return codes
  253  */
  254 
  255 #define LPL_TOPO_CORRECT                        0
  256 #define LPL_TOPO_PART_HAS_NO_LPL                -1
  257 #define LPL_TOPO_CPUS_NOT_EMPTY                 -2
  258 #define LPL_TOPO_LGRP_MISMATCH                  -3
  259 #define LPL_TOPO_MISSING_PARENT                 -4
  260 #define LPL_TOPO_PARENT_MISMATCH                -5
  261 #define LPL_TOPO_BAD_CPUCNT                     -6
  262 #define LPL_TOPO_RSET_MISMATCH                  -7
  263 #define LPL_TOPO_LPL_ORPHANED                   -8
  264 #define LPL_TOPO_LPL_BAD_NCPU                   -9
  265 #define LPL_TOPO_RSET_MSSNG_LF                  -10
  266 #define LPL_TOPO_CPU_HAS_BAD_LPL                -11
  267 #define LPL_TOPO_NONLEAF_HAS_CPUS               -12
  268 #define LPL_TOPO_LGRP_NOT_LEAF                  -13
  269 #define LPL_TOPO_BAD_RSETCNT                    -14
  270 
  271 /*
  272  * Return whether lgroup optimizations should be enabled on this system
  273  */
  274 int
  275 lgrp_optimizations(void)
  276 {
  277         /*
  278          * System must have more than 2 lgroups to enable lgroup optimizations
  279          *
  280          * XXX This assumes that a 2 lgroup system has an empty root lgroup
  281          * with one child lgroup containing all the resources. A 2 lgroup
  282          * system with a root lgroup directly containing CPUs or memory might
  283          * need lgroup optimizations with its child lgroup, but there
  284          * isn't such a machine for now....
  285          */
  286         if (nlgrps > 2)
  287                 return (1);
  288 
  289         return (0);
  290 }
  291 
  292 /*
  293  * Setup root lgroup
  294  */
  295 static void
  296 lgrp_root_init(void)
  297 {
  298         lgrp_handle_t   hand;
  299         int             i;
  300         lgrp_id_t       id;
  301 
  302         /*
  303          * Create the "root" lgroup
  304          */
  305         ASSERT(nlgrps == 0);
  306         id = nlgrps++;
  307 
  308         lgrp_root = &lroot;
  309 
  310         lgrp_root->lgrp_cpu = NULL;
  311         lgrp_root->lgrp_mnodes = 0;
  312         lgrp_root->lgrp_nmnodes = 0;
  313         hand = lgrp_plat_root_hand();
  314         lgrp_root->lgrp_plathand = hand;
  315 
  316         lgrp_root->lgrp_id = id;
  317         lgrp_root->lgrp_cpucnt = 0;
  318         lgrp_root->lgrp_childcnt = 0;
  319         klgrpset_clear(lgrp_root->lgrp_children);
  320         klgrpset_clear(lgrp_root->lgrp_leaves);
  321         lgrp_root->lgrp_parent = NULL;
  322         lgrp_root->lgrp_latency = lgrp_plat_latency(hand, hand);
  323 
  324         for (i = 0; i < LGRP_RSRC_COUNT; i++)
  325                 klgrpset_clear(lgrp_root->lgrp_set[i]);
  326 
  327         lgrp_root->lgrp_kstat = NULL;
  328 
  329         lgrp_table[id] = lgrp_root;
  330 
  331         /*
  332          * Setup initial lpl list for CPU0 and initial t0 home.
  333          * The only lpl space we have so far is lpl_bootstrap. It is used for
  334          * all topology operations until cp_default is initialized at which
  335          * point t0.t_lpl will be updated.
  336          */
  337         lpl_bootstrap = lpl_bootstrap_list;
  338         t0.t_lpl = lpl_bootstrap;
  339         cp_default.cp_nlgrploads = LPL_BOOTSTRAP_SIZE;
  340         lpl_bootstrap_list[1].lpl_lgrpid = 1;
  341 
  342         /*
  343          * Set up the bootstrap rset
  344          * Since the bootstrap toplogy has just the root, and a leaf,
  345          * the rset contains just the leaf, and both lpls can use the same rset
  346          */
  347         lpl_bootstrap_rset[0] = &lpl_bootstrap_list[1];
  348         lpl_bootstrap_list[0].lpl_rset_sz = 1;
  349         lpl_bootstrap_list[0].lpl_rset = lpl_bootstrap_rset;
  350         lpl_bootstrap_list[0].lpl_id2rset = lpl_bootstrap_id2rset;
  351 
  352         lpl_bootstrap_list[1].lpl_rset_sz = 1;
  353         lpl_bootstrap_list[1].lpl_rset = lpl_bootstrap_rset;
  354         lpl_bootstrap_list[1].lpl_id2rset = lpl_bootstrap_id2rset;
  355 
  356         cp_default.cp_lgrploads = lpl_bootstrap;
  357 }
  358 
  359 /*
  360  * Initialize the lgroup framework and allow the platform to do the same
  361  *
  362  * This happens in stages during boot and is all funnelled through this routine
  363  * (see definition of lgrp_init_stages_t to see what happens at each stage and
  364  * when)
  365  */
  366 void
  367 lgrp_init(lgrp_init_stages_t stage)
  368 {
  369         /*
  370          * Initialize the platform
  371          */
  372         lgrp_plat_init(stage);
  373 
  374         switch (stage) {
  375         case LGRP_INIT_STAGE1:
  376                 /*
  377                  * Set max number of lgroups supported on this platform which
  378                  * must be less than the max number of lgroups supported by the
  379                  * common lgroup framework (eg. NLGRPS_MAX is max elements in
  380                  * lgrp_table[], etc.)
  381                  */
  382                 nlgrpsmax = lgrp_plat_max_lgrps();
  383                 ASSERT(nlgrpsmax <= NLGRPS_MAX);
  384                 break;
  385 
  386         case LGRP_INIT_STAGE2:
  387                 lgrp_setup();
  388                 break;
  389 
  390         case LGRP_INIT_STAGE4:
  391                 lgrp_main_init();
  392                 break;
  393 
  394         case LGRP_INIT_STAGE5:
  395                 lgrp_main_mp_init();
  396                 break;
  397 
  398         default:
  399                 break;
  400         }
  401 }
  402 
  403 /*
  404  * Create the root and cpu0's lgroup, and set t0's home.
  405  */
  406 static void
  407 lgrp_setup(void)
  408 {
  409         /*
  410          * Setup the root lgroup
  411          */
  412         lgrp_root_init();
  413 
  414         /*
  415          * Add cpu0 to an lgroup
  416          */
  417         lgrp_config(LGRP_CONFIG_CPU_ADD, (uintptr_t)CPU, 0);
  418         lgrp_config(LGRP_CONFIG_CPU_ONLINE, (uintptr_t)CPU, 0);
  419 }
  420 
  421 /*
  422  * true when lgrp initialization has been completed.
  423  */
  424 int     lgrp_initialized = 0;
  425 
  426 /*
  427  * True when lgrp topology is constructed.
  428  */
  429 int     lgrp_topo_initialized = 0;
  430 
  431 /*
  432  * Init routine called after startup(), /etc/system has been processed,
  433  * and cpu0 has been added to an lgroup.
  434  */
  435 static void
  436 lgrp_main_init(void)
  437 {
  438         cpu_t           *cp = CPU;
  439         lgrp_id_t       lgrpid;
  440         int             i;
  441         extern void     pg_cpu0_reinit();
  442 
  443         /*
  444          * Enforce a valid lgrp_mem_default_policy
  445          */
  446         if ((lgrp_mem_default_policy <= LGRP_MEM_POLICY_DEFAULT) ||
  447             (lgrp_mem_default_policy >= LGRP_NUM_MEM_POLICIES) ||
  448             (lgrp_mem_default_policy == LGRP_MEM_POLICY_NEXT_SEG))
  449                 lgrp_mem_default_policy = LGRP_MEM_POLICY_NEXT;
  450 
  451         /*
  452          * See if mpo should be disabled.
  453          * This may happen in the case of null proc LPA on Starcat.
  454          * The platform won't be able to detect null proc LPA until after
  455          * cpu0 and memory have already been added to lgroups.
  456          * When and if it is detected, the Starcat platform will return
  457          * a different platform handle for cpu0 which is what we check for
  458          * here. If mpo should be disabled move cpu0 to it's rightful place
  459          * (the root), and destroy the remaining lgroups. This effectively
  460          * provides an UMA lgroup topology.
  461          */
  462         lgrpid = cp->cpu_lpl->lpl_lgrpid;
  463         if (lgrp_table[lgrpid]->lgrp_plathand !=
  464             lgrp_plat_cpu_to_hand(cp->cpu_id)) {
  465                 lgrp_part_del_cpu(cp);
  466                 lgrp_cpu_fini(cp, lgrpid);
  467 
  468                 lgrp_cpu_init(cp);
  469                 lgrp_part_add_cpu(cp, cp->cpu_lpl->lpl_lgrpid);
  470 
  471                 ASSERT(cp->cpu_lpl->lpl_lgrpid == LGRP_ROOTID);
  472 
  473                 /*
  474                  * Notify the PG subsystem that the CPU's lgrp
  475                  * association has changed
  476                  */
  477                 pg_cpu0_reinit();
  478 
  479                 /*
  480                  * Destroy all lgroups except for root
  481                  */
  482                 for (i = 0; i <= lgrp_alloc_max; i++) {
  483                         if (LGRP_EXISTS(lgrp_table[i]) &&
  484                             lgrp_table[i] != lgrp_root)
  485                                 lgrp_destroy(lgrp_table[i]);
  486                 }
  487 
  488                 /*
  489                  * Fix up root to point at itself for leaves and resources
  490                  * and not have any children
  491                  */
  492                 lgrp_root->lgrp_childcnt = 0;
  493                 klgrpset_clear(lgrp_root->lgrp_children);
  494                 klgrpset_clear(lgrp_root->lgrp_leaves);
  495                 klgrpset_add(lgrp_root->lgrp_leaves, LGRP_ROOTID);
  496                 klgrpset_clear(lgrp_root->lgrp_set[LGRP_RSRC_MEM]);
  497                 klgrpset_add(lgrp_root->lgrp_set[LGRP_RSRC_MEM], LGRP_ROOTID);
  498         }
  499 
  500         /*
  501          * Initialize kstats framework.
  502          */
  503         lgrp_kstat_init();
  504         /*
  505          * cpu0 is finally where it should be, so create it's lgroup's kstats
  506          */
  507         mutex_enter(&cpu_lock);
  508         lgrp_kstat_create(cp);
  509         mutex_exit(&cpu_lock);
  510 
  511         lgrp_initialized = 1;
  512 }
  513 
  514 /*
  515  * Finish lgrp initialization after all CPUS are brought on-line.
  516  * This routine is called after start_other_cpus().
  517  */
  518 static void
  519 lgrp_main_mp_init(void)
  520 {
  521         klgrpset_t changed;
  522 
  523         /*
  524          * Update lgroup topology (if necessary)
  525          */
  526         klgrpset_clear(changed);
  527         (void) lgrp_topo_update(lgrp_table, lgrp_alloc_max + 1, &changed);
  528         lgrp_topo_initialized = 1;
  529 }
  530 
  531 /*
  532  * Change latency of lgroup with specified lgroup platform handle (if one is
  533  * given) or change all lgroups with old latency to new latency
  534  */
  535 void
  536 lgrp_latency_change(lgrp_handle_t hand, u_longlong_t oldtime,
  537     u_longlong_t newtime)
  538 {
  539         lgrp_t          *lgrp;
  540         int             i;
  541 
  542         for (i = 0; i <= lgrp_alloc_max; i++) {
  543                 lgrp = lgrp_table[i];
  544 
  545                 if (!LGRP_EXISTS(lgrp))
  546                         continue;
  547 
  548                 if ((hand == LGRP_NULL_HANDLE &&
  549                     lgrp->lgrp_latency == oldtime) ||
  550                     (hand != LGRP_NULL_HANDLE && lgrp->lgrp_plathand == hand))
  551                         lgrp->lgrp_latency = (int)newtime;
  552         }
  553 }
  554 
  555 /*
  556  * Handle lgroup (re)configuration events (eg. addition of CPU, etc.)
  557  */
  558 void
  559 lgrp_config(lgrp_config_flag_t event, uintptr_t resource, uintptr_t where)
  560 {
  561         klgrpset_t      changed;
  562         cpu_t           *cp;
  563         lgrp_id_t       id;
  564         int             rc;
  565 
  566         switch (event) {
  567         /*
  568          * The following (re)configuration events are common code
  569          * initiated. lgrp_plat_config() is called here to inform the
  570          * platform of the reconfiguration event.
  571          */
  572         case LGRP_CONFIG_CPU_ADD:
  573                 cp = (cpu_t *)resource;
  574 
  575                 /*
  576                  * Initialize the new CPU's lgrp related next/prev
  577                  * links, and give it a bootstrap lpl so that it can
  578                  * survive should it need to enter the dispatcher.
  579                  */
  580                 cp->cpu_next_lpl = cp;
  581                 cp->cpu_prev_lpl = cp;
  582                 cp->cpu_next_lgrp = cp;
  583                 cp->cpu_prev_lgrp = cp;
  584                 cp->cpu_lpl = lpl_bootstrap;
  585 
  586                 lgrp_plat_config(event, resource);
  587                 atomic_add_32(&lgrp_gen, 1);
  588 
  589                 break;
  590         case LGRP_CONFIG_CPU_DEL:
  591                 lgrp_plat_config(event, resource);
  592                 atomic_add_32(&lgrp_gen, 1);
  593 
  594                 break;
  595         case LGRP_CONFIG_CPU_ONLINE:
  596                 cp = (cpu_t *)resource;
  597                 lgrp_cpu_init(cp);
  598                 lgrp_part_add_cpu(cp, cp->cpu_lpl->lpl_lgrpid);
  599                 rc = lpl_topo_verify(cp->cpu_part);
  600                 if (rc != LPL_TOPO_CORRECT) {
  601                         panic("lpl_topo_verify failed: %d", rc);
  602                 }
  603                 lgrp_plat_config(event, resource);
  604                 atomic_add_32(&lgrp_gen, 1);
  605 
  606                 break;
  607         case LGRP_CONFIG_CPU_OFFLINE:
  608                 cp = (cpu_t *)resource;
  609                 id = cp->cpu_lpl->lpl_lgrpid;
  610                 lgrp_part_del_cpu(cp);
  611                 lgrp_cpu_fini(cp, id);
  612                 rc = lpl_topo_verify(cp->cpu_part);
  613                 if (rc != LPL_TOPO_CORRECT) {
  614                         panic("lpl_topo_verify failed: %d", rc);
  615                 }
  616                 lgrp_plat_config(event, resource);
  617                 atomic_add_32(&lgrp_gen, 1);
  618 
  619                 break;
  620         case LGRP_CONFIG_CPUPART_ADD:
  621                 cp = (cpu_t *)resource;
  622                 lgrp_part_add_cpu((cpu_t *)resource, (lgrp_id_t)where);
  623                 rc = lpl_topo_verify(cp->cpu_part);
  624                 if (rc != LPL_TOPO_CORRECT) {
  625                         panic("lpl_topo_verify failed: %d", rc);
  626                 }
  627                 lgrp_plat_config(event, resource);
  628 
  629                 break;
  630         case LGRP_CONFIG_CPUPART_DEL:
  631                 cp = (cpu_t *)resource;
  632                 lgrp_part_del_cpu((cpu_t *)resource);
  633                 rc = lpl_topo_verify(cp->cpu_part);
  634                 if (rc != LPL_TOPO_CORRECT) {
  635                         panic("lpl_topo_verify failed: %d", rc);
  636                 }
  637                 lgrp_plat_config(event, resource);
  638 
  639                 break;
  640         /*
  641          * The following events are initiated by the memnode
  642          * subsystem.
  643          */
  644         case LGRP_CONFIG_MEM_ADD:
  645                 lgrp_mem_init((int)resource, where, B_FALSE);
  646                 atomic_add_32(&lgrp_gen, 1);
  647 
  648                 break;
  649         case LGRP_CONFIG_MEM_DEL:
  650                 lgrp_mem_fini((int)resource, where, B_FALSE);
  651                 atomic_add_32(&lgrp_gen, 1);
  652 
  653                 break;
  654         case LGRP_CONFIG_MEM_RENAME: {
  655                 lgrp_config_mem_rename_t *ren_arg =
  656                     (lgrp_config_mem_rename_t *)where;
  657 
  658                 lgrp_mem_rename((int)resource,
  659                     ren_arg->lmem_rename_from,
  660                     ren_arg->lmem_rename_to);
  661                 atomic_add_32(&lgrp_gen, 1);
  662 
  663                 break;
  664         }
  665         case LGRP_CONFIG_GEN_UPDATE:
  666                 atomic_add_32(&lgrp_gen, 1);
  667 
  668                 break;
  669         case LGRP_CONFIG_FLATTEN:
  670                 if (where == 0)
  671                         lgrp_topo_levels = (int)resource;
  672                 else
  673                         (void) lgrp_topo_flatten(resource,
  674                             lgrp_table, lgrp_alloc_max, &changed);
  675 
  676                 break;
  677         /*
  678          * Update any lgroups with old latency to new latency
  679          */
  680         case LGRP_CONFIG_LAT_CHANGE_ALL:
  681                 lgrp_latency_change(LGRP_NULL_HANDLE, (u_longlong_t)resource,
  682                     (u_longlong_t)where);
  683 
  684                 break;
  685         /*
  686          * Update lgroup with specified lgroup platform handle to have
  687          * new latency
  688          */
  689         case LGRP_CONFIG_LAT_CHANGE:
  690                 lgrp_latency_change((lgrp_handle_t)resource, 0,
  691                     (u_longlong_t)where);
  692 
  693                 break;
  694         case LGRP_CONFIG_NOP:
  695 
  696                 break;
  697         default:
  698                 break;
  699         }
  700 
  701 }
  702 
  703 /*
  704  * Called to add lgrp info into cpu structure from cpu_add_unit;
  705  * do not assume cpu is in cpu[] yet!
  706  *
  707  * CPUs are brought online with all other CPUs paused so we can't
  708  * allocate memory or we could deadlock the system, so we rely on
  709  * the platform to statically allocate as much space as we need
  710  * for the lgrp structs and stats.
  711  */
  712 static void
  713 lgrp_cpu_init(struct cpu *cp)
  714 {
  715         klgrpset_t      changed;
  716         int             count;
  717         lgrp_handle_t   hand;
  718         int             first_cpu;
  719         lgrp_t          *my_lgrp;
  720         lgrp_id_t       lgrpid;
  721         struct cpu      *cptr;
  722 
  723         /*
  724          * This is the first time through if the resource set
  725          * for the root lgroup is empty. After cpu0 has been
  726          * initially added to an lgroup, the root's CPU resource
  727          * set can never be empty, since the system's last CPU
  728          * cannot be offlined.
  729          */
  730         if (klgrpset_isempty(lgrp_root->lgrp_set[LGRP_RSRC_CPU])) {
  731                 /*
  732                  * First time through.
  733                  */
  734                 first_cpu = 1;
  735         } else {
  736                 /*
  737                  * If cpu0 needs to move lgroups, we may come
  738                  * through here again, at which time cpu_lock won't
  739                  * be held, and lgrp_initialized will be false.
  740                  */
  741                 ASSERT(MUTEX_HELD(&cpu_lock) || !lgrp_initialized);
  742                 ASSERT(cp->cpu_part != NULL);
  743                 first_cpu = 0;
  744         }
  745 
  746         hand = lgrp_plat_cpu_to_hand(cp->cpu_id);
  747         my_lgrp = lgrp_hand_to_lgrp(hand);
  748 
  749         if (my_lgrp == NULL) {
  750                 /*
  751                  * Create new lgrp and add it to lgroup topology
  752                  */
  753                 my_lgrp = lgrp_create();
  754                 my_lgrp->lgrp_plathand = hand;
  755                 my_lgrp->lgrp_latency = lgrp_plat_latency(hand, hand);
  756                 lgrpid = my_lgrp->lgrp_id;
  757                 klgrpset_add(my_lgrp->lgrp_leaves, lgrpid);
  758                 klgrpset_add(my_lgrp->lgrp_set[LGRP_RSRC_CPU], lgrpid);
  759 
  760                 count = 0;
  761                 klgrpset_clear(changed);
  762                 count += lgrp_leaf_add(my_lgrp, lgrp_table, lgrp_alloc_max + 1,
  763                     &changed);
  764                 /*
  765                  * May have added new intermediate lgroups, so need to add
  766                  * resources other than CPUs which are added below
  767                  */
  768                 (void) lgrp_mnode_update(changed, NULL);
  769         } else if (my_lgrp->lgrp_latency == 0 && lgrp_plat_latency(hand, hand)
  770             > 0) {
  771                 /*
  772                  * Leaf lgroup was created, but latency wasn't available
  773                  * then.  So, set latency for it and fill in rest of lgroup
  774                  * topology  now that we know how far it is from other leaf
  775                  * lgroups.
  776                  */
  777                 lgrpid = my_lgrp->lgrp_id;
  778                 klgrpset_clear(changed);
  779                 if (!klgrpset_ismember(my_lgrp->lgrp_set[LGRP_RSRC_CPU],
  780                     lgrpid))
  781                         klgrpset_add(my_lgrp->lgrp_set[LGRP_RSRC_CPU], lgrpid);
  782                 count = lgrp_leaf_add(my_lgrp, lgrp_table, lgrp_alloc_max + 1,
  783                     &changed);
  784 
  785                 /*
  786                  * May have added new intermediate lgroups, so need to add
  787                  * resources other than CPUs which are added below
  788                  */
  789                 (void) lgrp_mnode_update(changed, NULL);
  790         } else if (!klgrpset_ismember(my_lgrp->lgrp_set[LGRP_RSRC_CPU],
  791             my_lgrp->lgrp_id)) {
  792                 int     i;
  793 
  794                 /*
  795                  * Update existing lgroup and lgroups containing it with CPU
  796                  * resource
  797                  */
  798                 lgrpid = my_lgrp->lgrp_id;
  799                 klgrpset_add(my_lgrp->lgrp_set[LGRP_RSRC_CPU], lgrpid);
  800                 for (i = 0; i <= lgrp_alloc_max; i++) {
  801                         lgrp_t          *lgrp;
  802 
  803                         lgrp = lgrp_table[i];
  804                         if (!LGRP_EXISTS(lgrp) ||
  805                             !lgrp_rsets_member(lgrp->lgrp_set, lgrpid))
  806                                 continue;
  807 
  808                         klgrpset_add(lgrp->lgrp_set[LGRP_RSRC_CPU], lgrpid);
  809                 }
  810         }
  811 
  812         lgrpid = my_lgrp->lgrp_id;
  813         cp->cpu_lpl = &cp->cpu_part->cp_lgrploads[lgrpid];
  814 
  815         /*
  816          * For multi-lgroup systems, need to setup lpl for CPU0 or CPU0 will
  817          * end up in lpl for lgroup 0 whether it is supposed to be in there or
  818          * not since none of lgroup IDs in the lpl's have been set yet.
  819          */
  820         if (first_cpu && nlgrpsmax > 1 && lgrpid != cp->cpu_lpl->lpl_lgrpid)
  821                 cp->cpu_lpl->lpl_lgrpid = lgrpid;
  822 
  823         /*
  824          * link the CPU into the lgrp's CPU list
  825          */
  826         if (my_lgrp->lgrp_cpucnt == 0) {
  827                 my_lgrp->lgrp_cpu = cp;
  828                 cp->cpu_next_lgrp = cp->cpu_prev_lgrp = cp;
  829         } else {
  830                 cptr = my_lgrp->lgrp_cpu;
  831                 cp->cpu_next_lgrp = cptr;
  832                 cp->cpu_prev_lgrp = cptr->cpu_prev_lgrp;
  833                 cptr->cpu_prev_lgrp->cpu_next_lgrp = cp;
  834                 cptr->cpu_prev_lgrp = cp;
  835         }
  836         my_lgrp->lgrp_cpucnt++;
  837 }
  838 
  839 lgrp_t *
  840 lgrp_create(void)
  841 {
  842         lgrp_t          *my_lgrp;
  843         lgrp_id_t       lgrpid;
  844         int             i;
  845 
  846         ASSERT(!lgrp_initialized || MUTEX_HELD(&cpu_lock));
  847 
  848         /*
  849          * Find an open slot in the lgroup table and recycle unused lgroup
  850          * left there if any
  851          */
  852         my_lgrp = NULL;
  853         if (lgrp_alloc_hint == -1)
  854                 /*
  855                  * Allocate from end when hint not set yet because no lgroups
  856                  * have been deleted yet
  857                  */
  858                 lgrpid = nlgrps++;
  859         else {
  860                 /*
  861                  * Start looking for next open slot from hint and leave hint
  862                  * at slot allocated
  863                  */
  864                 for (i = lgrp_alloc_hint; i < nlgrpsmax; i++) {
  865                         my_lgrp = lgrp_table[i];
  866                         if (!LGRP_EXISTS(my_lgrp)) {
  867                                 lgrpid = i;
  868                                 nlgrps++;
  869                                 break;
  870                         }
  871                 }
  872                 lgrp_alloc_hint = lgrpid;
  873         }
  874 
  875         /*
  876          * Keep track of max lgroup ID allocated so far to cut down on searches
  877          */
  878         if (lgrpid > lgrp_alloc_max)
  879                 lgrp_alloc_max = lgrpid;
  880 
  881         /*
  882          * Need to allocate new lgroup if next open slot didn't have one
  883          * for recycling
  884          */
  885         if (my_lgrp == NULL)
  886                 my_lgrp = lgrp_plat_alloc(lgrpid);
  887 
  888         if (nlgrps > nlgrpsmax || my_lgrp == NULL)
  889                 panic("Too many lgrps for platform (%d)", nlgrps);
  890 
  891         my_lgrp->lgrp_id = lgrpid;
  892         my_lgrp->lgrp_latency = 0;
  893         my_lgrp->lgrp_plathand = LGRP_NULL_HANDLE;
  894         my_lgrp->lgrp_parent = NULL;
  895         my_lgrp->lgrp_childcnt = 0;
  896         my_lgrp->lgrp_mnodes = (mnodeset_t)0;
  897         my_lgrp->lgrp_nmnodes = 0;
  898         klgrpset_clear(my_lgrp->lgrp_children);
  899         klgrpset_clear(my_lgrp->lgrp_leaves);
  900         for (i = 0; i < LGRP_RSRC_COUNT; i++)
  901                 klgrpset_clear(my_lgrp->lgrp_set[i]);
  902 
  903         my_lgrp->lgrp_cpu = NULL;
  904         my_lgrp->lgrp_cpucnt = 0;
  905 
  906         if (my_lgrp->lgrp_kstat != NULL)
  907                 lgrp_kstat_reset(lgrpid);
  908 
  909         lgrp_table[my_lgrp->lgrp_id] = my_lgrp;
  910 
  911         return (my_lgrp);
  912 }
  913 
  914 void
  915 lgrp_destroy(lgrp_t *lgrp)
  916 {
  917         int             i;
  918 
  919         /*
  920          * Unless this lgroup is being destroyed on behalf of
  921          * the boot CPU, cpu_lock must be held
  922          */
  923         ASSERT(!lgrp_initialized || MUTEX_HELD(&cpu_lock));
  924 
  925         if (nlgrps == 1)
  926                 cmn_err(CE_PANIC, "Can't destroy only lgroup!");
  927 
  928         if (!LGRP_EXISTS(lgrp))
  929                 return;
  930 
  931         /*
  932          * Set hint to lgroup being deleted and try to keep lower numbered
  933          * hints to facilitate finding empty slots
  934          */
  935         if (lgrp_alloc_hint == -1 || lgrp->lgrp_id < lgrp_alloc_hint)
  936                 lgrp_alloc_hint = lgrp->lgrp_id;
  937 
  938         /*
  939          * Mark this lgroup to be recycled by setting its lgroup ID to
  940          * LGRP_NONE and clear relevant fields
  941          */
  942         lgrp->lgrp_id = LGRP_NONE;
  943         lgrp->lgrp_latency = 0;
  944         lgrp->lgrp_plathand = LGRP_NULL_HANDLE;
  945         lgrp->lgrp_parent = NULL;
  946         lgrp->lgrp_childcnt = 0;
  947 
  948         klgrpset_clear(lgrp->lgrp_children);
  949         klgrpset_clear(lgrp->lgrp_leaves);
  950         for (i = 0; i < LGRP_RSRC_COUNT; i++)
  951                 klgrpset_clear(lgrp->lgrp_set[i]);
  952 
  953         lgrp->lgrp_mnodes = (mnodeset_t)0;
  954         lgrp->lgrp_nmnodes = 0;
  955 
  956         lgrp->lgrp_cpu = NULL;
  957         lgrp->lgrp_cpucnt = 0;
  958 
  959         nlgrps--;
  960 }
  961 
  962 /*
  963  * Initialize kstat data. Called from lgrp intialization code.
  964  */
  965 static void
  966 lgrp_kstat_init(void)
  967 {
  968         lgrp_stat_t     stat;
  969 
  970         mutex_init(&lgrp_kstat_mutex, NULL, MUTEX_DEFAULT, NULL);
  971 
  972         for (stat = 0; stat < LGRP_NUM_STATS; stat++)
  973                 kstat_named_init(&lgrp_kstat_data[stat],
  974                     lgrp_kstat_names[stat], KSTAT_DATA_INT64);
  975 }
  976 
  977 /*
  978  * initialize an lgrp's kstats if needed
  979  * called with cpu_lock held but not with cpus paused.
  980  * we don't tear these down now because we don't know about
  981  * memory leaving the lgrp yet...
  982  */
  983 
  984 void
  985 lgrp_kstat_create(cpu_t *cp)
  986 {
  987         kstat_t         *lgrp_kstat;
  988         lgrp_id_t       lgrpid;
  989         lgrp_t          *my_lgrp;
  990 
  991         ASSERT(MUTEX_HELD(&cpu_lock));
  992 
  993         lgrpid = cp->cpu_lpl->lpl_lgrpid;
  994         my_lgrp = lgrp_table[lgrpid];
  995 
  996         if (my_lgrp->lgrp_kstat != NULL)
  997                 return; /* already initialized */
  998 
  999         lgrp_kstat = kstat_create("lgrp", lgrpid, NULL, "misc",
 1000             KSTAT_TYPE_NAMED, LGRP_NUM_STATS,
 1001             KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE);
 1002 
 1003         if (lgrp_kstat != NULL) {
 1004                 lgrp_kstat->ks_lock = &lgrp_kstat_mutex;
 1005                 lgrp_kstat->ks_private = my_lgrp;
 1006                 lgrp_kstat->ks_data = &lgrp_kstat_data;
 1007                 lgrp_kstat->ks_update = lgrp_kstat_extract;
 1008                 my_lgrp->lgrp_kstat = lgrp_kstat;
 1009                 kstat_install(lgrp_kstat);
 1010         }
 1011 }
 1012 
 1013 /*
 1014  * this will do something when we manage to remove now unused lgrps
 1015  */
 1016 
 1017 /* ARGSUSED */
 1018 void
 1019 lgrp_kstat_destroy(cpu_t *cp)
 1020 {
 1021         ASSERT(MUTEX_HELD(&cpu_lock));
 1022 }
 1023 
 1024 /*
 1025  * Called when a CPU is off-lined.
 1026  */
 1027 static void
 1028 lgrp_cpu_fini(struct cpu *cp, lgrp_id_t lgrpid)
 1029 {
 1030         lgrp_t *my_lgrp;
 1031         struct cpu *prev;
 1032         struct cpu *next;
 1033 
 1034         ASSERT(MUTEX_HELD(&cpu_lock) || !lgrp_initialized);
 1035 
 1036         prev = cp->cpu_prev_lgrp;
 1037         next = cp->cpu_next_lgrp;
 1038 
 1039         prev->cpu_next_lgrp = next;
 1040         next->cpu_prev_lgrp = prev;
 1041 
 1042         /*
 1043          * just because I'm paranoid doesn't mean...
 1044          */
 1045 
 1046         cp->cpu_next_lgrp = cp->cpu_prev_lgrp = NULL;
 1047 
 1048         my_lgrp = lgrp_table[lgrpid];
 1049         my_lgrp->lgrp_cpucnt--;
 1050 
 1051         /*
 1052          * Removing last CPU in lgroup, so update lgroup topology
 1053          */
 1054         if (my_lgrp->lgrp_cpucnt == 0) {
 1055                 klgrpset_t      changed;
 1056                 int             count;
 1057                 int             i;
 1058 
 1059                 my_lgrp->lgrp_cpu = NULL;
 1060 
 1061                 /*
 1062                  * Remove this lgroup from its lgroup CPU resources and remove
 1063                  * lgroup from lgroup topology if it doesn't have any more
 1064                  * resources in it now
 1065                  */
 1066                 klgrpset_del(my_lgrp->lgrp_set[LGRP_RSRC_CPU], lgrpid);
 1067                 if (lgrp_rsets_empty(my_lgrp->lgrp_set)) {
 1068                         count = 0;
 1069                         klgrpset_clear(changed);
 1070                         count += lgrp_leaf_delete(my_lgrp, lgrp_table,
 1071                             lgrp_alloc_max + 1, &changed);
 1072                         return;
 1073                 }
 1074 
 1075                 /*
 1076                  * This lgroup isn't empty, so just remove it from CPU
 1077                  * resources of any lgroups that contain it as such
 1078                  */
 1079                 for (i = 0; i <= lgrp_alloc_max; i++) {
 1080                         lgrp_t          *lgrp;
 1081 
 1082                         lgrp = lgrp_table[i];
 1083                         if (!LGRP_EXISTS(lgrp) ||
 1084                             !klgrpset_ismember(lgrp->lgrp_set[LGRP_RSRC_CPU],
 1085                             lgrpid))
 1086                                 continue;
 1087 
 1088                         klgrpset_del(lgrp->lgrp_set[LGRP_RSRC_CPU], lgrpid);
 1089                 }
 1090                 return;
 1091         }
 1092 
 1093         if (my_lgrp->lgrp_cpu == cp)
 1094                 my_lgrp->lgrp_cpu = next;
 1095 
 1096 }
 1097 
 1098 /*
 1099  * Update memory nodes in target lgroups and return ones that get changed
 1100  */
 1101 int
 1102 lgrp_mnode_update(klgrpset_t target, klgrpset_t *changed)
 1103 {
 1104         int     count;
 1105         int     i;
 1106         int     j;
 1107         lgrp_t  *lgrp;
 1108         lgrp_t  *lgrp_rsrc;
 1109 
 1110         count = 0;
 1111         if (changed)
 1112                 klgrpset_clear(*changed);
 1113 
 1114         if (klgrpset_isempty(target))
 1115                 return (0);
 1116 
 1117         /*
 1118          * Find each lgroup in target lgroups
 1119          */
 1120         for (i = 0; i <= lgrp_alloc_max; i++) {
 1121                 /*
 1122                  * Skip any lgroups that don't exist or aren't in target group
 1123                  */
 1124                 lgrp = lgrp_table[i];
 1125                 if (!klgrpset_ismember(target, i) || !LGRP_EXISTS(lgrp)) {
 1126                         continue;
 1127                 }
 1128 
 1129                 /*
 1130                  * Initialize memnodes for intermediate lgroups to 0
 1131                  * and update them from scratch since they may have completely
 1132                  * changed
 1133                  */
 1134                 if (lgrp->lgrp_childcnt && lgrp != lgrp_root) {
 1135                         lgrp->lgrp_mnodes = (mnodeset_t)0;
 1136                         lgrp->lgrp_nmnodes = 0;
 1137                 }
 1138 
 1139                 /*
 1140                  * Update memory nodes of of target lgroup with memory nodes
 1141                  * from each lgroup in its lgroup memory resource set
 1142                  */
 1143                 for (j = 0; j <= lgrp_alloc_max; j++) {
 1144                         int     k;
 1145 
 1146                         /*
 1147                          * Skip any lgroups that don't exist or aren't in
 1148                          * memory resources of target lgroup
 1149                          */
 1150                         lgrp_rsrc = lgrp_table[j];
 1151                         if (!LGRP_EXISTS(lgrp_rsrc) ||
 1152                             !klgrpset_ismember(lgrp->lgrp_set[LGRP_RSRC_MEM],
 1153                             j))
 1154                                 continue;
 1155 
 1156                         /*
 1157                          * Update target lgroup's memnodes to include memnodes
 1158                          * of this lgroup
 1159                          */
 1160                         for (k = 0; k < sizeof (mnodeset_t) * NBBY; k++) {
 1161                                 mnodeset_t      mnode_mask;
 1162 
 1163                                 mnode_mask = (mnodeset_t)1 << k;
 1164                                 if ((lgrp_rsrc->lgrp_mnodes & mnode_mask) &&
 1165                                     !(lgrp->lgrp_mnodes & mnode_mask)) {
 1166                                         lgrp->lgrp_mnodes |= mnode_mask;
 1167                                         lgrp->lgrp_nmnodes++;
 1168                                 }
 1169                         }
 1170                         count++;
 1171                         if (changed)
 1172                                 klgrpset_add(*changed, lgrp->lgrp_id);
 1173                 }
 1174         }
 1175 
 1176         return (count);
 1177 }
 1178 
 1179 /*
 1180  * Memory copy-rename. Called when the "mnode" containing the kernel cage memory
 1181  * is moved from one board to another. The "from" and "to" arguments specify the
 1182  * source and the destination of the move.
 1183  *
 1184  * See plat_lgrp_config() for a detailed description of the copy-rename
 1185  * semantics.
 1186  *
 1187  * The lgrp_mem_rename() is called by the platform copy-rename code to update
 1188  * the lgroup topology which is changing as memory moves from one lgroup to
 1189  * another. It removes the mnode from the source lgroup and re-inserts it in the
 1190  * target lgroup.
 1191  *
 1192  * The lgrp_mem_rename() function passes a flag to lgrp_mem_init() and
 1193  * lgrp_mem_fini() telling that the insertion and deleteion are part of a DR
 1194  * copy-rename operation.
 1195  *
 1196  * There is one case which requires special handling. If the system contains
 1197  * only two boards (mnodes), the lgrp_mem_fini() removes the only mnode from the
 1198  * lgroup hierarchy. This mnode is soon re-inserted back in the hierarchy by
 1199  * lgrp_mem_init), but there is a window when the system has no memory in the
 1200  * lgroup hierarchy. If another thread tries to allocate memory during this
 1201  * window, the allocation will fail, although the system has physical memory.
 1202  * This may cause a system panic or a deadlock (some sleeping memory allocations
 1203  * happen with cpu_lock held which prevents lgrp_mem_init() from re-inserting
 1204  * the mnode back).
 1205  *
 1206  * The lgrp_memnode_choose() function walks the lgroup hierarchy looking for the
 1207  * lgrp with non-empty lgrp_mnodes. To deal with the special case above,
 1208  * lgrp_mem_fini() does not remove the last mnode from the lroot->lgrp_mnodes,
 1209  * but it updates the rest of the lgroup topology as if the mnode was actually
 1210  * removed. The lgrp_mem_init() function recognizes that the mnode being
 1211  * inserted represents such a special case and updates the topology
 1212  * appropriately.
 1213  */
 1214 void
 1215 lgrp_mem_rename(int mnode, lgrp_handle_t from, lgrp_handle_t to)
 1216 {
 1217         /*
 1218          * Remove the memory from the source node and add it to the destination
 1219          * node.
 1220          */
 1221         lgrp_mem_fini(mnode, from, B_TRUE);
 1222         lgrp_mem_init(mnode, to, B_TRUE);
 1223 }
 1224 
 1225 /*
 1226  * Called to indicate that the lgrp with platform handle "hand" now
 1227  * contains the memory identified by "mnode".
 1228  *
 1229  * LOCKING for this routine is a bit tricky. Usually it is called without
 1230  * cpu_lock and it must must grab cpu_lock here to prevent racing with other
 1231  * callers. During DR of the board containing the caged memory it may be called
 1232  * with cpu_lock already held and CPUs paused.
 1233  *
 1234  * If the insertion is part of the DR copy-rename and the inserted mnode (and
 1235  * only this mnode) is already present in the lgrp_root->lgrp_mnodes set, we are
 1236  * dealing with the special case of DR copy-rename described in
 1237  * lgrp_mem_rename().
 1238  */
 1239 void
 1240 lgrp_mem_init(int mnode, lgrp_handle_t hand, boolean_t is_copy_rename)
 1241 {
 1242         klgrpset_t      changed;
 1243         int             count;
 1244         int             i;
 1245         lgrp_t          *my_lgrp;
 1246         lgrp_id_t       lgrpid;
 1247         mnodeset_t      mnodes_mask = ((mnodeset_t)1 << mnode);
 1248         boolean_t       drop_lock = B_FALSE;
 1249         boolean_t       need_synch = B_FALSE;
 1250 
 1251         /*
 1252          * Grab CPU lock (if we haven't already)
 1253          */
 1254         if (!MUTEX_HELD(&cpu_lock)) {
 1255                 mutex_enter(&cpu_lock);
 1256                 drop_lock = B_TRUE;
 1257         }
 1258 
 1259         /*
 1260          * This routine may be called from a context where we already
 1261          * hold cpu_lock, and have already paused cpus.
 1262          */
 1263         if (!cpus_paused())
 1264                 need_synch = B_TRUE;
 1265 
 1266         /*
 1267          * Check if this mnode is already configured and return immediately if
 1268          * it is.
 1269          *
 1270          * NOTE: in special case of copy-rename of the only remaining mnode,
 1271          * lgrp_mem_fini() refuses to remove the last mnode from the root, so we
 1272          * recognize this case and continue as usual, but skip the update to
 1273          * the lgrp_mnodes and the lgrp_nmnodes. This restores the inconsistency
 1274          * in topology, temporarily introduced by lgrp_mem_fini().
 1275          */
 1276         if (! (is_copy_rename && (lgrp_root->lgrp_mnodes == mnodes_mask)) &&
 1277             lgrp_root->lgrp_mnodes & mnodes_mask) {
 1278                 if (drop_lock)
 1279                         mutex_exit(&cpu_lock);
 1280                 return;
 1281         }
 1282 
 1283         /*
 1284          * Update lgroup topology with new memory resources, keeping track of
 1285          * which lgroups change
 1286          */
 1287         count = 0;
 1288         klgrpset_clear(changed);
 1289         my_lgrp = lgrp_hand_to_lgrp(hand);
 1290         if (my_lgrp == NULL) {
 1291                 /* new lgrp */
 1292                 my_lgrp = lgrp_create();
 1293                 lgrpid = my_lgrp->lgrp_id;
 1294                 my_lgrp->lgrp_plathand = hand;
 1295                 my_lgrp->lgrp_latency = lgrp_plat_latency(hand, hand);
 1296                 klgrpset_add(my_lgrp->lgrp_leaves, lgrpid);
 1297                 klgrpset_add(my_lgrp->lgrp_set[LGRP_RSRC_MEM], lgrpid);
 1298 
 1299                 if (need_synch)
 1300                         pause_cpus(NULL);
 1301                 count = lgrp_leaf_add(my_lgrp, lgrp_table, lgrp_alloc_max + 1,
 1302                     &changed);
 1303                 if (need_synch)
 1304                         start_cpus();
 1305         } else if (my_lgrp->lgrp_latency == 0 && lgrp_plat_latency(hand, hand)
 1306             > 0) {
 1307                 /*
 1308                  * Leaf lgroup was created, but latency wasn't available
 1309                  * then.  So, set latency for it and fill in rest of lgroup
 1310                  * topology  now that we know how far it is from other leaf
 1311                  * lgroups.
 1312                  */
 1313                 klgrpset_clear(changed);
 1314                 lgrpid = my_lgrp->lgrp_id;
 1315                 if (!klgrpset_ismember(my_lgrp->lgrp_set[LGRP_RSRC_MEM],
 1316                     lgrpid))
 1317                         klgrpset_add(my_lgrp->lgrp_set[LGRP_RSRC_MEM], lgrpid);
 1318                 if (need_synch)
 1319                         pause_cpus(NULL);
 1320                 count = lgrp_leaf_add(my_lgrp, lgrp_table, lgrp_alloc_max + 1,
 1321                     &changed);
 1322                 if (need_synch)
 1323                         start_cpus();
 1324         } else if (!klgrpset_ismember(my_lgrp->lgrp_set[LGRP_RSRC_MEM],
 1325             my_lgrp->lgrp_id)) {
 1326                 /*
 1327                  * Add new lgroup memory resource to existing lgroup
 1328                  */
 1329                 lgrpid = my_lgrp->lgrp_id;
 1330                 klgrpset_add(my_lgrp->lgrp_set[LGRP_RSRC_MEM], lgrpid);
 1331                 klgrpset_add(changed, lgrpid);
 1332                 count++;
 1333                 for (i = 0; i <= lgrp_alloc_max; i++) {
 1334                         lgrp_t          *lgrp;
 1335 
 1336                         lgrp = lgrp_table[i];
 1337                         if (!LGRP_EXISTS(lgrp) ||
 1338                             !lgrp_rsets_member(lgrp->lgrp_set, lgrpid))
 1339                                 continue;
 1340 
 1341                         klgrpset_add(lgrp->lgrp_set[LGRP_RSRC_MEM], lgrpid);
 1342                         klgrpset_add(changed, lgrp->lgrp_id);
 1343                         count++;
 1344                 }
 1345         }
 1346 
 1347         /*
 1348          * Add memory node to lgroup and remove lgroup from ones that need
 1349          * to be updated
 1350          */
 1351         if (!(my_lgrp->lgrp_mnodes & mnodes_mask)) {
 1352                 my_lgrp->lgrp_mnodes |= mnodes_mask;
 1353                 my_lgrp->lgrp_nmnodes++;
 1354         }
 1355         klgrpset_del(changed, lgrpid);
 1356 
 1357         /*
 1358          * Update memory node information for all lgroups that changed and
 1359          * contain new memory node as a resource
 1360          */
 1361         if (count)
 1362                 (void) lgrp_mnode_update(changed, NULL);
 1363 
 1364         if (drop_lock)
 1365                 mutex_exit(&cpu_lock);
 1366 }
 1367 
 1368 /*
 1369  * Called to indicate that the lgroup associated with the platform
 1370  * handle "hand" no longer contains given memory node
 1371  *
 1372  * LOCKING for this routine is a bit tricky. Usually it is called without
 1373  * cpu_lock and it must must grab cpu_lock here to prevent racing with other
 1374  * callers. During DR of the board containing the caged memory it may be called
 1375  * with cpu_lock already held and CPUs paused.
 1376  *
 1377  * If the deletion is part of the DR copy-rename and the deleted mnode is the
 1378  * only one present in the lgrp_root->lgrp_mnodes, all the topology is updated,
 1379  * but lgrp_root->lgrp_mnodes is left intact. Later, lgrp_mem_init() will insert
 1380  * the same mnode back into the topology. See lgrp_mem_rename() and
 1381  * lgrp_mem_init() for additional details.
 1382  */
 1383 void
 1384 lgrp_mem_fini(int mnode, lgrp_handle_t hand, boolean_t is_copy_rename)
 1385 {
 1386         klgrpset_t      changed;
 1387         int             count;
 1388         int             i;
 1389         lgrp_t          *my_lgrp;
 1390         lgrp_id_t       lgrpid;
 1391         mnodeset_t      mnodes_mask;
 1392         boolean_t       drop_lock = B_FALSE;
 1393         boolean_t       need_synch = B_FALSE;
 1394 
 1395         /*
 1396          * Grab CPU lock (if we haven't already)
 1397          */
 1398         if (!MUTEX_HELD(&cpu_lock)) {
 1399                 mutex_enter(&cpu_lock);
 1400                 drop_lock = B_TRUE;
 1401         }
 1402 
 1403         /*
 1404          * This routine may be called from a context where we already
 1405          * hold cpu_lock and have already paused cpus.
 1406          */
 1407         if (!cpus_paused())
 1408                 need_synch = B_TRUE;
 1409 
 1410         my_lgrp = lgrp_hand_to_lgrp(hand);
 1411 
 1412         /*
 1413          * The lgrp *must* be pre-existing
 1414          */
 1415         ASSERT(my_lgrp != NULL);
 1416 
 1417         /*
 1418          * Delete memory node from lgroups which contain it
 1419          */
 1420         mnodes_mask = ((mnodeset_t)1 << mnode);
 1421         for (i = 0; i <= lgrp_alloc_max; i++) {
 1422                 lgrp_t *lgrp = lgrp_table[i];
 1423                 /*
 1424                  * Skip any non-existent lgroups and any lgroups that don't
 1425                  * contain leaf lgroup of memory as a memory resource
 1426                  */
 1427                 if (!LGRP_EXISTS(lgrp) ||
 1428                     !(lgrp->lgrp_mnodes & mnodes_mask))
 1429                         continue;
 1430 
 1431                 /*
 1432                  * Avoid removing the last mnode from the root in the DR
 1433                  * copy-rename case. See lgrp_mem_rename() for details.
 1434                  */
 1435                 if (is_copy_rename &&
 1436                     (lgrp == lgrp_root) && (lgrp->lgrp_mnodes == mnodes_mask))
 1437                         continue;
 1438 
 1439                 /*
 1440                  * Remove memory node from lgroup.
 1441                  */
 1442                 lgrp->lgrp_mnodes &= ~mnodes_mask;
 1443                 lgrp->lgrp_nmnodes--;
 1444                 ASSERT(lgrp->lgrp_nmnodes >= 0);
 1445         }
 1446         ASSERT(lgrp_root->lgrp_nmnodes > 0);
 1447 
 1448         /*
 1449          * Don't need to update lgroup topology if this lgroup still has memory.
 1450          *
 1451          * In the special case of DR copy-rename with the only mnode being
 1452          * removed, the lgrp_mnodes for the root is always non-zero, but we
 1453          * still need to update the lgroup topology.
 1454          */
 1455         if ((my_lgrp->lgrp_nmnodes > 0) &&
 1456             !(is_copy_rename && (my_lgrp == lgrp_root) &&
 1457             (my_lgrp->lgrp_mnodes == mnodes_mask))) {
 1458                 if (drop_lock)
 1459                         mutex_exit(&cpu_lock);
 1460                 return;
 1461         }
 1462 
 1463         /*
 1464          * This lgroup does not contain any memory now
 1465          */
 1466         klgrpset_clear(my_lgrp->lgrp_set[LGRP_RSRC_MEM]);
 1467 
 1468         /*
 1469          * Remove this lgroup from lgroup topology if it does not contain any
 1470          * resources now
 1471          */
 1472         lgrpid = my_lgrp->lgrp_id;
 1473         count = 0;
 1474         klgrpset_clear(changed);
 1475         if (lgrp_rsets_empty(my_lgrp->lgrp_set)) {
 1476                 /*
 1477                  * Delete lgroup when no more resources
 1478                  */
 1479                 if (need_synch)
 1480                         pause_cpus(NULL);
 1481                 count = lgrp_leaf_delete(my_lgrp, lgrp_table,
 1482                     lgrp_alloc_max + 1, &changed);
 1483                 ASSERT(count > 0);
 1484                 if (need_synch)
 1485                         start_cpus();
 1486         } else {
 1487                 /*
 1488                  * Remove lgroup from memory resources of any lgroups that
 1489                  * contain it as such
 1490                  */
 1491                 for (i = 0; i <= lgrp_alloc_max; i++) {
 1492                         lgrp_t          *lgrp;
 1493 
 1494                         lgrp = lgrp_table[i];
 1495                         if (!LGRP_EXISTS(lgrp) ||
 1496                             !klgrpset_ismember(lgrp->lgrp_set[LGRP_RSRC_MEM],
 1497                             lgrpid))
 1498                                 continue;
 1499 
 1500                         klgrpset_del(lgrp->lgrp_set[LGRP_RSRC_MEM], lgrpid);
 1501                 }
 1502         }
 1503         if (drop_lock)
 1504                 mutex_exit(&cpu_lock);
 1505 }
 1506 
 1507 /*
 1508  * Return lgroup with given platform handle
 1509  */
 1510 lgrp_t *
 1511 lgrp_hand_to_lgrp(lgrp_handle_t hand)
 1512 {
 1513         int     i;
 1514         lgrp_t  *lgrp;
 1515 
 1516         if (hand == LGRP_NULL_HANDLE)
 1517                 return (NULL);
 1518 
 1519         for (i = 0; i <= lgrp_alloc_max; i++) {
 1520                 lgrp = lgrp_table[i];
 1521                 if (LGRP_EXISTS(lgrp) && lgrp->lgrp_plathand == hand)
 1522                         return (lgrp);
 1523         }
 1524         return (NULL);
 1525 }
 1526 
 1527 /*
 1528  * Return the home lgroup of the current thread.
 1529  * We must do this with kernel preemption disabled, since we don't want our
 1530  * thread to be re-homed while we're poking around with its lpl, and the lpl
 1531  * should never be NULL.
 1532  *
 1533  * NOTE: Can't guarantee that lgroup will be valid once kernel preemption
 1534  * is enabled because of DR.  Callers can use disable kernel preemption
 1535  * around this call to guarantee that the lgroup will be valid beyond this
 1536  * routine, since kernel preemption can be recursive.
 1537  */
 1538 lgrp_t *
 1539 lgrp_home_lgrp(void)
 1540 {
 1541         lgrp_t  *lgrp;
 1542         lpl_t   *lpl;
 1543 
 1544         kpreempt_disable();
 1545 
 1546         lpl = curthread->t_lpl;
 1547         ASSERT(lpl != NULL);
 1548         ASSERT(lpl->lpl_lgrpid >= 0 && lpl->lpl_lgrpid <= lgrp_alloc_max);
 1549         ASSERT(LGRP_EXISTS(lgrp_table[lpl->lpl_lgrpid]));
 1550         lgrp = lgrp_table[lpl->lpl_lgrpid];
 1551 
 1552         kpreempt_enable();
 1553 
 1554         return (lgrp);
 1555 }
 1556 
 1557 /*
 1558  * Return ID of home lgroup for given thread
 1559  * (See comments for lgrp_home_lgrp() for special care and handling
 1560  * instructions)
 1561  */
 1562 lgrp_id_t
 1563 lgrp_home_id(kthread_t *t)
 1564 {
 1565         lgrp_id_t       lgrp;
 1566         lpl_t           *lpl;
 1567 
 1568         ASSERT(t != NULL);
 1569         /*
 1570          * We'd like to ASSERT(MUTEX_HELD(&ttoproc(t)->p_lock)), but we
 1571          * cannot since the HAT layer can call into this routine to
 1572          * determine the locality for its data structures in the context
 1573          * of a page fault.
 1574          */
 1575 
 1576         kpreempt_disable();
 1577 
 1578         lpl = t->t_lpl;
 1579         ASSERT(lpl != NULL);
 1580         ASSERT(lpl->lpl_lgrpid >= 0 && lpl->lpl_lgrpid <= lgrp_alloc_max);
 1581         lgrp = lpl->lpl_lgrpid;
 1582 
 1583         kpreempt_enable();
 1584 
 1585         return (lgrp);
 1586 }
 1587 
 1588 /*
 1589  * Return lgroup containing the physical memory for the given page frame number
 1590  */
 1591 lgrp_t *
 1592 lgrp_pfn_to_lgrp(pfn_t pfn)
 1593 {
 1594         lgrp_handle_t   hand;
 1595         int             i;
 1596         lgrp_t          *lgrp;
 1597 
 1598         hand = lgrp_plat_pfn_to_hand(pfn);
 1599         if (hand != LGRP_NULL_HANDLE)
 1600                 for (i = 0; i <= lgrp_alloc_max; i++) {
 1601                         lgrp = lgrp_table[i];
 1602                         if (LGRP_EXISTS(lgrp) && lgrp->lgrp_plathand == hand)
 1603                                 return (lgrp);
 1604                 }
 1605         return (NULL);
 1606 }
 1607 
 1608 /*
 1609  * Return lgroup containing the physical memory for the given page frame number
 1610  */
 1611 lgrp_t *
 1612 lgrp_phys_to_lgrp(u_longlong_t physaddr)
 1613 {
 1614         lgrp_handle_t   hand;
 1615         int             i;
 1616         lgrp_t          *lgrp;
 1617         pfn_t           pfn;
 1618 
 1619         pfn = btop(physaddr);
 1620         hand = lgrp_plat_pfn_to_hand(pfn);
 1621         if (hand != LGRP_NULL_HANDLE)
 1622                 for (i = 0; i <= lgrp_alloc_max; i++) {
 1623                         lgrp = lgrp_table[i];
 1624                         if (LGRP_EXISTS(lgrp) && lgrp->lgrp_plathand == hand)
 1625                                 return (lgrp);
 1626                 }
 1627         return (NULL);
 1628 }
 1629 
 1630 /*
 1631  * Return the leaf lgroup containing the given CPU
 1632  *
 1633  * The caller needs to take precautions necessary to prevent
 1634  * "cpu", and it's lpl from going away across a call to this function.
 1635  * hint: kpreempt_disable()/kpreempt_enable()
 1636  */
 1637 static lgrp_t *
 1638 lgrp_cpu_to_lgrp(cpu_t *cpu)
 1639 {
 1640         return (cpu->cpu_lpl->lpl_lgrp);
 1641 }
 1642 
 1643 /*
 1644  * Return the sum of the partition loads in an lgrp divided by
 1645  * the number of CPUs in the lgrp.  This is our best approximation
 1646  * of an 'lgroup load average' for a useful per-lgroup kstat.
 1647  */
 1648 static uint64_t
 1649 lgrp_sum_loadavgs(lgrp_t *lgrp)
 1650 {
 1651         cpu_t *cpu;
 1652         int ncpu;
 1653         uint64_t loads = 0;
 1654 
 1655         mutex_enter(&cpu_lock);
 1656 
 1657         cpu = lgrp->lgrp_cpu;
 1658         ncpu = lgrp->lgrp_cpucnt;
 1659 
 1660         if (cpu == NULL || ncpu == 0) {
 1661                 mutex_exit(&cpu_lock);
 1662                 return (0ull);
 1663         }
 1664 
 1665         do {
 1666                 loads += cpu->cpu_lpl->lpl_loadavg;
 1667                 cpu = cpu->cpu_next_lgrp;
 1668         } while (cpu != lgrp->lgrp_cpu);
 1669 
 1670         mutex_exit(&cpu_lock);
 1671 
 1672         return (loads / ncpu);
 1673 }
 1674 
 1675 void
 1676 lgrp_stat_add(lgrp_id_t lgrpid, lgrp_stat_t stat, int64_t val)
 1677 {
 1678         struct lgrp_stats *pstats;
 1679 
 1680         /*
 1681          * Verify that the caller isn't trying to add to
 1682          * a statistic for an lgroup that has gone away
 1683          */
 1684         if (lgrpid < 0 || lgrpid > lgrp_alloc_max)
 1685                 return;
 1686 
 1687         pstats = &lgrp_stats[lgrpid];
 1688         atomic_add_64((uint64_t *)LGRP_STAT_WRITE_PTR(pstats, stat), val);
 1689 }
 1690 
 1691 int64_t
 1692 lgrp_stat_read(lgrp_id_t lgrpid, lgrp_stat_t stat)
 1693 {
 1694         uint64_t val;
 1695         struct lgrp_stats *pstats;
 1696 
 1697         if (lgrpid < 0 || lgrpid > lgrp_alloc_max)
 1698                 return ((int64_t)0);
 1699 
 1700         pstats = &lgrp_stats[lgrpid];
 1701         LGRP_STAT_READ(pstats, stat, val);
 1702         return (val);
 1703 }
 1704 
 1705 /*
 1706  * Reset all kstats for lgrp specified by its lgrpid.
 1707  */
 1708 static void
 1709 lgrp_kstat_reset(lgrp_id_t lgrpid)
 1710 {
 1711         lgrp_stat_t stat;
 1712 
 1713         if (lgrpid < 0 || lgrpid > lgrp_alloc_max)
 1714                 return;
 1715 
 1716         for (stat = 0; stat < LGRP_NUM_COUNTER_STATS; stat++) {
 1717                 LGRP_STAT_RESET(&lgrp_stats[lgrpid], stat);
 1718         }
 1719 }
 1720 
 1721 /*
 1722  * Collect all per-lgrp statistics for the lgrp associated with this
 1723  * kstat, and store them in the ks_data array.
 1724  *
 1725  * The superuser can reset all the running counter statistics for an
 1726  * lgrp by writing to any of the lgrp's stats.
 1727  */
 1728 static int
 1729 lgrp_kstat_extract(kstat_t *ksp, int rw)
 1730 {
 1731         lgrp_stat_t             stat;
 1732         struct kstat_named      *ksd;
 1733         lgrp_t                  *lgrp;
 1734         lgrp_id_t               lgrpid;
 1735 
 1736         lgrp = (lgrp_t *)ksp->ks_private;
 1737 
 1738         ksd = (struct kstat_named *)ksp->ks_data;
 1739         ASSERT(ksd == (struct kstat_named *)&lgrp_kstat_data);
 1740 
 1741         lgrpid = lgrp->lgrp_id;
 1742 
 1743         if (lgrpid == LGRP_NONE) {
 1744                 /*
 1745                  * Return all zeroes as stats for freed lgrp.
 1746                  */
 1747                 for (stat = 0; stat < LGRP_NUM_COUNTER_STATS; stat++) {
 1748                         ksd[stat].value.i64 = 0;
 1749                 }
 1750                 ksd[stat + LGRP_NUM_CPUS].value.i64 = 0;
 1751                 ksd[stat + LGRP_NUM_PG_INSTALL].value.i64 = 0;
 1752                 ksd[stat + LGRP_NUM_PG_AVAIL].value.i64 = 0;
 1753                 ksd[stat + LGRP_NUM_PG_FREE].value.i64 = 0;
 1754                 ksd[stat + LGRP_LOADAVG].value.i64 = 0;
 1755         } else if (rw != KSTAT_WRITE) {
 1756                 /*
 1757                  * Handle counter stats
 1758                  */
 1759                 for (stat = 0; stat < LGRP_NUM_COUNTER_STATS; stat++) {
 1760                         ksd[stat].value.i64 = lgrp_stat_read(lgrpid, stat);
 1761                 }
 1762 
 1763                 /*
 1764                  * Handle kernel data snapshot stats
 1765                  */
 1766                 ksd[stat + LGRP_NUM_CPUS].value.i64 = lgrp->lgrp_cpucnt;
 1767                 ksd[stat + LGRP_NUM_PG_INSTALL].value.i64 =
 1768                     lgrp_mem_size(lgrpid, LGRP_MEM_SIZE_INSTALL);
 1769                 ksd[stat + LGRP_NUM_PG_AVAIL].value.i64 =
 1770                     lgrp_mem_size(lgrpid, LGRP_MEM_SIZE_AVAIL);
 1771                 ksd[stat + LGRP_NUM_PG_FREE].value.i64 =
 1772                     lgrp_mem_size(lgrpid, LGRP_MEM_SIZE_FREE);
 1773                 ksd[stat + LGRP_LOADAVG].value.i64 = lgrp_sum_loadavgs(lgrp);
 1774                 ksd[stat + LGRP_LOADAVG_SCALE].value.i64 =
 1775                     lgrp_loadavg_max_effect;
 1776         } else {
 1777                 lgrp_kstat_reset(lgrpid);
 1778         }
 1779 
 1780         return (0);
 1781 }
 1782 
 1783 int
 1784 lgrp_query_cpu(processorid_t id, lgrp_id_t *lp)
 1785 {
 1786         cpu_t   *cp;
 1787 
 1788         mutex_enter(&cpu_lock);
 1789 
 1790         if ((cp = cpu_get(id)) == NULL) {
 1791                 mutex_exit(&cpu_lock);
 1792                 return (EINVAL);
 1793         }
 1794 
 1795         if (cpu_is_offline(cp) || cpu_is_poweredoff(cp)) {
 1796                 mutex_exit(&cpu_lock);
 1797                 return (EINVAL);
 1798         }
 1799 
 1800         ASSERT(cp->cpu_lpl != NULL);
 1801 
 1802         *lp = cp->cpu_lpl->lpl_lgrpid;
 1803 
 1804         mutex_exit(&cpu_lock);
 1805 
 1806         return (0);
 1807 }
 1808 
 1809 int
 1810 lgrp_query_load(processorid_t id, lgrp_load_t *lp)
 1811 {
 1812         cpu_t *cp;
 1813 
 1814         mutex_enter(&cpu_lock);
 1815 
 1816         if ((cp = cpu_get(id)) == NULL) {
 1817                 mutex_exit(&cpu_lock);
 1818                 return (EINVAL);
 1819         }
 1820 
 1821         ASSERT(cp->cpu_lpl != NULL);
 1822 
 1823         *lp = cp->cpu_lpl->lpl_loadavg;
 1824 
 1825         mutex_exit(&cpu_lock);
 1826 
 1827         return (0);
 1828 }
 1829 
 1830 /*
 1831  * Add a resource named by lpl_leaf to rset of lpl_target
 1832  *
 1833  * This routine also adjusts ncpu and nrset if the call succeeds in adding a
 1834  * resource. It is adjusted here, as this is presently the only place that we
 1835  * can be certain a resource addition has succeeded.
 1836  *
 1837  * We keep the list of rsets sorted so that the dispatcher can quickly walk the
 1838  * list in order until it reaches a NULL.  (This list is required to be NULL
 1839  * terminated, too).  This is done so that we can mark start pos + 1, so that
 1840  * each lpl is traversed sequentially, but in a different order.  We hope this
 1841  * will improve performance a bit.  (Hopefully, less read-to-own traffic...)
 1842  */
 1843 
 1844 void
 1845 lpl_rset_add(lpl_t *lpl_target, lpl_t *lpl_leaf)
 1846 {
 1847         int             i;
 1848         int             entry_slot = 0;
 1849 
 1850         /* return if leaf is already present */
 1851         for (i = 0; i < lpl_target->lpl_nrset; i++) {
 1852                 if (lpl_target->lpl_rset[i] == lpl_leaf) {
 1853                         return;
 1854                 }
 1855 
 1856                 if (lpl_target->lpl_rset[i]->lpl_lgrpid >
 1857                     lpl_leaf->lpl_lgrpid) {
 1858                         break;
 1859                 }
 1860         }
 1861 
 1862         /* insert leaf, update counts */
 1863         entry_slot = i;
 1864         i = lpl_target->lpl_nrset++;
 1865 
 1866         /*
 1867          * Start at the end of the rset array and work backwards towards the
 1868          * slot into which the new lpl will be inserted. This effectively
 1869          * preserves the current ordering by scooting everybody over one entry,
 1870          * and placing the new entry into the space created.
 1871          */
 1872         while (i-- > entry_slot) {
 1873                 lpl_target->lpl_rset[i + 1] = lpl_target->lpl_rset[i];
 1874                 lpl_target->lpl_id2rset[lpl_target->lpl_rset[i]->lpl_lgrpid] =
 1875                     i + 1;
 1876         }
 1877 
 1878         lpl_target->lpl_rset[entry_slot] = lpl_leaf;
 1879         lpl_target->lpl_id2rset[lpl_leaf->lpl_lgrpid] = entry_slot;
 1880 
 1881         lpl_target->lpl_ncpu += lpl_leaf->lpl_ncpu;
 1882 }
 1883 
 1884 /*
 1885  * Update each of lpl_parent's children with a reference to their parent.
 1886  * The lgrp topology is used as the reference since it is fully
 1887  * consistent and correct at this point.
 1888  * This should be called after any potential change in lpl_parent's
 1889  * rset.
 1890  */
 1891 static void
 1892 lpl_child_update(lpl_t *lpl_parent, struct cpupart *cp)
 1893 {
 1894         klgrpset_t      children;
 1895         int             i;
 1896 
 1897         children = lgrp_table[lpl_parent->lpl_lgrpid]->lgrp_children;
 1898         if (klgrpset_isempty(children))
 1899                 return; /* nothing to do */
 1900 
 1901         for (i = 0; i <= lgrp_alloc_max; i++) {
 1902                 if (klgrpset_ismember(children, i)) {
 1903                         /*
 1904                          * (Re)set the parent. It may be incorrect if
 1905                          * lpl_parent is new in the topology.
 1906                          */
 1907                         cp->cp_lgrploads[i].lpl_parent = lpl_parent;
 1908                 }
 1909         }
 1910 }
 1911 
 1912 /*
 1913  * Delete resource lpl_leaf from rset of lpl_target, assuming it's there.
 1914  *
 1915  * This routine also adjusts ncpu and nrset if the call succeeds in deleting a
 1916  * resource. The values are adjusted here, as this is the only place that we can
 1917  * be certain a resource was successfully deleted.
 1918  */
 1919 void
 1920 lpl_rset_del(lpl_t *lpl_target, lpl_t *lpl_leaf)
 1921 {
 1922         int i;
 1923         lpl_t *leaf;
 1924 
 1925         if (lpl_target->lpl_nrset == 0)
 1926                 return;
 1927 
 1928         /* find leaf in intermediate node */
 1929         for (i = 0; i < lpl_target->lpl_nrset; i++) {
 1930                 if (lpl_target->lpl_rset[i] == lpl_leaf)
 1931                         break;
 1932         }
 1933 
 1934         /* return if leaf not found */
 1935         if (lpl_target->lpl_rset[i] != lpl_leaf)
 1936                 return;
 1937 
 1938         /* prune leaf, compress array */
 1939         lpl_target->lpl_rset[lpl_target->lpl_nrset--] = NULL;
 1940         lpl_target->lpl_id2rset[lpl_leaf->lpl_lgrpid] = -1;
 1941         lpl_target->lpl_ncpu--;
 1942         do {
 1943                 lpl_target->lpl_rset[i] = lpl_target->lpl_rset[i + 1];
 1944                 /*
 1945                  * Update the lgrp id <=> rset mapping
 1946                  */
 1947                 if ((leaf = lpl_target->lpl_rset[i]) != NULL) {
 1948                         lpl_target->lpl_id2rset[leaf->lpl_lgrpid] = i;
 1949                 }
 1950         } while (i++ < lpl_target->lpl_nrset);
 1951 }
 1952 
 1953 /*
 1954  * Check to see if the resource set of the target lpl contains the
 1955  * supplied leaf lpl.  This returns 1 if the lpl is found, 0 if it is not.
 1956  */
 1957 
 1958 int
 1959 lpl_rset_contains(lpl_t *lpl_target, lpl_t *lpl_leaf)
 1960 {
 1961         int i;
 1962 
 1963         for (i = 0; i < lpl_target->lpl_nrset; i++) {
 1964                 if (lpl_target->lpl_rset[i] == lpl_leaf)
 1965                         return (1);
 1966         }
 1967 
 1968         return (0);
 1969 }
 1970 
 1971 /*
 1972  * Called when we change cpu lpl membership.  This increments or decrements the
 1973  * per-cpu counter in every lpl in which our leaf appears.
 1974  */
 1975 void
 1976 lpl_cpu_adjcnt(lpl_act_t act, cpu_t *cp)
 1977 {
 1978         cpupart_t       *cpupart;
 1979         lgrp_t          *lgrp_leaf;
 1980         lgrp_t          *lgrp_cur;
 1981         lpl_t           *lpl_leaf;
 1982         lpl_t           *lpl_cur;
 1983         int             i;
 1984 
 1985         ASSERT(act == LPL_DECREMENT || act == LPL_INCREMENT);
 1986 
 1987         cpupart = cp->cpu_part;
 1988         lpl_leaf = cp->cpu_lpl;
 1989         lgrp_leaf = lgrp_table[lpl_leaf->lpl_lgrpid];
 1990 
 1991         for (i = 0; i <= lgrp_alloc_max; i++) {
 1992                 lgrp_cur = lgrp_table[i];
 1993 
 1994                 /*
 1995                  * Don't adjust if the lgrp isn't there, if we're the leaf lpl
 1996                  * for the cpu in question, or if the current lgrp and leaf
 1997                  * don't share the same resources.
 1998                  */
 1999 
 2000                 if (!LGRP_EXISTS(lgrp_cur) || (lgrp_cur == lgrp_leaf) ||
 2001                     !klgrpset_intersects(lgrp_leaf->lgrp_set[LGRP_RSRC_CPU],
 2002                     lgrp_cur->lgrp_set[LGRP_RSRC_CPU]))
 2003                         continue;
 2004 
 2005 
 2006                 lpl_cur = &cpupart->cp_lgrploads[lgrp_cur->lgrp_id];
 2007 
 2008                 if (lpl_cur->lpl_nrset > 0) {
 2009                         if (act == LPL_INCREMENT) {
 2010                                 lpl_cur->lpl_ncpu++;
 2011                         } else if (act == LPL_DECREMENT) {
 2012                                 lpl_cur->lpl_ncpu--;
 2013                         }
 2014                 }
 2015         }
 2016 }
 2017 
 2018 /*
 2019  * Initialize lpl with given resources and specified lgrp
 2020  */
 2021 void
 2022 lpl_init(lpl_t *lpl, lpl_t *lpl_leaf, lgrp_t *lgrp)
 2023 {
 2024         lpl->lpl_lgrpid = lgrp->lgrp_id;
 2025         lpl->lpl_loadavg = 0;
 2026         if (lpl == lpl_leaf)
 2027                 lpl->lpl_ncpu = 1;
 2028         else
 2029                 lpl->lpl_ncpu = lpl_leaf->lpl_ncpu;
 2030         lpl->lpl_nrset = 1;
 2031         lpl->lpl_rset[0] = lpl_leaf;
 2032         lpl->lpl_id2rset[lpl_leaf->lpl_lgrpid] = 0;
 2033         lpl->lpl_lgrp = lgrp;
 2034         lpl->lpl_parent = NULL; /* set by lpl_leaf_insert() */
 2035         lpl->lpl_cpus = NULL; /* set by lgrp_part_add_cpu() */
 2036 }
 2037 
 2038 /*
 2039  * Clear an unused lpl
 2040  */
 2041 void
 2042 lpl_clear(lpl_t *lpl)
 2043 {
 2044         /*
 2045          * Clear out all fields in the lpl except:
 2046          *    lpl_lgrpid - to facilitate debugging
 2047          *    lpl_rset, lpl_rset_sz, lpl_id2rset - rset array references / size
 2048          *
 2049          * Note that the lpl's rset and id2rset mapping are cleared as well.
 2050          */
 2051         lpl->lpl_loadavg = 0;
 2052         lpl->lpl_ncpu = 0;
 2053         lpl->lpl_lgrp = NULL;
 2054         lpl->lpl_parent = NULL;
 2055         lpl->lpl_cpus = NULL;
 2056         lpl->lpl_nrset = 0;
 2057         lpl->lpl_homed_time = 0;
 2058         bzero(lpl->lpl_rset, sizeof (lpl->lpl_rset[0]) * lpl->lpl_rset_sz);
 2059         bzero(lpl->lpl_id2rset,
 2060             sizeof (lpl->lpl_id2rset[0]) * lpl->lpl_rset_sz);
 2061 }
 2062 
 2063 /*
 2064  * Given a CPU-partition, verify that the lpl topology in the CPU-partition
 2065  * is in sync with the lgroup toplogy in the system.  The lpl topology may not
 2066  * make full use of all of the lgroup topology, but this checks to make sure
 2067  * that for the parts that it does use, it has correctly understood the
 2068  * relationships that exist. This function returns
 2069  * 0 if the topology is correct, and a non-zero error code, for non-debug
 2070  * kernels if incorrect.  Asserts are spread throughout the code to aid in
 2071  * debugging on a DEBUG kernel.
 2072  */
 2073 int
 2074 lpl_topo_verify(cpupart_t *cpupart)
 2075 {
 2076         lgrp_t          *lgrp;
 2077         lpl_t           *lpl;
 2078         klgrpset_t      rset;
 2079         klgrpset_t      cset;
 2080         cpu_t           *cpu;
 2081         cpu_t           *cp_start;
 2082         int             i;
 2083         int             j;
 2084         int             sum;
 2085 
 2086         /* topology can't be incorrect if it doesn't exist */
 2087         if (!lgrp_topo_initialized || !lgrp_initialized)
 2088                 return (LPL_TOPO_CORRECT);
 2089 
 2090         ASSERT(cpupart != NULL);
 2091 
 2092         for (i = 0; i <= lgrp_alloc_max; i++) {
 2093                 lgrp = lgrp_table[i];
 2094                 lpl = NULL;
 2095                 /* make sure lpls are allocated */
 2096                 ASSERT(cpupart->cp_lgrploads);
 2097                 if (!cpupart->cp_lgrploads)
 2098                         return (LPL_TOPO_PART_HAS_NO_LPL);
 2099 
 2100                 lpl = &cpupart->cp_lgrploads[i];
 2101                 /* make sure our index is good */
 2102                 ASSERT(i < cpupart->cp_nlgrploads);
 2103 
 2104                 /* if lgroup doesn't exist, make sure lpl is empty */
 2105                 if (!LGRP_EXISTS(lgrp)) {
 2106                         ASSERT(lpl->lpl_ncpu == 0);
 2107                         if (lpl->lpl_ncpu > 0) {
 2108                                 return (LPL_TOPO_CPUS_NOT_EMPTY);
 2109                         } else {
 2110                                 continue;
 2111                         }
 2112                 }
 2113 
 2114                 /* verify that lgroup and lpl are identically numbered */
 2115                 ASSERT(lgrp->lgrp_id == lpl->lpl_lgrpid);
 2116 
 2117                 /* if lgroup isn't in our partition, make sure lpl is empty */
 2118                 if (!klgrpset_intersects(lgrp->lgrp_leaves,
 2119                     cpupart->cp_lgrpset)) {
 2120                         ASSERT(lpl->lpl_ncpu == 0);
 2121                         if (lpl->lpl_ncpu > 0) {
 2122                                 return (LPL_TOPO_CPUS_NOT_EMPTY);
 2123                         }
 2124                         /*
 2125                          * lpl is empty, and lgroup isn't in partition.  verify
 2126                          * that lpl doesn't show up in anyone else's rsets (in
 2127                          * this partition, anyway)
 2128                          */
 2129                         for (j = 0; j < cpupart->cp_nlgrploads; j++) {
 2130                                 lpl_t *i_lpl; /* lpl we're iterating over */
 2131 
 2132                                 i_lpl = &cpupart->cp_lgrploads[j];
 2133 
 2134                                 ASSERT(!lpl_rset_contains(i_lpl, lpl));
 2135                                 if (lpl_rset_contains(i_lpl, lpl)) {
 2136                                         return (LPL_TOPO_LPL_ORPHANED);
 2137                                 }
 2138                         }
 2139                         /* lgroup is empty, and everything is ok. continue */
 2140                         continue;
 2141                 }
 2142 
 2143 
 2144                 /* lgroup is in this partition, now check it against lpl */
 2145 
 2146                 /* do both have matching lgrps? */
 2147                 ASSERT(lgrp == lpl->lpl_lgrp);
 2148                 if (lgrp != lpl->lpl_lgrp) {
 2149                         return (LPL_TOPO_LGRP_MISMATCH);
 2150                 }
 2151 
 2152                 /* do the parent lgroups exist and do they match? */
 2153                 if (lgrp->lgrp_parent) {
 2154                         ASSERT(lpl->lpl_parent);
 2155                         ASSERT(lgrp->lgrp_parent->lgrp_id ==
 2156                             lpl->lpl_parent->lpl_lgrpid);
 2157 
 2158                         if (!lpl->lpl_parent) {
 2159                                 return (LPL_TOPO_MISSING_PARENT);
 2160                         } else if (lgrp->lgrp_parent->lgrp_id !=
 2161                             lpl->lpl_parent->lpl_lgrpid) {
 2162                                 return (LPL_TOPO_PARENT_MISMATCH);
 2163                         }
 2164                 }
 2165 
 2166                 /* only leaf lgroups keep a cpucnt, only check leaves */
 2167                 if ((lpl->lpl_nrset == 1) && (lpl == lpl->lpl_rset[0])) {
 2168 
 2169                         /* verify that lgrp is also a leaf */
 2170                         ASSERT((lgrp->lgrp_childcnt == 0) &&
 2171                             (klgrpset_ismember(lgrp->lgrp_leaves,
 2172                             lpl->lpl_lgrpid)));
 2173 
 2174                         if ((lgrp->lgrp_childcnt > 0) ||
 2175                             (!klgrpset_ismember(lgrp->lgrp_leaves,
 2176                             lpl->lpl_lgrpid))) {
 2177                                 return (LPL_TOPO_LGRP_NOT_LEAF);
 2178                         }
 2179 
 2180                         ASSERT((lgrp->lgrp_cpucnt >= lpl->lpl_ncpu) &&
 2181                             (lpl->lpl_ncpu > 0));
 2182                         if ((lgrp->lgrp_cpucnt < lpl->lpl_ncpu) ||
 2183                             (lpl->lpl_ncpu <= 0)) {
 2184                                 return (LPL_TOPO_BAD_CPUCNT);
 2185                         }
 2186 
 2187                         /*
 2188                          * Check that lpl_ncpu also matches the number of
 2189                          * cpus in the lpl's linked list.  This only exists in
 2190                          * leaves, but they should always match.
 2191                          */
 2192                         j = 0;
 2193                         cpu = cp_start = lpl->lpl_cpus;
 2194                         while (cpu != NULL) {
 2195                                 j++;
 2196 
 2197                                 /* check to make sure cpu's lpl is leaf lpl */
 2198                                 ASSERT(cpu->cpu_lpl == lpl);
 2199                                 if (cpu->cpu_lpl != lpl) {
 2200                                         return (LPL_TOPO_CPU_HAS_BAD_LPL);
 2201                                 }
 2202 
 2203                                 /* check next cpu */
 2204                                 if ((cpu = cpu->cpu_next_lpl) != cp_start) {
 2205                                         continue;
 2206                                 } else {
 2207                                         cpu = NULL;
 2208                                 }
 2209                         }
 2210 
 2211                         ASSERT(j == lpl->lpl_ncpu);
 2212                         if (j != lpl->lpl_ncpu) {
 2213                                 return (LPL_TOPO_LPL_BAD_NCPU);
 2214                         }
 2215 
 2216                         /*
 2217                          * Also, check that leaf lpl is contained in all
 2218                          * intermediate lpls that name the leaf as a descendant
 2219                          */
 2220                         for (j = 0; j <= lgrp_alloc_max; j++) {
 2221                                 klgrpset_t intersect;
 2222                                 lgrp_t *lgrp_cand;
 2223                                 lpl_t *lpl_cand;
 2224 
 2225                                 lgrp_cand = lgrp_table[j];
 2226                                 intersect = klgrpset_intersects(
 2227                                     lgrp_cand->lgrp_set[LGRP_RSRC_CPU],
 2228                                     cpupart->cp_lgrpset);
 2229 
 2230                                 if (!LGRP_EXISTS(lgrp_cand) ||
 2231                                     !klgrpset_intersects(lgrp_cand->lgrp_leaves,
 2232                                     cpupart->cp_lgrpset) ||
 2233                                     (intersect == 0))
 2234                                         continue;
 2235 
 2236                                 lpl_cand =
 2237                                     &cpupart->cp_lgrploads[lgrp_cand->lgrp_id];
 2238 
 2239                                 if (klgrpset_ismember(intersect,
 2240                                     lgrp->lgrp_id)) {
 2241                                         ASSERT(lpl_rset_contains(lpl_cand,
 2242                                             lpl));
 2243 
 2244                                         if (!lpl_rset_contains(lpl_cand, lpl)) {
 2245                                                 return (LPL_TOPO_RSET_MSSNG_LF);
 2246                                         }
 2247                                 }
 2248                         }
 2249 
 2250                 } else { /* non-leaf specific checks */
 2251 
 2252                         /*
 2253                          * Non-leaf lpls should have lpl_cpus == NULL
 2254                          * verify that this is so
 2255                          */
 2256                         ASSERT(lpl->lpl_cpus == NULL);
 2257                         if (lpl->lpl_cpus != NULL) {
 2258                                 return (LPL_TOPO_NONLEAF_HAS_CPUS);
 2259                         }
 2260 
 2261                         /*
 2262                          * verify that the sum of the cpus in the leaf resources
 2263                          * is equal to the total ncpu in the intermediate
 2264                          */
 2265                         for (j = sum = 0; j < lpl->lpl_nrset; j++) {
 2266                                 sum += lpl->lpl_rset[j]->lpl_ncpu;
 2267                         }
 2268 
 2269                         ASSERT(sum == lpl->lpl_ncpu);
 2270                         if (sum != lpl->lpl_ncpu) {
 2271                                 return (LPL_TOPO_LPL_BAD_NCPU);
 2272                         }
 2273                 }
 2274 
 2275                 /*
 2276                  * Check the rset of the lpl in question.  Make sure that each
 2277                  * rset contains a subset of the resources in
 2278                  * lgrp_set[LGRP_RSRC_CPU] and in cp_lgrpset.  This also makes
 2279                  * sure that each rset doesn't include resources that are
 2280                  * outside of that set.  (Which would be resources somehow not
 2281                  * accounted for).
 2282                  */
 2283                 klgrpset_clear(rset);
 2284                 for (j = 0; j < lpl->lpl_nrset; j++) {
 2285                         klgrpset_add(rset, lpl->lpl_rset[j]->lpl_lgrpid);
 2286                 }
 2287                 klgrpset_copy(cset, rset);
 2288                 /* make sure lpl rset matches lgrp rset */
 2289                 klgrpset_diff(rset, lgrp->lgrp_set[LGRP_RSRC_CPU]);
 2290                 /* make sure rset is contained with in partition, too */
 2291                 klgrpset_diff(cset, cpupart->cp_lgrpset);
 2292 
 2293                 ASSERT(klgrpset_isempty(rset) && klgrpset_isempty(cset));
 2294                 if (!klgrpset_isempty(rset) || !klgrpset_isempty(cset)) {
 2295                         return (LPL_TOPO_RSET_MISMATCH);
 2296                 }
 2297 
 2298                 /*
 2299                  * check to make sure lpl_nrset matches the number of rsets
 2300                  * contained in the lpl
 2301                  */
 2302                 for (j = 0; j < lpl->lpl_nrset; j++) {
 2303                         if (lpl->lpl_rset[j] == NULL)
 2304                                 break;
 2305                 }
 2306 
 2307                 ASSERT(j == lpl->lpl_nrset);
 2308                 if (j != lpl->lpl_nrset) {
 2309                         return (LPL_TOPO_BAD_RSETCNT);
 2310                 }
 2311 
 2312         }
 2313         return (LPL_TOPO_CORRECT);
 2314 }
 2315 
 2316 /*
 2317  * Flatten lpl topology to given number of levels.  This is presently only
 2318  * implemented for a flatten to 2 levels, which will prune out the intermediates
 2319  * and home the leaf lpls to the root lpl.
 2320  */
 2321 int
 2322 lpl_topo_flatten(int levels)
 2323 {
 2324         int             i;
 2325         uint_t          sum;
 2326         lgrp_t          *lgrp_cur;
 2327         lpl_t           *lpl_cur;
 2328         lpl_t           *lpl_root;
 2329         cpupart_t       *cp;
 2330 
 2331         if (levels != 2)
 2332                 return (0);
 2333 
 2334         /* called w/ cpus paused - grab no locks! */
 2335         ASSERT(MUTEX_HELD(&cpu_lock) || curthread->t_preempt > 0 ||
 2336             !lgrp_initialized);
 2337 
 2338         cp = cp_list_head;
 2339         do {
 2340                 lpl_root = &cp->cp_lgrploads[lgrp_root->lgrp_id];
 2341                 ASSERT(LGRP_EXISTS(lgrp_root) && (lpl_root->lpl_ncpu > 0));
 2342 
 2343                 for (i = 0; i <= lgrp_alloc_max; i++) {
 2344                         lgrp_cur = lgrp_table[i];
 2345                         lpl_cur = &cp->cp_lgrploads[i];
 2346 
 2347                         if ((lgrp_cur == lgrp_root) ||
 2348                             (!LGRP_EXISTS(lgrp_cur) &&
 2349                             (lpl_cur->lpl_ncpu == 0)))
 2350                                 continue;
 2351 
 2352                         if (!LGRP_EXISTS(lgrp_cur) && (lpl_cur->lpl_ncpu > 0)) {
 2353                                 /*
 2354                                  * this should be a deleted intermediate, so
 2355                                  * clear it
 2356                                  */
 2357                                 lpl_clear(lpl_cur);
 2358                         } else if ((lpl_cur->lpl_nrset == 1) &&
 2359                             (lpl_cur->lpl_rset[0] == lpl_cur) &&
 2360                             ((lpl_cur->lpl_parent->lpl_ncpu == 0) ||
 2361                             (!LGRP_EXISTS(lpl_cur->lpl_parent->lpl_lgrp)))) {
 2362                                 /*
 2363                                  * this is a leaf whose parent was deleted, or
 2364                                  * whose parent had their lgrp deleted.  (And
 2365                                  * whose parent will soon be deleted).  Point
 2366                                  * this guy back to the root lpl.
 2367                                  */
 2368                                 lpl_cur->lpl_parent = lpl_root;
 2369                                 lpl_rset_add(lpl_root, lpl_cur);
 2370                         }
 2371 
 2372                 }
 2373 
 2374                 /*
 2375                  * Now that we're done, make sure the count on the root lpl is
 2376                  * correct, and update the hints of the children for the sake of
 2377                  * thoroughness
 2378                  */
 2379                 for (i = sum = 0; i < lpl_root->lpl_nrset; i++) {
 2380                         sum += lpl_root->lpl_rset[i]->lpl_ncpu;
 2381                 }
 2382                 lpl_root->lpl_ncpu = sum;
 2383                 lpl_child_update(lpl_root, cp);
 2384 
 2385                 cp = cp->cp_next;
 2386         } while (cp != cp_list_head);
 2387 
 2388         return (levels);
 2389 }
 2390 
 2391 /*
 2392  * Insert a lpl into the resource hierarchy and create any additional lpls that
 2393  * are necessary to represent the varying states of locality for the cpu
 2394  * resoruces newly added to the partition.
 2395  *
 2396  * This routine is clever enough that it can correctly add resources from the
 2397  * new leaf into both direct and indirect resource sets in the hierarchy.  (Ie,
 2398  * those for which the lpl is a leaf as opposed to simply a named equally local
 2399  * resource).  The one special case that needs additional processing is when a
 2400  * new intermediate lpl is introduced.  Since the main loop only traverses
 2401  * looking to add the leaf resource where it does not yet exist, additional work
 2402  * is necessary to add other leaf resources that may need to exist in the newly
 2403  * created intermediate.  This is performed by the second inner loop, and is
 2404  * only done when the check for more than one overlapping resource succeeds.
 2405  */
 2406 
 2407 void
 2408 lpl_leaf_insert(lpl_t *lpl_leaf, cpupart_t *cpupart)
 2409 {
 2410         int             i;
 2411         int             j;
 2412         int             rset_num_intersect;
 2413         lgrp_t          *lgrp_cur;
 2414         lpl_t           *lpl_cur;
 2415         lpl_t           *lpl_parent;
 2416         lgrp_id_t       parent_id;
 2417         klgrpset_t      rset_intersect; /* resources in cpupart and lgrp */
 2418 
 2419         for (i = 0; i <= lgrp_alloc_max; i++) {
 2420                 lgrp_cur = lgrp_table[i];
 2421 
 2422                 /*
 2423                  * Don't insert if the lgrp isn't there, if the leaf isn't
 2424                  * contained within the current lgrp, or if the current lgrp has
 2425                  * no leaves in this partition
 2426                  */
 2427 
 2428                 if (!LGRP_EXISTS(lgrp_cur) ||
 2429                     !klgrpset_ismember(lgrp_cur->lgrp_set[LGRP_RSRC_CPU],
 2430                     lpl_leaf->lpl_lgrpid) ||
 2431                     !klgrpset_intersects(lgrp_cur->lgrp_leaves,
 2432                     cpupart->cp_lgrpset))
 2433                         continue;
 2434 
 2435                 lpl_cur = &cpupart->cp_lgrploads[lgrp_cur->lgrp_id];
 2436                 if (lgrp_cur->lgrp_parent != NULL) {
 2437                         /* if lgrp has a parent, assign it properly */
 2438                         parent_id = lgrp_cur->lgrp_parent->lgrp_id;
 2439                         lpl_parent = &cpupart->cp_lgrploads[parent_id];
 2440                 } else {
 2441                         /* if not, make sure parent ptr gets set to null */
 2442                         lpl_parent = NULL;
 2443                 }
 2444 
 2445                 if (lpl_cur == lpl_leaf) {
 2446                         /*
 2447                          * Almost all leaf state was initialized elsewhere.  The
 2448                          * only thing left to do is to set the parent.
 2449                          */
 2450                         lpl_cur->lpl_parent = lpl_parent;
 2451                         continue;
 2452                 }
 2453 
 2454                 lpl_clear(lpl_cur);
 2455                 lpl_init(lpl_cur, lpl_leaf, lgrp_cur);
 2456 
 2457                 lpl_cur->lpl_parent = lpl_parent;
 2458 
 2459                 /* does new lpl need to be populated with other resources? */
 2460                 rset_intersect =
 2461                     klgrpset_intersects(lgrp_cur->lgrp_set[LGRP_RSRC_CPU],
 2462                     cpupart->cp_lgrpset);
 2463                 klgrpset_nlgrps(rset_intersect, rset_num_intersect);
 2464 
 2465                 if (rset_num_intersect > 1) {
 2466                         /*
 2467                          * If so, figure out what lpls have resources that
 2468                          * intersect this one, and add them.
 2469                          */
 2470                         for (j = 0; j <= lgrp_alloc_max; j++) {
 2471                                 lgrp_t  *lgrp_cand;     /* candidate lgrp */
 2472                                 lpl_t   *lpl_cand;      /* candidate lpl */
 2473 
 2474                                 lgrp_cand = lgrp_table[j];
 2475                                 if (!LGRP_EXISTS(lgrp_cand) ||
 2476                                     !klgrpset_ismember(rset_intersect,
 2477                                     lgrp_cand->lgrp_id))
 2478                                         continue;
 2479                                 lpl_cand =
 2480                                     &cpupart->cp_lgrploads[lgrp_cand->lgrp_id];
 2481                                 lpl_rset_add(lpl_cur, lpl_cand);
 2482                         }
 2483                 }
 2484                 /*
 2485                  * This lpl's rset has changed. Update the hint in it's
 2486                  * children.
 2487                  */
 2488                 lpl_child_update(lpl_cur, cpupart);
 2489         }
 2490 }
 2491 
 2492 /*
 2493  * remove a lpl from the hierarchy of resources, clearing its state when
 2494  * finished.  If the lpls at the intermediate levels of the hierarchy have no
 2495  * remaining resources, or no longer name a leaf resource in the cpu-partition,
 2496  * delete them as well.
 2497  */
 2498 
 2499 void
 2500 lpl_leaf_remove(lpl_t *lpl_leaf, cpupart_t *cpupart)
 2501 {
 2502         int             i;
 2503         lgrp_t          *lgrp_cur;
 2504         lpl_t           *lpl_cur;
 2505         klgrpset_t      leaf_intersect; /* intersection of leaves */
 2506 
 2507         for (i = 0; i <= lgrp_alloc_max; i++) {
 2508                 lgrp_cur = lgrp_table[i];
 2509 
 2510                 /*
 2511                  * Don't attempt to remove from lgrps that aren't there, that
 2512                  * don't contain our leaf, or from the leaf itself. (We do that
 2513                  * later)
 2514                  */
 2515 
 2516                 if (!LGRP_EXISTS(lgrp_cur))
 2517                         continue;
 2518 
 2519                 lpl_cur = &cpupart->cp_lgrploads[lgrp_cur->lgrp_id];
 2520 
 2521                 if (!klgrpset_ismember(lgrp_cur->lgrp_set[LGRP_RSRC_CPU],
 2522                     lpl_leaf->lpl_lgrpid) ||
 2523                     (lpl_cur == lpl_leaf)) {
 2524                         continue;
 2525                 }
 2526 
 2527                 /*
 2528                  * This is a slightly sleazy simplification in that we have
 2529                  * already marked the cp_lgrpset as no longer containing the
 2530                  * leaf we've deleted.  Any lpls that pass the above checks
 2531                  * based upon lgrp membership but not necessarily cpu-part
 2532                  * membership also get cleared by the checks below.  Currently
 2533                  * this is harmless, as the lpls should be empty anyway.
 2534                  *
 2535                  * In particular, we want to preserve lpls that have additional
 2536                  * leaf resources, even though we don't yet have a processor
 2537                  * architecture that represents resources this way.
 2538                  */
 2539 
 2540                 leaf_intersect = klgrpset_intersects(lgrp_cur->lgrp_leaves,
 2541                     cpupart->cp_lgrpset);
 2542 
 2543                 lpl_rset_del(lpl_cur, lpl_leaf);
 2544                 if ((lpl_cur->lpl_nrset == 0) || (!leaf_intersect)) {
 2545                         lpl_clear(lpl_cur);
 2546                 } else {
 2547                         /*
 2548                          * Update this lpl's children
 2549                          */
 2550                         lpl_child_update(lpl_cur, cpupart);
 2551                 }
 2552         }
 2553         lpl_clear(lpl_leaf);
 2554 }
 2555 
 2556 /*
 2557  * add a cpu to a partition in terms of lgrp load avg bookeeping
 2558  *
 2559  * The lpl (cpu partition load average information) is now arranged in a
 2560  * hierarchical fashion whereby resources that are closest, ie. most local, to
 2561  * the cpu in question are considered to be leaves in a tree of resources.
 2562  * There are two general cases for cpu additon:
 2563  *
 2564  * 1. A lpl structure that contains resources already in the hierarchy tree.
 2565  * In this case, all of the associated lpl relationships have been defined, and
 2566  * all that is necessary is that we link the new cpu into the per-lpl list of
 2567  * cpus, and increment the ncpu count of all places where this cpu resource will
 2568  * be accounted for.  lpl_cpu_adjcnt updates the cpu count, and the cpu pointer
 2569  * pushing is accomplished by this routine.
 2570  *
 2571  * 2. The lpl to contain the resources in this cpu-partition for this lgrp does
 2572  * not exist yet.  In this case, it is necessary to build the leaf lpl, and
 2573  * construct the hierarchy of state necessary to name it's more distant
 2574  * resources, if they should exist.  The leaf structure is initialized by this
 2575  * routine, as is the cpu-partition state for the lgrp membership.  This routine
 2576  * also calls lpl_leaf_insert() which inserts the named lpl into the hierarchy
 2577  * and builds all of the "ancestoral" state necessary to identify resources at
 2578  * differing levels of locality.
 2579  */
 2580 void
 2581 lgrp_part_add_cpu(cpu_t *cp, lgrp_id_t lgrpid)
 2582 {
 2583         cpupart_t       *cpupart;
 2584         lgrp_t          *lgrp_leaf;
 2585         lpl_t           *lpl_leaf;
 2586 
 2587         /* called sometimes w/ cpus paused - grab no locks */
 2588         ASSERT(MUTEX_HELD(&cpu_lock) || !lgrp_initialized);
 2589 
 2590         cpupart = cp->cpu_part;
 2591         lgrp_leaf = lgrp_table[lgrpid];
 2592 
 2593         /* don't add non-existent lgrp */
 2594         ASSERT(LGRP_EXISTS(lgrp_leaf));
 2595         lpl_leaf = &cpupart->cp_lgrploads[lgrpid];
 2596         cp->cpu_lpl = lpl_leaf;
 2597 
 2598         /* only leaf lpls contain cpus */
 2599 
 2600         if (lpl_leaf->lpl_ncpu++ == 0) {
 2601                 lpl_init(lpl_leaf, lpl_leaf, lgrp_leaf);
 2602                 klgrpset_add(cpupart->cp_lgrpset, lgrpid);
 2603                 lpl_leaf_insert(lpl_leaf, cpupart);
 2604         } else {
 2605                 /*
 2606                  * the lpl should already exist in the parent, so just update
 2607                  * the count of available CPUs
 2608                  */
 2609                 lpl_cpu_adjcnt(LPL_INCREMENT, cp);
 2610         }
 2611 
 2612         /* link cpu into list of cpus in lpl */
 2613 
 2614         if (lpl_leaf->lpl_cpus) {
 2615                 cp->cpu_next_lpl = lpl_leaf->lpl_cpus;
 2616                 cp->cpu_prev_lpl = lpl_leaf->lpl_cpus->cpu_prev_lpl;
 2617                 lpl_leaf->lpl_cpus->cpu_prev_lpl->cpu_next_lpl = cp;
 2618                 lpl_leaf->lpl_cpus->cpu_prev_lpl = cp;
 2619         } else {
 2620                 /*
 2621                  * We increment ncpu immediately after we create a new leaf
 2622                  * lpl, so assert that ncpu == 1 for the case where we don't
 2623                  * have any cpu pointers yet.
 2624                  */
 2625                 ASSERT(lpl_leaf->lpl_ncpu == 1);
 2626                 lpl_leaf->lpl_cpus = cp->cpu_next_lpl = cp->cpu_prev_lpl = cp;
 2627         }
 2628 
 2629 }
 2630 
 2631 
 2632 /*
 2633  * remove a cpu from a partition in terms of lgrp load avg bookeeping
 2634  *
 2635  * The lpl (cpu partition load average information) is now arranged in a
 2636  * hierarchical fashion whereby resources that are closest, ie. most local, to
 2637  * the cpu in question are considered to be leaves in a tree of resources.
 2638  * There are two removal cases in question:
 2639  *
 2640  * 1. Removal of the resource in the leaf leaves other resources remaining in
 2641  * that leaf.  (Another cpu still exists at this level of locality).  In this
 2642  * case, the count of available cpus is decremented in all assocated lpls by
 2643  * calling lpl_adj_cpucnt(), and the pointer to the removed cpu is pruned
 2644  * from the per-cpu lpl list.
 2645  *
 2646  * 2. Removal of the resource results in the lpl containing no resources.  (It's
 2647  * empty)  In this case, all of what has occurred for the first step must take
 2648  * place; however, additionally we must remove the lpl structure itself, prune
 2649  * out any stranded lpls that do not directly name a leaf resource, and mark the
 2650  * cpu partition in question as no longer containing resources from the lgrp of
 2651  * the lpl that has been delted.  Cpu-partition changes are handled by this
 2652  * method, but the lpl_leaf_remove function deals with the details of pruning
 2653  * out the empty lpl and any of its orphaned direct ancestors.
 2654  */
 2655 void
 2656 lgrp_part_del_cpu(cpu_t *cp)
 2657 {
 2658         lpl_t           *lpl;
 2659         lpl_t           *leaf_lpl;
 2660         lgrp_t          *lgrp_leaf;
 2661 
 2662         /* called sometimes w/ cpus paused - grab no locks */
 2663 
 2664         ASSERT(MUTEX_HELD(&cpu_lock) || !lgrp_initialized);
 2665 
 2666         lpl = leaf_lpl = cp->cpu_lpl;
 2667         lgrp_leaf = leaf_lpl->lpl_lgrp;
 2668 
 2669         /* don't delete a leaf that isn't there */
 2670         ASSERT(LGRP_EXISTS(lgrp_leaf));
 2671 
 2672         /* no double-deletes */
 2673         ASSERT(lpl->lpl_ncpu);
 2674         if (--lpl->lpl_ncpu == 0) {
 2675                 /*
 2676                  * This was the last cpu in this lgroup for this partition,
 2677                  * clear its bit in the partition's lgroup bitmask
 2678                  */
 2679                 klgrpset_del(cp->cpu_part->cp_lgrpset, lpl->lpl_lgrpid);
 2680 
 2681                 /* eliminate remaning lpl link pointers in cpu, lpl */
 2682                 lpl->lpl_cpus = cp->cpu_next_lpl = cp->cpu_prev_lpl = NULL;
 2683 
 2684                 lpl_leaf_remove(leaf_lpl, cp->cpu_part);
 2685         } else {
 2686 
 2687                 /* unlink cpu from lists of cpus in lpl */
 2688                 cp->cpu_prev_lpl->cpu_next_lpl = cp->cpu_next_lpl;
 2689                 cp->cpu_next_lpl->cpu_prev_lpl = cp->cpu_prev_lpl;
 2690                 if (lpl->lpl_cpus == cp) {
 2691                         lpl->lpl_cpus = cp->cpu_next_lpl;
 2692                 }
 2693 
 2694                 /*
 2695                  * Update the cpu count in the lpls associated with parent
 2696                  * lgroups.
 2697                  */
 2698                 lpl_cpu_adjcnt(LPL_DECREMENT, cp);
 2699 
 2700         }
 2701         /* clear cpu's lpl ptr when we're all done */
 2702         cp->cpu_lpl = NULL;
 2703 }
 2704 
 2705 /*
 2706  * Recompute load average for the specified partition/lgrp fragment.
 2707  *
 2708  * We rely on the fact that this routine is called from the clock thread
 2709  * at a point before the clock thread can block (i.e. before its first
 2710  * lock request).  Since the clock thread can not be preempted (since it
 2711  * runs at highest priority), we know that cpu partitions can not change
 2712  * (since doing so would require either the repartition requester or the
 2713  * cpu_pause thread to run on this cpu), so we can update the cpu's load
 2714  * without grabbing cpu_lock.
 2715  */
 2716 void
 2717 lgrp_loadavg(lpl_t *lpl, uint_t nrcpus, int ageflag)
 2718 {
 2719         uint_t          ncpu;
 2720         int64_t         old, new, f;
 2721 
 2722         /*
 2723          * 1 - exp(-1/(20 * ncpu)) << 13 = 400 for 1 cpu...
 2724          */
 2725         static short expval[] = {
 2726             0, 3196, 1618, 1083,
 2727             814, 652, 543, 466,
 2728             408, 363, 326, 297,
 2729             272, 251, 233, 218,
 2730             204, 192, 181, 172,
 2731             163, 155, 148, 142,
 2732             136, 130, 125, 121,
 2733             116, 112, 109, 105
 2734         };
 2735 
 2736         /* ASSERT (called from clock level) */
 2737 
 2738         if ((lpl == NULL) ||    /* we're booting - this is easiest for now */
 2739             ((ncpu = lpl->lpl_ncpu) == 0)) {
 2740                 return;
 2741         }
 2742 
 2743         for (;;) {
 2744 
 2745                 if (ncpu >= sizeof (expval) / sizeof (expval[0]))
 2746                         f = expval[1]/ncpu; /* good approx. for large ncpu */
 2747                 else
 2748                         f = expval[ncpu];
 2749 
 2750                 /*
 2751                  * Modify the load average atomically to avoid losing
 2752                  * anticipatory load updates (see lgrp_move_thread()).
 2753                  */
 2754                 if (ageflag) {
 2755                         /*
 2756                          * We're supposed to both update and age the load.
 2757                          * This happens 10 times/sec. per cpu.  We do a
 2758                          * little hoop-jumping to avoid integer overflow.
 2759                          */
 2760                         int64_t         q, r;
 2761 
 2762                         do {
 2763                                 old = new = lpl->lpl_loadavg;
 2764                                 q = (old  >> 16) << 7;
 2765                                 r = (old  & 0xffff) << 7;
 2766                                 new += ((long long)(nrcpus - q) * f -
 2767                                     ((r * f) >> 16)) >> 7;
 2768 
 2769                                 /*
 2770                                  * Check for overflow
 2771                                  */
 2772                                 if (new > LGRP_LOADAVG_MAX)
 2773                                         new = LGRP_LOADAVG_MAX;
 2774                                 else if (new < 0)
 2775                                         new = 0;
 2776                         } while (cas32((lgrp_load_t *)&lpl->lpl_loadavg, old,
 2777                             new) != old);
 2778                 } else {
 2779                         /*
 2780                          * We're supposed to update the load, but not age it.
 2781                          * This option is used to update the load (which either
 2782                          * has already been aged in this 1/10 sec. interval or
 2783                          * soon will be) to account for a remotely executing
 2784                          * thread.
 2785                          */
 2786                         do {
 2787                                 old = new = lpl->lpl_loadavg;
 2788                                 new += f;
 2789                                 /*
 2790                                  * Check for overflow
 2791                                  * Underflow not possible here
 2792                                  */
 2793                                 if (new < old)
 2794                                         new = LGRP_LOADAVG_MAX;
 2795                         } while (cas32((lgrp_load_t *)&lpl->lpl_loadavg, old,
 2796                             new) != old);
 2797                 }
 2798 
 2799                 /*
 2800                  * Do the same for this lpl's parent
 2801                  */
 2802                 if ((lpl = lpl->lpl_parent) == NULL)
 2803                         break;
 2804                 ncpu = lpl->lpl_ncpu;
 2805         }
 2806 }
 2807 
 2808 /*
 2809  * Initialize lpl topology in the target based on topology currently present in
 2810  * lpl_bootstrap.
 2811  *
 2812  * lpl_topo_bootstrap is only called once from cpupart_initialize_default() to
 2813  * initialize cp_default list of lpls. Up to this point all topology operations
 2814  * were performed using lpl_bootstrap. Now cp_default has its own list of lpls
 2815  * and all subsequent lpl operations should use it instead of lpl_bootstrap. The
 2816  * `target' points to the list of lpls in cp_default and `size' is the size of
 2817  * this list.
 2818  *
 2819  * This function walks the lpl topology in lpl_bootstrap and does for things:
 2820  *
 2821  * 1) Copies all fields from lpl_bootstrap to the target.
 2822  *
 2823  * 2) Sets CPU0 lpl pointer to the correct element of the target list.
 2824  *
 2825  * 3) Updates lpl_parent pointers to point to the lpls in the target list
 2826  *    instead of lpl_bootstrap.
 2827  *
 2828  * 4) Updates pointers in the resource list of the target to point to the lpls
 2829  *    in the target list instead of lpl_bootstrap.
 2830  *
 2831  * After lpl_topo_bootstrap() completes, target contains the same information
 2832  * that would be present there if it were used during boot instead of
 2833  * lpl_bootstrap. There is no need in information in lpl_bootstrap after this
 2834  * and it is bzeroed.
 2835  */
 2836 void
 2837 lpl_topo_bootstrap(lpl_t *target, int size)
 2838 {
 2839         lpl_t   *lpl = lpl_bootstrap;
 2840         lpl_t   *target_lpl = target;
 2841         lpl_t   **rset;
 2842         int     *id2rset;
 2843         int     sz;
 2844         int     howmany;
 2845         int     id;
 2846         int     i;
 2847 
 2848         /*
 2849          * The only target that should be passed here is cp_default lpl list.
 2850          */
 2851         ASSERT(target == cp_default.cp_lgrploads);
 2852         ASSERT(size == cp_default.cp_nlgrploads);
 2853         ASSERT(!lgrp_topo_initialized);
 2854         ASSERT(ncpus == 1);
 2855 
 2856         howmany = MIN(LPL_BOOTSTRAP_SIZE, size);
 2857         for (i = 0; i < howmany; i++, lpl++, target_lpl++) {
 2858                 /*
 2859                  * Copy all fields from lpl, except for the rset,
 2860                  * lgrp id <=> rset mapping storage,
 2861                  * and amount of storage
 2862                  */
 2863                 rset = target_lpl->lpl_rset;
 2864                 id2rset = target_lpl->lpl_id2rset;
 2865                 sz = target_lpl->lpl_rset_sz;
 2866 
 2867                 *target_lpl = *lpl;
 2868 
 2869                 target_lpl->lpl_rset_sz = sz;
 2870                 target_lpl->lpl_rset = rset;
 2871                 target_lpl->lpl_id2rset = id2rset;
 2872 
 2873                 /*
 2874                  * Substitute CPU0 lpl pointer with one relative to target.
 2875                  */
 2876                 if (lpl->lpl_cpus == CPU) {
 2877                         ASSERT(CPU->cpu_lpl == lpl);
 2878                         CPU->cpu_lpl = target_lpl;
 2879                 }
 2880 
 2881                 /*
 2882                  * Substitute parent information with parent relative to target.
 2883                  */
 2884                 if (lpl->lpl_parent != NULL)
 2885                         target_lpl->lpl_parent = (lpl_t *)
 2886                             (((uintptr_t)lpl->lpl_parent -
 2887                             (uintptr_t)lpl_bootstrap) +
 2888                             (uintptr_t)target);
 2889 
 2890                 /*
 2891                  * Walk over resource set substituting pointers relative to
 2892                  * lpl_bootstrap's rset to pointers relative to target's
 2893                  */
 2894                 ASSERT(lpl->lpl_nrset <= 1);
 2895 
 2896                 for (id = 0; id < lpl->lpl_nrset; id++) {
 2897                         if (lpl->lpl_rset[id] != NULL) {
 2898                                 target_lpl->lpl_rset[id] = (lpl_t *)
 2899                                     (((uintptr_t)lpl->lpl_rset[id] -
 2900                                     (uintptr_t)lpl_bootstrap) +
 2901                                     (uintptr_t)target);
 2902                         }
 2903                         target_lpl->lpl_id2rset[id] =
 2904                             lpl->lpl_id2rset[id];
 2905                 }
 2906         }
 2907 
 2908         /*
 2909          * Clean up the bootstrap lpls since we have switched over to the
 2910          * actual lpl array in the default cpu partition.
 2911          *
 2912          * We still need to keep one empty lpl around for newly starting
 2913          * slave CPUs to reference should they need to make it through the
 2914          * dispatcher prior to their lgrp/lpl initialization.
 2915          *
 2916          * The lpl related dispatcher code has been designed to work properly
 2917          * (and without extra checks) for this special case of a zero'ed
 2918          * bootstrap lpl. Such an lpl appears to the dispatcher as an lpl
 2919          * with lgrpid 0 and an empty resource set. Iteration over the rset
 2920          * array by the dispatcher is also NULL terminated for this reason.
 2921          *
 2922          * This provides the desired behaviour for an uninitialized CPU.
 2923          * It shouldn't see any other CPU to either dispatch to or steal
 2924          * from until it is properly initialized.
 2925          */
 2926         bzero(lpl_bootstrap_list, sizeof (lpl_bootstrap_list));
 2927         bzero(lpl_bootstrap_id2rset, sizeof (lpl_bootstrap_id2rset));
 2928         bzero(lpl_bootstrap_rset, sizeof (lpl_bootstrap_rset));
 2929 
 2930         lpl_bootstrap_list[0].lpl_rset = lpl_bootstrap_rset;
 2931         lpl_bootstrap_list[0].lpl_id2rset = lpl_bootstrap_id2rset;
 2932 }
 2933 
 2934 /*
 2935  * If the lowest load among the lgroups a process' threads are currently
 2936  * spread across is greater than lgrp_expand_proc_thresh, we'll consider
 2937  * expanding the process to a new lgroup.
 2938  */
 2939 #define LGRP_EXPAND_PROC_THRESH_DEFAULT 62250
 2940 lgrp_load_t     lgrp_expand_proc_thresh = LGRP_EXPAND_PROC_THRESH_DEFAULT;
 2941 
 2942 #define LGRP_EXPAND_PROC_THRESH(ncpu) \
 2943         ((lgrp_expand_proc_thresh) / (ncpu))
 2944 
 2945 /*
 2946  * A process will be expanded to a new lgroup only if the difference between
 2947  * the lowest load on the lgroups the process' thread's are currently spread
 2948  * across and the lowest load on the other lgroups in the process' partition
 2949  * is greater than lgrp_expand_proc_diff.
 2950  */
 2951 #define LGRP_EXPAND_PROC_DIFF_DEFAULT 60000
 2952 lgrp_load_t     lgrp_expand_proc_diff = LGRP_EXPAND_PROC_DIFF_DEFAULT;
 2953 
 2954 #define LGRP_EXPAND_PROC_DIFF(ncpu) \
 2955         ((lgrp_expand_proc_diff) / (ncpu))
 2956 
 2957 /*
 2958  * The loadavg tolerance accounts for "noise" inherent in the load, which may
 2959  * be present due to impreciseness of the load average decay algorithm.
 2960  *
 2961  * The default tolerance is lgrp_loadavg_max_effect. Note that the tunable
 2962  * tolerance is scaled by the number of cpus in the lgroup just like
 2963  * lgrp_loadavg_max_effect. For example, if lgrp_loadavg_tolerance = 0x10000,
 2964  * and ncpu = 4, then lgrp_choose will consider differences in lgroup loads
 2965  * of: 0x10000 / 4 => 0x4000 or greater to be significant.
 2966  */
 2967 uint32_t        lgrp_loadavg_tolerance = LGRP_LOADAVG_THREAD_MAX;
 2968 #define LGRP_LOADAVG_TOLERANCE(ncpu)    \
 2969         ((lgrp_loadavg_tolerance) / ncpu)
 2970 
 2971 /*
 2972  * lgrp_choose() will choose root lgroup as home when lowest lgroup load
 2973  * average is above this threshold
 2974  */
 2975 uint32_t        lgrp_load_thresh = UINT32_MAX;
 2976 
 2977 /*
 2978  * lgrp_choose() will try to skip any lgroups with less memory
 2979  * than this free when choosing a home lgroup
 2980  */
 2981 pgcnt_t lgrp_mem_free_thresh = 0;
 2982 
 2983 /*
 2984  * When choosing between similarly loaded lgroups, lgrp_choose() will pick
 2985  * one based on one of the following policies:
 2986  * - Random selection
 2987  * - Pseudo round robin placement
 2988  * - Longest time since a thread was last placed
 2989  */
 2990 #define LGRP_CHOOSE_RANDOM      1
 2991 #define LGRP_CHOOSE_RR          2
 2992 #define LGRP_CHOOSE_TIME        3
 2993 
 2994 int     lgrp_choose_policy = LGRP_CHOOSE_TIME;
 2995 
 2996 /*
 2997  * Choose a suitable leaf lgroup for a kthread.  The kthread is assumed not to
 2998  * be bound to a CPU or processor set.
 2999  *
 3000  * Arguments:
 3001  *      t               The thread
 3002  *      cpupart         The partition the thread belongs to.
 3003  *
 3004  * NOTE: Should at least be called with the cpu_lock held, kernel preemption
 3005  *       disabled, or thread_lock held (at splhigh) to protect against the CPU
 3006  *       partitions changing out from under us and assumes that given thread is
 3007  *       protected.  Also, called sometimes w/ cpus paused or kernel preemption
 3008  *       disabled, so don't grab any locks because we should never block under
 3009  *       those conditions.
 3010  */
 3011 lpl_t *
 3012 lgrp_choose(kthread_t *t, cpupart_t *cpupart)
 3013 {
 3014         lgrp_load_t     bestload, bestrload;
 3015         int             lgrpid_offset, lgrp_count;
 3016         lgrp_id_t       lgrpid, lgrpid_start;
 3017         lpl_t           *lpl, *bestlpl, *bestrlpl;
 3018         klgrpset_t      lgrpset;
 3019         proc_t          *p;
 3020 
 3021         ASSERT(t != NULL);
 3022         ASSERT(MUTEX_HELD(&cpu_lock) || curthread->t_preempt > 0 ||
 3023             THREAD_LOCK_HELD(t));
 3024         ASSERT(cpupart != NULL);
 3025 
 3026         p = t->t_procp;
 3027 
 3028         /* A process should always be in an active partition */
 3029         ASSERT(!klgrpset_isempty(cpupart->cp_lgrpset));
 3030 
 3031         bestlpl = bestrlpl = NULL;
 3032         bestload = bestrload = LGRP_LOADAVG_MAX;
 3033         lgrpset = cpupart->cp_lgrpset;
 3034 
 3035         switch (lgrp_choose_policy) {
 3036         case LGRP_CHOOSE_RR:
 3037                 lgrpid = cpupart->cp_lgrp_hint;
 3038                 do {
 3039                         if (++lgrpid > lgrp_alloc_max)
 3040                                 lgrpid = 0;
 3041                 } while (!klgrpset_ismember(lgrpset, lgrpid));
 3042 
 3043                 break;
 3044         default:
 3045         case LGRP_CHOOSE_TIME:
 3046         case LGRP_CHOOSE_RANDOM:
 3047                 klgrpset_nlgrps(lgrpset, lgrp_count);
 3048                 lgrpid_offset =
 3049                     (((ushort_t)(gethrtime() >> 4)) % lgrp_count) + 1;
 3050                 for (lgrpid = 0; ; lgrpid++) {
 3051                         if (klgrpset_ismember(lgrpset, lgrpid)) {
 3052                                 if (--lgrpid_offset == 0)
 3053                                         break;
 3054                         }
 3055                 }
 3056                 break;
 3057         }
 3058 
 3059         lgrpid_start = lgrpid;
 3060 
 3061         DTRACE_PROBE2(lgrp_choose_start, lgrp_id_t, lgrpid_start,
 3062             lgrp_id_t, cpupart->cp_lgrp_hint);
 3063 
 3064         /*
 3065          * Use lgroup affinities (if any) to choose best lgroup
 3066          *
 3067          * NOTE: Assumes that thread is protected from going away and its
 3068          *       lgroup affinities won't change (ie. p_lock, or
 3069          *       thread_lock() being held and/or CPUs paused)
 3070          */
 3071         if (t->t_lgrp_affinity) {
 3072                 lpl = lgrp_affinity_best(t, cpupart, lgrpid_start, B_FALSE);
 3073                 if (lpl != NULL)
 3074                         return (lpl);
 3075         }
 3076 
 3077         ASSERT(klgrpset_ismember(lgrpset, lgrpid_start));
 3078 
 3079         do {
 3080                 pgcnt_t npgs;
 3081 
 3082                 /*
 3083                  * Skip any lgroups outside of thread's pset
 3084                  */
 3085                 if (!klgrpset_ismember(lgrpset, lgrpid)) {
 3086                         if (++lgrpid > lgrp_alloc_max)
 3087                                 lgrpid = 0;     /* wrap the search */
 3088                         continue;
 3089                 }
 3090 
 3091                 /*
 3092                  * Skip any non-leaf lgroups
 3093                  */
 3094                 if (lgrp_table[lgrpid]->lgrp_childcnt != 0)
 3095                         continue;
 3096 
 3097                 /*
 3098                  * Skip any lgroups without enough free memory
 3099                  * (when threshold set to nonzero positive value)
 3100                  */
 3101                 if (lgrp_mem_free_thresh > 0) {
 3102                         npgs = lgrp_mem_size(lgrpid, LGRP_MEM_SIZE_FREE);
 3103                         if (npgs < lgrp_mem_free_thresh) {
 3104                                 if (++lgrpid > lgrp_alloc_max)
 3105                                         lgrpid = 0;     /* wrap the search */
 3106                                 continue;
 3107                         }
 3108                 }
 3109 
 3110                 lpl = &cpupart->cp_lgrploads[lgrpid];
 3111                 if (klgrpset_isempty(p->p_lgrpset) ||
 3112                     klgrpset_ismember(p->p_lgrpset, lgrpid)) {
 3113                         /*
 3114                          * Either this is a new process or the process already
 3115                          * has threads on this lgrp, so this is a preferred
 3116                          * lgroup for the thread.
 3117                          */
 3118                         if (bestlpl == NULL ||
 3119                             lpl_pick(lpl, bestlpl)) {
 3120                                 bestload = lpl->lpl_loadavg;
 3121                                 bestlpl = lpl;
 3122                         }
 3123                 } else {
 3124                         /*
 3125                          * The process doesn't have any threads on this lgrp,
 3126                          * but we're willing to consider this lgrp if the load
 3127                          * difference is big enough to justify splitting up
 3128                          * the process' threads.
 3129                          */
 3130                         if (bestrlpl == NULL ||
 3131                             lpl_pick(lpl, bestrlpl)) {
 3132                                 bestrload = lpl->lpl_loadavg;
 3133                                 bestrlpl = lpl;
 3134                         }
 3135                 }
 3136                 if (++lgrpid > lgrp_alloc_max)
 3137                         lgrpid = 0;     /* wrap the search */
 3138         } while (lgrpid != lgrpid_start);
 3139 
 3140         /*
 3141          * Return root lgroup if threshold isn't set to maximum value and
 3142          * lowest lgroup load average more than a certain threshold
 3143          */
 3144         if (lgrp_load_thresh != UINT32_MAX &&
 3145             bestload >= lgrp_load_thresh && bestrload >= lgrp_load_thresh)
 3146                 return (&cpupart->cp_lgrploads[lgrp_root->lgrp_id]);
 3147 
 3148         /*
 3149          * If all the lgroups over which the thread's process is spread are
 3150          * heavily loaded, or otherwise undesirable, we'll consider placing
 3151          * the thread on one of the other leaf lgroups in the thread's
 3152          * partition.
 3153          */
 3154         if ((bestlpl == NULL) ||
 3155             ((bestload > LGRP_EXPAND_PROC_THRESH(bestlpl->lpl_ncpu)) &&
 3156             (bestrload < bestload) &&   /* paranoid about wraparound */
 3157             (bestrload + LGRP_EXPAND_PROC_DIFF(bestrlpl->lpl_ncpu) <
 3158             bestload))) {
 3159                 bestlpl = bestrlpl;
 3160         }
 3161 
 3162         if (bestlpl == NULL) {
 3163                 /*
 3164                  * No lgroup looked particularly good, but we still
 3165                  * have to pick something. Go with the randomly selected
 3166                  * legal lgroup we started with above.
 3167                  */
 3168                 bestlpl = &cpupart->cp_lgrploads[lgrpid_start];
 3169         }
 3170 
 3171         cpupart->cp_lgrp_hint = bestlpl->lpl_lgrpid;
 3172         bestlpl->lpl_homed_time = gethrtime_unscaled();
 3173 
 3174         ASSERT(bestlpl->lpl_ncpu > 0);
 3175         return (bestlpl);
 3176 }
 3177 
 3178 /*
 3179  * Decide if lpl1 is a better candidate than lpl2 for lgrp homing.
 3180  * Returns non-zero if lpl1 is a better candidate, and 0 otherwise.
 3181  */
 3182 static int
 3183 lpl_pick(lpl_t *lpl1, lpl_t *lpl2)
 3184 {
 3185         lgrp_load_t     l1, l2;
 3186         lgrp_load_t     tolerance = LGRP_LOADAVG_TOLERANCE(lpl1->lpl_ncpu);
 3187 
 3188         l1 = lpl1->lpl_loadavg;
 3189         l2 = lpl2->lpl_loadavg;
 3190 
 3191         if ((l1 + tolerance < l2) && (l1 < l2)) {
 3192                 /* lpl1 is significantly less loaded than lpl2 */
 3193                 return (1);
 3194         }
 3195 
 3196         if (lgrp_choose_policy == LGRP_CHOOSE_TIME &&
 3197             l1 + tolerance >= l2 && l1 < l2 &&
 3198             lpl1->lpl_homed_time < lpl2->lpl_homed_time) {
 3199                 /*
 3200                  * lpl1's load is within the tolerance of lpl2. We're
 3201                  * willing to consider it be to better however if
 3202                  * it has been longer since we last homed a thread there
 3203                  */
 3204                 return (1);
 3205         }
 3206 
 3207         return (0);
 3208 }
 3209 
 3210 /*
 3211  * lgrp_trthr_moves counts the number of times main thread (t_tid = 1) of a
 3212  * process that uses text replication changed home lgrp. This info is used by
 3213  * segvn asyncronous thread to detect if it needs to recheck what lgrps
 3214  * should be used for text replication.
 3215  */
 3216 static uint64_t lgrp_trthr_moves = 0;
 3217 
 3218 uint64_t
 3219 lgrp_get_trthr_migrations(void)
 3220 {
 3221         return (lgrp_trthr_moves);
 3222 }
 3223 
 3224 void
 3225 lgrp_update_trthr_migrations(uint64_t incr)
 3226 {
 3227         atomic_add_64(&lgrp_trthr_moves, incr);
 3228 }
 3229 
 3230 /*
 3231  * An LWP is expected to be assigned to an lgroup for at least this long
 3232  * for its anticipatory load to be justified.  NOTE that this value should
 3233  * not be set extremely huge (say, larger than 100 years), to avoid problems
 3234  * with overflow in the calculation that uses it.
 3235  */
 3236 #define LGRP_MIN_NSEC   (NANOSEC / 10)          /* 1/10 of a second */
 3237 hrtime_t lgrp_min_nsec = LGRP_MIN_NSEC;
 3238 
 3239 /*
 3240  * Routine to change a thread's lgroup affiliation.  This routine updates
 3241  * the thread's kthread_t struct and its process' proc_t struct to note the
 3242  * thread's new lgroup affiliation, and its lgroup affinities.
 3243  *
 3244  * Note that this is the only routine that modifies a thread's t_lpl field,
 3245  * and that adds in or removes anticipatory load.
 3246  *
 3247  * If the thread is exiting, newlpl is NULL.
 3248  *
 3249  * Locking:
 3250  * The following lock must be held on entry:
 3251  *      cpu_lock, kpreempt_disable(), or thread_lock -- to assure t's new lgrp
 3252  *              doesn't get removed from t's partition
 3253  *
 3254  * This routine is not allowed to grab any locks, since it may be called
 3255  * with cpus paused (such as from cpu_offline).
 3256  */
 3257 void
 3258 lgrp_move_thread(kthread_t *t, lpl_t *newlpl, int do_lgrpset_delete)
 3259 {
 3260         proc_t          *p;
 3261         lpl_t           *lpl, *oldlpl;
 3262         lgrp_id_t       oldid;
 3263         kthread_t       *tp;
 3264         uint_t          ncpu;
 3265         lgrp_load_t     old, new;
 3266 
 3267         ASSERT(t);
 3268         ASSERT(MUTEX_HELD(&cpu_lock) || curthread->t_preempt > 0 ||
 3269             THREAD_LOCK_HELD(t));
 3270 
 3271         /*
 3272          * If not changing lpls, just return
 3273          */
 3274         if ((oldlpl = t->t_lpl) == newlpl)
 3275                 return;
 3276 
 3277         /*
 3278          * Make sure the thread's lwp hasn't exited (if so, this thread is now
 3279          * associated with process 0 rather than with its original process).
 3280          */
 3281         if (t->t_proc_flag & TP_LWPEXIT) {
 3282                 if (newlpl != NULL) {
 3283                         t->t_lpl = newlpl;
 3284                 }
 3285                 return;
 3286         }
 3287 
 3288         p = ttoproc(t);
 3289 
 3290         /*
 3291          * If the thread had a previous lgroup, update its process' p_lgrpset
 3292          * to account for it being moved from its old lgroup.
 3293          */
 3294         if ((oldlpl != NULL) && /* thread had a previous lgroup */
 3295             (p->p_tlist != NULL)) {
 3296                 oldid = oldlpl->lpl_lgrpid;
 3297 
 3298                 if (newlpl != NULL)
 3299                         lgrp_stat_add(oldid, LGRP_NUM_MIGR, 1);
 3300 
 3301                 if ((do_lgrpset_delete) &&
 3302                     (klgrpset_ismember(p->p_lgrpset, oldid))) {
 3303                         for (tp = p->p_tlist->t_forw; ; tp = tp->t_forw) {
 3304                                 /*
 3305                                  * Check if a thread other than the thread
 3306                                  * that's moving is assigned to the same
 3307                                  * lgroup as the thread that's moving.  Note
 3308                                  * that we have to compare lgroup IDs, rather
 3309                                  * than simply comparing t_lpl's, since the
 3310                                  * threads may belong to different partitions
 3311                                  * but be assigned to the same lgroup.
 3312                                  */
 3313                                 ASSERT(tp->t_lpl != NULL);
 3314 
 3315                                 if ((tp != t) &&
 3316                                     (tp->t_lpl->lpl_lgrpid == oldid)) {
 3317                                         /*
 3318                                          * Another thread is assigned to the
 3319                                          * same lgroup as the thread that's
 3320                                          * moving, p_lgrpset doesn't change.
 3321                                          */
 3322                                         break;
 3323                                 } else if (tp == p->p_tlist) {
 3324                                         /*
 3325                                          * No other thread is assigned to the
 3326                                          * same lgroup as the exiting thread,
 3327                                          * clear the lgroup's bit in p_lgrpset.
 3328                                          */
 3329                                         klgrpset_del(p->p_lgrpset, oldid);
 3330                                         break;
 3331                                 }
 3332                         }
 3333                 }
 3334 
 3335                 /*
 3336                  * If this thread was assigned to its old lgroup for such a
 3337                  * short amount of time that the anticipatory load that was
 3338                  * added on its behalf has aged very little, remove that
 3339                  * anticipatory load.
 3340                  */
 3341                 if ((t->t_anttime + lgrp_min_nsec > gethrtime()) &&
 3342                     ((ncpu = oldlpl->lpl_ncpu) > 0)) {
 3343                         lpl = oldlpl;
 3344                         for (;;) {
 3345                                 do {
 3346                                         old = new = lpl->lpl_loadavg;
 3347                                         new -= LGRP_LOADAVG_MAX_EFFECT(ncpu);
 3348                                         if (new > old) {
 3349                                                 /*
 3350                                                  * this can happen if the load
 3351                                                  * average was aged since we
 3352                                                  * added in the anticipatory
 3353                                                  * load
 3354                                                  */
 3355                                                 new = 0;
 3356                                         }
 3357                                 } while (cas32(
 3358                                     (lgrp_load_t *)&lpl->lpl_loadavg, old,
 3359                                     new) != old);
 3360 
 3361                                 lpl = lpl->lpl_parent;
 3362                                 if (lpl == NULL)
 3363                                         break;
 3364 
 3365                                 ncpu = lpl->lpl_ncpu;
 3366                                 ASSERT(ncpu > 0);
 3367                         }
 3368                 }
 3369         }
 3370         /*
 3371          * If the thread has a new lgroup (i.e. it's not exiting), update its
 3372          * t_lpl and its process' p_lgrpset, and apply an anticipatory load
 3373          * to its new lgroup to account for its move to its new lgroup.
 3374          */
 3375         if (newlpl != NULL) {
 3376                 /*
 3377                  * This thread is moving to a new lgroup
 3378                  */
 3379                 t->t_lpl = newlpl;
 3380                 if (t->t_tid == 1 && p->p_t1_lgrpid != newlpl->lpl_lgrpid) {
 3381                         p->p_t1_lgrpid = newlpl->lpl_lgrpid;
 3382                         membar_producer();
 3383                         if (p->p_tr_lgrpid != LGRP_NONE &&
 3384                             p->p_tr_lgrpid != p->p_t1_lgrpid) {
 3385                                 lgrp_update_trthr_migrations(1);
 3386                         }
 3387                 }
 3388 
 3389                 /*
 3390                  * Reflect move in load average of new lgroup
 3391                  * unless it is root lgroup
 3392                  */
 3393                 if (lgrp_table[newlpl->lpl_lgrpid] == lgrp_root)
 3394                         return;
 3395 
 3396                 if (!klgrpset_ismember(p->p_lgrpset, newlpl->lpl_lgrpid)) {
 3397                         klgrpset_add(p->p_lgrpset, newlpl->lpl_lgrpid);
 3398                 }
 3399 
 3400                 /*
 3401                  * It'll take some time for the load on the new lgroup
 3402                  * to reflect this thread's placement on it.  We'd
 3403                  * like not, however, to have all threads between now
 3404                  * and then also piling on to this lgroup.  To avoid
 3405                  * this pileup, we anticipate the load this thread
 3406                  * will generate on its new lgroup.  The goal is to
 3407                  * make the lgroup's load appear as though the thread
 3408                  * had been there all along.  We're very conservative
 3409                  * in calculating this anticipatory load, we assume
 3410                  * the worst case case (100% CPU-bound thread).  This
 3411                  * may be modified in the future to be more accurate.
 3412                  */
 3413                 lpl = newlpl;
 3414                 for (;;) {
 3415                         ncpu = lpl->lpl_ncpu;
 3416                         ASSERT(ncpu > 0);
 3417                         do {
 3418                                 old = new = lpl->lpl_loadavg;
 3419                                 new += LGRP_LOADAVG_MAX_EFFECT(ncpu);
 3420                                 /*
 3421                                  * Check for overflow
 3422                                  * Underflow not possible here
 3423                                  */
 3424                                 if (new < old)
 3425                                         new = UINT32_MAX;
 3426                         } while (cas32((lgrp_load_t *)&lpl->lpl_loadavg, old,
 3427                             new) != old);
 3428 
 3429                         lpl = lpl->lpl_parent;
 3430                         if (lpl == NULL)
 3431                                 break;
 3432                 }
 3433                 t->t_anttime = gethrtime();
 3434         }
 3435 }
 3436 
 3437 /*
 3438  * Return lgroup memory allocation policy given advice from madvise(3C)
 3439  */
 3440 lgrp_mem_policy_t
 3441 lgrp_madv_to_policy(uchar_t advice, size_t size, int type)
 3442 {
 3443         switch (advice) {
 3444         case MADV_ACCESS_LWP:
 3445                 return (LGRP_MEM_POLICY_NEXT);
 3446         case MADV_ACCESS_MANY:
 3447                 return (LGRP_MEM_POLICY_RANDOM);
 3448         default:
 3449                 return (lgrp_mem_policy_default(size, type));
 3450         }
 3451 }
 3452 
 3453 /*
 3454  * Figure out default policy
 3455  */
 3456 lgrp_mem_policy_t
 3457 lgrp_mem_policy_default(size_t size, int type)
 3458 {
 3459         cpupart_t               *cp;
 3460         lgrp_mem_policy_t       policy;
 3461         size_t                  pset_mem_size;
 3462 
 3463         /*
 3464          * Randomly allocate memory across lgroups for shared memory
 3465          * beyond a certain threshold
 3466          */
 3467         if ((type != MAP_SHARED && size > lgrp_privm_random_thresh) ||
 3468             (type == MAP_SHARED && size > lgrp_shm_random_thresh)) {
 3469                 /*
 3470                  * Get total memory size of current thread's pset
 3471                  */
 3472                 kpreempt_disable();
 3473                 cp = curthread->t_cpupart;
 3474                 klgrpset_totalsize(cp->cp_lgrpset, pset_mem_size);
 3475                 kpreempt_enable();
 3476 
 3477                 /*
 3478                  * Choose policy to randomly allocate memory across
 3479                  * lgroups in pset if it will fit and is not default
 3480                  * partition.  Otherwise, allocate memory randomly
 3481                  * across machine.
 3482                  */
 3483                 if (lgrp_mem_pset_aware && size < pset_mem_size)
 3484                         policy = LGRP_MEM_POLICY_RANDOM_PSET;
 3485                 else
 3486                         policy = LGRP_MEM_POLICY_RANDOM;
 3487         } else
 3488                 /*
 3489                  * Apply default policy for private memory and
 3490                  * shared memory under the respective random
 3491                  * threshold.
 3492                  */
 3493                 policy = lgrp_mem_default_policy;
 3494 
 3495         return (policy);
 3496 }
 3497 
 3498 /*
 3499  * Get memory allocation policy for this segment
 3500  */
 3501 lgrp_mem_policy_info_t *
 3502 lgrp_mem_policy_get(struct seg *seg, caddr_t vaddr)
 3503 {
 3504         lgrp_mem_policy_info_t  *policy_info;
 3505         extern struct seg_ops   segspt_ops;
 3506         extern struct seg_ops   segspt_shmops;
 3507 
 3508         /*
 3509          * This is for binary compatibility to protect against third party
 3510          * segment drivers which haven't recompiled to allow for
 3511          * SEGOP_GETPOLICY()
 3512          */
 3513         if (seg->s_ops != &segvn_ops && seg->s_ops != &segspt_ops &&
 3514             seg->s_ops != &segspt_shmops)
 3515                 return (NULL);
 3516 
 3517         policy_info = NULL;
 3518         if (seg->s_ops->getpolicy != NULL)
 3519                 policy_info = SEGOP_GETPOLICY(seg, vaddr);
 3520 
 3521         return (policy_info);
 3522 }
 3523 
 3524 /*
 3525  * Set policy for allocating private memory given desired policy, policy info,
 3526  * size in bytes of memory that policy is being applied.
 3527  * Return 0 if policy wasn't set already and 1 if policy was set already
 3528  */
 3529 int
 3530 lgrp_privm_policy_set(lgrp_mem_policy_t policy,
 3531     lgrp_mem_policy_info_t *policy_info, size_t size)
 3532 {
 3533 
 3534         ASSERT(policy_info != NULL);
 3535 
 3536         if (policy == LGRP_MEM_POLICY_DEFAULT)
 3537                 policy = lgrp_mem_policy_default(size, MAP_PRIVATE);
 3538 
 3539         /*
 3540          * Policy set already?
 3541          */
 3542         if (policy == policy_info->mem_policy)
 3543                 return (1);
 3544 
 3545         /*
 3546          * Set policy
 3547          */
 3548         policy_info->mem_policy = policy;
 3549         policy_info->mem_lgrpid = LGRP_NONE;
 3550 
 3551         return (0);
 3552 }
 3553 
 3554 
 3555 /*
 3556  * Get shared memory allocation policy with given tree and offset
 3557  */
 3558 lgrp_mem_policy_info_t *
 3559 lgrp_shm_policy_get(struct anon_map *amp, ulong_t anon_index, vnode_t *vp,
 3560     u_offset_t vn_off)
 3561 {
 3562         u_offset_t              off;
 3563         lgrp_mem_policy_info_t  *policy_info;
 3564         lgrp_shm_policy_seg_t   *policy_seg;
 3565         lgrp_shm_locality_t     *shm_locality;
 3566         avl_tree_t              *tree;
 3567         avl_index_t             where;
 3568 
 3569         /*
 3570          * Get policy segment tree from anon_map or vnode and use specified
 3571          * anon index or vnode offset as offset
 3572          *
 3573          * Assume that no lock needs to be held on anon_map or vnode, since
 3574          * they should be protected by their reference count which must be
 3575          * nonzero for an existing segment
 3576          */
 3577         if (amp) {
 3578                 ASSERT(amp->refcnt != 0);
 3579                 shm_locality = amp->locality;
 3580                 if (shm_locality == NULL)
 3581                         return (NULL);
 3582                 tree = shm_locality->loc_tree;
 3583                 off = ptob(anon_index);
 3584         } else if (vp) {
 3585                 shm_locality = vp->v_locality;
 3586                 if (shm_locality == NULL)
 3587                         return (NULL);
 3588                 ASSERT(shm_locality->loc_count != 0);
 3589                 tree = shm_locality->loc_tree;
 3590                 off = vn_off;
 3591         }
 3592 
 3593         if (tree == NULL)
 3594                 return (NULL);
 3595 
 3596         /*
 3597          * Lookup policy segment for offset into shared object and return
 3598          * policy info
 3599          */
 3600         rw_enter(&shm_locality->loc_lock, RW_READER);
 3601         policy_info = NULL;
 3602         policy_seg = avl_find(tree, &off, &where);
 3603         if (policy_seg)
 3604                 policy_info = &policy_seg->shm_policy;
 3605         rw_exit(&shm_locality->loc_lock);
 3606 
 3607         return (policy_info);
 3608 }
 3609 
 3610 /*
 3611  * Default memory allocation policy for kernel segmap pages
 3612  */
 3613 lgrp_mem_policy_t       lgrp_segmap_default_policy = LGRP_MEM_POLICY_RANDOM;
 3614 
 3615 /*
 3616  * Return lgroup to use for allocating memory
 3617  * given the segment and address
 3618  *
 3619  * There isn't any mutual exclusion that exists between calls
 3620  * to this routine and DR, so this routine and whomever calls it
 3621  * should be mindful of the possibility that the lgrp returned
 3622  * may be deleted. If this happens, dereferences of the lgrp
 3623  * pointer will still be safe, but the resources in the lgrp will
 3624  * be gone, and LGRP_EXISTS() will no longer be true.
 3625  */
 3626 lgrp_t *
 3627 lgrp_mem_choose(struct seg *seg, caddr_t vaddr, size_t pgsz)
 3628 {
 3629         int                     i;
 3630         lgrp_t                  *lgrp;
 3631         klgrpset_t              lgrpset;
 3632         int                     lgrps_spanned;
 3633         unsigned long           off;
 3634         lgrp_mem_policy_t       policy;
 3635         lgrp_mem_policy_info_t  *policy_info;
 3636         ushort_t                random;
 3637         int                     stat = 0;
 3638         extern struct seg       *segkmap;
 3639 
 3640         /*
 3641          * Just return null if the lgrp framework hasn't finished
 3642          * initializing or if this is a UMA machine.
 3643          */
 3644         if (nlgrps == 1 || !lgrp_initialized)
 3645                 return (lgrp_root);
 3646 
 3647         /*
 3648          * Get memory allocation policy for this segment
 3649          */
 3650         policy = lgrp_mem_default_policy;
 3651         if (seg != NULL) {
 3652                 if (seg->s_as == &kas) {
 3653                         if (seg == segkmap)
 3654                                 policy = lgrp_segmap_default_policy;
 3655                         if (policy == LGRP_MEM_POLICY_RANDOM_PROC ||
 3656                             policy == LGRP_MEM_POLICY_RANDOM_PSET)
 3657                                 policy = LGRP_MEM_POLICY_RANDOM;
 3658                 } else {
 3659                         policy_info = lgrp_mem_policy_get(seg, vaddr);
 3660                         if (policy_info != NULL) {
 3661                                 policy = policy_info->mem_policy;
 3662                                 if (policy == LGRP_MEM_POLICY_NEXT_SEG) {
 3663                                         lgrp_id_t id = policy_info->mem_lgrpid;
 3664                                         ASSERT(id != LGRP_NONE);
 3665                                         ASSERT(id < NLGRPS_MAX);
 3666                                         lgrp = lgrp_table[id];
 3667                                         if (!LGRP_EXISTS(lgrp)) {
 3668                                                 policy = LGRP_MEM_POLICY_NEXT;
 3669                                         } else {
 3670                                                 lgrp_stat_add(id,
 3671                                                     LGRP_NUM_NEXT_SEG, 1);
 3672                                                 return (lgrp);
 3673                                         }
 3674                                 }
 3675                         }
 3676                 }
 3677         }
 3678         lgrpset = 0;
 3679 
 3680         /*
 3681          * Initialize lgroup to home by default
 3682          */
 3683         lgrp = lgrp_home_lgrp();
 3684 
 3685         /*
 3686          * When homing threads on root lgrp, override default memory
 3687          * allocation policies with root lgroup memory allocation policy
 3688          */
 3689         if (lgrp == lgrp_root)
 3690                 policy = lgrp_mem_policy_root;
 3691 
 3692         /*
 3693          * Implement policy
 3694          */
 3695         switch (policy) {
 3696         case LGRP_MEM_POLICY_NEXT_CPU:
 3697 
 3698                 /*
 3699                  * Return lgroup of current CPU which faulted on memory
 3700                  * If the CPU isn't currently in an lgrp, then opt to
 3701                  * allocate from the root.
 3702                  *
 3703                  * Kernel preemption needs to be disabled here to prevent
 3704                  * the current CPU from going away before lgrp is found.
 3705                  */
 3706                 if (LGRP_CPU_HAS_NO_LGRP(CPU)) {
 3707                         lgrp = lgrp_root;
 3708                 } else {
 3709                         kpreempt_disable();
 3710                         lgrp = lgrp_cpu_to_lgrp(CPU);
 3711                         kpreempt_enable();
 3712                 }
 3713                 break;
 3714 
 3715         case LGRP_MEM_POLICY_NEXT:
 3716         case LGRP_MEM_POLICY_DEFAULT:
 3717         default:
 3718 
 3719                 /*
 3720                  * Just return current thread's home lgroup
 3721                  * for default policy (next touch)
 3722                  * If the thread is homed to the root,
 3723                  * then the default policy is random across lgroups.
 3724                  * Fallthrough to the random case.
 3725                  */
 3726                 if (lgrp != lgrp_root) {
 3727                         if (policy == LGRP_MEM_POLICY_NEXT)
 3728                                 lgrp_stat_add(lgrp->lgrp_id, LGRP_NUM_NEXT, 1);
 3729                         else
 3730                                 lgrp_stat_add(lgrp->lgrp_id,
 3731                                     LGRP_NUM_DEFAULT, 1);
 3732                         break;
 3733                 }
 3734                 /* LINTED fallthrough on case statement */
 3735         case LGRP_MEM_POLICY_RANDOM:
 3736 
 3737                 /*
 3738                  * Return a random leaf lgroup with memory
 3739                  */
 3740                 lgrpset = lgrp_root->lgrp_set[LGRP_RSRC_MEM];
 3741                 /*
 3742                  * Count how many lgroups are spanned
 3743                  */
 3744                 klgrpset_nlgrps(lgrpset, lgrps_spanned);
 3745 
 3746                 /*
 3747                  * There may be no memnodes in the root lgroup during DR copy
 3748                  * rename on a system with only two boards (memnodes)
 3749                  * configured. In this case just return the root lgrp.
 3750                  */
 3751                 if (lgrps_spanned == 0) {
 3752                         lgrp = lgrp_root;
 3753                         break;
 3754                 }
 3755 
 3756                 /*
 3757                  * Pick a random offset within lgroups spanned
 3758                  * and return lgroup at that offset
 3759                  */
 3760                 random = (ushort_t)gethrtime() >> 4;
 3761                 off = random % lgrps_spanned;
 3762                 ASSERT(off <= lgrp_alloc_max);
 3763 
 3764                 for (i = 0; i <= lgrp_alloc_max; i++) {
 3765                         if (!klgrpset_ismember(lgrpset, i))
 3766                                 continue;
 3767                         if (off)
 3768                                 off--;
 3769                         else {
 3770                                 lgrp = lgrp_table[i];
 3771                                 lgrp_stat_add(lgrp->lgrp_id, LGRP_NUM_RANDOM,
 3772                                     1);
 3773                                 break;
 3774                         }
 3775                 }
 3776                 break;
 3777 
 3778         case LGRP_MEM_POLICY_RANDOM_PROC:
 3779 
 3780                 /*
 3781                  * Grab copy of bitmask of lgroups spanned by
 3782                  * this process
 3783                  */
 3784                 klgrpset_copy(lgrpset, curproc->p_lgrpset);
 3785                 stat = LGRP_NUM_RANDOM_PROC;
 3786 
 3787                 /* LINTED fallthrough on case statement */
 3788         case LGRP_MEM_POLICY_RANDOM_PSET:
 3789 
 3790                 if (!stat)
 3791                         stat = LGRP_NUM_RANDOM_PSET;
 3792 
 3793                 if (klgrpset_isempty(lgrpset)) {
 3794                         /*
 3795                          * Grab copy of bitmask of lgroups spanned by
 3796                          * this processor set
 3797                          */
 3798                         kpreempt_disable();
 3799                         klgrpset_copy(lgrpset,
 3800                             curthread->t_cpupart->cp_lgrpset);
 3801                         kpreempt_enable();
 3802                 }
 3803 
 3804                 /*
 3805                  * Count how many lgroups are spanned
 3806                  */
 3807                 klgrpset_nlgrps(lgrpset, lgrps_spanned);
 3808                 ASSERT(lgrps_spanned <= nlgrps);
 3809 
 3810                 /*
 3811                  * Probably lgrps_spanned should be always non-zero, but to be
 3812                  * on the safe side we return lgrp_root if it is empty.
 3813                  */
 3814                 if (lgrps_spanned == 0) {
 3815                         lgrp = lgrp_root;
 3816                         break;
 3817                 }
 3818 
 3819                 /*
 3820                  * Pick a random offset within lgroups spanned
 3821                  * and return lgroup at that offset
 3822                  */
 3823                 random = (ushort_t)gethrtime() >> 4;
 3824                 off = random % lgrps_spanned;
 3825                 ASSERT(off <= lgrp_alloc_max);
 3826 
 3827                 for (i = 0; i <= lgrp_alloc_max; i++) {
 3828                         if (!klgrpset_ismember(lgrpset, i))
 3829                                 continue;
 3830                         if (off)
 3831                                 off--;
 3832                         else {
 3833                                 lgrp = lgrp_table[i];
 3834                                 lgrp_stat_add(lgrp->lgrp_id, LGRP_NUM_RANDOM,
 3835                                     1);
 3836                                 break;
 3837                         }
 3838                 }
 3839                 break;
 3840 
 3841         case LGRP_MEM_POLICY_ROUNDROBIN:
 3842 
 3843                 /*
 3844                  * Use offset within segment to determine
 3845                  * offset from home lgroup to choose for
 3846                  * next lgroup to allocate memory from
 3847                  */
 3848                 off = ((unsigned long)(vaddr - seg->s_base) / pgsz) %
 3849                     (lgrp_alloc_max + 1);
 3850 
 3851                 kpreempt_disable();
 3852                 lgrpset = lgrp_root->lgrp_set[LGRP_RSRC_MEM];
 3853                 i = lgrp->lgrp_id;
 3854                 kpreempt_enable();
 3855 
 3856                 while (off > 0) {
 3857                         i = (i + 1) % (lgrp_alloc_max + 1);
 3858                         lgrp = lgrp_table[i];
 3859                         if (klgrpset_ismember(lgrpset, i))
 3860                                 off--;
 3861                 }
 3862                 lgrp_stat_add(lgrp->lgrp_id, LGRP_NUM_ROUNDROBIN, 1);
 3863 
 3864                 break;
 3865         }
 3866 
 3867         ASSERT(lgrp != NULL);
 3868         return (lgrp);
 3869 }
 3870 
 3871 /*
 3872  * Return the number of pages in an lgroup
 3873  *
 3874  * NOTE: NUMA test (numat) driver uses this, so changing arguments or semantics
 3875  *       could cause tests that rely on the numat driver to fail....
 3876  */
 3877 pgcnt_t
 3878 lgrp_mem_size(lgrp_id_t lgrpid, lgrp_mem_query_t query)
 3879 {
 3880         lgrp_t *lgrp;
 3881 
 3882         lgrp = lgrp_table[lgrpid];
 3883         if (!LGRP_EXISTS(lgrp) ||
 3884             klgrpset_isempty(lgrp->lgrp_set[LGRP_RSRC_MEM]) ||
 3885             !klgrpset_ismember(lgrp->lgrp_set[LGRP_RSRC_MEM], lgrpid))
 3886                 return (0);
 3887 
 3888         return (lgrp_plat_mem_size(lgrp->lgrp_plathand, query));
 3889 }
 3890 
 3891 /*
 3892  * Initialize lgroup shared memory allocation policy support
 3893  */
 3894 void
 3895 lgrp_shm_policy_init(struct anon_map *amp, vnode_t *vp)
 3896 {
 3897         lgrp_shm_locality_t     *shm_locality;
 3898 
 3899         /*
 3900          * Initialize locality field in anon_map
 3901          * Don't need any locks because this is called when anon_map is
 3902          * allocated, but not used anywhere yet.
 3903          */
 3904         if (amp) {
 3905                 ANON_LOCK_ENTER(&amp->a_rwlock, RW_WRITER);
 3906                 if (amp->locality == NULL) {
 3907                         /*
 3908                          * Allocate and initialize shared memory locality info
 3909                          * and set anon_map locality pointer to it
 3910                          * Drop lock across kmem_alloc(KM_SLEEP)
 3911                          */
 3912                         ANON_LOCK_EXIT(&amp->a_rwlock);
 3913                         shm_locality = kmem_alloc(sizeof (*shm_locality),
 3914                             KM_SLEEP);
 3915                         rw_init(&shm_locality->loc_lock, NULL, RW_DEFAULT,
 3916                             NULL);
 3917                         shm_locality->loc_count = 1;    /* not used for amp */
 3918                         shm_locality->loc_tree = NULL;
 3919 
 3920                         /*
 3921                          * Reacquire lock and check to see whether anyone beat
 3922                          * us to initializing the locality info
 3923                          */
 3924                         ANON_LOCK_ENTER(&amp->a_rwlock, RW_WRITER);
 3925                         if (amp->locality != NULL) {
 3926                                 rw_destroy(&shm_locality->loc_lock);
 3927                                 kmem_free(shm_locality,
 3928                                     sizeof (*shm_locality));
 3929                         } else
 3930                                 amp->locality = shm_locality;
 3931                 }
 3932                 ANON_LOCK_EXIT(&amp->a_rwlock);
 3933                 return;
 3934         }
 3935 
 3936         /*
 3937          * Allocate shared vnode policy info if vnode is not locality aware yet
 3938          */
 3939         mutex_enter(&vp->v_lock);
 3940         if ((vp->v_flag & V_LOCALITY) == 0) {
 3941                 /*
 3942                  * Allocate and initialize shared memory locality info
 3943                  */
 3944                 mutex_exit(&vp->v_lock);
 3945                 shm_locality = kmem_alloc(sizeof (*shm_locality), KM_SLEEP);
 3946                 rw_init(&shm_locality->loc_lock, NULL, RW_DEFAULT, NULL);
 3947                 shm_locality->loc_count = 1;
 3948                 shm_locality->loc_tree = NULL;
 3949 
 3950                 /*
 3951                  * Point vnode locality field at shared vnode policy info
 3952                  * and set locality aware flag in vnode
 3953                  */
 3954                 mutex_enter(&vp->v_lock);
 3955                 if ((vp->v_flag & V_LOCALITY) == 0) {
 3956                         vp->v_locality = shm_locality;
 3957                         vp->v_flag |= V_LOCALITY;
 3958                 } else {
 3959                         /*
 3960                          * Lost race so free locality info and increment count.
 3961                          */
 3962                         rw_destroy(&shm_locality->loc_lock);
 3963                         kmem_free(shm_locality, sizeof (*shm_locality));
 3964                         shm_locality = vp->v_locality;
 3965                         shm_locality->loc_count++;
 3966                 }
 3967                 mutex_exit(&vp->v_lock);
 3968 
 3969                 return;
 3970         }
 3971 
 3972         /*
 3973          * Increment reference count of number of segments mapping this vnode
 3974          * shared
 3975          */
 3976         shm_locality = vp->v_locality;
 3977         shm_locality->loc_count++;
 3978         mutex_exit(&vp->v_lock);
 3979 }
 3980 
 3981 /*
 3982  * Destroy the given shared memory policy segment tree
 3983  */
 3984 void
 3985 lgrp_shm_policy_tree_destroy(avl_tree_t *tree)
 3986 {
 3987         lgrp_shm_policy_seg_t   *cur;
 3988         lgrp_shm_policy_seg_t   *next;
 3989 
 3990         if (tree == NULL)
 3991                 return;
 3992 
 3993         cur = (lgrp_shm_policy_seg_t *)avl_first(tree);
 3994         while (cur != NULL) {
 3995                 next = AVL_NEXT(tree, cur);
 3996                 avl_remove(tree, cur);
 3997                 kmem_free(cur, sizeof (*cur));
 3998                 cur = next;
 3999         }
 4000         kmem_free(tree, sizeof (avl_tree_t));
 4001 }
 4002 
 4003 /*
 4004  * Uninitialize lgroup shared memory allocation policy support
 4005  */
 4006 void
 4007 lgrp_shm_policy_fini(struct anon_map *amp, vnode_t *vp)
 4008 {
 4009         lgrp_shm_locality_t     *shm_locality;
 4010 
 4011         /*
 4012          * For anon_map, deallocate shared memory policy tree and
 4013          * zero locality field
 4014          * Don't need any locks because anon_map is being freed
 4015          */
 4016         if (amp) {
 4017                 if (amp->locality == NULL)
 4018                         return;
 4019                 shm_locality = amp->locality;
 4020                 shm_locality->loc_count = 0;    /* not really used for amp */
 4021                 rw_destroy(&shm_locality->loc_lock);
 4022                 lgrp_shm_policy_tree_destroy(shm_locality->loc_tree);
 4023                 kmem_free(shm_locality, sizeof (*shm_locality));
 4024                 amp->locality = 0;
 4025                 return;
 4026         }
 4027 
 4028         /*
 4029          * For vnode, decrement reference count of segments mapping this vnode
 4030          * shared and delete locality info if reference count drops to 0
 4031          */
 4032         mutex_enter(&vp->v_lock);
 4033         shm_locality = vp->v_locality;
 4034         shm_locality->loc_count--;
 4035 
 4036         if (shm_locality->loc_count == 0) {
 4037                 rw_destroy(&shm_locality->loc_lock);
 4038                 lgrp_shm_policy_tree_destroy(shm_locality->loc_tree);
 4039                 kmem_free(shm_locality, sizeof (*shm_locality));
 4040                 vp->v_locality = 0;
 4041                 vp->v_flag &= ~V_LOCALITY;
 4042         }
 4043         mutex_exit(&vp->v_lock);
 4044 }
 4045 
 4046 /*
 4047  * Compare two shared memory policy segments
 4048  * Used by AVL tree code for searching
 4049  */
 4050 int
 4051 lgrp_shm_policy_compar(const void *x, const void *y)
 4052 {
 4053         lgrp_shm_policy_seg_t *a = (lgrp_shm_policy_seg_t *)x;
 4054         lgrp_shm_policy_seg_t *b = (lgrp_shm_policy_seg_t *)y;
 4055 
 4056         if (a->shm_off < b->shm_off)
 4057                 return (-1);
 4058         if (a->shm_off >= b->shm_off + b->shm_size)
 4059                 return (1);
 4060         return (0);
 4061 }
 4062 
 4063 /*
 4064  * Concatenate seg1 with seg2 and remove seg2
 4065  */
 4066 static int
 4067 lgrp_shm_policy_concat(avl_tree_t *tree, lgrp_shm_policy_seg_t *seg1,
 4068     lgrp_shm_policy_seg_t *seg2)
 4069 {
 4070         if (!seg1 || !seg2 ||
 4071             seg1->shm_off + seg1->shm_size != seg2->shm_off ||
 4072             seg1->shm_policy.mem_policy != seg2->shm_policy.mem_policy)
 4073                 return (-1);
 4074 
 4075         seg1->shm_size += seg2->shm_size;
 4076         avl_remove(tree, seg2);
 4077         kmem_free(seg2, sizeof (*seg2));
 4078         return (0);
 4079 }
 4080 
 4081 /*
 4082  * Split segment at given offset and return rightmost (uppermost) segment
 4083  * Assumes that there are no overlapping segments
 4084  */
 4085 static lgrp_shm_policy_seg_t *
 4086 lgrp_shm_policy_split(avl_tree_t *tree, lgrp_shm_policy_seg_t *seg,
 4087     u_offset_t off)
 4088 {
 4089         lgrp_shm_policy_seg_t   *newseg;
 4090         avl_index_t             where;
 4091 
 4092         ASSERT(seg != NULL);
 4093         ASSERT(off >= seg->shm_off && off <= seg->shm_off + seg->shm_size);
 4094 
 4095         if (!seg || off < seg->shm_off || off > seg->shm_off +
 4096             seg->shm_size)
 4097                 return (NULL);
 4098 
 4099         if (off == seg->shm_off || off == seg->shm_off + seg->shm_size)
 4100                 return (seg);
 4101 
 4102         /*
 4103          * Adjust size of left segment and allocate new (right) segment
 4104          */
 4105         newseg = kmem_alloc(sizeof (lgrp_shm_policy_seg_t), KM_SLEEP);
 4106         newseg->shm_policy = seg->shm_policy;
 4107         newseg->shm_off = off;
 4108         newseg->shm_size = seg->shm_size - (off - seg->shm_off);
 4109         seg->shm_size = off - seg->shm_off;
 4110 
 4111         /*
 4112          * Find where to insert new segment in AVL tree and insert it
 4113          */
 4114         (void) avl_find(tree, &off, &where);
 4115         avl_insert(tree, newseg, where);
 4116 
 4117         return (newseg);
 4118 }
 4119 
 4120 /*
 4121  * Set shared memory allocation policy on specified shared object at given
 4122  * offset and length
 4123  *
 4124  * Return 0 if policy wasn't set already, 1 if policy was set already, and
 4125  * -1 if can't set policy.
 4126  */
 4127 int
 4128 lgrp_shm_policy_set(lgrp_mem_policy_t policy, struct anon_map *amp,
 4129     ulong_t anon_index, vnode_t *vp, u_offset_t vn_off, size_t len)
 4130 {
 4131         u_offset_t              eoff;
 4132         lgrp_shm_policy_seg_t   *next;
 4133         lgrp_shm_policy_seg_t   *newseg;
 4134         u_offset_t              off;
 4135         u_offset_t              oldeoff;
 4136         lgrp_shm_policy_seg_t   *prev;
 4137         int                     retval;
 4138         lgrp_shm_policy_seg_t   *seg;
 4139         lgrp_shm_locality_t     *shm_locality;
 4140         avl_tree_t              *tree;
 4141         avl_index_t             where;
 4142 
 4143         ASSERT(amp || vp);
 4144         ASSERT((len & PAGEOFFSET) == 0);
 4145 
 4146         if (len == 0)
 4147                 return (-1);
 4148 
 4149         retval = 0;
 4150 
 4151         /*
 4152          * Get locality info and starting offset into shared object
 4153          * Try anon map first and then vnode
 4154          * Assume that no locks need to be held on anon_map or vnode, since
 4155          * it should be protected by its reference count which must be nonzero
 4156          * for an existing segment.
 4157          */
 4158         if (amp) {
 4159                 /*
 4160                  * Get policy info from anon_map
 4161                  *
 4162                  */
 4163                 ASSERT(amp->refcnt != 0);
 4164                 if (amp->locality == NULL)
 4165                         lgrp_shm_policy_init(amp, NULL);
 4166                 shm_locality = amp->locality;
 4167                 off = ptob(anon_index);
 4168         } else if (vp) {
 4169                 /*
 4170                  * Get policy info from vnode
 4171                  */
 4172                 if ((vp->v_flag & V_LOCALITY) == 0 || vp->v_locality == NULL)
 4173                         lgrp_shm_policy_init(NULL, vp);
 4174                 shm_locality = vp->v_locality;
 4175                 ASSERT(shm_locality->loc_count != 0);
 4176                 off = vn_off;
 4177         } else
 4178                 return (-1);
 4179 
 4180         ASSERT((off & PAGEOFFSET) == 0);
 4181 
 4182         /*
 4183          * Figure out default policy
 4184          */
 4185         if (policy == LGRP_MEM_POLICY_DEFAULT)
 4186                 policy = lgrp_mem_policy_default(len, MAP_SHARED);
 4187 
 4188         /*
 4189          * Create AVL tree if there isn't one yet
 4190          * and set locality field to point at it
 4191          */
 4192         rw_enter(&shm_locality->loc_lock, RW_WRITER);
 4193         tree = shm_locality->loc_tree;
 4194         if (!tree) {
 4195                 rw_exit(&shm_locality->loc_lock);
 4196 
 4197                 tree = kmem_alloc(sizeof (avl_tree_t), KM_SLEEP);
 4198 
 4199                 rw_enter(&shm_locality->loc_lock, RW_WRITER);
 4200                 if (shm_locality->loc_tree == NULL) {
 4201                         avl_create(tree, lgrp_shm_policy_compar,
 4202                             sizeof (lgrp_shm_policy_seg_t),
 4203                             offsetof(lgrp_shm_policy_seg_t, shm_tree));
 4204                         shm_locality->loc_tree = tree;
 4205                 } else {
 4206                         /*
 4207                          * Another thread managed to set up the tree
 4208                          * before we could. Free the tree we allocated
 4209                          * and use the one that's already there.
 4210                          */
 4211                         kmem_free(tree, sizeof (*tree));
 4212                         tree = shm_locality->loc_tree;
 4213                 }
 4214         }
 4215 
 4216         /*
 4217          * Set policy
 4218          *
 4219          * Need to maintain hold on writer's lock to keep tree from
 4220          * changing out from under us
 4221          */
 4222         while (len != 0) {
 4223                 /*
 4224                  * Find policy segment for specified offset into shared object
 4225                  */
 4226                 seg = avl_find(tree, &off, &where);
 4227 
 4228                 /*
 4229                  * Didn't find any existing segment that contains specified
 4230                  * offset, so allocate new segment, insert it, and concatenate
 4231                  * with adjacent segments if possible
 4232                  */
 4233                 if (seg == NULL) {
 4234                         newseg = kmem_alloc(sizeof (lgrp_shm_policy_seg_t),
 4235                             KM_SLEEP);
 4236                         newseg->shm_policy.mem_policy = policy;
 4237                         newseg->shm_policy.mem_lgrpid = LGRP_NONE;
 4238                         newseg->shm_off = off;
 4239                         avl_insert(tree, newseg, where);
 4240 
 4241                         /*
 4242                          * Check to see whether new segment overlaps with next
 4243                          * one, set length of new segment accordingly, and
 4244                          * calculate remaining length and next offset
 4245                          */
 4246                         seg = AVL_NEXT(tree, newseg);
 4247                         if (seg == NULL || off + len <= seg->shm_off) {
 4248                                 newseg->shm_size = len;
 4249                                 len = 0;
 4250                         } else {
 4251                                 newseg->shm_size = seg->shm_off - off;
 4252                                 off = seg->shm_off;
 4253                                 len -= newseg->shm_size;
 4254                         }
 4255 
 4256                         /*
 4257                          * Try to concatenate new segment with next and
 4258                          * previous ones, since they might have the same policy
 4259                          * now.  Grab previous and next segments first because
 4260                          * they will change on concatenation.
 4261                          */
 4262                         prev =  AVL_PREV(tree, newseg);
 4263                         next = AVL_NEXT(tree, newseg);
 4264                         (void) lgrp_shm_policy_concat(tree, newseg, next);
 4265                         (void) lgrp_shm_policy_concat(tree, prev, newseg);
 4266 
 4267                         continue;
 4268                 }
 4269 
 4270                 eoff = off + len;
 4271                 oldeoff = seg->shm_off + seg->shm_size;
 4272 
 4273                 /*
 4274                  * Policy set already?
 4275                  */
 4276                 if (policy == seg->shm_policy.mem_policy) {
 4277                         /*
 4278                          * Nothing left to do if offset and length
 4279                          * fall within this segment
 4280                          */
 4281                         if (eoff <= oldeoff) {
 4282                                 retval = 1;
 4283                                 break;
 4284                         } else {
 4285                                 len = eoff - oldeoff;
 4286                                 off = oldeoff;
 4287                                 continue;
 4288                         }
 4289                 }
 4290 
 4291                 /*
 4292                  * Specified offset and length match existing segment exactly
 4293                  */
 4294                 if (off == seg->shm_off && len == seg->shm_size) {
 4295                         /*
 4296                          * Set policy and update current length
 4297                          */
 4298                         seg->shm_policy.mem_policy = policy;
 4299                         seg->shm_policy.mem_lgrpid = LGRP_NONE;
 4300                         len = 0;
 4301 
 4302                         /*
 4303                          * Try concatenating new segment with previous and next
 4304                          * segments, since they might have the same policy now.
 4305                          * Grab previous and next segments first because they
 4306                          * will change on concatenation.
 4307                          */
 4308                         prev =  AVL_PREV(tree, seg);
 4309                         next = AVL_NEXT(tree, seg);
 4310                         (void) lgrp_shm_policy_concat(tree, seg, next);
 4311                         (void) lgrp_shm_policy_concat(tree, prev, seg);
 4312                 } else {
 4313                         /*
 4314                          * Specified offset and length only apply to part of
 4315                          * existing segment
 4316                          */
 4317 
 4318                         /*
 4319                          * New segment starts in middle of old one, so split
 4320                          * new one off near beginning of old one
 4321                          */
 4322                         newseg = NULL;
 4323                         if (off > seg->shm_off) {
 4324                                 newseg = lgrp_shm_policy_split(tree, seg, off);
 4325 
 4326                                 /*
 4327                                  * New segment ends where old one did, so try
 4328                                  * to concatenate with next segment
 4329                                  */
 4330                                 if (eoff == oldeoff) {
 4331                                         newseg->shm_policy.mem_policy = policy;
 4332                                         newseg->shm_policy.mem_lgrpid =
 4333                                             LGRP_NONE;
 4334                                         (void) lgrp_shm_policy_concat(tree,
 4335                                             newseg, AVL_NEXT(tree, newseg));
 4336                                         break;
 4337                                 }
 4338                         }
 4339 
 4340                         /*
 4341                          * New segment ends before old one, so split off end of
 4342                          * old one
 4343                          */
 4344                         if (eoff < oldeoff) {
 4345                                 if (newseg) {
 4346                                         (void) lgrp_shm_policy_split(tree,
 4347                                             newseg, eoff);
 4348                                         newseg->shm_policy.mem_policy = policy;
 4349                                         newseg->shm_policy.mem_lgrpid =
 4350                                             LGRP_NONE;
 4351                                 } else {
 4352                                         (void) lgrp_shm_policy_split(tree, seg,
 4353                                             eoff);
 4354                                         seg->shm_policy.mem_policy = policy;
 4355                                         seg->shm_policy.mem_lgrpid = LGRP_NONE;
 4356                                 }
 4357 
 4358                                 if (off == seg->shm_off)
 4359                                         (void) lgrp_shm_policy_concat(tree,
 4360                                             AVL_PREV(tree, seg), seg);
 4361                                 break;
 4362                         }
 4363 
 4364                         /*
 4365                          * Calculate remaining length and next offset
 4366                          */
 4367                         len = eoff - oldeoff;
 4368                         off = oldeoff;
 4369                 }
 4370         }
 4371 
 4372         rw_exit(&shm_locality->loc_lock);
 4373         return (retval);
 4374 }
 4375 
 4376 /*
 4377  * Return the best memnode from which to allocate memory given
 4378  * an lgroup.
 4379  *
 4380  * "c" is for cookie, which is good enough for me.
 4381  * It references a cookie struct that should be zero'ed to initialize.
 4382  * The cookie should live on the caller's stack.
 4383  *
 4384  * The routine returns -1 when:
 4385  *      - traverse is 0, and all the memnodes in "lgrp" have been returned.
 4386  *      - traverse is 1, and all the memnodes in the system have been
 4387  *        returned.
 4388  */
 4389 int
 4390 lgrp_memnode_choose(lgrp_mnode_cookie_t *c)
 4391 {
 4392         lgrp_t          *lp = c->lmc_lgrp;
 4393         mnodeset_t      nodes = c->lmc_nodes;
 4394         int             cnt = c->lmc_cnt;
 4395         int             offset, mnode;
 4396 
 4397         extern int      max_mem_nodes;
 4398 
 4399         /*
 4400          * If the set is empty, and the caller is willing, traverse
 4401          * up the hierarchy until we find a non-empty set.
 4402          */
 4403         while (nodes == (mnodeset_t)0 || cnt <= 0) {
 4404                 if (c->lmc_scope == LGRP_SRCH_LOCAL ||
 4405                     ((lp = lp->lgrp_parent) == NULL))
 4406                         return (-1);
 4407 
 4408                 nodes = lp->lgrp_mnodes & ~(c->lmc_tried);
 4409                 cnt = lp->lgrp_nmnodes - c->lmc_ntried;
 4410         }
 4411 
 4412         /*
 4413          * Select a memnode by picking one at a "random" offset.
 4414          * Because of DR, memnodes can come and go at any time.
 4415          * This code must be able to cope with the possibility
 4416          * that the nodes count "cnt" is inconsistent with respect
 4417          * to the number of elements actually in "nodes", and
 4418          * therefore that the offset chosen could be greater than
 4419          * the number of elements in the set (some memnodes may
 4420          * have dissapeared just before cnt was read).
 4421          * If this happens, the search simply wraps back to the
 4422          * beginning of the set.
 4423          */
 4424         ASSERT(nodes != (mnodeset_t)0 && cnt > 0);
 4425         offset = c->lmc_rand % cnt;
 4426         do {
 4427                 for (mnode = 0; mnode < max_mem_nodes; mnode++)
 4428                         if (nodes & ((mnodeset_t)1 << mnode))
 4429                                 if (!offset--)
 4430                                         break;
 4431         } while (mnode >= max_mem_nodes);
 4432 
 4433         /* Found a node. Store state before returning. */
 4434         c->lmc_lgrp = lp;
 4435         c->lmc_nodes = (nodes & ~((mnodeset_t)1 << mnode));
 4436         c->lmc_cnt = cnt - 1;
 4437         c->lmc_tried = (c->lmc_tried | ((mnodeset_t)1 << mnode));
 4438         c->lmc_ntried++;
 4439 
 4440         return (mnode);
 4441 }

Cache object: 4b6ca1dd3e4edd34846246b06220c599


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.