xref: /illumos-gate/usr/src/cmd/mdb/common/modules/genunix/cpupart.c (revision bdfc6d18da790deeec2e0eb09c625902defe2498)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 
30 #include <mdb/mdb_param.h>
31 #include <mdb/mdb_modapi.h>
32 #include <mdb/mdb_ks.h>
33 
34 #include "lgrp.h"
35 #include "cpupart_mdb.h"
36 
37 #include <sys/cpuvar.h>
38 #include <sys/cpupart.h>
39 
40 /* ARGSUSED */
41 static int
42 cpupart_cpulist_callback(uintptr_t addr, const void *arg, void *cb_data)
43 {
44 	cpu_t *cpu = (cpu_t *)arg;
45 
46 	ulong_t *cpuset = cb_data;
47 
48 	BT_SET(cpuset, cpu->cpu_id);
49 
50 	return (WALK_NEXT);
51 }
52 
53 /* ARGSUSED */
54 int
55 cpupart(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
56 {
57 	cpupart_t cpupart;
58 	int cpusetsize;
59 	int _ncpu;
60 	ulong_t *cpuset;
61 
62 	if (argc != 0)
63 		return (DCMD_USAGE);
64 
65 	if (!(flags & DCMD_ADDRSPEC)) {
66 		if (mdb_walk_dcmd("cpupart_walk", "cpupart", argc, argv)
67 		    == -1) {
68 			mdb_warn("can't walk 'cpupart'");
69 			return (DCMD_ERR);
70 		}
71 		return (DCMD_OK);
72 	}
73 
74 
75 	if (DCMD_HDRSPEC(flags)) {
76 		mdb_printf("%3s %?s %4s %4s\n",
77 		    "ID",
78 		    "ADDR",
79 		    "#CPU",
80 		    "CPUS");
81 	}
82 
83 	if (mdb_vread(&cpupart, sizeof (cpupart_t), addr) == -1) {
84 		mdb_warn("unable to read 'cpupart_t' at %p", addr);
85 		return (DCMD_ERR);
86 	}
87 
88 	mdb_printf("%3d %?p %4d ",
89 	    cpupart.cp_id,
90 	    addr,
91 	    cpupart.cp_ncpus);
92 
93 	if (cpupart.cp_ncpus == 0) {
94 		mdb_printf("\n");
95 		return (DCMD_OK);
96 	}
97 
98 	/*
99 	 * figure out what cpus we've got
100 	 */
101 
102 
103 	if (mdb_readsym(&_ncpu, sizeof (int), "_ncpu") == -1) {
104 		mdb_warn("symbol '_ncpu' not found");
105 		return (DCMD_ERR);
106 	}
107 
108 	/*
109 	 * allocate enough space for set of longs to hold cpuid bitfield
110 	 */
111 
112 	cpusetsize = BT_BITOUL(_ncpu) * sizeof (ulong_t);
113 	cpuset = mdb_zalloc(cpusetsize, UM_SLEEP | UM_GC);
114 
115 	if (mdb_pwalk("cpupart_cpulist", cpupart_cpulist_callback, cpuset,
116 	    addr) == -1) {
117 		mdb_warn("unable to walk cpupart_cpulist");
118 		return (DCMD_ERR);
119 	}
120 
121 	print_cpuset_range(cpuset, cpusetsize/sizeof (ulong_t), 0);
122 
123 	mdb_printf("\n");
124 
125 	return (DCMD_OK);
126 }
127 
128 typedef struct cpupart_cpulist_walk {
129 	uintptr_t	ccw_firstcpu;
130 	int 		ccw_cpusleft;
131 } cpupart_cpulist_walk_t;
132 
133 int
134 cpupart_cpulist_walk_init(mdb_walk_state_t *wsp)
135 {
136 	cpupart_cpulist_walk_t *ccw;
137 	cpupart_t cpupart;
138 
139 	ccw = mdb_alloc(sizeof (cpupart_cpulist_walk_t), UM_SLEEP | UM_GC);
140 
141 	if (mdb_vread(&cpupart, sizeof (cpupart_t), wsp->walk_addr) == -1) {
142 		mdb_warn("couldn't read 'cpupart' at %p", wsp->walk_addr);
143 		return (WALK_ERR);
144 	}
145 
146 	ccw->ccw_firstcpu = (uintptr_t)cpupart.cp_cpulist;
147 	ccw->ccw_cpusleft = cpupart.cp_ncpus;
148 
149 	wsp->walk_data = ccw;
150 	wsp->walk_addr = ccw->ccw_firstcpu;
151 
152 	return (WALK_NEXT);
153 }
154 
155 int
156 cpupart_cpulist_walk_step(mdb_walk_state_t *wsp)
157 {
158 	cpupart_cpulist_walk_t *ccw = (cpupart_cpulist_walk_t *)
159 	    wsp->walk_data;
160 	uintptr_t addr = wsp->walk_addr;
161 	cpu_t cpu;
162 	int status;
163 
164 	if (mdb_vread(&cpu, sizeof (cpu_t), addr) == -1) {
165 		mdb_warn("couldn't read 'cpupart' at %p", addr);
166 		return (WALK_ERR);
167 	}
168 
169 	status = wsp->walk_callback(addr, &cpu, wsp->walk_cbdata);
170 
171 	if (status != WALK_NEXT)
172 		return (status);
173 
174 	addr = (uintptr_t)cpu.cpu_next_part;
175 	wsp->walk_addr = addr;
176 
177 	ccw->ccw_cpusleft--;
178 
179 	if (ccw->ccw_cpusleft < 0) {
180 		mdb_warn("cpu count doesn't match cpupart list");
181 		return (WALK_ERR);
182 	}
183 
184 	if (ccw->ccw_firstcpu == addr) {
185 		if (ccw->ccw_cpusleft != 0) {
186 			mdb_warn("cpu count doesn't match cpupart list");
187 			return (WALK_ERR);
188 		}
189 		return (WALK_DONE);
190 	}
191 
192 	return (WALK_NEXT);
193 }
194 
195 int
196 cpupart_walk_init(mdb_walk_state_t *wsp)
197 {
198 	GElf_Sym sym;
199 	uintptr_t addr;
200 
201 	if (mdb_lookup_by_name("cp_default", &sym) == -1) {
202 		mdb_warn("failed to find 'cp_default'\n");
203 		return (WALK_ERR);
204 	}
205 
206 	addr = (uintptr_t)sym.st_value;
207 	wsp->walk_data = (void *)addr;
208 	wsp->walk_addr = addr;
209 
210 	return (WALK_NEXT);
211 }
212 
213 int
214 cpupart_walk_step(mdb_walk_state_t *wsp)
215 {
216 	cpupart_t cpupart;
217 	int status;
218 
219 	if (mdb_vread(&cpupart, sizeof (cpupart_t),
220 	    wsp->walk_addr) == -1) {
221 		mdb_warn("unable to read cpupart at %p",
222 		    wsp->walk_addr);
223 		return (WALK_ERR);
224 	}
225 
226 	status = wsp->walk_callback(wsp->walk_addr, &cpupart,
227 	    wsp->walk_cbdata);
228 
229 	if (status != WALK_NEXT)
230 		return (status);
231 
232 	wsp->walk_addr = (uintptr_t)cpupart.cp_next;
233 
234 	if (wsp->walk_addr == (uintptr_t)wsp->walk_data)
235 		return (WALK_DONE);
236 
237 	return (WALK_NEXT);
238 
239 }
240