fiq_debugger_arm64.c revision e139164eb6468f39be07f58a40b657d2e95e787d
1/*
2 * Copyright (C) 2014 Google, Inc.
3 * Author: Colin Cross <ccross@android.com>
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 */
15
16#include <linux/ptrace.h>
17#include <asm/stacktrace.h>
18
19#include "fiq_debugger_priv.h"
20
21static char *mode_name(const struct pt_regs *regs)
22{
23	if (compat_user_mode(regs)) {
24		return "USR";
25	} else {
26		switch (processor_mode(regs)) {
27		case PSR_MODE_EL0t: return "EL0t";
28		case PSR_MODE_EL1t: return "EL1t";
29		case PSR_MODE_EL1h: return "EL1h";
30		case PSR_MODE_EL2t: return "EL2t";
31		case PSR_MODE_EL2h: return "EL2h";
32		default: return "???";
33		}
34	}
35}
36
37void fiq_debugger_dump_pc(struct fiq_debugger_state *state,
38		const struct pt_regs *regs)
39{
40	fiq_debugger_printf(state, " pc %016lx cpsr %08lx mode %s\n",
41		regs->pc, regs->pstate, mode_name(regs));
42}
43
44void fiq_debugger_dump_regs_aarch32(struct fiq_debugger_state *state,
45		const struct pt_regs *regs)
46{
47	fiq_debugger_printf(state, " r0 %08x  r1 %08x  r2 %08x  r3 %08x\n",
48			regs->compat_usr(0), regs->compat_usr(1),
49			regs->compat_usr(2), regs->compat_usr(3));
50	fiq_debugger_printf(state, " r4 %08x  r5 %08x  r6 %08x  r7 %08x\n",
51			regs->compat_usr(4), regs->compat_usr(5),
52			regs->compat_usr(6), regs->compat_usr(7));
53	fiq_debugger_printf(state, " r8 %08x  r9 %08x r10 %08x r11 %08x\n",
54			regs->compat_usr(8), regs->compat_usr(9),
55			regs->compat_usr(10), regs->compat_usr(11));
56	fiq_debugger_printf(state, " ip %08x  sp %08x  lr %08x  pc %08x\n",
57			regs->compat_usr(12), regs->compat_sp,
58			regs->compat_lr, regs->pc);
59	fiq_debugger_printf(state, " cpsr %08x (%s)\n",
60			regs->pstate, mode_name(regs));
61}
62
63void fiq_debugger_dump_regs_aarch64(struct fiq_debugger_state *state,
64		const struct pt_regs *regs)
65{
66
67	fiq_debugger_printf(state, "  x0 %016lx   x1 %016lx\n",
68			regs->regs[0], regs->regs[1]);
69	fiq_debugger_printf(state, "  x2 %016lx   x3 %016lx\n",
70			regs->regs[2], regs->regs[3]);
71	fiq_debugger_printf(state, "  x4 %016lx   x5 %016lx\n",
72			regs->regs[4], regs->regs[5]);
73	fiq_debugger_printf(state, "  x6 %016lx   x7 %016lx\n",
74			regs->regs[6], regs->regs[7]);
75	fiq_debugger_printf(state, "  x8 %016lx   x9 %016lx\n",
76			regs->regs[8], regs->regs[9]);
77	fiq_debugger_printf(state, " x10 %016lx  x11 %016lx\n",
78			regs->regs[10], regs->regs[11]);
79	fiq_debugger_printf(state, " x12 %016lx  x13 %016lx\n",
80			regs->regs[12], regs->regs[13]);
81	fiq_debugger_printf(state, " x14 %016lx  x15 %016lx\n",
82			regs->regs[14], regs->regs[15]);
83	fiq_debugger_printf(state, " x16 %016lx  x17 %016lx\n",
84			regs->regs[16], regs->regs[17]);
85	fiq_debugger_printf(state, " x18 %016lx  x19 %016lx\n",
86			regs->regs[18], regs->regs[19]);
87	fiq_debugger_printf(state, " x20 %016lx  x21 %016lx\n",
88			regs->regs[20], regs->regs[21]);
89	fiq_debugger_printf(state, " x22 %016lx  x23 %016lx\n",
90			regs->regs[22], regs->regs[23]);
91	fiq_debugger_printf(state, " x24 %016lx  x25 %016lx\n",
92			regs->regs[24], regs->regs[25]);
93	fiq_debugger_printf(state, " x26 %016lx  x27 %016lx\n",
94			regs->regs[26], regs->regs[27]);
95	fiq_debugger_printf(state, " x28 %016lx  x29 %016lx\n",
96			regs->regs[28], regs->regs[29]);
97	fiq_debugger_printf(state, " x30 %016lx   sp %016lx\n",
98			regs->regs[30], regs->sp);
99	fiq_debugger_printf(state, "  pc %016lx cpsr %08x (%s)\n",
100			regs->pc, regs->pstate, mode_name(regs));
101}
102
103void fiq_debugger_dump_regs(struct fiq_debugger_state *state,
104		const struct pt_regs *regs)
105{
106	if (compat_user_mode(regs))
107		fiq_debugger_dump_regs_aarch32(state, regs);
108	else
109		fiq_debugger_dump_regs_aarch64(state, regs);
110}
111
112#define READ_SPECIAL_REG(x) ({ \
113	u64 val; \
114	asm volatile ("mrs %0, " # x : "=r"(val)); \
115	val; \
116})
117
118void fiq_debugger_dump_allregs(struct fiq_debugger_state *state,
119		const struct pt_regs *regs)
120{
121	u32 pstate = READ_SPECIAL_REG(CurrentEl);
122	bool in_el2 = (pstate & PSR_MODE_MASK) >= PSR_MODE_EL2t;
123
124	fiq_debugger_dump_regs(state, regs);
125
126	fiq_debugger_printf(state, " sp_el0   %016lx\n",
127			READ_SPECIAL_REG(sp_el0));
128
129	if (in_el2)
130		fiq_debugger_printf(state, " sp_el1   %016lx\n",
131				READ_SPECIAL_REG(sp_el1));
132
133	fiq_debugger_printf(state, " elr_el1  %016lx\n",
134			READ_SPECIAL_REG(elr_el1));
135
136	fiq_debugger_printf(state, " spsr_el1 %08lx\n",
137			READ_SPECIAL_REG(spsr_el1));
138
139	if (in_el2) {
140		fiq_debugger_printf(state, " spsr_irq %08lx\n",
141				READ_SPECIAL_REG(spsr_irq));
142		fiq_debugger_printf(state, " spsr_abt %08lx\n",
143				READ_SPECIAL_REG(spsr_abt));
144		fiq_debugger_printf(state, " spsr_und %08lx\n",
145				READ_SPECIAL_REG(spsr_und));
146		fiq_debugger_printf(state, " spsr_fiq %08lx\n",
147				READ_SPECIAL_REG(spsr_fiq));
148		fiq_debugger_printf(state, " spsr_el2 %08lx\n",
149				READ_SPECIAL_REG(elr_el2));
150		fiq_debugger_printf(state, " spsr_el2 %08lx\n",
151				READ_SPECIAL_REG(spsr_el2));
152	}
153}
154
155struct stacktrace_state {
156	struct fiq_debugger_state *state;
157	unsigned int depth;
158};
159
160static int report_trace(struct stackframe *frame, void *d)
161{
162	struct stacktrace_state *sts = d;
163
164	if (sts->depth) {
165		fiq_debugger_printf(sts->state, "%pF:\n", frame->pc);
166		fiq_debugger_printf(sts->state,
167				"  pc %016lx   sp %016lx   fp %016lx\n",
168				frame->pc, frame->sp, frame->fp);
169		sts->depth--;
170		return 0;
171	}
172	fiq_debugger_printf(sts->state, "  ...\n");
173
174	return sts->depth == 0;
175}
176
177void fiq_debugger_dump_stacktrace(struct fiq_debugger_state *state,
178		const struct pt_regs *regs, unsigned int depth, void *ssp)
179{
180	struct thread_info *real_thread_info = THREAD_INFO(ssp);
181	struct stacktrace_state sts;
182
183	sts.depth = depth;
184	sts.state = state;
185	*current_thread_info() = *real_thread_info;
186
187	if (!current)
188		fiq_debugger_printf(state, "current NULL\n");
189	else
190		fiq_debugger_printf(state, "pid: %d  comm: %s\n",
191			current->pid, current->comm);
192	fiq_debugger_dump_regs(state, regs);
193
194	if (!user_mode(regs)) {
195		struct stackframe frame;
196		frame.fp = regs->regs[29];
197		frame.sp = regs->sp;
198		frame.pc = regs->pc;
199		fiq_debugger_printf(state, "\n");
200		walk_stackframe(&frame, report_trace, &sts);
201	}
202}
203