2 * Copyright \e.A\eN) 2007 MIPS Technologies, Inc. All Rights Reserved
4 * This software is part of the M5 simulator.
6 * THIS IS A LEGAL AGREEMENT. BY DOWNLOADING, USING, COPYING, CREATING
7 * DERIVATIVE WORKS, AND/OR DISTRIBUTING THIS SOFTWARE YOU ARE AGREEING
8 * TO THESE TERMS AND CONDITIONS.
10 * Permission is granted to use, copy, create derivative works and
11 * distribute this software and such derivative works for any purpose,
12 * so long as (1) the copyright notice above, this grant of permission,
13 * and the disclaimer below appear in all copies and derivative works
14 * made, (2) the copyright notice above is augmented as appropriate to
15 * reflect the addition of any new copyrightable work in a derivative
16 * work (e.g., Copyright \e.A\eN) <Publication Year> Copyright Owner), and (3)
17 * the name of MIPS Technologies, Inc. (\e$B!H\e(BMIPS\e$B!I\e(B) is not used in any
18 * advertising or publicity pertaining to the use or distribution of
19 * this software without specific, written prior authorization.
21 * THIS SOFTWARE IS PROVIDED \e$B!H\e(BAS IS.\e$B!I\e(B MIPS MAKES NO WARRANTIES AND
22 * DISCLAIMS ALL WARRANTIES, WHETHER EXPRESS, STATUTORY, IMPLIED OR
23 * OTHERWISE, INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
25 * NON-INFRINGEMENT OF THIRD PARTY RIGHTS, REGARDING THIS SOFTWARE.
26 * IN NO EVENT SHALL MIPS BE LIABLE FOR ANY DAMAGES, INCLUDING DIRECT,
27 * INDIRECT, INCIDENTAL, CONSEQUENTIAL, SPECIAL, OR PUNITIVE DAMAGES OF
28 * ANY KIND OR NATURE, ARISING OUT OF OR IN CONNECTION WITH THIS AGREEMENT,
29 * THIS SOFTWARE AND/OR THE USE OF THIS SOFTWARE, WHETHER SUCH LIABILITY
30 * IS ASSERTED ON THE BASIS OF CONTRACT, TORT (INCLUDING NEGLIGENCE OR
31 * STRICT LIABILITY), OR OTHERWISE, EVEN IF MIPS HAS BEEN WARNED OF THE
32 * POSSIBILITY OF ANY SUCH LOSS OR DAMAGE IN ADVANCE.
34 * Authors: Nathan L. Binkert
39 #include "arch/mips/isa_traits.hh"
40 #include "arch/mips/stacktrace.hh"
41 #include "arch/mips/vtophys.hh"
42 #include "base/bitfield.hh"
43 #include "base/trace.hh"
44 #include "cpu/base.hh"
45 #include "cpu/thread_context.hh"
46 #include "sim/system.hh"
49 using namespace MipsISA
;
51 ProcessInfo::ProcessInfo(ThreadContext
*_tc
)
58 vp
= tc
->getVirtPort();
60 // if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr))
61 // panic("thread info not compiled into kernel\n");
62 // thread_info_size = vp->readGtoH<int32_t>(addr);
64 // if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr))
65 // panic("thread info not compiled into kernel\n");
66 // task_struct_size = vp->readGtoH<int32_t>(addr);
68 // if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr))
69 // panic("thread info not compiled into kernel\n");
70 // task_off = vp->readGtoH<int32_t>(addr);
72 // if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr))
73 // panic("thread info not compiled into kernel\n");
74 // pid_off = vp->readGtoH<int32_t>(addr);
76 // if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr))
77 // panic("thread info not compiled into kernel\n");
78 // name_off = vp->readGtoH<int32_t>(addr);
84 ProcessInfo::task(Addr ksp
) const
86 Addr base
= ksp
& ~0x3fff;
87 if (base
== ULL(0xfffffc0000000000))
94 vp
= tc
->getVirtPort();
95 tsk
= vp
->readGtoH
<Addr
>(base
+ task_off
);
102 ProcessInfo::pid(Addr ksp
) const
104 Addr task
= this->task(ksp
);
112 vp
= tc
->getVirtPort();
113 pd
= vp
->readGtoH
<uint16_t>(task
+ pid_off
);
120 ProcessInfo::name(Addr ksp
) const
122 Addr task
= this->task(ksp
);
127 CopyStringOut(tc
, comm
, task
+ name_off
, sizeof(comm
));
134 StackTrace::StackTrace()
139 StackTrace::StackTrace(ThreadContext
*_tc
, StaticInstPtr inst
)
145 StackTrace::~StackTrace()
150 StackTrace::trace(ThreadContext
*_tc
, bool is_call
)
153 /* FIXME - Jaidev - What is IPR_DTB_CM in Alpha? */
155 //(tc->readMiscReg(MipsISA::IPR_DTB_CM) & 0x18) != 0;
157 // Addr pc = tc->readNextPC();
158 // bool kernel = tc->getSystemPtr()->kernelStart <= pc &&
159 // pc <= tc->getSystemPtr()->kernelEnd;
162 stack
.push_back(user
);
167 // stack.push_back(console);
171 // SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
172 // Addr ksp = tc->readIntReg(TheISA::StackPointerReg);
173 // Addr bottom = ksp & ~0x3fff;
177 // if (!symtab->findNearestAddr(pc, addr))
178 // panic("could not find address %#x", pc);
180 // stack.push_back(addr);
181 // pc = tc->readPC();
187 // while (ksp > bottom) {
188 // if (!symtab->findNearestAddr(pc, addr))
189 // panic("could not find symbol for pc=%#x", pc);
190 // assert(pc >= addr && "symbol botch: callpc < func");
192 // stack.push_back(addr);
194 // if (isEntry(addr))
197 // if (decodePrologue(ksp, pc, addr, size, ra)) {
202 // stack.push_back(unknown);
209 // stack.push_back(unknown);
213 // bool kernel = tc->getSystemPtr()->kernelStart <= pc &&
214 // pc <= tc->getSystemPtr()->kernelEnd;
218 // if (stack.size() >= 1000)
219 // panic("unwinding too far");
222 // panic("unwinding too far");
226 StackTrace::isEntry(Addr addr
)
228 /* if (addr == tc->readMiscReg(MipsISA::IPR_PALtemp2))
235 StackTrace::decodeStack(MachInst inst
, int &disp
)
237 // lda $sp, -disp($sp)
239 // Opcode<31:26> == 0x08
243 const MachInst mem_mask
= 0xffff0000;
244 const MachInst lda_pattern
= 0x23de0000;
245 const MachInst lda_disp_mask
= 0x0000ffff;
247 // subq $sp, disp, $sp
248 // addq $sp, disp, $sp
250 // Opcode<31:26> == 0x10
254 // Func<11:5> == 0x20 (addq)
255 // Func<11:5> == 0x29 (subq)
257 const MachInst intop_mask
= 0xffe01fff;
258 const MachInst addq_pattern
= 0x43c0141e;
259 const MachInst subq_pattern
= 0x43c0153e;
260 const MachInst intop_disp_mask
= 0x001fe000;
261 const int intop_disp_shift
= 13;
263 if ((inst
& mem_mask
) == lda_pattern
)
264 disp
= -sext
<16>(inst
& lda_disp_mask
);
265 else if ((inst
& intop_mask
) == addq_pattern
)
266 disp
= -int((inst
& intop_disp_mask
) >> intop_disp_shift
);
267 else if ((inst
& intop_mask
) == subq_pattern
)
268 disp
= int((inst
& intop_disp_mask
) >> intop_disp_shift
);
276 StackTrace::decodeSave(MachInst inst
, int ®
, int &disp
)
278 // lda $stq, disp($sp)
280 // Opcode<31:26> == 0x08
284 const MachInst stq_mask
= 0xfc1f0000;
285 const MachInst stq_pattern
= 0xb41e0000;
286 const MachInst stq_disp_mask
= 0x0000ffff;
287 const MachInst reg_mask
= 0x03e00000;
288 const int reg_shift
= 21;
290 if ((inst
& stq_mask
) == stq_pattern
) {
291 reg
= (inst
& reg_mask
) >> reg_shift
;
292 disp
= sext
<16>(inst
& stq_disp_mask
);
301 * Decode the function prologue for the function we're in, and note
302 * which registers are stored where, and how large the stack frame is.
305 StackTrace::decodePrologue(Addr sp
, Addr callpc
, Addr func
,
311 for (Addr pc
= func
; pc
< callpc
; pc
+= sizeof(MachInst
)) {
313 CopyOut(tc
, (uint8_t *)&inst
, pc
, sizeof(MachInst
));
316 if (decodeStack(inst
, disp
)) {
318 // panic("decoding frame size again");
322 } else if (decodeSave(inst
, reg
, disp
)) {
323 if (!ra
&& reg
== ReturnAddressReg
) {
324 CopyOut(tc
, (uint8_t *)&ra
, sp
+ disp
, sizeof(Addr
));
326 // panic("no return address value pc=%#x\n", pc);
340 StringWrap
name(tc
->getCpuPtr()->name());
341 // SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
343 DPRINTFN("------ Stack ------\n");
346 // for (int i = 0, size = stack.size(); i < size; ++i) {
347 // Addr addr = stack[size - i - 1];
350 // else if (addr == console)
351 // symbol = "console";
352 // else if (addr == unknown)
353 // symbol = "unknown";
355 // symtab->findSymbol(addr, symbol);
357 // DPRINTFN("%#x: %s\n", addr, symbol);