kernel_stats.cc revision 2159
1/* 2 * Copyright (c) 2004-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <map> 30#include <stack> 31#include <string> 32 33#include "arch/alpha/osfpal.hh" 34#include "base/trace.hh" 35#include "cpu/exec_context.hh" 36#include "kern/kernel_stats.hh" 37#include "kern/tru64/tru64_syscalls.hh" 38 39using namespace std; 40using namespace Stats; 41 42namespace Kernel { 43 44const char *modestr[] = { "kernel", "user", "idle", "interrupt" }; 45 46Statistics::Statistics(ExecContext *context) 47 : xc(context), idleProcess((Addr)-1), themode(kernel), lastModeTick(0), 48 iplLast(0), iplLastTick(0) 49{ 50 bin_int = xc->system->params->bin_int; 51} 52 53void 54Statistics::regStats(const string &_name) 55{ 56 myname = _name; 57 58 _arm 59 .name(name() + ".inst.arm") 60 .desc("number of arm instructions executed") 61 ; 62 63 _quiesce 64 .name(name() + ".inst.quiesce") 65 .desc("number of quiesce instructions executed") 66 ; 67 68 _ivlb 69 .name(name() + ".inst.ivlb") 70 .desc("number of ivlb instructions executed") 71 ; 72 73 _ivle 74 .name(name() + ".inst.ivle") 75 .desc("number of ivle instructions executed") 76 ; 77 78 _hwrei 79 .name(name() + ".inst.hwrei") 80 .desc("number of hwrei instructions executed") 81 ; 82 83 _iplCount 84 .init(32) 85 .name(name() + ".ipl_count") 86 .desc("number of times we switched to this ipl") 87 .flags(total | pdf | nozero | nonan) 88 ; 89 90 _iplGood 91 .init(32) 92 .name(name() + ".ipl_good") 93 .desc("number of times we switched to this ipl from a different ipl") 94 .flags(total | pdf | nozero | nonan) 95 ; 96 97 _iplTicks 98 .init(32) 99 .name(name() + ".ipl_ticks") 100 .desc("number of cycles we spent at this ipl") 101 .flags(total | pdf | nozero | nonan) 102 ; 103 104 _iplUsed 105 .name(name() + ".ipl_used") 106 .desc("fraction of swpipl calls that actually changed the ipl") 107 .flags(total | nozero | nonan) 108 ; 109 110 _iplUsed = _iplGood / _iplCount; 111 112 _callpal 113 .init(256) 114 .name(name() + ".callpal") 115 .desc("number of callpals executed") 116 .flags(total | pdf | nozero | nonan) 117 ; 118 119 for (int i = 0; i < PAL::NumCodes; ++i) { 120 const char *str = PAL::name(i); 121 if (str) 122 _callpal.subname(i, str); 123 } 124 125 _syscall 126 .init(SystemCalls<Tru64>::Number) 127 .name(name() + ".syscall") 128 .desc("number of syscalls executed") 129 .flags(total | pdf | nozero | nonan) 130 ; 131 132 for (int i = 0; i < SystemCalls<Tru64>::Number; ++i) { 133 const char *str = SystemCalls<Tru64>::name(i); 134 if (str) { 135 _syscall.subname(i, str); 136 } 137 } 138 139 _faults 140 .init(NumFaults) 141 .name(name() + ".faults") 142 .desc("number of faults") 143 .flags(total | pdf | nozero | nonan) 144 ; 145 146 for (int i = 1; i < NumFaults; ++i) { 147 const char *str = (*ListOfFaults[i])->name; 148 if (str) 149 _faults.subname(i, str); 150 } 151 152 _mode 153 .init(cpu_mode_num) 154 .name(name() + ".mode_switch") 155 .desc("number of protection mode switches") 156 ; 157 158 for (int i = 0; i < cpu_mode_num; ++i) 159 _mode.subname(i, modestr[i]); 160 161 _modeGood 162 .init(cpu_mode_num) 163 .name(name() + ".mode_good") 164 ; 165 166 for (int i = 0; i < cpu_mode_num; ++i) 167 _modeGood.subname(i, modestr[i]); 168 169 _modeFraction 170 .name(name() + ".mode_switch_good") 171 .desc("fraction of useful protection mode switches") 172 .flags(total) 173 ; 174 175 for (int i = 0; i < cpu_mode_num; ++i) 176 _modeFraction.subname(i, modestr[i]); 177 178 _modeFraction = _modeGood / _mode; 179 180 _modeTicks 181 .init(cpu_mode_num) 182 .name(name() + ".mode_ticks") 183 .desc("number of ticks spent at the given mode") 184 .flags(pdf) 185 ; 186 for (int i = 0; i < cpu_mode_num; ++i) 187 _modeTicks.subname(i, modestr[i]); 188 189 _swap_context 190 .name(name() + ".swap_context") 191 .desc("number of times the context was actually changed") 192 ; 193} 194 195void 196Statistics::setIdleProcess(Addr idlepcbb) 197{ 198 assert(themode == kernel || themode == interrupt); 199 idleProcess = idlepcbb; 200 themode = idle; 201 changeMode(themode); 202} 203 204void 205Statistics::changeMode(cpu_mode newmode) 206{ 207 _mode[newmode]++; 208 209 if (newmode == themode) 210 return; 211 212 DPRINTF(Context, "old mode=%-8s new mode=%-8s\n", 213 modestr[themode], modestr[newmode]); 214 215 _modeGood[newmode]++; 216 _modeTicks[themode] += curTick - lastModeTick; 217 218 xc->system->kernelBinning->changeMode(newmode); 219 220 lastModeTick = curTick; 221 themode = newmode; 222} 223 224void 225Statistics::swpipl(int ipl) 226{ 227 assert(ipl >= 0 && ipl <= 0x1f && "invalid IPL\n"); 228 229 _iplCount[ipl]++; 230 231 if (ipl == iplLast) 232 return; 233 234 _iplGood[ipl]++; 235 _iplTicks[iplLast] += curTick - iplLastTick; 236 iplLastTick = curTick; 237 iplLast = ipl; 238} 239 240void 241Statistics::mode(cpu_mode newmode) 242{ 243 Addr pcbb = xc->readMiscReg(AlphaISA::IPR_PALtemp23); 244 245 if ((newmode == kernel || newmode == interrupt) && 246 pcbb == idleProcess) 247 newmode = idle; 248 249 if (bin_int == false && newmode == interrupt) 250 newmode = kernel; 251 252 changeMode(newmode); 253} 254 255void 256Statistics::context(Addr oldpcbb, Addr newpcbb) 257{ 258 assert(themode != user); 259 260 _swap_context++; 261 changeMode(newpcbb == idleProcess ? idle : kernel); 262} 263 264void 265Statistics::callpal(int code) 266{ 267 if (!PAL::name(code)) 268 return; 269 270 _callpal[code]++; 271 272 switch (code) { 273 case PAL::callsys: { 274 int number = xc->regs.intRegFile[0]; 275 if (SystemCalls<Tru64>::validSyscallNumber(number)) { 276 int cvtnum = SystemCalls<Tru64>::convert(number); 277 _syscall[cvtnum]++; 278 } 279 } break; 280 281 case PAL::swpctx: 282 if (xc->system->kernelBinning) 283 xc->system->kernelBinning->palSwapContext(xc); 284 break; 285 } 286} 287 288void 289Statistics::serialize(ostream &os) 290{ 291 int exemode = themode; 292 SERIALIZE_SCALAR(exemode); 293 SERIALIZE_SCALAR(idleProcess); 294 SERIALIZE_SCALAR(iplLast); 295 SERIALIZE_SCALAR(iplLastTick); 296 SERIALIZE_SCALAR(lastModeTick); 297} 298 299void 300Statistics::unserialize(Checkpoint *cp, const string §ion) 301{ 302 int exemode; 303 UNSERIALIZE_SCALAR(exemode); 304 UNSERIALIZE_SCALAR(idleProcess); 305 UNSERIALIZE_SCALAR(iplLast); 306 UNSERIALIZE_SCALAR(iplLastTick); 307 UNSERIALIZE_SCALAR(lastModeTick); 308 themode = (cpu_mode)exemode; 309} 310 311/* end namespace Kernel */ } 312