kernel_stats.cc revision 1108
1/* 2 * Copyright (c) 2003 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 "base/statistics.hh" 36#include "base/stats/bin.hh" 37#include "cpu/exec_context.hh" 38#include "cpu/pc_event.hh" 39#include "cpu/static_inst.hh" 40#include "kern/kernel_stats.hh" 41#include "kern/linux/linux_syscalls.hh" 42#include "kern/tru64/tru64_syscalls.hh" 43 44using namespace std; 45using namespace Stats; 46 47namespace Kernel { 48 49const char *modestr[] = { "kernel", "user", "idle", "interrupt" }; 50 51Statistics::Statistics(ExecContext *context) 52 : xc(context), idleProcess((Addr)-1), themode(kernel), lastModeTick(0), 53 iplLast(0), iplLastTick(0) 54{ 55 bin_int = xc->system->params->bin_int; 56} 57 58void 59Statistics::regStats(const string &_name) 60{ 61 myname = _name; 62 63 _arm 64 .name(name() + ".inst.arm") 65 .desc("number of arm instructions executed") 66 ; 67 68 _quiesce 69 .name(name() + ".inst.quiesce") 70 .desc("number of quiesce instructions executed") 71 ; 72 73 _ivlb 74 .name(name() + ".inst.ivlb") 75 .desc("number of ivlb instructions executed") 76 ; 77 78 _ivle 79 .name(name() + ".inst.ivle") 80 .desc("number of ivle instructions executed") 81 ; 82 83 _hwrei 84 .name(name() + ".inst.hwrei") 85 .desc("number of hwrei instructions executed") 86 ; 87 88 _iplCount 89 .init(32) 90 .name(name() + ".ipl_count") 91 .desc("number of times we switched to this ipl") 92 .flags(total | pdf | nozero | nonan) 93 ; 94 95 _iplGood 96 .init(32) 97 .name(name() + ".ipl_good") 98 .desc("number of times we switched to this ipl from a different ipl") 99 .flags(total | pdf | nozero | nonan) 100 ; 101 102 _iplTicks 103 .init(32) 104 .name(name() + ".ipl_ticks") 105 .desc("number of cycles we spent at this ipl") 106 .flags(total | pdf | nozero | nonan) 107 ; 108 109 _iplUsed 110 .name(name() + ".ipl_used") 111 .desc("fraction of swpipl calls that actually changed the ipl") 112 .flags(total | nozero | nonan) 113 ; 114 115 _iplUsed = _iplGood / _iplCount; 116 117 _callpal 118 .init(256) 119 .name(name() + ".callpal") 120 .desc("number of callpals executed") 121 .flags(total | pdf | nozero | nonan) 122 ; 123 124 for (int i = 0; i < PAL::NumCodes; ++i) { 125 const char *str = PAL::name(i); 126 if (str) 127 _callpal.subname(i, str); 128 } 129 130 _syscall 131 .init(SystemCalls<Tru64>::Number) 132 .name(name() + ".syscall") 133 .desc("number of syscalls executed") 134 .flags(total | pdf | nozero | nonan) 135 ; 136 137 for (int i = 0; i < SystemCalls<Tru64>::Number; ++i) { 138 const char *str = SystemCalls<Tru64>::name(i); 139 if (str) { 140 _syscall.subname(i, str); 141 } 142 } 143 144 _faults 145 .init(Num_Faults) 146 .name(name() + ".faults") 147 .desc("number of faults") 148 .flags(total | pdf | nozero | nonan) 149 ; 150 151 for (int i = 1; i < Num_Faults; ++i) { 152 const char *str = FaultName(i); 153 if (str) 154 _faults.subname(i, str); 155 } 156 157 _mode 158 .init(cpu_mode_num) 159 .name(name() + ".mode_switch") 160 .desc("number of protection mode switches") 161 ; 162 163 for (int i = 0; i < cpu_mode_num; ++i) 164 _mode.subname(i, modestr[i]); 165 166 _modeGood 167 .init(cpu_mode_num) 168 .name(name() + ".mode_good") 169 ; 170 171 for (int i = 0; i < cpu_mode_num; ++i) 172 _modeGood.subname(i, modestr[i]); 173 174 _modeFraction 175 .name(name() + ".mode_switch_good") 176 .desc("fraction of useful protection mode switches") 177 .flags(total) 178 ; 179 180 for (int i = 0; i < cpu_mode_num; ++i) 181 _modeFraction.subname(i, modestr[i]); 182 183 _modeFraction = _modeGood / _mode; 184 185 _modeTicks 186 .init(cpu_mode_num) 187 .name(name() + ".mode_ticks") 188 .desc("number of ticks spent at the given mode") 189 .flags(pdf) 190 ; 191 for (int i = 0; i < cpu_mode_num; ++i) 192 _modeTicks.subname(i, modestr[i]); 193 194 _swap_context 195 .name(name() + ".swap_context") 196 .desc("number of times the context was actually changed") 197 ; 198} 199 200void 201Statistics::setIdleProcess(Addr idlepcbb) 202{ 203 assert(themode == kernel || themode == interrupt); 204 idleProcess = idlepcbb; 205 themode = idle; 206 changeMode(themode); 207} 208 209void 210Statistics::changeMode(cpu_mode newmode) 211{ 212 _mode[newmode]++; 213 214 if (newmode == themode) 215 return; 216 217 DPRINTF(Context, "old mode=%-8s new mode=%-8s\n", 218 modestr[themode], modestr[newmode]); 219 220 _modeGood[newmode]++; 221 _modeTicks[themode] += curTick - lastModeTick; 222 223 xc->system->kernelBinning->changeMode(newmode); 224 225 lastModeTick = curTick; 226 themode = newmode; 227} 228 229void 230Statistics::swpipl(int ipl) 231{ 232 assert(ipl >= 0 && ipl <= 0x1f && "invalid IPL\n"); 233 234 _iplCount[ipl]++; 235 236 if (ipl == iplLast) 237 return; 238 239 _iplGood[ipl]++; 240 _iplTicks[iplLast] += curTick - iplLastTick; 241 iplLastTick = curTick; 242 iplLast = ipl; 243} 244 245void 246Statistics::mode(cpu_mode newmode) 247{ 248 Addr pcbb = xc->regs.ipr[AlphaISA::IPR_PALtemp23]; 249 250 if ((newmode == kernel || newmode == interrupt) && 251 pcbb == idleProcess) 252 newmode = idle; 253 254 if (bin_int == false && newmode == interrupt) 255 newmode = kernel; 256 257 changeMode(newmode); 258} 259 260void 261Statistics::context(Addr oldpcbb, Addr newpcbb) 262{ 263 assert(themode != user); 264 265 _swap_context++; 266 changeMode(newpcbb == idleProcess ? idle : kernel); 267} 268 269void 270Statistics::callpal(int code) 271{ 272 if (!PAL::name(code)) 273 return; 274 275 _callpal[code]++; 276 277 switch (code) { 278 case PAL::callsys: { 279 int number = xc->regs.intRegFile[0]; 280 if (SystemCalls<Tru64>::validSyscallNumber(number)) { 281 int cvtnum = SystemCalls<Tru64>::convert(number); 282 _syscall[cvtnum]++; 283 } 284 } break; 285 286 case PAL::swpctx: 287 if (xc->system->kernelBinning) 288 xc->system->kernelBinning->palSwapContext(xc); 289 break; 290 } 291} 292 293void 294Statistics::serialize(ostream &os) 295{ 296 int exemode = themode; 297 SERIALIZE_SCALAR(exemode); 298 SERIALIZE_SCALAR(idleProcess); 299 SERIALIZE_SCALAR(iplLast); 300 SERIALIZE_SCALAR(iplLastTick); 301 SERIALIZE_SCALAR(lastModeTick); 302} 303 304void 305Statistics::unserialize(Checkpoint *cp, const string §ion) 306{ 307 int exemode; 308 UNSERIALIZE_SCALAR(exemode); 309 UNSERIALIZE_SCALAR(idleProcess); 310 UNSERIALIZE_SCALAR(iplLast); 311 UNSERIALIZE_SCALAR(iplLastTick); 312 UNSERIALIZE_SCALAR(lastModeTick); 313 themode = (cpu_mode)exemode; 314} 315 316/* end namespace Kernel */ } 317