xref: /onnv-gate/usr/src/cmd/mdb/common/modules/genunix/cpupart.c (revision 537:c8af0ad12fe3)
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
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
23*537Smishra  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate 
300Sstevel@tonic-gate #include <mdb/mdb_param.h>
310Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
320Sstevel@tonic-gate #include <mdb/mdb_ks.h>
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #include "lgrp.h"
350Sstevel@tonic-gate #include "cpupart_mdb.h"
360Sstevel@tonic-gate 
370Sstevel@tonic-gate #include <sys/cpuvar.h>
380Sstevel@tonic-gate #include <sys/cpupart.h>
390Sstevel@tonic-gate 
400Sstevel@tonic-gate /* ARGSUSED */
410Sstevel@tonic-gate static int
cpupart_cpulist_callback(uintptr_t addr,const void * arg,void * cb_data)420Sstevel@tonic-gate cpupart_cpulist_callback(uintptr_t addr, const void *arg, void *cb_data)
430Sstevel@tonic-gate {
440Sstevel@tonic-gate 	cpu_t *cpu = (cpu_t *)arg;
450Sstevel@tonic-gate 
460Sstevel@tonic-gate 	ulong_t *cpuset = cb_data;
470Sstevel@tonic-gate 
480Sstevel@tonic-gate 	BT_SET(cpuset, cpu->cpu_id);
490Sstevel@tonic-gate 
500Sstevel@tonic-gate 	return (WALK_NEXT);
510Sstevel@tonic-gate }
520Sstevel@tonic-gate 
53*537Smishra #define	CPUPART_IDWIDTH		3
54*537Smishra 
55*537Smishra #ifdef _LP64
56*537Smishra #define	CPUPART_CPUWIDTH	21
57*537Smishra #if defined(__amd64)
58*537Smishra #define	CPUPART_TWIDTH		16
59*537Smishra #else
60*537Smishra #define	CPUPART_TWIDTH		11
61*537Smishra #endif
62*537Smishra #else
63*537Smishra #define	CPUPART_CPUWIDTH	13
64*537Smishra #define	CPUPART_TWIDTH		8
65*537Smishra #endif
66*537Smishra 
67*537Smishra 
68*537Smishra #define	CPUPART_THRDELT		(CPUPART_IDWIDTH + CPUPART_CPUWIDTH)
69*537Smishra #define	CPUPART_INDENT		mdb_printf("%*s", CPUPART_THRDELT, "")
70*537Smishra 
71*537Smishra int
cpupart_disp_threads(disp_t * disp)72*537Smishra cpupart_disp_threads(disp_t *disp)
73*537Smishra {
74*537Smishra 	dispq_t	*dq;
75*537Smishra 	int i, npri = disp->disp_npri;
76*537Smishra 	proc_t p;
77*537Smishra 	kthread_t t;
78*537Smishra 
79*537Smishra 	dq = mdb_alloc(sizeof (dispq_t) * npri, UM_SLEEP | UM_GC);
80*537Smishra 
81*537Smishra 	if (mdb_vread(dq, sizeof (dispq_t) * npri,
82*537Smishra 	    (uintptr_t)disp->disp_q) == -1) {
83*537Smishra 		mdb_warn("failed to read dispq_t at %p", disp->disp_q);
84*537Smishra 		return (DCMD_ERR);
85*537Smishra 	}
86*537Smishra 
87*537Smishra 	CPUPART_INDENT;
88*537Smishra 	mdb_printf("|\n");
89*537Smishra 	CPUPART_INDENT;
90*537Smishra 	mdb_printf("+-->  %3s %-*s %s\n", "PRI", CPUPART_TWIDTH, "THREAD",
91*537Smishra 	    "PROC");
92*537Smishra 
93*537Smishra 	for (i = npri - 1; i >= 0; i--) {
94*537Smishra 		uintptr_t taddr = (uintptr_t)dq[i].dq_first;
95*537Smishra 
96*537Smishra 		while (taddr != NULL) {
97*537Smishra 			if (mdb_vread(&t, sizeof (t), taddr) == -1) {
98*537Smishra 				mdb_warn("failed to read kthread_t at %p",
99*537Smishra 				    taddr);
100*537Smishra 				return (DCMD_ERR);
101*537Smishra 			}
102*537Smishra 
103*537Smishra 			if (mdb_vread(&p, sizeof (p),
104*537Smishra 			    (uintptr_t)t.t_procp) == -1) {
105*537Smishra 				mdb_warn("failed to read proc_t at %p",
106*537Smishra 				    t.t_procp);
107*537Smishra 				return (DCMD_ERR);
108*537Smishra 			}
109*537Smishra 
110*537Smishra 			CPUPART_INDENT;
111*537Smishra 			mdb_printf("%9d %0*p %s\n", t.t_pri, CPUPART_TWIDTH,
112*537Smishra 			    taddr, p.p_user.u_comm);
113*537Smishra 
114*537Smishra 			taddr = (uintptr_t)t.t_link;
115*537Smishra 		}
116*537Smishra 	}
117*537Smishra 
118*537Smishra 	return (DCMD_OK);
119*537Smishra }
120*537Smishra 
1210Sstevel@tonic-gate /* ARGSUSED */
1220Sstevel@tonic-gate int
cpupart(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)1230Sstevel@tonic-gate cpupart(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1240Sstevel@tonic-gate {
1250Sstevel@tonic-gate 	cpupart_t cpupart;
1260Sstevel@tonic-gate 	int cpusetsize;
1270Sstevel@tonic-gate 	int _ncpu;
1280Sstevel@tonic-gate 	ulong_t *cpuset;
129*537Smishra 	uint_t verbose = FALSE;
1300Sstevel@tonic-gate 
131*537Smishra 	if (mdb_getopts(argc, argv,
132*537Smishra 	    'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc)
1330Sstevel@tonic-gate 		return (DCMD_USAGE);
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC)) {
1360Sstevel@tonic-gate 		if (mdb_walk_dcmd("cpupart_walk", "cpupart", argc, argv)
1370Sstevel@tonic-gate 		    == -1) {
1380Sstevel@tonic-gate 			mdb_warn("can't walk 'cpupart'");
1390Sstevel@tonic-gate 			return (DCMD_ERR);
1400Sstevel@tonic-gate 		}
1410Sstevel@tonic-gate 		return (DCMD_OK);
1420Sstevel@tonic-gate 	}
1430Sstevel@tonic-gate 
1440Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags)) {
145*537Smishra 		mdb_printf("%3s %?s %4s %4s %4s\n",
1460Sstevel@tonic-gate 		    "ID",
1470Sstevel@tonic-gate 		    "ADDR",
148*537Smishra 		    "NRUN",
1490Sstevel@tonic-gate 		    "#CPU",
1500Sstevel@tonic-gate 		    "CPUS");
1510Sstevel@tonic-gate 	}
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 	if (mdb_vread(&cpupart, sizeof (cpupart_t), addr) == -1) {
1540Sstevel@tonic-gate 		mdb_warn("unable to read 'cpupart_t' at %p", addr);
1550Sstevel@tonic-gate 		return (DCMD_ERR);
1560Sstevel@tonic-gate 	}
1570Sstevel@tonic-gate 
158*537Smishra 	mdb_printf("%3d %?p %4d %4d ",
1590Sstevel@tonic-gate 	    cpupart.cp_id,
1600Sstevel@tonic-gate 	    addr,
161*537Smishra 	    cpupart.cp_kp_queue.disp_nrunnable,
1620Sstevel@tonic-gate 	    cpupart.cp_ncpus);
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate 	if (cpupart.cp_ncpus == 0) {
1650Sstevel@tonic-gate 		mdb_printf("\n");
1660Sstevel@tonic-gate 		return (DCMD_OK);
1670Sstevel@tonic-gate 	}
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 	/*
1700Sstevel@tonic-gate 	 * figure out what cpus we've got
1710Sstevel@tonic-gate 	 */
1720Sstevel@tonic-gate 	if (mdb_readsym(&_ncpu, sizeof (int), "_ncpu") == -1) {
1730Sstevel@tonic-gate 		mdb_warn("symbol '_ncpu' not found");
1740Sstevel@tonic-gate 		return (DCMD_ERR);
1750Sstevel@tonic-gate 	}
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 	/*
1780Sstevel@tonic-gate 	 * allocate enough space for set of longs to hold cpuid bitfield
1790Sstevel@tonic-gate 	 */
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	cpusetsize = BT_BITOUL(_ncpu) * sizeof (ulong_t);
1820Sstevel@tonic-gate 	cpuset = mdb_zalloc(cpusetsize, UM_SLEEP | UM_GC);
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 	if (mdb_pwalk("cpupart_cpulist", cpupart_cpulist_callback, cpuset,
1850Sstevel@tonic-gate 	    addr) == -1) {
1860Sstevel@tonic-gate 		mdb_warn("unable to walk cpupart_cpulist");
1870Sstevel@tonic-gate 		return (DCMD_ERR);
1880Sstevel@tonic-gate 	}
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 	print_cpuset_range(cpuset, cpusetsize/sizeof (ulong_t), 0);
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate 	mdb_printf("\n");
193*537Smishra 	/*
194*537Smishra 	 * If there are any threads on kp queue and -v is specified
195*537Smishra 	 */
196*537Smishra 	if (verbose && cpupart.cp_kp_queue.disp_nrunnable) {
197*537Smishra 		if (cpupart_disp_threads(&cpupart.cp_kp_queue) != DCMD_OK)
198*537Smishra 			return (DCMD_ERR);
199*537Smishra 	}
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 	return (DCMD_OK);
2020Sstevel@tonic-gate }
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate typedef struct cpupart_cpulist_walk {
2050Sstevel@tonic-gate 	uintptr_t	ccw_firstcpu;
2060Sstevel@tonic-gate 	int 		ccw_cpusleft;
2070Sstevel@tonic-gate } cpupart_cpulist_walk_t;
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate int
cpupart_cpulist_walk_init(mdb_walk_state_t * wsp)2100Sstevel@tonic-gate cpupart_cpulist_walk_init(mdb_walk_state_t *wsp)
2110Sstevel@tonic-gate {
2120Sstevel@tonic-gate 	cpupart_cpulist_walk_t *ccw;
2130Sstevel@tonic-gate 	cpupart_t cpupart;
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate 	ccw = mdb_alloc(sizeof (cpupart_cpulist_walk_t), UM_SLEEP | UM_GC);
2160Sstevel@tonic-gate 
2170Sstevel@tonic-gate 	if (mdb_vread(&cpupart, sizeof (cpupart_t), wsp->walk_addr) == -1) {
2180Sstevel@tonic-gate 		mdb_warn("couldn't read 'cpupart' at %p", wsp->walk_addr);
2190Sstevel@tonic-gate 		return (WALK_ERR);
2200Sstevel@tonic-gate 	}
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate 	ccw->ccw_firstcpu = (uintptr_t)cpupart.cp_cpulist;
2230Sstevel@tonic-gate 	ccw->ccw_cpusleft = cpupart.cp_ncpus;
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate 	wsp->walk_data = ccw;
2260Sstevel@tonic-gate 	wsp->walk_addr = ccw->ccw_firstcpu;
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 	return (WALK_NEXT);
2290Sstevel@tonic-gate }
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate int
cpupart_cpulist_walk_step(mdb_walk_state_t * wsp)2320Sstevel@tonic-gate cpupart_cpulist_walk_step(mdb_walk_state_t *wsp)
2330Sstevel@tonic-gate {
2340Sstevel@tonic-gate 	cpupart_cpulist_walk_t *ccw = (cpupart_cpulist_walk_t *)
2350Sstevel@tonic-gate 	    wsp->walk_data;
2360Sstevel@tonic-gate 	uintptr_t addr = wsp->walk_addr;
2370Sstevel@tonic-gate 	cpu_t cpu;
2380Sstevel@tonic-gate 	int status;
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 	if (mdb_vread(&cpu, sizeof (cpu_t), addr) == -1) {
2410Sstevel@tonic-gate 		mdb_warn("couldn't read 'cpupart' at %p", addr);
2420Sstevel@tonic-gate 		return (WALK_ERR);
2430Sstevel@tonic-gate 	}
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 	status = wsp->walk_callback(addr, &cpu, wsp->walk_cbdata);
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate 	if (status != WALK_NEXT)
2480Sstevel@tonic-gate 		return (status);
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate 	addr = (uintptr_t)cpu.cpu_next_part;
2510Sstevel@tonic-gate 	wsp->walk_addr = addr;
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 	ccw->ccw_cpusleft--;
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate 	if (ccw->ccw_cpusleft < 0) {
2560Sstevel@tonic-gate 		mdb_warn("cpu count doesn't match cpupart list");
2570Sstevel@tonic-gate 		return (WALK_ERR);
2580Sstevel@tonic-gate 	}
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate 	if (ccw->ccw_firstcpu == addr) {
2610Sstevel@tonic-gate 		if (ccw->ccw_cpusleft != 0) {
2620Sstevel@tonic-gate 			mdb_warn("cpu count doesn't match cpupart list");
2630Sstevel@tonic-gate 			return (WALK_ERR);
2640Sstevel@tonic-gate 		}
2650Sstevel@tonic-gate 		return (WALK_DONE);
2660Sstevel@tonic-gate 	}
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate 	return (WALK_NEXT);
2690Sstevel@tonic-gate }
2700Sstevel@tonic-gate 
2710Sstevel@tonic-gate int
cpupart_walk_init(mdb_walk_state_t * wsp)2720Sstevel@tonic-gate cpupart_walk_init(mdb_walk_state_t *wsp)
2730Sstevel@tonic-gate {
2740Sstevel@tonic-gate 	GElf_Sym sym;
2750Sstevel@tonic-gate 	uintptr_t addr;
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate 	if (mdb_lookup_by_name("cp_default", &sym) == -1) {
2780Sstevel@tonic-gate 		mdb_warn("failed to find 'cp_default'\n");
2790Sstevel@tonic-gate 		return (WALK_ERR);
2800Sstevel@tonic-gate 	}
2810Sstevel@tonic-gate 
2820Sstevel@tonic-gate 	addr = (uintptr_t)sym.st_value;
2830Sstevel@tonic-gate 	wsp->walk_data = (void *)addr;
2840Sstevel@tonic-gate 	wsp->walk_addr = addr;
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate 	return (WALK_NEXT);
2870Sstevel@tonic-gate }
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate int
cpupart_walk_step(mdb_walk_state_t * wsp)2900Sstevel@tonic-gate cpupart_walk_step(mdb_walk_state_t *wsp)
2910Sstevel@tonic-gate {
2920Sstevel@tonic-gate 	cpupart_t cpupart;
2930Sstevel@tonic-gate 	int status;
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate 	if (mdb_vread(&cpupart, sizeof (cpupart_t),
2960Sstevel@tonic-gate 	    wsp->walk_addr) == -1) {
2970Sstevel@tonic-gate 		mdb_warn("unable to read cpupart at %p",
2980Sstevel@tonic-gate 		    wsp->walk_addr);
2990Sstevel@tonic-gate 		return (WALK_ERR);
3000Sstevel@tonic-gate 	}
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate 	status = wsp->walk_callback(wsp->walk_addr, &cpupart,
3030Sstevel@tonic-gate 	    wsp->walk_cbdata);
3040Sstevel@tonic-gate 
3050Sstevel@tonic-gate 	if (status != WALK_NEXT)
3060Sstevel@tonic-gate 		return (status);
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)cpupart.cp_next;
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate 	if (wsp->walk_addr == (uintptr_t)wsp->walk_data)
3110Sstevel@tonic-gate 		return (WALK_DONE);
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate 	return (WALK_NEXT);
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate }
316