10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 52685Sakolb * Common Development and Distribution License (the "License"). 62685Sakolb * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 212685Sakolb 220Sstevel@tonic-gate /* 23*10710Sjonathan.chew@sun.com * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #ifndef _LGRP_H 280Sstevel@tonic-gate #define _LGRP_H 290Sstevel@tonic-gate 300Sstevel@tonic-gate /* 310Sstevel@tonic-gate * locality group definitions for kernel 320Sstevel@tonic-gate */ 330Sstevel@tonic-gate 340Sstevel@tonic-gate #include <sys/types.h> 350Sstevel@tonic-gate 360Sstevel@tonic-gate #ifdef __cplusplus 370Sstevel@tonic-gate extern "C" { 380Sstevel@tonic-gate #endif 390Sstevel@tonic-gate 400Sstevel@tonic-gate #define LGRP_NONE (-1) /* non-existent lgroup ID */ 410Sstevel@tonic-gate 420Sstevel@tonic-gate #if (!defined(_KERNEL) && !defined(_KMEMUSER)) 430Sstevel@tonic-gate typedef struct lgrp_mem_policy_info { int opaque[2]; } lgrp_mem_policy_info_t; 440Sstevel@tonic-gate #endif /* !_KERNEL && !_KMEMUSER */ 450Sstevel@tonic-gate 460Sstevel@tonic-gate #if (defined(_KERNEL) || defined(_KMEMUSER)) 470Sstevel@tonic-gate #include <sys/cpuvar.h> 480Sstevel@tonic-gate #include <sys/bitmap.h> 490Sstevel@tonic-gate #include <sys/vnode.h> 500Sstevel@tonic-gate #include <vm/anon.h> 510Sstevel@tonic-gate #include <vm/seg.h> 520Sstevel@tonic-gate #include <sys/lgrp_user.h> 530Sstevel@tonic-gate #include <sys/param.h> 540Sstevel@tonic-gate 550Sstevel@tonic-gate typedef uint32_t lgrp_load_t; /* lgrp_loadavg type */ 560Sstevel@tonic-gate typedef uintptr_t lgrp_handle_t; /* lgrp handle */ 570Sstevel@tonic-gate 580Sstevel@tonic-gate #define LGRP_NONE_SUCH LGRP_NONE /* non-existent lgroup ID */ 590Sstevel@tonic-gate /* null platform handle */ 600Sstevel@tonic-gate #define LGRP_NULL_HANDLE ((lgrp_handle_t)0xbadbad) 610Sstevel@tonic-gate #define LGRP_DEFAULT_HANDLE ((lgrp_handle_t)0xbabecafe) /* uma handle */ 620Sstevel@tonic-gate #define LGRP_ROOTID (0) /* root lgroup ID */ 630Sstevel@tonic-gate 640Sstevel@tonic-gate /* 650Sstevel@tonic-gate * Maximum number of lgrps a platform may define. 660Sstevel@tonic-gate */ 670Sstevel@tonic-gate #define NLGRPS_MAX 64 680Sstevel@tonic-gate #define LGRP_LOADAVG_MAX UINT32_MAX 690Sstevel@tonic-gate 700Sstevel@tonic-gate /* 710Sstevel@tonic-gate * The load-average we expect for one cpu-bound thread's worth of load 720Sstevel@tonic-gate */ 730Sstevel@tonic-gate #define LGRP_LOADAVG_THREAD_MAX 65516 740Sstevel@tonic-gate 750Sstevel@tonic-gate /* 760Sstevel@tonic-gate * The input to the load-average generating function for one cpu-bound thread's 770Sstevel@tonic-gate * worth of load 780Sstevel@tonic-gate */ 790Sstevel@tonic-gate 800Sstevel@tonic-gate #define LGRP_LOADAVG_IN_THREAD_MAX 128 810Sstevel@tonic-gate 820Sstevel@tonic-gate /* 830Sstevel@tonic-gate * LPL actions 840Sstevel@tonic-gate */ 850Sstevel@tonic-gate 860Sstevel@tonic-gate typedef enum { 870Sstevel@tonic-gate LPL_INCREMENT, 880Sstevel@tonic-gate LPL_DECREMENT 890Sstevel@tonic-gate } lpl_act_t; 900Sstevel@tonic-gate 910Sstevel@tonic-gate /* 920Sstevel@tonic-gate * lgroup statistics. Most of these are counters that are updated 930Sstevel@tonic-gate * dynamically so they are hashed to CPU buckets to reduce cache 940Sstevel@tonic-gate * interference. The remaining statistics are snapshots of kernel 950Sstevel@tonic-gate * data, so they aren't stored in the array of counter stats. 960Sstevel@tonic-gate * 970Sstevel@tonic-gate * For the hashed stats to make sense, you have to sum all the buckets for 980Sstevel@tonic-gate * that stat, hence macros are provided to read the stats. 990Sstevel@tonic-gate */ 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate #define LGRP_NUM_CPU_BUCKETS 8 /* must be power of 2 */ 1020Sstevel@tonic-gate #define LGRP_CPU_BUCKET_MASK (LGRP_NUM_CPU_BUCKETS - 1) 1030Sstevel@tonic-gate 1040Sstevel@tonic-gate /* 1050Sstevel@tonic-gate * Flags for what to do with lgroup memory policy 1060Sstevel@tonic-gate * Used for heap and stack where policy is extended to new segments added to 1070Sstevel@tonic-gate * the end 1080Sstevel@tonic-gate */ 1090Sstevel@tonic-gate #define LGRP_MP_FLAG_EXTEND_UP 0x1 /* policy should extend up */ 1100Sstevel@tonic-gate #define LGRP_MP_FLAG_EXTEND_DOWN 0x2 /* policy should extend down */ 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate #define LGRP_STAT(stats, bucket, whichstat) \ 1130Sstevel@tonic-gate ((stats)->ls_data[bucket][whichstat]) 1140Sstevel@tonic-gate 1150Sstevel@tonic-gate /* Return a pointer suitable for an atomic 64-bit op on the bucket */ 1160Sstevel@tonic-gate #define LGRP_STAT_WRITE_PTR(stats, whichstat) \ 1170Sstevel@tonic-gate (&LGRP_STAT(stats, (CPU->cpu_id) & LGRP_CPU_BUCKET_MASK, \ 1180Sstevel@tonic-gate whichstat)) 1190Sstevel@tonic-gate 1200Sstevel@tonic-gate /* Sum up all the buckets and return the value in 'val' */ 1210Sstevel@tonic-gate #define LGRP_STAT_READ(stats, whichstat, val) { \ 1220Sstevel@tonic-gate int bkt; \ 1230Sstevel@tonic-gate for (val = 0, bkt = 0; bkt < LGRP_NUM_CPU_BUCKETS; bkt++) \ 1240Sstevel@tonic-gate val += LGRP_STAT(stats, bkt, whichstat); \ 1250Sstevel@tonic-gate } 1260Sstevel@tonic-gate 1270Sstevel@tonic-gate /* Reset all buckets for the stat to 0 */ 1280Sstevel@tonic-gate #define LGRP_STAT_RESET(stats, stat) { \ 1290Sstevel@tonic-gate int i; \ 1300Sstevel@tonic-gate for (i = 0; i < LGRP_NUM_CPU_BUCKETS; i++) \ 1310Sstevel@tonic-gate LGRP_STAT(stats, i, stat) = 0; \ 1320Sstevel@tonic-gate } 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate /* 1350Sstevel@tonic-gate * Define all of the statistics that are kept for lgrp kstats, 1360Sstevel@tonic-gate * and their corresponding text names. 1370Sstevel@tonic-gate */ 1380Sstevel@tonic-gate 1390Sstevel@tonic-gate typedef enum lgrp_stat_types { 1400Sstevel@tonic-gate LGRP_NUM_MIGR, /* # migrations away from this lgrp */ 1410Sstevel@tonic-gate LGRP_NUM_ALLOC_FAIL, /* # times alloc fails for chosen lgrp */ 1420Sstevel@tonic-gate LGRP_PM_SRC_PGS, /* # pages migrated from this lgrp */ 1430Sstevel@tonic-gate LGRP_PM_DEST_PGS, /* # pages migrated to this lgrp */ 1440Sstevel@tonic-gate LGRP_PM_FAIL_ALLOC_PGS, /* # pages failed to migrate to this lgrp */ 1450Sstevel@tonic-gate LGRP_PM_FAIL_LOCK_PGS, /* # pages failed to migrate from this lgrp */ 1460Sstevel@tonic-gate LGRP_PMM_PGS, /* # pages marked to migrate from this lgrp */ 1470Sstevel@tonic-gate LGRP_PMM_FAIL_PGS, /* # pages marked to migrate from this lgrp */ 1480Sstevel@tonic-gate LGRP_NUM_DEFAULT, /* # of times default policy applied */ 1490Sstevel@tonic-gate LGRP_NUM_NEXT, /* # of times next touch policy applied */ 1500Sstevel@tonic-gate LGRP_NUM_RANDOM, /* # of times random policy applied */ 1510Sstevel@tonic-gate LGRP_NUM_RANDOM_PROC, /* # of times random proc policy applied */ 1520Sstevel@tonic-gate LGRP_NUM_RANDOM_PSET, /* # of times random pset policy applied */ 1530Sstevel@tonic-gate LGRP_NUM_ROUNDROBIN, /* # of times round robin policy applied */ 1544426Saguzovsk LGRP_NUM_NEXT_SEG, /* # of times next to seg policy applied */ 1550Sstevel@tonic-gate LGRP_NUM_COUNTER_STATS, /* always last */ 1560Sstevel@tonic-gate LGRP_CTR_STATS_ALLOC = 16 /* cache-align pad - multiple of 8 */ 1570Sstevel@tonic-gate /* always keep >= LGRP_NUM_COUNTER_STATS */ 1580Sstevel@tonic-gate } lgrp_stat_t; 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate typedef enum lgrp_snap_stat_types { 1610Sstevel@tonic-gate LGRP_NUM_CPUS, /* number of CPUs */ 1620Sstevel@tonic-gate LGRP_NUM_PG_FREE, /* # of free pages */ 1630Sstevel@tonic-gate LGRP_NUM_PG_AVAIL, /* # of allocatable physical pages */ 1640Sstevel@tonic-gate LGRP_NUM_PG_INSTALL, /* # of installed physical pages */ 1652685Sakolb LGRP_LOADAVG, /* unscaled load average of this lgrp */ 1662685Sakolb LGRP_LOADAVG_SCALE, /* load unit of one CPU bound thread */ 1670Sstevel@tonic-gate LGRP_NUM_SNAPSHOT_STATS /* always last */ 1680Sstevel@tonic-gate } lgrp_snap_stat_t; 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate #define LGRP_KSTAT_NAMES \ 1710Sstevel@tonic-gate static char *lgrp_kstat_names[] = { \ 1720Sstevel@tonic-gate \ 1730Sstevel@tonic-gate /* Counter stats */ \ 1740Sstevel@tonic-gate "lwp migrations", \ 1750Sstevel@tonic-gate "alloc fail", \ 1760Sstevel@tonic-gate "pages migrated from", \ 1770Sstevel@tonic-gate "pages migrated to", \ 1780Sstevel@tonic-gate "pages failed to migrate to", \ 1790Sstevel@tonic-gate "pages failed to migrate from", \ 1800Sstevel@tonic-gate "pages marked for migration", \ 1810Sstevel@tonic-gate "pages failed to mark", \ 1820Sstevel@tonic-gate "default policy", \ 1830Sstevel@tonic-gate "next-touch policy", \ 1840Sstevel@tonic-gate "random policy", \ 1850Sstevel@tonic-gate "span process policy", \ 1860Sstevel@tonic-gate "span psrset policy", \ 1870Sstevel@tonic-gate "round robin policy", \ 1884426Saguzovsk "next-seg policy", \ 1890Sstevel@tonic-gate \ 1900Sstevel@tonic-gate /* Snapshot stats */ \ 1910Sstevel@tonic-gate "cpus", \ 1920Sstevel@tonic-gate "pages free", \ 1930Sstevel@tonic-gate "pages avail", \ 1940Sstevel@tonic-gate "pages installed", \ 1952685Sakolb "load average", \ 1962685Sakolb "loadscale" \ 1970Sstevel@tonic-gate } 1980Sstevel@tonic-gate 1990Sstevel@tonic-gate #define LGRP_NUM_STATS ((int)LGRP_NUM_COUNTER_STATS + \ 2000Sstevel@tonic-gate (int)LGRP_NUM_SNAPSHOT_STATS) 2010Sstevel@tonic-gate 2020Sstevel@tonic-gate /* 2030Sstevel@tonic-gate * The contents of this structure are opaque and should only be 2040Sstevel@tonic-gate * accessed through the LGRP_STAT macro. 2050Sstevel@tonic-gate */ 2060Sstevel@tonic-gate struct lgrp_stats { 2070Sstevel@tonic-gate int64_t ls_data[LGRP_NUM_CPU_BUCKETS][LGRP_CTR_STATS_ALLOC]; 2080Sstevel@tonic-gate }; 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate /* The kernel's version of a bitmap of lgroups */ 2110Sstevel@tonic-gate typedef uint64_t klgrpset_t; 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate /* 2140Sstevel@tonic-gate * This really belongs in memnode.h, but it must be defined here to avoid 2150Sstevel@tonic-gate * recursive inclusion problems. Note that memnode.h includes this header. 2160Sstevel@tonic-gate */ 2170Sstevel@tonic-gate typedef uint64_t mnodeset_t; 2180Sstevel@tonic-gate 2190Sstevel@tonic-gate /* 2200Sstevel@tonic-gate * lgroup structure 2210Sstevel@tonic-gate * 2220Sstevel@tonic-gate * Visible to generic code and contains the lgroup ID, CPUs in this lgroup, 2230Sstevel@tonic-gate * and a platform handle used to identify this lgroup to the lgroup platform 2240Sstevel@tonic-gate * support code 2250Sstevel@tonic-gate */ 2260Sstevel@tonic-gate typedef struct lgrp { 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate lgrp_id_t lgrp_id; /* which lgroup */ 2290Sstevel@tonic-gate int lgrp_latency; 2300Sstevel@tonic-gate lgrp_handle_t lgrp_plathand; /* handle for platform calls */ 2310Sstevel@tonic-gate struct lgrp *lgrp_parent; /* parent lgroup */ 2320Sstevel@tonic-gate uint_t lgrp_reserved1; /* filler */ 2330Sstevel@tonic-gate uint_t lgrp_childcnt; /* number of children lgroups */ 2340Sstevel@tonic-gate klgrpset_t lgrp_children; /* children lgroups */ 2350Sstevel@tonic-gate klgrpset_t lgrp_leaves; /* (direct decendant) leaf lgroups */ 2360Sstevel@tonic-gate 2370Sstevel@tonic-gate /* 2380Sstevel@tonic-gate * set of lgroups containing a given type of resource 2390Sstevel@tonic-gate * at this level of locality 2400Sstevel@tonic-gate */ 2410Sstevel@tonic-gate klgrpset_t lgrp_set[LGRP_RSRC_COUNT]; 2420Sstevel@tonic-gate 2430Sstevel@tonic-gate mnodeset_t lgrp_mnodes; /* set of memory nodes in this lgroup */ 2440Sstevel@tonic-gate uint_t lgrp_nmnodes; /* number of memnodes */ 2450Sstevel@tonic-gate uint_t lgrp_reserved2; /* filler */ 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate struct cpu *lgrp_cpu; /* pointer to a cpu may be null */ 2480Sstevel@tonic-gate uint_t lgrp_cpucnt; /* number of cpus in this lgrp */ 2490Sstevel@tonic-gate kstat_t *lgrp_kstat; /* per-lgrp kstats */ 2500Sstevel@tonic-gate } lgrp_t; 2510Sstevel@tonic-gate 2520Sstevel@tonic-gate /* 2530Sstevel@tonic-gate * lgroup load average structure 2540Sstevel@tonic-gate */ 2550Sstevel@tonic-gate 2560Sstevel@tonic-gate typedef struct lgrp_ld { 2570Sstevel@tonic-gate lgrp_load_t lpl_loadavg; /* load average */ 2580Sstevel@tonic-gate uint_t lpl_ncpu; /* how many cpus */ 2590Sstevel@tonic-gate lgrp_id_t lpl_lgrpid; /* which group this lpl part of */ 2600Sstevel@tonic-gate lgrp_t *lpl_lgrp; /* ptr to lpl's lgrp */ 2610Sstevel@tonic-gate struct lgrp_ld *lpl_parent; /* lpl of parent lgrp */ 2620Sstevel@tonic-gate struct cpu *lpl_cpus; /* list of cpus in lpl */ 2630Sstevel@tonic-gate /* NULL for non-leaf lgrps */ 2640Sstevel@tonic-gate uint_t lpl_nrset; /* no. of leaf lpls for lgrp */ 2650Sstevel@tonic-gate hrtime_t lpl_homed_time; /* time of last homing to this lpl */ 2668408SEric.Saxe@Sun.COM uint_t lpl_rset_sz; /* Resource set capacity */ 2678408SEric.Saxe@Sun.COM struct lgrp_ld **lpl_rset; /* leaf lpls for lgrp */ 2680Sstevel@tonic-gate /* contains ptr to self for leaf lgrp */ 2698408SEric.Saxe@Sun.COM int *lpl_id2rset; /* mapping of lgrpid to rset index */ 2700Sstevel@tonic-gate } lpl_t; 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate /* 2730Sstevel@tonic-gate * 1 << LGRP_MAX_EFFECT_SHFT == lgrp_loadavg_max_effect 2740Sstevel@tonic-gate */ 2750Sstevel@tonic-gate #define LGRP_MAX_EFFECT_SHFT 16 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate /* 2780Sstevel@tonic-gate * Operations handled by lgrp_config() 2790Sstevel@tonic-gate */ 2800Sstevel@tonic-gate typedef enum lgrp_config_flag { 2810Sstevel@tonic-gate LGRP_CONFIG_NOP, 2820Sstevel@tonic-gate LGRP_CONFIG_CPU_ADD, 2830Sstevel@tonic-gate LGRP_CONFIG_CPU_DEL, 2840Sstevel@tonic-gate LGRP_CONFIG_CPU_ONLINE, 2850Sstevel@tonic-gate LGRP_CONFIG_CPU_OFFLINE, 2860Sstevel@tonic-gate LGRP_CONFIG_CPUPART_ADD, 2870Sstevel@tonic-gate LGRP_CONFIG_CPUPART_DEL, 2880Sstevel@tonic-gate LGRP_CONFIG_MEM_ADD, 2890Sstevel@tonic-gate LGRP_CONFIG_MEM_DEL, 2900Sstevel@tonic-gate LGRP_CONFIG_MEM_RENAME, 2910Sstevel@tonic-gate LGRP_CONFIG_GEN_UPDATE, 2920Sstevel@tonic-gate LGRP_CONFIG_FLATTEN, 2932988Sjjc LGRP_CONFIG_LAT_CHANGE_ALL, 2942988Sjjc LGRP_CONFIG_LAT_CHANGE 2950Sstevel@tonic-gate } lgrp_config_flag_t; 2960Sstevel@tonic-gate 2970Sstevel@tonic-gate /* 298*10710Sjonathan.chew@sun.com * Stages of lgroup framework initialization (done through lgrp_init()): 299*10710Sjonathan.chew@sun.com * 300*10710Sjonathan.chew@sun.com * 1) Initialize common and platform specific code (called in mlsetup()) 301*10710Sjonathan.chew@sun.com * 302*10710Sjonathan.chew@sun.com * 2) Setup root lgroup and add CPU 0 to lgroup(s) (called near beginning of 303*10710Sjonathan.chew@sun.com * main() before startup()) 304*10710Sjonathan.chew@sun.com * 305*10710Sjonathan.chew@sun.com * 3) Probe from CPU 0 and copy and release any BOP_ALLOC-ed memory temporarily 306*10710Sjonathan.chew@sun.com * allocated before kernel memory allocator is setup (called in main() 307*10710Sjonathan.chew@sun.com * after startup(), gethrtime() is setup, and before interrupts enabled) 308*10710Sjonathan.chew@sun.com * 309*10710Sjonathan.chew@sun.com * 4) Check for null proc LPA on Starcat, collapse lgroup topology (if 310*10710Sjonathan.chew@sun.com * necessary), setup lgroup kstats, etc. (called before start_other_cpus()) 311*10710Sjonathan.chew@sun.com * 312*10710Sjonathan.chew@sun.com * 5) Finish any lgroup initialization needed including updating lgroup 313*10710Sjonathan.chew@sun.com * topology after all CPUs started (called after start_other_cpus()) 314*10710Sjonathan.chew@sun.com */ 315*10710Sjonathan.chew@sun.com typedef enum lgrp_init_stages { 316*10710Sjonathan.chew@sun.com LGRP_INIT_STAGE1, 317*10710Sjonathan.chew@sun.com LGRP_INIT_STAGE2, 318*10710Sjonathan.chew@sun.com LGRP_INIT_STAGE3, 319*10710Sjonathan.chew@sun.com LGRP_INIT_STAGE4, 320*10710Sjonathan.chew@sun.com LGRP_INIT_STAGE5 321*10710Sjonathan.chew@sun.com } lgrp_init_stages_t; 322*10710Sjonathan.chew@sun.com 323*10710Sjonathan.chew@sun.com /* 3240Sstevel@tonic-gate * Memory allocation policies 3250Sstevel@tonic-gate */ 3260Sstevel@tonic-gate typedef enum lgrp_mem_policy { 3270Sstevel@tonic-gate LGRP_MEM_POLICY_DEFAULT, 3280Sstevel@tonic-gate LGRP_MEM_POLICY_NEXT, /* near LWP to next touch */ 3290Sstevel@tonic-gate LGRP_MEM_POLICY_RANDOM_PROC, /* randomly across process */ 3300Sstevel@tonic-gate LGRP_MEM_POLICY_RANDOM_PSET, /* randomly across processor set */ 3310Sstevel@tonic-gate LGRP_MEM_POLICY_RANDOM, /* randomly across all lgroups */ 3320Sstevel@tonic-gate LGRP_MEM_POLICY_ROUNDROBIN, /* round robin across all lgroups */ 3330Sstevel@tonic-gate LGRP_MEM_POLICY_NEXT_CPU, /* Near next CPU to touch memory */ 3344426Saguzovsk LGRP_MEM_POLICY_NEXT_SEG, /* lgrp specified directly by seg */ 3350Sstevel@tonic-gate LGRP_NUM_MEM_POLICIES 3360Sstevel@tonic-gate } lgrp_mem_policy_t; 3370Sstevel@tonic-gate 3380Sstevel@tonic-gate /* 3390Sstevel@tonic-gate * Search scopes for finding resouces 3400Sstevel@tonic-gate */ 3410Sstevel@tonic-gate typedef enum lgrp_res_ss { 3420Sstevel@tonic-gate LGRP_SRCH_LOCAL, /* Search local lgroup only */ 3430Sstevel@tonic-gate LGRP_SRCH_HIER /* Search entire hierarchy */ 3440Sstevel@tonic-gate } lgrp_res_ss_t; 3450Sstevel@tonic-gate 3460Sstevel@tonic-gate /* 3470Sstevel@tonic-gate * Cookie used for lgrp mnode selection 3480Sstevel@tonic-gate */ 3490Sstevel@tonic-gate typedef struct lgrp_mnode_cookie { 3500Sstevel@tonic-gate lgrp_t *lmc_lgrp; /* lgrp under consideration */ 3510Sstevel@tonic-gate mnodeset_t lmc_nodes; /* nodes not yet tried in lgrp */ 3520Sstevel@tonic-gate int lmc_cnt; /* how many nodes in untried set */ 3530Sstevel@tonic-gate mnodeset_t lmc_tried; /* nodes already tried */ 3540Sstevel@tonic-gate int lmc_ntried; /* how many nodes in tried set */ 3550Sstevel@tonic-gate lgrp_res_ss_t lmc_scope; /* consider non-local nodes? */ 3560Sstevel@tonic-gate ushort_t lmc_rand; /* a "random" number */ 3570Sstevel@tonic-gate } lgrp_mnode_cookie_t; 3580Sstevel@tonic-gate 3590Sstevel@tonic-gate /* 3600Sstevel@tonic-gate * Information needed to implement memory allocation policy 3610Sstevel@tonic-gate */ 3620Sstevel@tonic-gate typedef struct lgrp_mem_policy_info { 3634426Saguzovsk int mem_policy; /* memory allocation policy */ 3644426Saguzovsk lgrp_id_t mem_lgrpid; /* lgroup id */ 3650Sstevel@tonic-gate } lgrp_mem_policy_info_t; 3660Sstevel@tonic-gate 3670Sstevel@tonic-gate /* 3680Sstevel@tonic-gate * Shared memory policy segment 3690Sstevel@tonic-gate */ 3700Sstevel@tonic-gate typedef struct lgrp_shm_policy_seg { 3710Sstevel@tonic-gate u_offset_t shm_off; /* offset into shared object */ 3720Sstevel@tonic-gate size_t shm_size; /* size of segment */ 3730Sstevel@tonic-gate lgrp_mem_policy_info_t shm_policy; /* memory allocation policy */ 3740Sstevel@tonic-gate avl_node_t shm_tree; /* AVL tree */ 3750Sstevel@tonic-gate } lgrp_shm_policy_seg_t; 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate /* 3780Sstevel@tonic-gate * Shared memory locality info 3790Sstevel@tonic-gate */ 3800Sstevel@tonic-gate typedef struct lgrp_shm_locality { 3810Sstevel@tonic-gate size_t loc_count; /* reference count */ 3820Sstevel@tonic-gate avl_tree_t *loc_tree; /* policy segment tree */ 3830Sstevel@tonic-gate krwlock_t loc_lock; /* protects tree */ 3840Sstevel@tonic-gate } lgrp_shm_locality_t; 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate /* 3870Sstevel@tonic-gate * Queries that may be made to determine lgroup memory size 3880Sstevel@tonic-gate */ 3890Sstevel@tonic-gate typedef enum { 3900Sstevel@tonic-gate LGRP_MEM_SIZE_FREE, /* number of free pages */ 3910Sstevel@tonic-gate LGRP_MEM_SIZE_AVAIL, /* number of pages in phys_avail */ 3920Sstevel@tonic-gate LGRP_MEM_SIZE_INSTALL /* number of pages in phys_install */ 3930Sstevel@tonic-gate } lgrp_mem_query_t; 3940Sstevel@tonic-gate 3950Sstevel@tonic-gate /* 3960Sstevel@tonic-gate * Argument for the memory copy-rename operation, contains the source and the 3970Sstevel@tonic-gate * destination platform handles. 3980Sstevel@tonic-gate */ 3990Sstevel@tonic-gate typedef struct lgrp_config_mem_rename { 4000Sstevel@tonic-gate lgrp_handle_t lmem_rename_from; 4010Sstevel@tonic-gate lgrp_handle_t lmem_rename_to; 4020Sstevel@tonic-gate } lgrp_config_mem_rename_t; 4030Sstevel@tonic-gate 4040Sstevel@tonic-gate /* Macro to clear an lgroup bitmap */ 4050Sstevel@tonic-gate #define klgrpset_clear(klgrpset) \ 4060Sstevel@tonic-gate (klgrpset) = (klgrpset_t)0 4070Sstevel@tonic-gate 4080Sstevel@tonic-gate /* Macro to fill an lgroup bitmap */ 4090Sstevel@tonic-gate #define klgrpset_fill(klgrpset) \ 4100Sstevel@tonic-gate (klgrpset) = (klgrpset_t)(-1) 4110Sstevel@tonic-gate 4120Sstevel@tonic-gate /* Macro to add an lgroup to an lgroup bitmap */ 4130Sstevel@tonic-gate #define klgrpset_add(klgrpset, lgrpid) \ 4140Sstevel@tonic-gate (klgrpset) |= ((klgrpset_t)1 << (lgrpid)) 4150Sstevel@tonic-gate 4160Sstevel@tonic-gate /* Macro to delete an lgroup from an lgroup bitmap */ 4170Sstevel@tonic-gate #define klgrpset_del(klgrpset, lgrpid) \ 4180Sstevel@tonic-gate (klgrpset) &= ~((klgrpset_t)1 << (lgrpid)) 4190Sstevel@tonic-gate 4200Sstevel@tonic-gate /* Macro to copy a klgrpset into another klgrpset */ 4210Sstevel@tonic-gate #define klgrpset_copy(klgrpset_to, klgrpset_from) \ 4220Sstevel@tonic-gate (klgrpset_to) = (klgrpset_from) 4230Sstevel@tonic-gate 4240Sstevel@tonic-gate /* Macro to perform an 'and' operation on a pair of lgroup bitmaps */ 4250Sstevel@tonic-gate #define klgrpset_and(klgrpset_rslt, klgrpset_arg) \ 4260Sstevel@tonic-gate (klgrpset_rslt) &= (klgrpset_arg) 4270Sstevel@tonic-gate 4280Sstevel@tonic-gate /* Macro to perform an 'or' operation on a pair of lgroup bitmaps */ 4290Sstevel@tonic-gate #define klgrpset_or(klgrpset_rslt, klgrpset_arg) \ 4300Sstevel@tonic-gate (klgrpset_rslt) |= (klgrpset_arg) 4310Sstevel@tonic-gate 4320Sstevel@tonic-gate /* Macro to perform a 'diff' operation on a pair of lgroup bitmaps */ 4330Sstevel@tonic-gate #define klgrpset_diff(klgrpset_rslt, klgrpset_arg) \ 4340Sstevel@tonic-gate (klgrpset_rslt) &= ~(klgrpset_arg) 4350Sstevel@tonic-gate 4360Sstevel@tonic-gate /* Macro to check if an lgroup is a member of an lgrpset */ 4370Sstevel@tonic-gate #define klgrpset_ismember(klgrpset, lgrpid) \ 4380Sstevel@tonic-gate ((klgrpset) & ((klgrpset_t)1 << (lgrpid))) 4390Sstevel@tonic-gate 4400Sstevel@tonic-gate /* Macro to check if an lgroup bitmap is empty */ 4410Sstevel@tonic-gate #define klgrpset_isempty(klgrpset) \ 4420Sstevel@tonic-gate ((klgrpset) == (klgrpset_t)0) 4430Sstevel@tonic-gate 4440Sstevel@tonic-gate /* Macro to check if two lgrpsets intersect */ 4450Sstevel@tonic-gate #define klgrpset_intersects(klgrpset1, klgrpset2) \ 4460Sstevel@tonic-gate ((klgrpset1) & (klgrpset2)) 4470Sstevel@tonic-gate 4480Sstevel@tonic-gate /* Macro to count the number of members in an lgrpset */ 4490Sstevel@tonic-gate #define klgrpset_nlgrps(klgrpset, count) \ 4500Sstevel@tonic-gate { \ 4510Sstevel@tonic-gate lgrp_id_t lgrpid; \ 4520Sstevel@tonic-gate for (lgrpid = 0, count = 0; lgrpid <= lgrp_alloc_max; lgrpid++) {\ 4530Sstevel@tonic-gate if (klgrpset_ismember(klgrpset, lgrpid)) \ 4540Sstevel@tonic-gate count++; \ 4550Sstevel@tonic-gate } \ 4560Sstevel@tonic-gate } 4570Sstevel@tonic-gate 4580Sstevel@tonic-gate /* Macro to get total memory size (in bytes) of a given set of lgroups */ 4590Sstevel@tonic-gate #define klgrpset_totalsize(klgrpset, size) \ 4600Sstevel@tonic-gate { \ 4610Sstevel@tonic-gate lgrp_handle_t hand; \ 4620Sstevel@tonic-gate lgrp_id_t lgrpid; \ 4630Sstevel@tonic-gate \ 4640Sstevel@tonic-gate for (lgrpid = 0, size = 0; lgrpid <= lgrp_alloc_max; lgrpid++) {\ 4650Sstevel@tonic-gate if (klgrpset_ismember(klgrpset, lgrpid) && \ 4660Sstevel@tonic-gate lgrp_table[lgrpid]) { \ 4670Sstevel@tonic-gate hand = lgrp_table[lgrpid]->lgrp_plathand; \ 4680Sstevel@tonic-gate size += lgrp_plat_mem_size(hand, \ 4690Sstevel@tonic-gate LGRP_MEM_SIZE_AVAIL) * PAGESIZE; \ 4700Sstevel@tonic-gate } \ 4710Sstevel@tonic-gate } \ 4720Sstevel@tonic-gate } 4730Sstevel@tonic-gate 4740Sstevel@tonic-gate /* 4750Sstevel@tonic-gate * Does this lgroup exist? 4760Sstevel@tonic-gate */ 4770Sstevel@tonic-gate #define LGRP_EXISTS(lgrp) \ 4780Sstevel@tonic-gate (lgrp != NULL && lgrp->lgrp_id != LGRP_NONE) 4790Sstevel@tonic-gate 4800Sstevel@tonic-gate /* 4818408SEric.Saxe@Sun.COM * Macro for testing if a CPU is contained in an lgrp. 4828408SEric.Saxe@Sun.COM */ 4838408SEric.Saxe@Sun.COM #define LGRP_CONTAINS_CPU(lgrp, cpu) \ 4848408SEric.Saxe@Sun.COM (klgrpset_ismember(lgrp->lgrp_set[LGRP_RSRC_CPU], \ 4858408SEric.Saxe@Sun.COM cpu->cpu_lpl->lpl_lgrpid)) 4868408SEric.Saxe@Sun.COM 4878408SEric.Saxe@Sun.COM /* 4880Sstevel@tonic-gate * Initialize an lgrp_mnode_cookie 4890Sstevel@tonic-gate */ 4900Sstevel@tonic-gate #define LGRP_MNODE_COOKIE_INIT(c, lgrp, scope) \ 4910Sstevel@tonic-gate { \ 4920Sstevel@tonic-gate bzero(&(c), sizeof (lgrp_mnode_cookie_t)); \ 4930Sstevel@tonic-gate (&(c))->lmc_lgrp = lgrp; \ 4940Sstevel@tonic-gate (&(c))->lmc_nodes = lgrp->lgrp_mnodes; \ 4950Sstevel@tonic-gate (&(c))->lmc_cnt = lgrp->lgrp_nmnodes; \ 4960Sstevel@tonic-gate (&(c))->lmc_scope = scope; \ 4970Sstevel@tonic-gate (&(c))->lmc_rand = (ushort_t)gethrtime_unscaled() >> 4; \ 4980Sstevel@tonic-gate } 4990Sstevel@tonic-gate 5000Sstevel@tonic-gate /* 5010Sstevel@tonic-gate * Upgrade cookie scope from LGRP_SRCH_LOCAL to LGRP_SRCH_HIER. 5020Sstevel@tonic-gate */ 5030Sstevel@tonic-gate #define LGRP_MNODE_COOKIE_UPGRADE(c) \ 5040Sstevel@tonic-gate { \ 5050Sstevel@tonic-gate ASSERT((&(c))->lmc_scope == LGRP_SRCH_LOCAL); \ 5060Sstevel@tonic-gate (&(c))->lmc_scope = LGRP_SRCH_HIER; \ 5070Sstevel@tonic-gate } 5080Sstevel@tonic-gate 5090Sstevel@tonic-gate /* 5100Sstevel@tonic-gate * Macro to see whether memory allocation policy can be reapplied 5110Sstevel@tonic-gate */ 5120Sstevel@tonic-gate #define LGRP_MEM_POLICY_REAPPLICABLE(p) \ 5130Sstevel@tonic-gate (p == LGRP_MEM_POLICY_NEXT) 5140Sstevel@tonic-gate 5150Sstevel@tonic-gate /* 5160Sstevel@tonic-gate * Return true if lgrp has CPU resources in the cpupart 5170Sstevel@tonic-gate */ 5180Sstevel@tonic-gate #define LGRP_CPUS_IN_PART(lgrpid, cpupart) \ 5190Sstevel@tonic-gate (cpupart->cp_lgrploads[lgrpid].lpl_ncpu > 0) 5200Sstevel@tonic-gate 5210Sstevel@tonic-gate extern int lgrp_alloc_max; 5220Sstevel@tonic-gate extern lgrp_t *lgrp_table[NLGRPS_MAX]; /* indexed by lgrp_id */ 5230Sstevel@tonic-gate extern int nlgrps; /* number of lgroups in machine */ 5240Sstevel@tonic-gate extern int nlgrpsmax; /* max number of lgroups on platform */ 5250Sstevel@tonic-gate extern lgrp_gen_t lgrp_gen; /* generation of lgroup hierarchy */ 5260Sstevel@tonic-gate extern int lgrp_initialized; /* single-CPU initialization done */ 5270Sstevel@tonic-gate extern int lgrp_topo_initialized; /* lgrp topology constructed */ 5280Sstevel@tonic-gate extern lgrp_t *lgrp_root; /* root lgroup */ 5290Sstevel@tonic-gate extern unsigned int lgrp_topo_levels; 5300Sstevel@tonic-gate extern lpl_t *lpl_bootstrap; /* bootstrap lpl for non-active CPUs */ 5310Sstevel@tonic-gate 5320Sstevel@tonic-gate 5330Sstevel@tonic-gate /* generic interfaces */ 5340Sstevel@tonic-gate 5350Sstevel@tonic-gate /* 5360Sstevel@tonic-gate * lgroup management 5370Sstevel@tonic-gate */ 5380Sstevel@tonic-gate int lgrp_optimizations(void); 539*10710Sjonathan.chew@sun.com void lgrp_init(lgrp_init_stages_t); 5400Sstevel@tonic-gate lgrp_t *lgrp_create(void); 5410Sstevel@tonic-gate void lgrp_destroy(lgrp_t *); 5420Sstevel@tonic-gate void lgrp_config(lgrp_config_flag_t, uintptr_t, uintptr_t); 5430Sstevel@tonic-gate lgrp_t *lgrp_hand_to_lgrp(lgrp_handle_t); 5440Sstevel@tonic-gate 5450Sstevel@tonic-gate /* 5460Sstevel@tonic-gate * lgroup stats 5470Sstevel@tonic-gate */ 5480Sstevel@tonic-gate void lgrp_kstat_create(struct cpu *); 5490Sstevel@tonic-gate void lgrp_kstat_destroy(struct cpu *); 5500Sstevel@tonic-gate void lgrp_stat_add(lgrp_id_t, lgrp_stat_t, int64_t); 5510Sstevel@tonic-gate int64_t lgrp_stat_read(lgrp_id_t, lgrp_stat_t); 5520Sstevel@tonic-gate 5530Sstevel@tonic-gate /* 5540Sstevel@tonic-gate * lgroup memory 5550Sstevel@tonic-gate */ 5560Sstevel@tonic-gate lgrp_mem_policy_t lgrp_madv_to_policy(uchar_t, size_t, int); 5570Sstevel@tonic-gate pgcnt_t lgrp_mem_size(lgrp_id_t, lgrp_mem_query_t); 5580Sstevel@tonic-gate lgrp_t *lgrp_mem_choose(struct seg *, caddr_t, size_t); 5590Sstevel@tonic-gate int lgrp_memnode_choose(lgrp_mnode_cookie_t *); 5600Sstevel@tonic-gate lgrp_mem_policy_t lgrp_mem_policy_default(size_t, int); 5610Sstevel@tonic-gate int lgrp_mnode_update(klgrpset_t, klgrpset_t *); 5620Sstevel@tonic-gate lgrp_t *lgrp_pfn_to_lgrp(pfn_t); 5630Sstevel@tonic-gate lgrp_t *lgrp_phys_to_lgrp(u_longlong_t); /* used by numat driver */ 5640Sstevel@tonic-gate int lgrp_privm_policy_set(lgrp_mem_policy_t, lgrp_mem_policy_info_t *, 5650Sstevel@tonic-gate size_t); 5660Sstevel@tonic-gate void lgrp_shm_policy_init(struct anon_map *, vnode_t *); 5670Sstevel@tonic-gate void lgrp_shm_policy_fini(struct anon_map *, vnode_t *); 5680Sstevel@tonic-gate lgrp_mem_policy_info_t *lgrp_shm_policy_get(struct anon_map *, ulong_t, 5690Sstevel@tonic-gate vnode_t *, u_offset_t); 5700Sstevel@tonic-gate int lgrp_shm_policy_set(lgrp_mem_policy_t, struct anon_map *, ulong_t, 5710Sstevel@tonic-gate vnode_t *, u_offset_t, size_t); 5720Sstevel@tonic-gate 5730Sstevel@tonic-gate /* 5740Sstevel@tonic-gate * Used by numat driver 5750Sstevel@tonic-gate */ 5760Sstevel@tonic-gate int lgrp_query_cpu(processorid_t, lgrp_id_t *); 5770Sstevel@tonic-gate int lgrp_query_load(processorid_t, lgrp_load_t *); 5780Sstevel@tonic-gate 5790Sstevel@tonic-gate /* 5800Sstevel@tonic-gate * lgroup thread placement 5810Sstevel@tonic-gate */ 5822988Sjjc lpl_t *lgrp_affinity_best(kthread_t *, struct cpupart *, lgrp_id_t, 5832988Sjjc boolean_t); 5840Sstevel@tonic-gate void lgrp_affinity_init(lgrp_affinity_t **); 5850Sstevel@tonic-gate void lgrp_affinity_free(lgrp_affinity_t **); 5860Sstevel@tonic-gate lpl_t *lgrp_choose(kthread_t *t, struct cpupart *); 5870Sstevel@tonic-gate lgrp_t *lgrp_home_lgrp(void); 5880Sstevel@tonic-gate lgrp_id_t lgrp_home_id(kthread_t *); 5890Sstevel@tonic-gate void lgrp_loadavg(lpl_t *, uint_t, int); 5900Sstevel@tonic-gate void lgrp_move_thread(kthread_t *, lpl_t *, int); 5914426Saguzovsk uint64_t lgrp_get_trthr_migrations(void); 5924426Saguzovsk void lgrp_update_trthr_migrations(uint64_t); 5930Sstevel@tonic-gate 5940Sstevel@tonic-gate /* 5950Sstevel@tonic-gate * lgroup topology 5960Sstevel@tonic-gate */ 5970Sstevel@tonic-gate int lgrp_leaf_add(lgrp_t *, lgrp_t **, int, klgrpset_t *); 5980Sstevel@tonic-gate int lgrp_leaf_delete(lgrp_t *, lgrp_t **, int, klgrpset_t *); 5990Sstevel@tonic-gate int lgrp_rsets_empty(klgrpset_t *); 6000Sstevel@tonic-gate int lgrp_rsets_member(klgrpset_t *, lgrp_id_t); 6010Sstevel@tonic-gate int lgrp_topo_flatten(int, lgrp_t **, int, klgrpset_t *); 6020Sstevel@tonic-gate int lgrp_topo_ht_limit(void); 6030Sstevel@tonic-gate int lgrp_topo_ht_limit_default(void); 6040Sstevel@tonic-gate int lgrp_topo_ht_limit_set(int); 6050Sstevel@tonic-gate int lgrp_topo_update(lgrp_t **, int, klgrpset_t *); 6060Sstevel@tonic-gate 6070Sstevel@tonic-gate /* 6080Sstevel@tonic-gate * lpl topology 6090Sstevel@tonic-gate */ 6100Sstevel@tonic-gate void lpl_topo_bootstrap(lpl_t *, int); 6110Sstevel@tonic-gate int lpl_topo_flatten(int); 6120Sstevel@tonic-gate int lpl_topo_verify(struct cpupart *); 6130Sstevel@tonic-gate 6140Sstevel@tonic-gate 6150Sstevel@tonic-gate /* platform interfaces */ 616*10710Sjonathan.chew@sun.com void lgrp_plat_init(lgrp_init_stages_t); 6170Sstevel@tonic-gate lgrp_t *lgrp_plat_alloc(lgrp_id_t lgrpid); 6180Sstevel@tonic-gate void lgrp_plat_config(lgrp_config_flag_t, uintptr_t); 6190Sstevel@tonic-gate lgrp_handle_t lgrp_plat_cpu_to_hand(processorid_t); 6200Sstevel@tonic-gate lgrp_handle_t lgrp_plat_pfn_to_hand(pfn_t); 6210Sstevel@tonic-gate int lgrp_plat_max_lgrps(void); 6220Sstevel@tonic-gate pgcnt_t lgrp_plat_mem_size(lgrp_handle_t, lgrp_mem_query_t); 6230Sstevel@tonic-gate int lgrp_plat_latency(lgrp_handle_t, lgrp_handle_t); 6240Sstevel@tonic-gate lgrp_handle_t lgrp_plat_root_hand(void); 6250Sstevel@tonic-gate 6264769Sdp78419 extern uint32_t lgrp_expand_proc_thresh; 6274769Sdp78419 extern uint32_t lgrp_expand_proc_diff; 6284769Sdp78419 extern pgcnt_t lgrp_mem_free_thresh; 6294769Sdp78419 extern uint32_t lgrp_loadavg_tolerance; 6304769Sdp78419 extern uint32_t lgrp_loadavg_max_effect; 6314769Sdp78419 extern uint32_t lgrp_load_thresh; 6324769Sdp78419 extern lgrp_mem_policy_t lgrp_mem_policy_root; 6334769Sdp78419 6340Sstevel@tonic-gate #endif /* _KERNEL && _KMEMUSER */ 6350Sstevel@tonic-gate 6360Sstevel@tonic-gate #ifdef __cplusplus 6370Sstevel@tonic-gate } 6380Sstevel@tonic-gate #endif 6390Sstevel@tonic-gate 6400Sstevel@tonic-gate #endif /* _LGRP_H */ 641