2 * Copyright (c) 2003 The Regents of The University of Michigan
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.
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.
33 #include "base/statistics.hh"
34 #include "base/trace.hh"
35 #include "cpu/exec_context.hh"
36 #include "kern/kernel_stats.hh"
37 #include "sim/stats.hh"
38 #include "sim/sw_context.hh"
39 #include "targetarch/isa_traits.hh"
40 #include "targetarch/osfpal.hh"
41 #include "targetarch/syscalls.hh"
44 using namespace Stats
;
54 KSData(ExecContext
*_xc
, BaseCPU
*_cpu
)
55 : xc(_xc
), cpu(_cpu
), iplLast(0), iplLastTick(0), lastUser(false),
59 const string
&name() { return _name
; }
60 void regStats(const string
&name
);
80 Formula _modeFraction
;
83 Scalar
<> _swap_context
;
95 void callpal(int code
);
98 KernelStats::KernelStats(ExecContext
*xc
, BaseCPU
*cpu
)
99 { data
= new KSData(xc
, cpu
); }
101 KernelStats::~KernelStats()
105 KernelStats::regStats(const string
&name
)
106 { data
->regStats(name
); }
109 KSData::regStats(const string
&name
)
114 .name(name
+ ".inst.arm")
115 .desc("number of arm instructions executed")
119 .name(name
+ ".inst.quiesce")
120 .desc("number of quiesce instructions executed")
124 .name(name
+ ".inst.ivlb")
125 .desc("number of ivlb instructions executed")
129 .name(name
+ ".inst.ivle")
130 .desc("number of ivle instructions executed")
134 .name(name
+ ".inst.hwrei")
135 .desc("number of hwrei instructions executed")
140 .name(name
+ ".ipl_count")
141 .desc("number of times we switched to this ipl")
142 .flags(total
| pdf
| nozero
| nonan
)
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
)
154 .name(name
+ ".ipl_ticks")
155 .desc("number of cycles we spent at this ipl")
156 .flags(total
| pdf
| nozero
| nonan
)
160 .name(name
+ ".ipl_used")
161 .desc("fraction of swpipl calls that actually changed the ipl")
162 .flags(total
| nozero
| nonan
)
165 _iplUsed
= _iplGood
/ _iplCount
;
169 .name(name
+ ".callpal")
170 .desc("number of callpals executed")
171 .flags(total
| pdf
| nozero
| nonan
)
174 for (int i
= 0; i
< PAL::NumCodes
; ++i
) {
175 const char *str
= PAL::name(i
);
177 _callpal
.subname(i
, str
);
181 .init(SystemCalls
<Tru64
>::Number
)
182 .name(name
+ ".syscall")
183 .desc("number of syscalls executed")
184 .flags(total
| pdf
| nozero
| nonan
)
187 for (int i
= 0; i
< SystemCalls
<Tru64
>::Number
; ++i
) {
188 const char *str
= SystemCalls
<Tru64
>::name(i
);
190 _syscall
.subname(i
, str
);
196 .name(name
+ ".faults")
197 .desc("number of faults")
198 .flags(total
| pdf
| nozero
| nonan
)
201 for (int i
= 1; i
< Num_Faults
; ++i
) {
202 const char *str
= FaultName(i
);
204 _faults
.subname(i
, str
);
209 .name(name
+ ".mode_switch")
210 .subname(0, "kernel")
212 .desc("number of protection mode switches")
220 .name(name
+ ".mode_switch_good")
221 .subname(0, "kernel")
223 .desc("fraction of useful protection mode switches")
226 _modeFraction
= _modeGood
/ _mode
;
230 .name(name
+ ".mode_ticks")
231 .subname(0, "kernel")
233 .desc("number of ticks spent at the given mode")
238 .name(name
+ ".swap_context")
239 .desc("number of times the context was actually changed")
248 KernelStats::quiesce()
249 { data
->_quiesce
++; }
264 KernelStats::fault(Fault fault
)
265 { data
->_faults
[fault
]++; }
268 KernelStats::swpipl(int ipl
)
269 { data
->swpipl(ipl
); }
272 KernelStats::mode(bool user
)
273 { data
->mode(user
); }
276 KernelStats::context(Addr old_pcbb
, Addr new_pcbb
)
277 { data
->_swap_context
++; }
280 KernelStats::callpal(int code
)
281 { data
->callpal(code
); }
285 KSData::swpipl(int ipl
)
287 assert(ipl
>= 0 && ipl
<= 0x1f && "invalid IPL\n");
295 _iplTicks
[iplLast
] += curTick
- iplLastTick
;
296 iplLastTick
= curTick
;
301 KSData::mode(bool user
)
304 if (user
== lastUser
)
308 _modeTicks
[lastUser
] += curTick
- lastModeTick
;
310 lastModeTick
= curTick
;
313 if (xc
->system
->bin
) {
314 if (!xc
->swCtx
|| xc
->swCtx
->callStack
.empty()) {
316 xc
->system
->User
->activate();
318 xc
->system
->Kernel
->activate();
324 KSData::callpal(int code
)
326 if (!PAL::name(code
))
334 int number
= xc
->regs
.intRegFile
[0];
335 if (SystemCalls
<Tru64
>::validSyscallNumber(number
)) {
336 int cvtnum
= SystemCalls
<Tru64
>::convert(number
);
343 if (code
== PAL::swpctx
) {
344 SWContext
*out
= xc
->swCtx
;
345 System
*sys
= xc
->system
;
348 DPRINTF(TCPIP
, "swpctx event\n");
350 DPRINTF(TCPIP
, "swapping context out with this stack!\n");
351 xc
->system
->dumpState(xc
);
352 Addr oldPCB
= xc
->regs
.ipr
[TheISA::IPR_PALtemp23
];
354 if (out
->callStack
.empty()) {
355 DPRINTF(TCPIP
, "but removing it, cuz empty!\n");
356 SWContext
*find
= sys
->findContext(oldPCB
);
358 assert(sys
->findContext(oldPCB
) == out
);
359 sys
->remContext(oldPCB
);
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");
372 Addr newPCB
= xc
->regs
.intRegFile
[16];
373 SWContext
*in
= sys
->findContext(newPCB
);
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();
387 sys
->Kernel
->activate();
389 DPRINTF(TCPIP
, "end swpctx\n");