kernel_stats.cc revision 754
16657Snate@binkert.org/* 26657Snate@binkert.org * Copyright (c) 2003 The Regents of The University of Michigan 36657Snate@binkert.org * All rights reserved. 46657Snate@binkert.org * 56657Snate@binkert.org * Redistribution and use in source and binary forms, with or without 66657Snate@binkert.org * modification, are permitted provided that the following conditions are 76657Snate@binkert.org * met: redistributions of source code must retain the above copyright 86657Snate@binkert.org * notice, this list of conditions and the following disclaimer; 96657Snate@binkert.org * redistributions in binary form must reproduce the above copyright 106657Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 116657Snate@binkert.org * documentation and/or other materials provided with the distribution; 126657Snate@binkert.org * neither the name of the copyright holders nor the names of its 136657Snate@binkert.org * contributors may be used to endorse or promote products derived from 146657Snate@binkert.org * this software without specific prior written permission. 156657Snate@binkert.org * 166657Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176657Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186657Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196657Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206657Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216657Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226657Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236657Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246657Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256657Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266657Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276657Snate@binkert.org */ 288453Snate@binkert.org 296657Snate@binkert.org#include <map> 306657Snate@binkert.org#include <stack> 316657Snate@binkert.org#include <string> 326657Snate@binkert.org 336657Snate@binkert.org#include "base/statistics.hh" 346657Snate@binkert.org#include "base/trace.hh" 356657Snate@binkert.org#include "cpu/exec_context.hh" 366999Snate@binkert.org#include "kern/kernel_stats.hh" 376999Snate@binkert.org#include "sim/stats.hh" 386999Snate@binkert.org#include "sim/sw_context.hh" 396657Snate@binkert.org#include "targetarch/isa_traits.hh" 406657Snate@binkert.org#include "targetarch/osfpal.hh" 416657Snate@binkert.org#include "targetarch/syscalls.hh" 426657Snate@binkert.org 436657Snate@binkert.orgusing namespace std; 446657Snate@binkert.orgusing namespace Stats; 458453Snate@binkert.org 468453Snate@binkert.orgclass KSData 476657Snate@binkert.org{ 486657Snate@binkert.org private: 496657Snate@binkert.org string _name; 506657Snate@binkert.org ExecContext *xc; 516657Snate@binkert.org BaseCPU *cpu; 528453Snate@binkert.org 538453Snate@binkert.org public: 546657Snate@binkert.org KSData(ExecContext *_xc, BaseCPU *_cpu) 556657Snate@binkert.org : xc(_xc), cpu(_cpu), iplLast(0), iplLastTick(0), lastUser(false), 566657Snate@binkert.org lastModeTick(0) 576657Snate@binkert.org {} 586657Snate@binkert.org 596999Snate@binkert.org const string &name() { return _name; } 606999Snate@binkert.org void regStats(const string &name); 616999Snate@binkert.org 626657Snate@binkert.org public: 636657Snate@binkert.org Scalar<> _arm; 646657Snate@binkert.org Scalar<> _quiesce; 656657Snate@binkert.org Scalar<> _ivlb; 666657Snate@binkert.org Scalar<> _ivle; 676657Snate@binkert.org Scalar<> _hwrei; 686657Snate@binkert.org 696657Snate@binkert.org Vector<> _iplCount; 706657Snate@binkert.org Vector<> _iplGood; 716657Snate@binkert.org Vector<> _iplTicks; 726657Snate@binkert.org Formula _iplUsed; 736657Snate@binkert.org 746657Snate@binkert.org Vector<> _callpal; 756657Snate@binkert.org Vector<> _syscall; 766657Snate@binkert.org Vector<> _faults; 776657Snate@binkert.org 786657Snate@binkert.org Vector<> _mode; 796657Snate@binkert.org Vector<> _modeGood; 806657Snate@binkert.org Formula _modeFraction; 816657Snate@binkert.org Vector<> _modeTicks; 826794SBrad.Beckmann@amd.com 836794SBrad.Beckmann@amd.com Scalar<> _swap_context; 846794SBrad.Beckmann@amd.com 856794SBrad.Beckmann@amd.com private: 866657Snate@binkert.org int iplLast; 876657Snate@binkert.org Tick iplLastTick; 886657Snate@binkert.org 896657Snate@binkert.org bool lastUser; 906657Snate@binkert.org Tick lastModeTick; 916657Snate@binkert.org 926657Snate@binkert.org public: 936657Snate@binkert.org void swpipl(int ipl); 946657Snate@binkert.org void mode(bool user); 956657Snate@binkert.org void callpal(int code); 966657Snate@binkert.org}; 976657Snate@binkert.org 986657Snate@binkert.orgKernelStats::KernelStats(ExecContext *xc, BaseCPU *cpu) 996657Snate@binkert.org{ data = new KSData(xc, cpu); } 1006657Snate@binkert.org 1016657Snate@binkert.orgKernelStats::~KernelStats() 1026657Snate@binkert.org{ delete data; } 1036657Snate@binkert.org 1046657Snate@binkert.orgvoid 1056657Snate@binkert.orgKernelStats::regStats(const string &name) 1066657Snate@binkert.org{ data->regStats(name); } 1076657Snate@binkert.org 1086657Snate@binkert.orgvoid 1096657Snate@binkert.orgKSData::regStats(const string &name) 1106657Snate@binkert.org{ 1116657Snate@binkert.org _name = name; 1126657Snate@binkert.org 1136657Snate@binkert.org _arm 1146657Snate@binkert.org .name(name + ".inst.arm") 1156657Snate@binkert.org .desc("number of arm instructions executed") 1166657Snate@binkert.org ; 1176657Snate@binkert.org 1186657Snate@binkert.org _quiesce 1196657Snate@binkert.org .name(name + ".inst.quiesce") 1206657Snate@binkert.org .desc("number of quiesce instructions executed") 1216657Snate@binkert.org ; 1226657Snate@binkert.org 1236657Snate@binkert.org _ivlb 1246657Snate@binkert.org .name(name + ".inst.ivlb") 1256657Snate@binkert.org .desc("number of ivlb instructions executed") 1266657Snate@binkert.org ; 1279219Spower.jg@gmail.com 1288453Snate@binkert.org _ivle 1298453Snate@binkert.org .name(name + ".inst.ivle") 1306999Snate@binkert.org .desc("number of ivle instructions executed") 1319219Spower.jg@gmail.com ; 1326657Snate@binkert.org 1339219Spower.jg@gmail.com _hwrei 1349219Spower.jg@gmail.com .name(name + ".inst.hwrei") 1359219Spower.jg@gmail.com .desc("number of hwrei instructions executed") 1366657Snate@binkert.org ; 1376657Snate@binkert.org 1386657Snate@binkert.org _iplCount 1396657Snate@binkert.org .init(32) 1406657Snate@binkert.org .name(name + ".ipl_count") 1416657Snate@binkert.org .desc("number of times we switched to this ipl") 1426657Snate@binkert.org .flags(total | pdf | nozero | nonan) 1439219Spower.jg@gmail.com ; 1446657Snate@binkert.org 1456657Snate@binkert.org _iplGood 1468453Snate@binkert.org .init(32) 1478453Snate@binkert.org .name(name + ".ipl_good") 1486657Snate@binkert.org .desc("number of times we switched to this ipl from a different ipl") 1496657Snate@binkert.org .flags(total | pdf | nozero | nonan) 1506657Snate@binkert.org ; 1516657Snate@binkert.org 1526657Snate@binkert.org _iplTicks 1536657Snate@binkert.org .init(32) 1546999Snate@binkert.org .name(name + ".ipl_ticks") 1556657Snate@binkert.org .desc("number of cycles we spent at this ipl") 1566657Snate@binkert.org .flags(total | pdf | nozero | nonan) 1576657Snate@binkert.org ; 1586657Snate@binkert.org 1596657Snate@binkert.org _iplUsed 1606657Snate@binkert.org .name(name + ".ipl_used") 1616657Snate@binkert.org .desc("fraction of swpipl calls that actually changed the ipl") 1626657Snate@binkert.org .flags(total | nozero | nonan) 1636657Snate@binkert.org ; 1646657Snate@binkert.org 1656657Snate@binkert.org _iplUsed = _iplGood / _iplCount; 1666657Snate@binkert.org 1676657Snate@binkert.org _callpal 1686999Snate@binkert.org .init(256) 1696657Snate@binkert.org .name(name + ".callpal") 1706657Snate@binkert.org .desc("number of callpals executed") 1716657Snate@binkert.org .flags(total | pdf | nozero | nonan) 1726657Snate@binkert.org ; 1736657Snate@binkert.org 1746657Snate@binkert.org for (int i = 0; i < PAL::NumCodes; ++i) { 1756657Snate@binkert.org const char *str = PAL::name(i); 176 if (str) 177 _callpal.subname(i, str); 178 } 179 180 _syscall 181 .init(SystemCalls<Tru64>::Number) 182 .name(name + ".syscall") 183 .desc("number of syscalls executed") 184 .flags(total | pdf | nozero | nonan) 185 ; 186 187 for (int i = 0; i < SystemCalls<Tru64>::Number; ++i) { 188 const char *str = SystemCalls<Tru64>::name(i); 189 if (str) { 190 _syscall.subname(i, str); 191 } 192 } 193 194 _faults 195 .init(Num_Faults) 196 .name(name + ".faults") 197 .desc("number of faults") 198 .flags(total | pdf | nozero | nonan) 199 ; 200 201 for (int i = 1; i < Num_Faults; ++i) { 202 const char *str = FaultName(i); 203 if (str) 204 _faults.subname(i, str); 205 } 206 207 _mode 208 .init(2) 209 .name(name + ".mode_switch") 210 .subname(0, "kernel") 211 .subname(1, "user") 212 .desc("number of protection mode switches") 213 ; 214 215 _modeGood 216 .init(2) 217 ; 218 219 _modeFraction 220 .name(name + ".mode_switch_good") 221 .subname(0, "kernel") 222 .subname(1, "user") 223 .desc("fraction of useful protection mode switches") 224 .flags(total) 225 ; 226 _modeFraction = _modeGood / _mode; 227 228 _modeTicks 229 .init(2) 230 .name(name + ".mode_ticks") 231 .subname(0, "kernel") 232 .subname(1, "user") 233 .desc("number of ticks spent at the given mode") 234 .flags(pdf) 235 ; 236 237 _swap_context 238 .name(name + ".swap_context") 239 .desc("number of times the context was actually changed") 240 ; 241} 242 243void 244KernelStats::arm() 245{ data->_arm++; } 246 247void 248KernelStats::quiesce() 249{ data->_quiesce++; } 250 251void 252KernelStats::ivlb() 253{ data->_ivlb++; } 254 255void 256KernelStats::ivle() 257{ data->_ivle++; } 258 259void 260KernelStats::hwrei() 261{ data->_hwrei++; } 262 263void 264KernelStats::fault(Fault fault) 265{ data->_faults[fault]++; } 266 267void 268KernelStats::swpipl(int ipl) 269{ data->swpipl(ipl); } 270 271void 272KernelStats::mode(bool user) 273{ data->mode(user); } 274 275void 276KernelStats::context(Addr old_pcbb, Addr new_pcbb) 277{ data->_swap_context++; } 278 279void 280KernelStats::callpal(int code) 281{ data->callpal(code); } 282 283 284void 285KSData::swpipl(int ipl) 286{ 287 assert(ipl >= 0 && ipl <= 0x1f && "invalid IPL\n"); 288 289 _iplCount[ipl]++; 290 291 if (ipl == iplLast) 292 return; 293 294 _iplGood[ipl]++; 295 _iplTicks[iplLast] += curTick - iplLastTick; 296 iplLastTick = curTick; 297 iplLast = ipl; 298} 299 300void 301KSData::mode(bool user) 302{ 303 _mode[user]++; 304 if (user == lastUser) 305 return; 306 307 _modeGood[user]++; 308 _modeTicks[lastUser] += curTick - lastModeTick; 309 310 lastModeTick = curTick; 311 lastUser = user; 312 313 if (xc->system->bin) { 314 if (!xc->swCtx || xc->swCtx->callStack.empty()) { 315 if (user) 316 xc->system->User->activate(); 317 else 318 xc->system->Kernel->activate(); 319 } 320 } 321} 322 323void 324KSData::callpal(int code) 325{ 326 if (!PAL::name(code)) 327 return; 328 329 _callpal[code]++; 330 331 switch (code) { 332 case PAL::callsys: 333 { 334 int number = xc->regs.intRegFile[0]; 335 if (SystemCalls<Tru64>::validSyscallNumber(number)) { 336 int cvtnum = SystemCalls<Tru64>::convert(number); 337 _syscall[cvtnum]++; 338 } 339 } 340 break; 341 } 342 343 if (code == PAL::swpctx) { 344 SWContext *out = xc->swCtx; 345 System *sys = xc->system; 346 if (!sys->bin) 347 return; 348 DPRINTF(TCPIP, "swpctx event\n"); 349 if (out) { 350 DPRINTF(TCPIP, "swapping context out with this stack!\n"); 351 xc->system->dumpState(xc); 352 Addr oldPCB = xc->regs.ipr[TheISA::IPR_PALtemp23]; 353 354 if (out->callStack.empty()) { 355 DPRINTF(TCPIP, "but removing it, cuz empty!\n"); 356 SWContext *find = sys->findContext(oldPCB); 357 if (find) { 358 assert(sys->findContext(oldPCB) == out); 359 sys->remContext(oldPCB); 360 } 361 delete out; 362 } else { 363 DPRINTF(TCPIP, "switching out context with pcb %#x, top fn %s\n", 364 oldPCB, out->callStack.top()->name); 365 if (!sys->findContext(oldPCB)) { 366 if (!sys->addContext(oldPCB, out)) 367 panic("could not add context"); 368 } 369 } 370 } 371 372 Addr newPCB = xc->regs.intRegFile[16]; 373 SWContext *in = sys->findContext(newPCB); 374 xc->swCtx = in; 375 376 if (in) { 377 assert(!in->callStack.empty() && 378 "should not be switching in empty context"); 379 DPRINTF(TCPIP, "swapping context in with this callstack!\n"); 380 xc->system->dumpState(xc); 381 sys->remContext(newPCB); 382 fnCall *top = in->callStack.top(); 383 DPRINTF(TCPIP, "switching in to pcb %#x, %s\n", newPCB, top->name); 384 assert(top->myBin && "should not switch to context with no Bin"); 385 top->myBin->activate(); 386 } else { 387 sys->Kernel->activate(); 388 } 389 DPRINTF(TCPIP, "end swpctx\n"); 390 } 391} 392