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