kernel_stats.cc revision 754
111660Stushar@ece.gatech.edu/*
211660Stushar@ece.gatech.edu * Copyright (c) 2003 The Regents of The University of Michigan
311660Stushar@ece.gatech.edu * All rights reserved.
411660Stushar@ece.gatech.edu *
511660Stushar@ece.gatech.edu * Redistribution and use in source and binary forms, with or without
611660Stushar@ece.gatech.edu * modification, are permitted provided that the following conditions are
711660Stushar@ece.gatech.edu * met: redistributions of source code must retain the above copyright
811660Stushar@ece.gatech.edu * notice, this list of conditions and the following disclaimer;
911660Stushar@ece.gatech.edu * redistributions in binary form must reproduce the above copyright
1011660Stushar@ece.gatech.edu * notice, this list of conditions and the following disclaimer in the
1111660Stushar@ece.gatech.edu * documentation and/or other materials provided with the distribution;
1211660Stushar@ece.gatech.edu * neither the name of the copyright holders nor the names of its
1311660Stushar@ece.gatech.edu * contributors may be used to endorse or promote products derived from
1411660Stushar@ece.gatech.edu * this software without specific prior written permission.
1511660Stushar@ece.gatech.edu *
1611660Stushar@ece.gatech.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1711660Stushar@ece.gatech.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1811660Stushar@ece.gatech.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1911660Stushar@ece.gatech.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2011660Stushar@ece.gatech.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2111660Stushar@ece.gatech.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2211660Stushar@ece.gatech.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2311660Stushar@ece.gatech.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2411660Stushar@ece.gatech.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2511660Stushar@ece.gatech.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2611660Stushar@ece.gatech.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2711660Stushar@ece.gatech.edu */
2811660Stushar@ece.gatech.edu
2911660Stushar@ece.gatech.edu#include <map>
3011660Stushar@ece.gatech.edu#include <stack>
3111660Stushar@ece.gatech.edu#include <string>
3211660Stushar@ece.gatech.edu
3311660Stushar@ece.gatech.edu#include "base/statistics.hh"
3411660Stushar@ece.gatech.edu#include "base/trace.hh"
3512065Snikos.nikoleris@arm.com#include "cpu/exec_context.hh"
3611660Stushar@ece.gatech.edu#include "kern/kernel_stats.hh"
3711660Stushar@ece.gatech.edu#include "sim/stats.hh"
3811660Stushar@ece.gatech.edu#include "sim/sw_context.hh"
3911660Stushar@ece.gatech.edu#include "targetarch/isa_traits.hh"
4011660Stushar@ece.gatech.edu#include "targetarch/osfpal.hh"
4111660Stushar@ece.gatech.edu#include "targetarch/syscalls.hh"
4211660Stushar@ece.gatech.edu
4311660Stushar@ece.gatech.eduusing namespace std;
4411660Stushar@ece.gatech.eduusing namespace Stats;
4512598Snikos.nikoleris@arm.com
4612598Snikos.nikoleris@arm.comclass KSData
4711660Stushar@ece.gatech.edu{
4811660Stushar@ece.gatech.edu  private:
4911660Stushar@ece.gatech.edu    string _name;
5011660Stushar@ece.gatech.edu    ExecContext *xc;
5111660Stushar@ece.gatech.edu    BaseCPU *cpu;
5211660Stushar@ece.gatech.edu
5311660Stushar@ece.gatech.edu  public:
5411660Stushar@ece.gatech.edu    KSData(ExecContext *_xc, BaseCPU *_cpu)
5511660Stushar@ece.gatech.edu        : xc(_xc), cpu(_cpu), iplLast(0), iplLastTick(0), lastUser(false),
5611660Stushar@ece.gatech.edu          lastModeTick(0)
5711660Stushar@ece.gatech.edu    {}
5811660Stushar@ece.gatech.edu
5911660Stushar@ece.gatech.edu    const string &name() { return _name; }
6011660Stushar@ece.gatech.edu    void regStats(const string &name);
6111660Stushar@ece.gatech.edu
6211660Stushar@ece.gatech.edu  public:
6311660Stushar@ece.gatech.edu    Scalar<> _arm;
6411660Stushar@ece.gatech.edu    Scalar<> _quiesce;
6511660Stushar@ece.gatech.edu    Scalar<> _ivlb;
6611660Stushar@ece.gatech.edu    Scalar<> _ivle;
6711660Stushar@ece.gatech.edu    Scalar<> _hwrei;
6811660Stushar@ece.gatech.edu
6913731Sandreas.sandberg@arm.com    Vector<> _iplCount;
7011660Stushar@ece.gatech.edu    Vector<> _iplGood;
7111660Stushar@ece.gatech.edu    Vector<> _iplTicks;
7211660Stushar@ece.gatech.edu    Formula _iplUsed;
7311660Stushar@ece.gatech.edu
7411660Stushar@ece.gatech.edu    Vector<> _callpal;
7511660Stushar@ece.gatech.edu    Vector<> _syscall;
7611660Stushar@ece.gatech.edu    Vector<> _faults;
7711660Stushar@ece.gatech.edu
7811660Stushar@ece.gatech.edu    Vector<> _mode;
7911660Stushar@ece.gatech.edu    Vector<> _modeGood;
8011660Stushar@ece.gatech.edu    Formula _modeFraction;
8111660Stushar@ece.gatech.edu    Vector<> _modeTicks;
8211660Stushar@ece.gatech.edu
8311660Stushar@ece.gatech.edu    Scalar<> _swap_context;
8411660Stushar@ece.gatech.edu
8511660Stushar@ece.gatech.edu  private:
8611660Stushar@ece.gatech.edu    int iplLast;
8711660Stushar@ece.gatech.edu    Tick iplLastTick;
8811660Stushar@ece.gatech.edu
8911660Stushar@ece.gatech.edu    bool lastUser;
9011660Stushar@ece.gatech.edu    Tick lastModeTick;
9111660Stushar@ece.gatech.edu
9211660Stushar@ece.gatech.edu  public:
9311660Stushar@ece.gatech.edu    void swpipl(int ipl);
9411660Stushar@ece.gatech.edu    void mode(bool user);
9511660Stushar@ece.gatech.edu    void callpal(int code);
9611660Stushar@ece.gatech.edu};
9711660Stushar@ece.gatech.edu
9811660Stushar@ece.gatech.eduKernelStats::KernelStats(ExecContext *xc, BaseCPU *cpu)
9911660Stushar@ece.gatech.edu{ data = new KSData(xc, cpu); }
10011660Stushar@ece.gatech.edu
10111660Stushar@ece.gatech.eduKernelStats::~KernelStats()
10211660Stushar@ece.gatech.edu{ delete data; }
10312598Snikos.nikoleris@arm.com
10412976Snikos.nikoleris@arm.comvoid
10512598Snikos.nikoleris@arm.comKernelStats::regStats(const string &name)
10612598Snikos.nikoleris@arm.com{ data->regStats(name); }
10712598Snikos.nikoleris@arm.com
10812065Snikos.nikoleris@arm.comvoid
10911660Stushar@ece.gatech.eduKSData::regStats(const string &name)
11011660Stushar@ece.gatech.edu{
11111660Stushar@ece.gatech.edu    _name = name;
11211660Stushar@ece.gatech.edu
11311660Stushar@ece.gatech.edu    _arm
11411660Stushar@ece.gatech.edu        .name(name + ".inst.arm")
11511660Stushar@ece.gatech.edu        .desc("number of arm instructions executed")
11611660Stushar@ece.gatech.edu        ;
11711660Stushar@ece.gatech.edu
11812598Snikos.nikoleris@arm.com    _quiesce
119        .name(name + ".inst.quiesce")
120        .desc("number of quiesce instructions executed")
121        ;
122
123    _ivlb
124        .name(name + ".inst.ivlb")
125        .desc("number of ivlb instructions executed")
126        ;
127
128    _ivle
129        .name(name + ".inst.ivle")
130        .desc("number of ivle instructions executed")
131        ;
132
133    _hwrei
134        .name(name + ".inst.hwrei")
135        .desc("number of hwrei instructions executed")
136        ;
137
138    _iplCount
139        .init(32)
140        .name(name + ".ipl_count")
141        .desc("number of times we switched to this ipl")
142        .flags(total | pdf | nozero | nonan)
143        ;
144
145    _iplGood
146        .init(32)
147        .name(name + ".ipl_good")
148        .desc("number of times we switched to this ipl from a different ipl")
149        .flags(total | pdf | nozero | nonan)
150        ;
151
152    _iplTicks
153        .init(32)
154        .name(name + ".ipl_ticks")
155        .desc("number of cycles we spent at this ipl")
156        .flags(total | pdf | nozero | nonan)
157        ;
158
159    _iplUsed
160        .name(name + ".ipl_used")
161        .desc("fraction of swpipl calls that actually changed the ipl")
162        .flags(total | nozero | nonan)
163        ;
164
165    _iplUsed = _iplGood / _iplCount;
166
167    _callpal
168        .init(256)
169        .name(name + ".callpal")
170        .desc("number of callpals executed")
171        .flags(total | pdf | nozero | nonan)
172        ;
173
174    for (int i = 0; i < PAL::NumCodes; ++i) {
175        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