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