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