kernel_stats.cc revision 1762
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 "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 &section)
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