xref: /OK3568_Linux_fs/kernel/drivers/soc/rockchip/fiq_debugger/fiq_debugger_arm64.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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 
mode_name(const struct pt_regs * regs)21 static 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 
fiq_debugger_dump_pc(struct fiq_debugger_output * output,const struct pt_regs * regs)37 void fiq_debugger_dump_pc(struct fiq_debugger_output *output,
38 		const struct pt_regs *regs)
39 {
40 	output->printf(output, " pc %016lx cpsr %08lx mode %s\n",
41 		regs->pc, regs->pstate, mode_name(regs));
42 }
43 
fiq_debugger_dump_regs_aarch32(struct fiq_debugger_output * output,const struct pt_regs * regs)44 void fiq_debugger_dump_regs_aarch32(struct fiq_debugger_output *output,
45 		const struct pt_regs *regs)
46 {
47 	output->printf(output, " 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 	output->printf(output, " 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 	output->printf(output, " 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 	output->printf(output, " ip %08x  sp %08x  lr %08x  pc %08x\n",
57 			regs->compat_usr(12), regs->compat_sp,
58 			regs->compat_lr, regs->pc);
59 	output->printf(output, " cpsr %08x (%s)\n",
60 			regs->pstate, mode_name(regs));
61 }
62 
fiq_debugger_dump_regs_aarch64(struct fiq_debugger_output * output,const struct pt_regs * regs)63 void fiq_debugger_dump_regs_aarch64(struct fiq_debugger_output *output,
64 		const struct pt_regs *regs)
65 {
66 
67 	output->printf(output, "  x0 %016lx   x1 %016lx\n",
68 			regs->regs[0], regs->regs[1]);
69 	output->printf(output, "  x2 %016lx   x3 %016lx\n",
70 			regs->regs[2], regs->regs[3]);
71 	output->printf(output, "  x4 %016lx   x5 %016lx\n",
72 			regs->regs[4], regs->regs[5]);
73 	output->printf(output, "  x6 %016lx   x7 %016lx\n",
74 			regs->regs[6], regs->regs[7]);
75 	output->printf(output, "  x8 %016lx   x9 %016lx\n",
76 			regs->regs[8], regs->regs[9]);
77 	output->printf(output, " x10 %016lx  x11 %016lx\n",
78 			regs->regs[10], regs->regs[11]);
79 	output->printf(output, " x12 %016lx  x13 %016lx\n",
80 			regs->regs[12], regs->regs[13]);
81 	output->printf(output, " x14 %016lx  x15 %016lx\n",
82 			regs->regs[14], regs->regs[15]);
83 	output->printf(output, " x16 %016lx  x17 %016lx\n",
84 			regs->regs[16], regs->regs[17]);
85 	output->printf(output, " x18 %016lx  x19 %016lx\n",
86 			regs->regs[18], regs->regs[19]);
87 	output->printf(output, " x20 %016lx  x21 %016lx\n",
88 			regs->regs[20], regs->regs[21]);
89 	output->printf(output, " x22 %016lx  x23 %016lx\n",
90 			regs->regs[22], regs->regs[23]);
91 	output->printf(output, " x24 %016lx  x25 %016lx\n",
92 			regs->regs[24], regs->regs[25]);
93 	output->printf(output, " x26 %016lx  x27 %016lx\n",
94 			regs->regs[26], regs->regs[27]);
95 	output->printf(output, " x28 %016lx  x29 %016lx\n",
96 			regs->regs[28], regs->regs[29]);
97 	output->printf(output, " x30 %016lx   sp %016lx\n",
98 			regs->regs[30], regs->sp);
99 	output->printf(output, "  pc %016lx cpsr %08x (%s)\n",
100 			regs->pc, regs->pstate, mode_name(regs));
101 }
102 
fiq_debugger_dump_regs(struct fiq_debugger_output * output,const struct pt_regs * regs)103 void fiq_debugger_dump_regs(struct fiq_debugger_output *output,
104 		const struct pt_regs *regs)
105 {
106 	if (compat_user_mode(regs))
107 		fiq_debugger_dump_regs_aarch32(output, regs);
108 	else
109 		fiq_debugger_dump_regs_aarch64(output, regs);
110 }
111 
112 #define READ_SPECIAL_REG(x) ({ \
113 	u64 val; \
114 	asm volatile ("mrs %0, " # x : "=r"(val)); \
115 	val; \
116 })
117 
fiq_debugger_dump_allregs(struct fiq_debugger_output * output,const struct pt_regs * regs)118 void fiq_debugger_dump_allregs(struct fiq_debugger_output *output,
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(output, regs);
125 
126 	output->printf(output, " sp_el0   %016lx\n",
127 			READ_SPECIAL_REG(sp_el0));
128 
129 	if (in_el2)
130 		output->printf(output, " sp_el1   %016lx\n",
131 				READ_SPECIAL_REG(sp_el1));
132 
133 	output->printf(output, " elr_el1  %016lx\n",
134 			READ_SPECIAL_REG(elr_el1));
135 
136 	output->printf(output, " spsr_el1 %08lx\n",
137 			READ_SPECIAL_REG(spsr_el1));
138 
139 	if (in_el2) {
140 		output->printf(output, " spsr_irq %08lx\n",
141 				READ_SPECIAL_REG(spsr_irq));
142 		output->printf(output, " spsr_abt %08lx\n",
143 				READ_SPECIAL_REG(spsr_abt));
144 		output->printf(output, " spsr_und %08lx\n",
145 				READ_SPECIAL_REG(spsr_und));
146 		output->printf(output, " spsr_fiq %08lx\n",
147 				READ_SPECIAL_REG(spsr_fiq));
148 		output->printf(output, " elr_el2 %08lx\n",
149 				READ_SPECIAL_REG(elr_el2));
150 		output->printf(output, " spsr_el2 %08lx\n",
151 				READ_SPECIAL_REG(spsr_el2));
152 	}
153 }
154 
155 #ifndef CONFIG_FIQ_DEBUGGER_MODULE
156 struct stacktrace_state {
157 	struct fiq_debugger_output *output;
158 	unsigned int depth;
159 };
160 
report_trace(void * data,unsigned long pc)161 static bool report_trace(void *data, unsigned long pc)
162 {
163 	struct stacktrace_state *sts = data;
164 
165 	if (sts->depth) {
166 		sts->output->printf(sts->output, "[<%016lx>] %pS:\n", pc, pc);
167 		sts->depth--;
168 		return true;
169 	}
170 	sts->output->printf(sts->output, "  ...\n");
171 
172 	return sts->depth != 0;
173 }
174 
fiq_debugger_dump_stacktrace(struct fiq_debugger_output * output,const struct pt_regs * regs,unsigned int depth,void * ssp)175 void fiq_debugger_dump_stacktrace(struct fiq_debugger_output *output,
176 		const struct pt_regs *regs, unsigned int depth, void *ssp)
177 {
178 	struct stacktrace_state sts;
179 
180 	sts.depth = depth;
181 	sts.output = output;
182 
183 	if (!current)
184 		output->printf(output, "current NULL\n");
185 	else
186 		output->printf(output, "pid: %d  comm: %s\n",
187 			current->pid, current->comm);
188 	fiq_debugger_dump_regs(output, regs);
189 
190 	if (!user_mode(regs)) {
191 		struct stackframe frame;
192 		frame.fp = regs->regs[29];
193 		frame.pc = regs->pc;
194 		frame.prev_type = STACK_TYPE_UNKNOWN;
195 		output->printf(output, "\n");
196 		walk_stackframe(current, &frame, report_trace, &sts);
197 	}
198 }
199 #endif
200