xref: /titanic_54/usr/src/uts/common/os/pghw.c (revision 0e7515250c8395f368aa45fb9acae7c4f8f8b786)
1fb2f18f8Sesaxe /*
2fb2f18f8Sesaxe  * CDDL HEADER START
3fb2f18f8Sesaxe  *
4fb2f18f8Sesaxe  * The contents of this file are subject to the terms of the
5fb2f18f8Sesaxe  * Common Development and Distribution License (the "License").
6fb2f18f8Sesaxe  * You may not use this file except in compliance with the License.
7fb2f18f8Sesaxe  *
8fb2f18f8Sesaxe  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fb2f18f8Sesaxe  * or http://www.opensolaris.org/os/licensing.
10fb2f18f8Sesaxe  * See the License for the specific language governing permissions
11fb2f18f8Sesaxe  * and limitations under the License.
12fb2f18f8Sesaxe  *
13fb2f18f8Sesaxe  * When distributing Covered Code, include this CDDL HEADER in each
14fb2f18f8Sesaxe  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fb2f18f8Sesaxe  * If applicable, add the following below this CDDL HEADER, with the
16fb2f18f8Sesaxe  * fields enclosed by brackets "[]" replaced with your own identifying
17fb2f18f8Sesaxe  * information: Portions Copyright [yyyy] [name of copyright owner]
18fb2f18f8Sesaxe  *
19fb2f18f8Sesaxe  * CDDL HEADER END
20fb2f18f8Sesaxe  */
21fb2f18f8Sesaxe /*
22*0e751525SEric Saxe  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23fb2f18f8Sesaxe  * Use is subject to license terms.
24fb2f18f8Sesaxe  */
25fb2f18f8Sesaxe 
26fb2f18f8Sesaxe #include <sys/systm.h>
27fb2f18f8Sesaxe #include <sys/types.h>
28fb2f18f8Sesaxe #include <sys/param.h>
29fb2f18f8Sesaxe #include <sys/thread.h>
30fb2f18f8Sesaxe #include <sys/cpuvar.h>
31fb2f18f8Sesaxe #include <sys/kmem.h>
32fb2f18f8Sesaxe #include <sys/cmn_err.h>
33fb2f18f8Sesaxe #include <sys/group.h>
34fb2f18f8Sesaxe #include <sys/pg.h>
35fb2f18f8Sesaxe #include <sys/pghw.h>
36*0e751525SEric Saxe #include <sys/cpu_pm.h>
37fb2f18f8Sesaxe 
38fb2f18f8Sesaxe /*
39fb2f18f8Sesaxe  * Processor Groups: Hardware sharing relationship layer
40fb2f18f8Sesaxe  *
41fb2f18f8Sesaxe  * This file implements an extension to Processor Groups to capture
42fb2f18f8Sesaxe  * hardware sharing relationships existing between logical CPUs. Examples of
43fb2f18f8Sesaxe  * hardware sharing relationships include shared caches on some CMT
44fb2f18f8Sesaxe  * procesoor architectures, or shared local memory controllers on NUMA
45fb2f18f8Sesaxe  * based system architectures.
46fb2f18f8Sesaxe  *
47fb2f18f8Sesaxe  * The pghw_t structure represents the extended PG. The first member
48fb2f18f8Sesaxe  * of the structure is the generic pg_t with the pghw specific members
49fb2f18f8Sesaxe  * following. The generic pg_t *must* remain the first member of the
50fb2f18f8Sesaxe  * structure as the code uses casting of structure references to access
51fb2f18f8Sesaxe  * the generic pg_t structure elements.
52fb2f18f8Sesaxe  *
53fb2f18f8Sesaxe  * In addition to the generic CPU grouping, physical PGs have a hardware
54fb2f18f8Sesaxe  * sharing relationship enumerated "type", and an instance id. The enumerated
55fb2f18f8Sesaxe  * type is defined by the pghw_type_t enumeration, while the instance id
56fb2f18f8Sesaxe  * uniquely identifies the sharing instance from among others of the same
57fb2f18f8Sesaxe  * hardware sharing type.
58fb2f18f8Sesaxe  *
59fb2f18f8Sesaxe  * The physical PGs are organized into an overall hierarchy, and are tracked
60fb2f18f8Sesaxe  * in a number of different per CPU, and per pghw_type_t type groups.
61fb2f18f8Sesaxe  * As an example:
62fb2f18f8Sesaxe  *
63fb2f18f8Sesaxe  * -------------
64fb2f18f8Sesaxe  * | pg_hw     |
65fb2f18f8Sesaxe  * | (group_t) |
66fb2f18f8Sesaxe  * -------------
67fb2f18f8Sesaxe  *  ||                          ============================
68fb2f18f8Sesaxe  *  ||\\-----------------------//       \\                 \\
69fb2f18f8Sesaxe  *  ||  | hwset (PGC_HW_CHIP) |        -------------      -------------
70fb2f18f8Sesaxe  *  ||  | (group_t)           |        | pghw_t    |      | pghw_t    |
71fb2f18f8Sesaxe  *  ||  -----------------------        | chip 0    |      | chip 1    |
72fb2f18f8Sesaxe  *  ||                                 -------------      -------------
73fb2f18f8Sesaxe  *  ||                                 \\  \\  \\  \\     \\  \\  \\  \\
74fb2f18f8Sesaxe  *  ||                                  cpu cpu cpu cpu    cpu cpu cpu cpu
75fb2f18f8Sesaxe  *  ||
76fb2f18f8Sesaxe  *  ||                          ============================
77fb2f18f8Sesaxe  *  ||\\-----------------------//       \\                 \\
78fb2f18f8Sesaxe  *  ||  | hwset (PGC_HW_IPIPE)|        -------------      -------------
79fb2f18f8Sesaxe  *  ||  | (group_t)           |        | pghw_t    |      | pghw_t    |
80fb2f18f8Sesaxe  *  ||  -----------------------        | ipipe 0   |      | ipipe 1   |
81fb2f18f8Sesaxe  *  ||                                 -------------      -------------
82fb2f18f8Sesaxe  *  ||                                 \\  \\             \\  \\
83fb2f18f8Sesaxe  *  ||                                  cpu cpu            cpu cpu
84fb2f18f8Sesaxe  *  ...
85fb2f18f8Sesaxe  *
86fb2f18f8Sesaxe  *
87fb2f18f8Sesaxe  * The top level pg_hw is a group of "hwset" groups. Each hwset holds of group
88fb2f18f8Sesaxe  * of physical PGs of the same hardware sharing type. Within each hwset, the
89fb2f18f8Sesaxe  * PG's instance id uniquely identifies the grouping relationshsip among other
90fb2f18f8Sesaxe  * groupings of the same sharing type. The instance id for a grouping is
91fb2f18f8Sesaxe  * platform defined, and in some cases may be used by platform code as a handle
92fb2f18f8Sesaxe  * to search for a particular relationship instance.
93fb2f18f8Sesaxe  *
94fb2f18f8Sesaxe  * Each physical PG (by virtue of the embedded pg_t) contains a group of CPUs
95fb2f18f8Sesaxe  * that participate in the sharing relationship. Each CPU also has associated
96fb2f18f8Sesaxe  * with it a grouping tracking the PGs in which the CPU belongs. This can be
97fb2f18f8Sesaxe  * used to iterate over the various relationships in which the CPU participates
98fb2f18f8Sesaxe  * (the CPU's chip, cache, lgroup, etc.).
99fb2f18f8Sesaxe  *
100fb2f18f8Sesaxe  * The hwsets are created dynamically as new hardware sharing relationship types
101*0e751525SEric Saxe  * are instantiated. They are never destroyed, as once a given relationship
102fb2f18f8Sesaxe  * type appears in the system, it is quite likely that at least one instance of
103fb2f18f8Sesaxe  * that relationship will always persist as long as the system is running.
104fb2f18f8Sesaxe  */
105fb2f18f8Sesaxe 
106fb2f18f8Sesaxe static group_t		*pg_hw;		/* top level pg hw group */
107fb2f18f8Sesaxe 
108fb2f18f8Sesaxe /*
109fb2f18f8Sesaxe  * Physical PG kstats
110fb2f18f8Sesaxe  */
111fb2f18f8Sesaxe struct pghw_kstat {
112fb2f18f8Sesaxe 	kstat_named_t	pg_id;
113fb2f18f8Sesaxe 	kstat_named_t	pg_class;
114fb2f18f8Sesaxe 	kstat_named_t	pg_ncpus;
115fb2f18f8Sesaxe 	kstat_named_t	pg_instance_id;
116fb2f18f8Sesaxe 	kstat_named_t	pg_hw;
117*0e751525SEric Saxe 	kstat_named_t	pg_policy;
118fb2f18f8Sesaxe } pghw_kstat = {
119fb2f18f8Sesaxe 	{ "id",			KSTAT_DATA_UINT64 },
120fb2f18f8Sesaxe 	{ "pg_class",		KSTAT_DATA_STRING },
121fb2f18f8Sesaxe 	{ "ncpus",		KSTAT_DATA_UINT64 },
122fb2f18f8Sesaxe 	{ "instance_id",	KSTAT_DATA_UINT64 },
123fb2f18f8Sesaxe 	{ "hardware",		KSTAT_DATA_STRING },
124*0e751525SEric Saxe 	{ "policy",		KSTAT_DATA_STRING },
125fb2f18f8Sesaxe };
126fb2f18f8Sesaxe 
127fb2f18f8Sesaxe kmutex_t		pghw_kstat_lock;
128fb2f18f8Sesaxe 
129fb2f18f8Sesaxe /*
130fb2f18f8Sesaxe  * hwset operations
131fb2f18f8Sesaxe  */
132fb2f18f8Sesaxe static group_t		*pghw_set_create(pghw_type_t);
133fb2f18f8Sesaxe static void		pghw_set_add(group_t *, pghw_t *);
134fb2f18f8Sesaxe static void		pghw_set_remove(group_t *, pghw_t *);
135fb2f18f8Sesaxe 
136fb2f18f8Sesaxe /*
137*0e751525SEric Saxe  * Initialize the physical portion of a hardware PG
138fb2f18f8Sesaxe  */
139fb2f18f8Sesaxe void
140fb2f18f8Sesaxe pghw_init(pghw_t *pg, cpu_t *cp, pghw_type_t hw)
141fb2f18f8Sesaxe {
142fb2f18f8Sesaxe 	group_t		*hwset;
143fb2f18f8Sesaxe 
144fb2f18f8Sesaxe 	if ((hwset = pghw_set_lookup(hw)) == NULL) {
145fb2f18f8Sesaxe 		/*
146fb2f18f8Sesaxe 		 * Haven't seen this hardware type yet
147fb2f18f8Sesaxe 		 */
148fb2f18f8Sesaxe 		hwset = pghw_set_create(hw);
149fb2f18f8Sesaxe 	}
150fb2f18f8Sesaxe 
151fb2f18f8Sesaxe 	pghw_set_add(hwset, pg);
152fb2f18f8Sesaxe 	pg->pghw_hw = hw;
153fb2f18f8Sesaxe 	pg->pghw_instance =
154fb2f18f8Sesaxe 	    pg_plat_hw_instance_id(cp, hw);
155fb2f18f8Sesaxe 	pghw_kstat_create(pg);
156*0e751525SEric Saxe 
157*0e751525SEric Saxe 	/*
158*0e751525SEric Saxe 	 * Hardware sharing relationship specific initialization
159*0e751525SEric Saxe 	 */
160*0e751525SEric Saxe 	switch (pg->pghw_hw) {
161*0e751525SEric Saxe 	case PGHW_POW_ACTIVE:
162*0e751525SEric Saxe 		pg->pghw_handle =
163*0e751525SEric Saxe 		    (pghw_handle_t)cpupm_domain_init(cp, CPUPM_DTYPE_ACTIVE);
164*0e751525SEric Saxe 		break;
165*0e751525SEric Saxe 	case PGHW_POW_IDLE:
166*0e751525SEric Saxe 		pg->pghw_handle =
167*0e751525SEric Saxe 		    (pghw_handle_t)cpupm_domain_init(cp, CPUPM_DTYPE_IDLE);
168*0e751525SEric Saxe 		break;
169*0e751525SEric Saxe 	default:
170*0e751525SEric Saxe 		pg->pghw_handle = (pghw_handle_t)NULL;
171*0e751525SEric Saxe 	}
172fb2f18f8Sesaxe }
173fb2f18f8Sesaxe 
174fb2f18f8Sesaxe /*
175fb2f18f8Sesaxe  * Teardown the physical portion of a physical PG
176fb2f18f8Sesaxe  */
177fb2f18f8Sesaxe void
178fb2f18f8Sesaxe pghw_fini(pghw_t *pg)
179fb2f18f8Sesaxe {
180fb2f18f8Sesaxe 	group_t		*hwset;
181fb2f18f8Sesaxe 
182fb2f18f8Sesaxe 	hwset = pghw_set_lookup(pg->pghw_hw);
183fb2f18f8Sesaxe 	ASSERT(hwset != NULL);
184fb2f18f8Sesaxe 
185fb2f18f8Sesaxe 	pghw_set_remove(hwset, pg);
186fb2f18f8Sesaxe 	pg->pghw_instance = (id_t)PGHW_INSTANCE_ANON;
187fb2f18f8Sesaxe 	pg->pghw_hw = (pghw_type_t)-1;
188fb2f18f8Sesaxe 
189fb2f18f8Sesaxe 	if (pg->pghw_kstat)
190fb2f18f8Sesaxe 		kstat_delete(pg->pghw_kstat);
191fb2f18f8Sesaxe }
192fb2f18f8Sesaxe 
193fb2f18f8Sesaxe /*
194fb2f18f8Sesaxe  * Find an existing physical PG in which to place
195fb2f18f8Sesaxe  * the given CPU for the specified hardware sharing
196fb2f18f8Sesaxe  * relationship
197fb2f18f8Sesaxe  */
198fb2f18f8Sesaxe pghw_t *
199fb2f18f8Sesaxe pghw_place_cpu(cpu_t *cp, pghw_type_t hw)
200fb2f18f8Sesaxe {
201fb2f18f8Sesaxe 	group_t		*hwset;
202fb2f18f8Sesaxe 
203fb2f18f8Sesaxe 	if ((hwset = pghw_set_lookup(hw)) == NULL) {
204fb2f18f8Sesaxe 		return (NULL);
205fb2f18f8Sesaxe 	}
206fb2f18f8Sesaxe 
207fb2f18f8Sesaxe 	return ((pghw_t *)pg_cpu_find_pg(cp, hwset));
208fb2f18f8Sesaxe }
209fb2f18f8Sesaxe 
210fb2f18f8Sesaxe /*
211fb2f18f8Sesaxe  * Find the pg representing the hw sharing relationship in which
212fb2f18f8Sesaxe  * cp belongs
213fb2f18f8Sesaxe  */
214fb2f18f8Sesaxe pghw_t *
215fb2f18f8Sesaxe pghw_find_pg(cpu_t *cp, pghw_type_t hw)
216fb2f18f8Sesaxe {
217fb2f18f8Sesaxe 	group_iter_t	i;
218fb2f18f8Sesaxe 	pghw_t	*pg;
219fb2f18f8Sesaxe 
220fb2f18f8Sesaxe 	group_iter_init(&i);
221fb2f18f8Sesaxe 	while ((pg = group_iterate(&cp->cpu_pg->pgs, &i)) != NULL) {
222fb2f18f8Sesaxe 		if (pg->pghw_hw == hw)
223fb2f18f8Sesaxe 			return (pg);
224fb2f18f8Sesaxe 	}
225fb2f18f8Sesaxe 	return (NULL);
226fb2f18f8Sesaxe }
227fb2f18f8Sesaxe 
228fb2f18f8Sesaxe /*
229fb2f18f8Sesaxe  * Find the PG of the given hardware sharing relationship
230fb2f18f8Sesaxe  * type with the given instance id
231fb2f18f8Sesaxe  */
232fb2f18f8Sesaxe pghw_t *
233fb2f18f8Sesaxe pghw_find_by_instance(id_t id, pghw_type_t hw)
234fb2f18f8Sesaxe {
235fb2f18f8Sesaxe 	group_iter_t	i;
236fb2f18f8Sesaxe 	group_t		*set;
237fb2f18f8Sesaxe 	pghw_t		*pg;
238fb2f18f8Sesaxe 
239fb2f18f8Sesaxe 	set = pghw_set_lookup(hw);
240fb2f18f8Sesaxe 	if (!set)
241fb2f18f8Sesaxe 		return (NULL);
242fb2f18f8Sesaxe 
243fb2f18f8Sesaxe 	group_iter_init(&i);
244fb2f18f8Sesaxe 	while ((pg = group_iterate(set, &i)) != NULL) {
245fb2f18f8Sesaxe 		if (pg->pghw_instance == id)
246fb2f18f8Sesaxe 			return (pg);
247fb2f18f8Sesaxe 	}
248fb2f18f8Sesaxe 	return (NULL);
249fb2f18f8Sesaxe }
250fb2f18f8Sesaxe 
251fb2f18f8Sesaxe /*
252fb2f18f8Sesaxe  * CPUs physical ID cache creation / destruction
253fb2f18f8Sesaxe  * The cache's elements are initialized to the CPU's id
254fb2f18f8Sesaxe  */
255fb2f18f8Sesaxe void
256fb2f18f8Sesaxe pghw_physid_create(cpu_t *cp)
257fb2f18f8Sesaxe {
258fb2f18f8Sesaxe 	int	i;
259fb2f18f8Sesaxe 
260fb2f18f8Sesaxe 	cp->cpu_physid = kmem_alloc(sizeof (cpu_physid_t), KM_SLEEP);
261fb2f18f8Sesaxe 
262fb2f18f8Sesaxe 	for (i = 0; i < (sizeof (cpu_physid_t) / sizeof (id_t)); i++) {
263fb2f18f8Sesaxe 		((id_t *)cp->cpu_physid)[i] = cp->cpu_id;
264fb2f18f8Sesaxe 	}
265fb2f18f8Sesaxe }
266fb2f18f8Sesaxe 
267fb2f18f8Sesaxe void
268fb2f18f8Sesaxe pghw_physid_destroy(cpu_t *cp)
269fb2f18f8Sesaxe {
270fb2f18f8Sesaxe 	if (cp->cpu_physid) {
271fb2f18f8Sesaxe 		kmem_free(cp->cpu_physid, sizeof (cpu_physid_t));
272fb2f18f8Sesaxe 		cp->cpu_physid = NULL;
273fb2f18f8Sesaxe 	}
274fb2f18f8Sesaxe }
275fb2f18f8Sesaxe 
276fb2f18f8Sesaxe /*
277fb2f18f8Sesaxe  * Create a new, empty hwset.
278fb2f18f8Sesaxe  * This routine may block, and must not be called from any
279fb2f18f8Sesaxe  * paused CPU context.
280fb2f18f8Sesaxe  */
281fb2f18f8Sesaxe static group_t	*
282fb2f18f8Sesaxe pghw_set_create(pghw_type_t hw)
283fb2f18f8Sesaxe {
284fb2f18f8Sesaxe 	group_t	*g;
285fb2f18f8Sesaxe 	int	ret;
286fb2f18f8Sesaxe 
287fb2f18f8Sesaxe 	/*
288fb2f18f8Sesaxe 	 * Create the top level PG hw group if it doesn't already exist
289fb2f18f8Sesaxe 	 * This is a "set" of hardware sets, that is ordered (and indexed)
290fb2f18f8Sesaxe 	 * by the pghw_type_t enum.
291fb2f18f8Sesaxe 	 */
292fb2f18f8Sesaxe 	if (pg_hw == NULL) {
293fb2f18f8Sesaxe 		pg_hw = kmem_alloc(sizeof (group_t), KM_SLEEP);
294fb2f18f8Sesaxe 		group_create(pg_hw);
295fb2f18f8Sesaxe 		group_expand(pg_hw, (uint_t)PGHW_NUM_COMPONENTS);
296fb2f18f8Sesaxe 	}
297fb2f18f8Sesaxe 
298fb2f18f8Sesaxe 	/*
299fb2f18f8Sesaxe 	 * Create the new hwset
300fb2f18f8Sesaxe 	 * Add it to the top level pg_hw group.
301fb2f18f8Sesaxe 	 */
302fb2f18f8Sesaxe 	g = kmem_alloc(sizeof (group_t), KM_SLEEP);
303fb2f18f8Sesaxe 	group_create(g);
304fb2f18f8Sesaxe 
305fb2f18f8Sesaxe 	ret = group_add_at(pg_hw, g, (uint_t)hw);
306fb2f18f8Sesaxe 	ASSERT(ret == 0);
307fb2f18f8Sesaxe 
308fb2f18f8Sesaxe 	return (g);
309fb2f18f8Sesaxe }
310fb2f18f8Sesaxe 
311fb2f18f8Sesaxe /*
312fb2f18f8Sesaxe  * Find the hwset associated with the given hardware sharing type
313fb2f18f8Sesaxe  */
314fb2f18f8Sesaxe group_t *
315fb2f18f8Sesaxe pghw_set_lookup(pghw_type_t hw)
316fb2f18f8Sesaxe {
317fb2f18f8Sesaxe 	group_t	*hwset;
318fb2f18f8Sesaxe 
319fb2f18f8Sesaxe 	if (pg_hw == NULL)
320fb2f18f8Sesaxe 		return (NULL);
321fb2f18f8Sesaxe 
322fb2f18f8Sesaxe 	hwset = GROUP_ACCESS(pg_hw, (uint_t)hw);
323fb2f18f8Sesaxe 	return (hwset);
324fb2f18f8Sesaxe }
325fb2f18f8Sesaxe 
326fb2f18f8Sesaxe /*
327fb2f18f8Sesaxe  * Add a PG to a hwset
328fb2f18f8Sesaxe  */
329fb2f18f8Sesaxe static void
330fb2f18f8Sesaxe pghw_set_add(group_t *hwset, pghw_t *pg)
331fb2f18f8Sesaxe {
332fb2f18f8Sesaxe 	(void) group_add(hwset, pg, GRP_RESIZE);
333fb2f18f8Sesaxe }
334fb2f18f8Sesaxe 
335fb2f18f8Sesaxe /*
336fb2f18f8Sesaxe  * Remove a PG from a hwset
337fb2f18f8Sesaxe  */
338fb2f18f8Sesaxe static void
339fb2f18f8Sesaxe pghw_set_remove(group_t *hwset, pghw_t *pg)
340fb2f18f8Sesaxe {
341fb2f18f8Sesaxe 	int result;
342fb2f18f8Sesaxe 
343fb2f18f8Sesaxe 	result = group_remove(hwset, pg, GRP_RESIZE);
344fb2f18f8Sesaxe 	ASSERT(result == 0);
345fb2f18f8Sesaxe }
346fb2f18f8Sesaxe 
347fb2f18f8Sesaxe 
348fb2f18f8Sesaxe /*
349fb2f18f8Sesaxe  * Return a string name given a pg_hw sharing type
350fb2f18f8Sesaxe  */
351fb2f18f8Sesaxe static char *
352fb2f18f8Sesaxe pghw_type_string(pghw_type_t hw)
353fb2f18f8Sesaxe {
354fb2f18f8Sesaxe 	switch (hw) {
355fb2f18f8Sesaxe 	case PGHW_IPIPE:
356*0e751525SEric Saxe 		return ("Integer Pipeline");
357fb2f18f8Sesaxe 	case PGHW_CACHE:
358*0e751525SEric Saxe 		return ("Cache");
359fb2f18f8Sesaxe 	case PGHW_FPU:
360*0e751525SEric Saxe 		return ("Floating Point Unit");
361e853d8c3Sjc25722 	case PGHW_MPIPE:
362*0e751525SEric Saxe 		return ("Data Pipe to memory");
363fb2f18f8Sesaxe 	case PGHW_CHIP:
364*0e751525SEric Saxe 		return ("Socket");
365fb2f18f8Sesaxe 	case PGHW_MEMORY:
366*0e751525SEric Saxe 		return ("Memory");
367*0e751525SEric Saxe 	case PGHW_POW_ACTIVE:
368*0e751525SEric Saxe 		return ("CPU PM Active Power Domain");
369*0e751525SEric Saxe 	case PGHW_POW_IDLE:
370*0e751525SEric Saxe 		return ("CPU PM Idle Power Domain");
371fb2f18f8Sesaxe 	default:
372fb2f18f8Sesaxe 		return ("unknown");
373fb2f18f8Sesaxe 	}
374fb2f18f8Sesaxe }
375fb2f18f8Sesaxe 
376fb2f18f8Sesaxe /*
377fb2f18f8Sesaxe  * Create / Update routines for PG hw kstats
378fb2f18f8Sesaxe  *
379fb2f18f8Sesaxe  * It is the intention of these kstats to provide some level
380fb2f18f8Sesaxe  * of informational / debugging observability into the types
381fb2f18f8Sesaxe  * and nature of the system's detected hardware sharing relationships
382fb2f18f8Sesaxe  */
383fb2f18f8Sesaxe void
384fb2f18f8Sesaxe pghw_kstat_create(pghw_t *pg)
385fb2f18f8Sesaxe {
386fb2f18f8Sesaxe 	/*
387fb2f18f8Sesaxe 	 * Create a physical pg kstat
388fb2f18f8Sesaxe 	 */
389fb2f18f8Sesaxe 	if ((pg->pghw_kstat = kstat_create("pg", ((pg_t *)pg)->pg_id,
390fb2f18f8Sesaxe 	    "pg", "pg", KSTAT_TYPE_NAMED,
391fb2f18f8Sesaxe 	    sizeof (pghw_kstat) / sizeof (kstat_named_t),
392fb2f18f8Sesaxe 	    KSTAT_FLAG_VIRTUAL)) != NULL) {
393*0e751525SEric Saxe 		/* Class string, hw string, and policy string */
394fb2f18f8Sesaxe 		pg->pghw_kstat->ks_data_size += PG_CLASS_NAME_MAX;
395*0e751525SEric Saxe 		pg->pghw_kstat->ks_data_size += PGHW_KSTAT_STR_LEN_MAX;
396*0e751525SEric Saxe 		pg->pghw_kstat->ks_data_size += PGHW_KSTAT_STR_LEN_MAX;
397fb2f18f8Sesaxe 		pg->pghw_kstat->ks_lock = &pghw_kstat_lock;
398fb2f18f8Sesaxe 		pg->pghw_kstat->ks_data = &pghw_kstat;
399fb2f18f8Sesaxe 		pg->pghw_kstat->ks_update = pghw_kstat_update;
400fb2f18f8Sesaxe 		pg->pghw_kstat->ks_private = pg;
401fb2f18f8Sesaxe 		kstat_install(pg->pghw_kstat);
402fb2f18f8Sesaxe 	}
403fb2f18f8Sesaxe }
404fb2f18f8Sesaxe 
405fb2f18f8Sesaxe int
406fb2f18f8Sesaxe pghw_kstat_update(kstat_t *ksp, int rw)
407fb2f18f8Sesaxe {
408fb2f18f8Sesaxe 	struct pghw_kstat	*pgsp = &pghw_kstat;
409fb2f18f8Sesaxe 	pghw_t			*pg = ksp->ks_private;
410fb2f18f8Sesaxe 
411fb2f18f8Sesaxe 	if (rw == KSTAT_WRITE)
412fb2f18f8Sesaxe 		return (EACCES);
413fb2f18f8Sesaxe 
414fb2f18f8Sesaxe 	pgsp->pg_id.value.ui64 = ((pg_t *)pg)->pg_id;
415fb2f18f8Sesaxe 	pgsp->pg_ncpus.value.ui64 = GROUP_SIZE(&((pg_t *)pg)->pg_cpus);
416fb2f18f8Sesaxe 	pgsp->pg_instance_id.value.ui64 = (uint64_t)pg->pghw_instance;
417fb2f18f8Sesaxe 	kstat_named_setstr(&pgsp->pg_class, ((pg_t *)pg)->pg_class->pgc_name);
418fb2f18f8Sesaxe 	kstat_named_setstr(&pgsp->pg_hw, pghw_type_string(pg->pghw_hw));
419*0e751525SEric Saxe 	kstat_named_setstr(&pgsp->pg_policy, pg_policy_name((pg_t *)pg));
420fb2f18f8Sesaxe 	return (0);
421fb2f18f8Sesaxe }
422